@@ -8,8 +8,8 @@ import { XHTMLEntities } from './xhtml-entities';
88
99interface MetaJSXElement {
1010 node : Marker ;
11- opening : JSXNode . JSXOpeningElement ;
12- closing : JSXNode . JSXClosingElement | null ;
11+ opening : JSXNode . JSXOpeningElement | JSXNode . JSXOpeningFragment ;
12+ closing : JSXNode . JSXClosingElement | JSXNode . JSXClosingFragment | null ;
1313 children : JSXNode . JSXChild [ ] ;
1414}
1515
@@ -463,10 +463,15 @@ export class JSXParser extends Parser {
463463 return attributes ;
464464 }
465465
466- parseJSXOpeningElement ( ) : JSXNode . JSXOpeningElement {
466+ parseJSXOpeningElement ( ) : JSXNode . JSXOpeningElement | JSXNode . JSXOpeningFragment {
467467 const node = this . createJSXNode ( ) ;
468468
469469 this . expectJSX ( '<' ) ;
470+ if ( this . matchJSX ( '>' ) ) {
471+ this . expectJSX ( '>' ) ;
472+ return this . finalize ( node , new JSXNode . JSXOpeningFragment ( false ) ) ;
473+ }
474+
470475 const name = this . parseJSXElementName ( ) ;
471476 const attributes = this . parseJSXAttributes ( ) ;
472477 const selfClosing = this . matchJSX ( '/' ) ;
@@ -478,12 +483,16 @@ export class JSXParser extends Parser {
478483 return this . finalize ( node , new JSXNode . JSXOpeningElement ( name , selfClosing , attributes ) ) ;
479484 }
480485
481- parseJSXBoundaryElement ( ) : JSXNode . JSXOpeningElement | JSXNode . JSXClosingElement {
486+ parseJSXBoundaryElement ( ) : JSXNode . JSXOpeningElement | JSXNode . JSXClosingElement | JSXNode . JSXOpeningFragment | JSXNode . JSXClosingFragment {
482487 const node = this . createJSXNode ( ) ;
483488
484489 this . expectJSX ( '<' ) ;
485490 if ( this . matchJSX ( '/' ) ) {
486491 this . expectJSX ( '/' ) ;
492+ if ( this . matchJSX ( '>' ) ) {
493+ this . expectJSX ( '>' ) ;
494+ return this . finalize ( node , new JSXNode . JSXClosingFragment ( ) ) ;
495+ }
487496 const elementName = this . parseJSXElementName ( ) ;
488497 this . expectJSX ( '>' ) ;
489498 return this . finalize ( node , new JSXNode . JSXClosingElement ( elementName ) ) ;
@@ -567,8 +576,8 @@ export class JSXParser extends Parser {
567576 }
568577 if ( element . type === JSXSyntax . JSXClosingElement ) {
569578 el . closing = element as JSXNode . JSXClosingElement ;
570- const open = getQualifiedElementName ( el . opening . name ) ;
571- const close = getQualifiedElementName ( el . closing . name ) ;
579+ const open = getQualifiedElementName ( ( el . opening as JSXNode . JSXOpeningElement ) . name ) ;
580+ const close = getQualifiedElementName ( ( el . closing as JSXNode . JSXClosingElement ) . name ) ;
572581 if ( open !== close ) {
573582 this . tolerateError ( 'Expected corresponding JSX closing tag for %0' , open ) ;
574583 }
@@ -581,6 +590,14 @@ export class JSXParser extends Parser {
581590 break ;
582591 }
583592 }
593+ if ( element . type === JSXSyntax . JSXClosingFragment ) {
594+ el . closing = element as JSXNode . JSXClosingFragment ;
595+ if ( el . opening . type !== JSXSyntax . JSXOpeningFragment ) {
596+ this . tolerateError ( 'Expected corresponding JSX closing tag for jsx fragment' ) ;
597+ } else {
598+ break ;
599+ }
600+ }
584601 }
585602
586603 return el ;
@@ -591,7 +608,7 @@ export class JSXParser extends Parser {
591608
592609 const opening = this . parseJSXOpeningElement ( ) ;
593610 let children : JSXNode . JSXChild [ ] = [ ] ;
594- let closing : JSXNode . JSXClosingElement | null = null ;
611+ let closing : JSXNode . JSXClosingElement | JSXNode . JSXClosingFragment | null = null ;
595612
596613 if ( ! opening . selfClosing ) {
597614 const el = this . parseComplexJSXElement ( { node, opening, closing, children } ) ;
0 commit comments