@@ -64,6 +64,7 @@ export type TransformTopLevelDeclaration = {
6464
6565export type TransformJsxSourceOptions = TranspileJsxSourceOptions & {
6666 collectTopLevelDeclarations ?: boolean
67+ collectTopLevelJsxExpression ?: boolean
6768}
6869
6970type InternalTransformJsxSourceOptions = TransformJsxSourceOptions & {
@@ -77,6 +78,7 @@ export type TransformJsxSourceResult = {
7778 imports : TransformImport [ ]
7879 diagnostics : TransformDiagnostic [ ]
7980 declarations ?: TransformTopLevelDeclaration [ ]
81+ hasTopLevelJsxExpression ?: boolean
8082}
8183
8284const createParserOptions = ( sourceType : TransformSourceType ) => ( {
@@ -394,6 +396,59 @@ const collectTopLevelDeclarationMetadata = (
394396 return declarations
395397}
396398
399+ const unwrapExpressionNode = ( value : unknown ) : unknown => {
400+ let current = value
401+
402+ while ( isObjectRecord ( current ) && typeof current . type === 'string' ) {
403+ if ( current . type === 'ParenthesizedExpression' ) {
404+ current = current . expression
405+ continue
406+ }
407+
408+ if (
409+ current . type === 'TSAsExpression' ||
410+ current . type === 'TSSatisfiesExpression' ||
411+ current . type === 'TSInstantiationExpression' ||
412+ current . type === 'TSNonNullExpression' ||
413+ current . type === 'TSTypeAssertion'
414+ ) {
415+ current = current . expression
416+ continue
417+ }
418+
419+ break
420+ }
421+
422+ return current
423+ }
424+
425+ const isJsxExpressionNode = ( value : unknown ) : boolean => {
426+ const unwrapped = unwrapExpressionNode ( value )
427+ if ( ! isObjectRecord ( unwrapped ) || typeof unwrapped . type !== 'string' ) {
428+ return false
429+ }
430+
431+ return unwrapped . type === 'JSXElement' || unwrapped . type === 'JSXFragment'
432+ }
433+
434+ const collectTopLevelJsxExpressionMetadata = ( body : unknown ) : boolean => {
435+ if ( ! Array . isArray ( body ) ) {
436+ return false
437+ }
438+
439+ for ( const statement of body ) {
440+ if ( ! isObjectRecord ( statement ) || statement . type !== 'ExpressionStatement' ) {
441+ continue
442+ }
443+
444+ if ( isJsxExpressionNode ( statement . expression ) ) {
445+ return true
446+ }
447+ }
448+
449+ return false
450+ }
451+
397452const ensureSupportedOptions = ( options : InternalTransformJsxSourceOptions ) => {
398453 if (
399454 options . sourceType !== undefined &&
@@ -433,6 +488,15 @@ const ensureSupportedOptions = (options: InternalTransformJsxSourceOptions) => {
433488 `[jsx] Unsupported collectTopLevelDeclarations value "${ String ( options . collectTopLevelDeclarations ) } ". Use true or false.` ,
434489 )
435490 }
491+
492+ if (
493+ options . collectTopLevelJsxExpression !== undefined &&
494+ typeof options . collectTopLevelJsxExpression !== 'boolean'
495+ ) {
496+ throw new Error (
497+ `[jsx] Unsupported collectTopLevelJsxExpression value "${ String ( options . collectTopLevelJsxExpression ) } ". Use true or false.` ,
498+ )
499+ }
436500}
437501
438502export function transformJsxSource (
@@ -458,6 +522,9 @@ export function transformJsxSource(
458522 const declarations = internalOptions . collectTopLevelDeclarations
459523 ? collectTopLevelDeclarationMetadata ( parsed . program . body )
460524 : undefined
525+ const hasTopLevelJsxExpression = internalOptions . collectTopLevelJsxExpression
526+ ? collectTopLevelJsxExpressionMetadata ( parsed . program . body )
527+ : undefined
461528
462529 if ( parserDiagnostics . length ) {
463530 return {
@@ -466,6 +533,7 @@ export function transformJsxSource(
466533 imports,
467534 diagnostics : parserDiagnostics ,
468535 declarations,
536+ hasTopLevelJsxExpression,
469537 }
470538 }
471539
@@ -484,6 +552,7 @@ export function transformJsxSource(
484552 imports,
485553 diagnostics : parserDiagnostics ,
486554 declarations,
555+ hasTopLevelJsxExpression,
487556 }
488557 }
489558
@@ -499,6 +568,7 @@ export function transformJsxSource(
499568 imports,
500569 diagnostics : parserDiagnostics ,
501570 declarations,
571+ hasTopLevelJsxExpression,
502572 }
503573 }
504574
@@ -522,6 +592,7 @@ export function transformJsxSource(
522592 imports,
523593 diagnostics,
524594 declarations,
595+ hasTopLevelJsxExpression,
525596 }
526597 }
527598
@@ -533,5 +604,6 @@ export function transformJsxSource(
533604 imports,
534605 diagnostics,
535606 declarations,
607+ hasTopLevelJsxExpression,
536608 }
537609}
0 commit comments