@@ -77,7 +77,6 @@ export default function inlineSveltePlugin({
7777 const VIRT = "virtual:inline-svelte/" ;
7878 const RSLV = "\0" + VIRT ;
7979
80- /** virtualId → full markup (with injected imports) */
8180 const cache = new Map < string , string > ( ) ;
8281
8382 return {
@@ -93,64 +92,37 @@ export default function inlineSveltePlugin({
9392 const imports = ( fenceRE . exec ( code ) ?. [ 1 ] ?? "" ) . trim ( ) ;
9493
9594 let importsToAdd = "" ;
96- let globalImportsForTpl = "" ;
9795 let hoistedCode = "" ;
98- const globalVarDefs = new Map < string , string > ( ) ;
9996 const hashToLocal = new Map < string , string > ( ) ;
10097 const globalComponentNames = new Set < string > ( ) ;
98+ const globalVarDefs = new Map < string , string > ( ) ;
99+ const depGraph = new Map < string , Set < string > > ( ) ;
100+ let allGlobalNames : string [ ] = [ ] ;
101+ let globalImportsForTpl = "" ;
101102
102103 /* 1. Process globals */
103104 const globalsMatch = globalsRE . exec ( code ) ;
104105 if ( globalsMatch ) {
105106 edited = true ;
106107 const globalsContent = globalsMatch [ 1 ] ?? "" ;
107108 ms . overwrite ( globalsMatch . index , globalsMatch . index + globalsMatch [ 0 ] . length , "" ) ;
108- hoistedCode = globalsContent ;
109-
110- const replacements = [ ] ;
111- let match ;
112- globalDefRE . lastIndex = 0 ;
113- while ( ( match = globalDefRE . exec ( globalsContent ) ) !== null ) {
114- const [ fullMatch , compName , templateLiteralWithTicks ] = match ;
115- globalComponentNames . add ( compName ) ;
116-
117- const rawMarkup = templateLiteralWithTicks . slice ( 1 , - 1 ) ;
118- const markup = applyImports ( rawMarkup , imports ) ;
119- const hash = createHash ( "sha1" ) . update ( markup ) . digest ( "hex" ) . slice ( 0 , 8 ) ;
120-
121- let local = hashToLocal . get ( hash ) ;
122- if ( ! local ) {
123- local = `Inline_${ hash } ` ;
124- hashToLocal . set ( hash , local ) ;
125- const virt = `${ VIRT } ${ hash } .js` ;
126- if ( ! cache . has ( virt ) ) cache . set ( virt , markup ) ;
127- const ns = `__InlineNS_${ hash } ` ;
128- importsToAdd += `import * as ${ ns } from '${ virt } ';\nconst ${ local } =Object.assign(${ ns } .default, ${ ns } );\n` ;
129- globalImportsForTpl += `import ${ compName } from '${ virt } ';\n` ;
130- }
131109
132- replacements . push ( {
133- start : match . index ,
134- end : match . index + fullMatch . length ,
135- newText : `const ${ compName } = ${ local } ` ,
136- } ) ;
137- }
138-
139- for ( const rep of replacements . reverse ( ) ) {
140- hoistedCode = hoistedCode . slice ( 0 , rep . start ) + rep . newText + hoistedCode . slice ( rep . end ) ;
141- }
110+ const componentMatches = [ ...globalsContent . matchAll ( globalDefRE ) ] ;
111+ componentMatches . forEach ( match => globalComponentNames . add ( match [ 1 ] ) ) ;
142112
143113 const startOfDeclRegex = / ^ (?: c o n s t | l e t | v a r ) \s + ( [ a - z A - Z 0 - 9 _ $ ] + ) / gm;
144114 let declMatch ;
145- while ( ( declMatch = startOfDeclRegex . exec ( hoistedCode ) ) !== null ) {
115+ while ( ( declMatch = startOfDeclRegex . exec ( globalsContent ) ) !== null ) {
146116 const varName = declMatch [ 1 ] ;
117+ if ( globalComponentNames . has ( varName ) ) continue ;
118+
147119 const startIndex = declMatch . index ;
148120 let braceDepth = 0 ,
149121 bracketDepth = 0 ,
150122 parenDepth = 0 ,
151123 endIndex = - 1 ;
152- for ( let i = startIndex ; i < hoistedCode . length ; i ++ ) {
153- const char = hoistedCode [ i ] ;
124+ for ( let i = startIndex ; i < globalsContent . length ; i ++ ) {
125+ const char = globalsContent [ i ] ;
154126 if ( char === "{" ) braceDepth ++ ;
155127 else if ( char === "}" ) braceDepth -- ;
156128 else if ( char === "[" ) bracketDepth ++ ;
@@ -163,24 +135,91 @@ export default function inlineSveltePlugin({
163135 }
164136 }
165137 if ( endIndex === - 1 ) {
166- const nextNewline = hoistedCode . indexOf ( "\n" , startIndex ) ;
167- endIndex = nextNewline !== - 1 ? nextNewline : hoistedCode . length ;
138+ const nextNewline = globalsContent . indexOf ( "\n" , startIndex ) ;
139+ endIndex = nextNewline !== - 1 ? nextNewline : globalsContent . length ;
168140 }
169- const definition = hoistedCode . substring ( startIndex , endIndex ) . trim ( ) ;
141+ const definition = globalsContent . substring ( startIndex , endIndex ) . trim ( ) ;
170142 if ( definition ) globalVarDefs . set ( varName , definition ) ;
171143 startOfDeclRegex . lastIndex = endIndex ;
172144 }
173- }
174145
175- const depGraph = new Map < string , Set < string > > ( ) ;
176- const allGlobalNames = [ ...globalVarDefs . keys ( ) ] ;
177- for ( const [ name , definition ] of globalVarDefs . entries ( ) ) {
178- const dependencies = new Set < string > ( ) ;
179- for ( const depName of allGlobalNames ) {
180- if ( name === depName ) continue ;
181- if ( new RegExp ( `\\b${ depName } \\b` ) . test ( definition ) ) dependencies . add ( depName ) ;
146+ allGlobalNames = [ ...globalComponentNames , ...globalVarDefs . keys ( ) ] ;
147+ const nameToMarkup = new Map ( componentMatches . map ( m => [ m [ 1 ] , m [ 2 ] . slice ( 1 , - 1 ) ] ) ) ;
148+
149+ for ( const name of allGlobalNames ) {
150+ const dependencies = new Set < string > ( ) ;
151+ const content = globalComponentNames . has ( name )
152+ ? nameToMarkup . get ( name ) !
153+ : globalVarDefs . get ( name ) ! ;
154+ for ( const depName of allGlobalNames ) {
155+ if ( name === depName ) continue ;
156+ if ( new RegExp ( `\\b${ depName } \\b` ) . test ( content ) ) dependencies . add ( depName ) ;
157+ }
158+ depGraph . set ( name , dependencies ) ;
159+ }
160+
161+ const sortedComponentNames = [ ...globalComponentNames ] . sort ( ( a , b ) => {
162+ const depsA = getTransitiveDependencies ( new Set ( [ a ] ) , depGraph ) ;
163+ if ( depsA . has ( b ) ) return 1 ;
164+ const depsB = getTransitiveDependencies ( new Set ( [ b ] ) , depGraph ) ;
165+ if ( depsB . has ( a ) ) return - 1 ;
166+ return allGlobalNames . indexOf ( a ) - allGlobalNames . indexOf ( b ) ;
167+ } ) ;
168+
169+ const componentInfo = new Map < string , { local : string ; virt : string } > ( ) ;
170+ const replacements = [ ] ;
171+
172+ for ( const compName of sortedComponentNames ) {
173+ const match = componentMatches . find ( m => m [ 1 ] === compName ) ! ;
174+ const [ , , templateLiteralWithTicks ] = match ;
175+ const rawMarkup = templateLiteralWithTicks . slice ( 1 , - 1 ) ;
176+
177+ const allDeps = getTransitiveDependencies ( new Set ( [ compName ] ) , depGraph ) ;
178+ allDeps . delete ( compName ) ;
179+
180+ let scriptToInject = "" ;
181+ const sortedDeps = [ ...allDeps ] . sort (
182+ ( a , b ) => allGlobalNames . indexOf ( a ) - allGlobalNames . indexOf ( b )
183+ ) ;
184+ for ( const depName of sortedDeps ) {
185+ if ( globalComponentNames . has ( depName ) ) {
186+ const info = componentInfo . get ( depName ) ;
187+ if ( info ) scriptToInject += `import ${ depName } from '${ info . virt } ';\n` ;
188+ } else {
189+ const definition = globalVarDefs . get ( depName ) ;
190+ if ( definition ) scriptToInject += `\n${ definition } ` ;
191+ }
192+ }
193+
194+ const markupWithDeps = applyImports ( rawMarkup , scriptToInject ) ;
195+ const markup = applyImports ( markupWithDeps , imports ) ;
196+ const hash = createHash ( "sha1" ) . update ( markup ) . digest ( "hex" ) . slice ( 0 , 8 ) ;
197+
198+ let local = hashToLocal . get ( hash ) ;
199+ const virt = `${ VIRT } ${ hash } .js` ;
200+ if ( ! local ) {
201+ local = `Inline_${ hash } ` ;
202+ hashToLocal . set ( hash , local ) ;
203+ if ( ! cache . has ( virt ) ) cache . set ( virt , markup ) ;
204+ const ns = `__InlineNS_${ hash } ` ;
205+ importsToAdd += `import * as ${ ns } from '${ virt } ';\nconst ${ local } =Object.assign(${ ns } .default, ${ ns } );\n` ;
206+ }
207+
208+ componentInfo . set ( compName , { local, virt } ) ;
209+ globalImportsForTpl += `import ${ compName } from '${ virt } ';\n` ;
210+ replacements . push ( {
211+ start : match . index ,
212+ end : match . index + match [ 0 ] . length ,
213+ newText : `const ${ compName } = ${ local } ;` ,
214+ } ) ;
215+ }
216+
217+ let tempHoistedCode = globalsContent ;
218+ for ( const rep of replacements . reverse ( ) ) {
219+ tempHoistedCode =
220+ tempHoistedCode . slice ( 0 , rep . start ) + rep . newText + tempHoistedCode . slice ( rep . end ) ;
182221 }
183- depGraph . set ( name , dependencies ) ;
222+ hoistedCode = tempHoistedCode ;
184223 }
185224
186225 /* 2. Process all regular templates */
@@ -209,10 +248,9 @@ export default function inlineSveltePlugin({
209248 for ( const name of sortedDeps ) {
210249 if ( globalComponentNames . has ( name ) ) continue ;
211250
212- // FIX: A more precise regex to check for actual declarations, not just usage.
213- const isDeclaredInScript = new RegExp (
214- `\\b(let|const|var)\\s+([^=;]*?)\\b${ name } \\b`
215- ) . test ( existingScriptContent ) ;
251+ const isDeclaredInScript = new RegExp ( `\\b(let|const|var)\\s+[^=;]*?\\b${ name } \\b` ) . test (
252+ existingScriptContent
253+ ) ;
216254 if ( isDeclaredInScript ) continue ;
217255
218256 const definition = globalVarDefs . get ( name ) ;
0 commit comments