@@ -148,26 +148,47 @@ export class Context {
148148 let start = 0 ;
149149 for ( const block of extractBlocks ( code ) ) {
150150 if ( block . tag === "template" ) {
151+ if ( block . selfClosing ) {
152+ continue ;
153+ }
151154 const lang = block . attrs . find ( ( attr ) => attr . key . name === "lang" ) ;
152155 if ( ! lang || ! lang . value || lang . value . value === "html" ) {
153156 continue ;
154157 }
155158 }
156159 this . blocks . push ( block ) ;
157- templateCode +=
158- code . slice ( start , block . contentRange [ 0 ] ) +
159- spaces . slice ( block . contentRange [ 0 ] , block . contentRange [ 1 ] ) ;
160- if ( block . tag === "script" ) {
161- scriptCode +=
162- spaces . slice ( start , block . contentRange [ 0 ] ) +
163- code . slice ( ...block . contentRange ) ;
164- for ( const attr of block . attrs ) {
165- scriptAttrs [ attr . key . name ] = attr . value ?. value ;
166- }
160+
161+ if ( block . selfClosing ) {
162+ // Self-closing blocks are temporarily replaced with `<s---->` or `<t---->` tag
163+ // because the svelte compiler cannot parse self-closing block(script, style) tags.
164+ // It will be restored later in `convertHTMLElement()` processing.
165+ templateCode += `${ code . slice (
166+ start ,
167+ block . startTagRange [ 0 ] + 2 /* `<` and first letter */
168+ ) } ${ "-" . repeat (
169+ block . tag . length - 1 /* skip first letter */
170+ ) } ${ code . slice (
171+ block . startTagRange [ 0 ] + 1 /* skip `<` */ + block . tag . length ,
172+ block . startTagRange [ 1 ]
173+ ) } `;
174+ scriptCode += spaces . slice ( start , block . startTagRange [ 1 ] ) ;
175+ start = block . startTagRange [ 1 ] ;
167176 } else {
168- scriptCode += spaces . slice ( start , block . contentRange [ 1 ] ) ;
177+ templateCode +=
178+ code . slice ( start , block . contentRange [ 0 ] ) +
179+ spaces . slice ( block . contentRange [ 0 ] , block . contentRange [ 1 ] ) ;
180+ if ( block . tag === "script" ) {
181+ scriptCode +=
182+ spaces . slice ( start , block . contentRange [ 0 ] ) +
183+ code . slice ( ...block . contentRange ) ;
184+ for ( const attr of block . attrs ) {
185+ scriptAttrs [ attr . key . name ] = attr . value ?. value ;
186+ }
187+ } else {
188+ scriptCode += spaces . slice ( start , block . contentRange [ 1 ] ) ;
189+ }
190+ start = block . contentRange [ 1 ] ;
169191 }
170- start = block . contentRange [ 1 ] ;
171192 }
172193 templateCode += code . slice ( start ) ;
173194 scriptCode += spaces . slice ( start ) ;
@@ -301,16 +322,43 @@ export class Context {
301322 return this . blocks . find (
302323 ( block ) =>
303324 block . tag === tag &&
325+ ! block . selfClosing &&
304326 element . range [ 0 ] <= block . contentRange [ 0 ] &&
305327 block . contentRange [ 1 ] <= element . range [ 1 ]
306328 ) ;
307329 }
330+
331+ public findSelfClosingBlock (
332+ element : SvelteElement
333+ ) : SelfClosingBlock | undefined {
334+ return this . blocks . find ( ( block ) : block is SelfClosingBlock =>
335+ Boolean (
336+ block . selfClosing &&
337+ element . startTag . range [ 0 ] <= block . startTagRange [ 0 ] &&
338+ block . startTagRange [ 1 ] <= element . startTag . range [ 1 ]
339+ )
340+ ) ;
341+ }
308342}
309343
310- type Block = {
344+ type Block =
345+ | {
346+ tag : "script" | "style" | "template" ;
347+ originalTag : string ;
348+ attrs : AttributeToken [ ] ;
349+ selfClosing ?: false ;
350+ contentRange : [ number , number ] ;
351+ startTagRange : [ number , number ] ;
352+ endTagRange : [ number , number ] ;
353+ }
354+ | SelfClosingBlock ;
355+
356+ type SelfClosingBlock = {
311357 tag : "script" | "style" | "template" ;
358+ originalTag : string ;
312359 attrs : AttributeToken [ ] ;
313- contentRange : [ number , number ] ;
360+ selfClosing : true ;
361+ startTagRange : [ number , number ] ;
314362} ;
315363
316364/** Extract <script> blocks */
@@ -325,23 +373,32 @@ function* extractBlocks(code: string): IterableIterator<Block> {
325373 if ( ! tag ) {
326374 continue ;
327375 }
376+ const startTagStart = startTagOpenMatch . index ;
328377 let startTagEnd = startTagOpenRe . lastIndex ;
329378
379+ const lowerTag = tag . toLowerCase ( ) as "script" | "style" | "template" ;
380+
330381 let attrs : AttributeToken [ ] = [ ] ;
331382 if ( ! nextChar . trim ( ) ) {
332383 const attrsData = parseAttributes ( code , startTagOpenRe . lastIndex ) ;
333384 attrs = attrsData . attributes ;
334385 startTagEnd = attrsData . index ;
335- if ( code [ startTagEnd ] === "/" ) {
336- startTagEnd ++ ;
386+ if ( code [ startTagEnd ] === "/" && code [ startTagEnd + 1 ] === ">" ) {
387+ yield {
388+ tag : lowerTag ,
389+ originalTag : tag ,
390+ attrs,
391+ selfClosing : true ,
392+ startTagRange : [ startTagStart , startTagEnd + 2 ] ,
393+ } ;
394+ continue ;
337395 }
338396 if ( code [ startTagEnd ] === ">" ) {
339397 startTagEnd ++ ;
340398 } else {
341399 continue ;
342400 }
343401 }
344- const lowerTag = tag . toLowerCase ( ) as "script" | "style" | "template" ;
345402 const endTagRe =
346403 lowerTag === "script"
347404 ? endScriptTagRe
@@ -352,13 +409,16 @@ function* extractBlocks(code: string): IterableIterator<Block> {
352409 const endTagMatch = endTagRe . exec ( code ) ;
353410 if ( endTagMatch ) {
354411 const endTagStart = endTagMatch . index ;
355- const contentRange : [ number , number ] = [ startTagEnd , endTagStart ] ;
412+ const endTagEnd = endTagRe . lastIndex ;
356413 yield {
357- contentRange,
358- attrs,
359414 tag : lowerTag ,
415+ originalTag : tag ,
416+ attrs,
417+ startTagRange : [ startTagStart , startTagEnd ] ,
418+ contentRange : [ startTagEnd , endTagStart ] ,
419+ endTagRange : [ endTagStart , endTagEnd ] ,
360420 } ;
361- startTagOpenRe . lastIndex = endTagRe . lastIndex ;
421+ startTagOpenRe . lastIndex = endTagEnd ;
362422 }
363423 }
364424}
0 commit comments