@@ -593,6 +593,78 @@ export interface BundleOptions {
593593 * - Inlines sub-composition HTML fragments (data-composition-src)
594594 * - Inlines small textual assets as data URLs
595595 */
596+
597+ function ensureExternalScriptTag ( doc : Document , src : string ) : void {
598+ if ( doc . querySelector ( `script[src="${ src } "]` ) ) return ;
599+ const el = doc . createElement ( "script" ) ;
600+ el . setAttribute ( "src" , src ) ;
601+ doc . body . appendChild ( el ) ;
602+ }
603+
604+ function hoistExternalScript (
605+ src : string ,
606+ projectDir : string ,
607+ doc : Document ,
608+ seenSrcs : Set < string > ,
609+ chunks : string [ ] ,
610+ ) : void {
611+ if ( seenSrcs . has ( src ) ) return ;
612+ seenSrcs . add ( src ) ;
613+ if ( ! isNonRelativeUrl ( src ) && ! isAbsolute ( src ) ) {
614+ const jsPath = resolveWithinProject ( projectDir , src ) ;
615+ const js = jsPath ? safeReadFile ( jsPath ) : null ;
616+ if ( js != null ) {
617+ chunks . push ( js ) ;
618+ return ;
619+ }
620+ }
621+ ensureExternalScriptTag ( doc , src ) ;
622+ }
623+
624+ function hoistCompositionScripts (
625+ container : { querySelectorAll : ( sel : string ) => NodeListOf < Element > } ,
626+ opts : {
627+ projectDir : string ;
628+ document : Document ;
629+ compId : string | null ;
630+ runtimeScope : string | undefined ;
631+ runtimeCompId : string | undefined ;
632+ authoredRootId : string | undefined ;
633+ seenCompScriptSrcs : Set < string > ;
634+ compScriptChunks : string [ ] ;
635+ } ,
636+ ) : void {
637+ for ( const scriptEl of [ ...container . querySelectorAll ( "script" ) ] ) {
638+ const externalSrc = ( scriptEl . getAttribute ( "src" ) || "" ) . trim ( ) ;
639+ if ( externalSrc ) {
640+ hoistExternalScript (
641+ externalSrc ,
642+ opts . projectDir ,
643+ opts . document ,
644+ opts . seenCompScriptSrcs ,
645+ opts . compScriptChunks ,
646+ ) ;
647+ } else {
648+ opts . compScriptChunks . push (
649+ opts . compId
650+ ? wrapScopedCompositionScript (
651+ scriptEl . textContent || "" ,
652+ opts . compId ,
653+ "[HyperFrames] composition script error:" ,
654+ opts . runtimeScope ,
655+ opts . runtimeCompId || opts . compId ,
656+ opts . authoredRootId ,
657+ )
658+ : wrapInlineScriptWithErrorBoundary (
659+ scriptEl . textContent || "" ,
660+ "[HyperFrames] composition script error:" ,
661+ ) ,
662+ ) ;
663+ }
664+ scriptEl . remove ( ) ;
665+ }
666+ }
667+
596668export async function bundleToSingleHtml (
597669 projectDir : string ,
598670 options ?: BundleOptions ,
@@ -775,47 +847,16 @@ export async function bundleToSingleHtml(
775847 ) ;
776848 styleEl . remove ( ) ;
777849 }
778- // Hoist scripts into the collected script chunks
779- for ( const scriptEl of [ ...innerRoot . querySelectorAll ( "script" ) ] ) {
780- const externalSrc = ( scriptEl . getAttribute ( "src" ) || "" ) . trim ( ) ;
781- if ( externalSrc ) {
782- if ( ! seenCompScriptSrcs . has ( externalSrc ) ) {
783- seenCompScriptSrcs . add ( externalSrc ) ;
784- if ( isRelativeUrl ( externalSrc ) ) {
785- const jsPath = resolveWithinProject ( projectDir , externalSrc ) ;
786- const js = jsPath ? safeReadFile ( jsPath ) : null ;
787- if ( js != null ) {
788- compScriptChunks . push ( js ) ;
789- } else if ( ! document . querySelector ( `script[src="${ externalSrc } "]` ) ) {
790- const extScript = document . createElement ( "script" ) ;
791- extScript . setAttribute ( "src" , externalSrc ) ;
792- document . body . appendChild ( extScript ) ;
793- }
794- } else if ( ! document . querySelector ( `script[src="${ externalSrc } "]` ) ) {
795- const extScript = document . createElement ( "script" ) ;
796- extScript . setAttribute ( "src" , externalSrc ) ;
797- document . body . appendChild ( extScript ) ;
798- }
799- }
800- } else {
801- compScriptChunks . push (
802- compId
803- ? wrapScopedCompositionScript (
804- scriptEl . textContent || "" ,
805- compId ,
806- "[HyperFrames] composition script error:" ,
807- runtimeScope ,
808- runtimeCompId || compId ,
809- authoredRootId ,
810- )
811- : wrapInlineScriptWithErrorBoundary (
812- scriptEl . textContent || "" ,
813- "[HyperFrames] composition script error:" ,
814- ) ,
815- ) ;
816- }
817- scriptEl . remove ( ) ;
818- }
850+ hoistCompositionScripts ( innerRoot , {
851+ projectDir,
852+ document,
853+ compId,
854+ runtimeScope,
855+ runtimeCompId,
856+ authoredRootId : authoredRootId ?? undefined ,
857+ seenCompScriptSrcs,
858+ compScriptChunks,
859+ } ) ;
819860
820861 // Copy dimension attributes from inner root to host if not already set
821862 const innerW = innerRoot . getAttribute ( "data-width" ) ;
@@ -831,45 +872,16 @@ export async function bundleToSingleHtml(
831872 compStyleChunks . push ( compId ? scopeCssToComposition ( css , compId , runtimeScope ) : css ) ;
832873 styleEl . remove ( ) ;
833874 }
834- for ( const scriptEl of [ ...innerDoc . querySelectorAll ( "script" ) ] ) {
835- const externalSrc = ( scriptEl . getAttribute ( "src" ) || "" ) . trim ( ) ;
836- if ( externalSrc ) {
837- if ( ! seenCompScriptSrcs . has ( externalSrc ) ) {
838- seenCompScriptSrcs . add ( externalSrc ) ;
839- if ( isRelativeUrl ( externalSrc ) ) {
840- const jsPath = resolveWithinProject ( projectDir , externalSrc ) ;
841- const js = jsPath ? safeReadFile ( jsPath ) : null ;
842- if ( js != null ) {
843- compScriptChunks . push ( js ) ;
844- } else if ( ! document . querySelector ( `script[src="${ externalSrc } "]` ) ) {
845- const extScript = document . createElement ( "script" ) ;
846- extScript . setAttribute ( "src" , externalSrc ) ;
847- document . body . appendChild ( extScript ) ;
848- }
849- } else if ( ! document . querySelector ( `script[src="${ externalSrc } "]` ) ) {
850- const extScript = document . createElement ( "script" ) ;
851- extScript . setAttribute ( "src" , externalSrc ) ;
852- document . body . appendChild ( extScript ) ;
853- }
854- }
855- } else {
856- compScriptChunks . push (
857- compId
858- ? wrapScopedCompositionScript (
859- scriptEl . textContent || "" ,
860- compId ,
861- "[HyperFrames] composition script error:" ,
862- runtimeScope ,
863- runtimeCompId || compId ,
864- )
865- : wrapInlineScriptWithErrorBoundary (
866- scriptEl . textContent || "" ,
867- "[HyperFrames] composition script error:" ,
868- ) ,
869- ) ;
870- }
871- scriptEl . remove ( ) ;
872- }
875+ hoistCompositionScripts ( innerDoc , {
876+ projectDir,
877+ document,
878+ compId,
879+ runtimeScope,
880+ runtimeCompId,
881+ authoredRootId : undefined ,
882+ seenCompScriptSrcs,
883+ compScriptChunks,
884+ } ) ;
873885
874886 host . innerHTML = innerDoc . body . innerHTML || "" ;
875887 }
0 commit comments