@@ -148,26 +148,47 @@ export class Context {
148
148
let start = 0 ;
149
149
for ( const block of extractBlocks ( code ) ) {
150
150
if ( block . tag === "template" ) {
151
+ if ( block . selfClosing ) {
152
+ continue ;
153
+ }
151
154
const lang = block . attrs . find ( ( attr ) => attr . key . name === "lang" ) ;
152
155
if ( ! lang || ! lang . value || lang . value . value === "html" ) {
153
156
continue ;
154
157
}
155
158
}
156
159
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 ] ;
167
176
} 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 ] ;
169
191
}
170
- start = block . contentRange [ 1 ] ;
171
192
}
172
193
templateCode += code . slice ( start ) ;
173
194
scriptCode += spaces . slice ( start ) ;
@@ -301,16 +322,43 @@ export class Context {
301
322
return this . blocks . find (
302
323
( block ) =>
303
324
block . tag === tag &&
325
+ ! block . selfClosing &&
304
326
element . range [ 0 ] <= block . contentRange [ 0 ] &&
305
327
block . contentRange [ 1 ] <= element . range [ 1 ]
306
328
) ;
307
329
}
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
+ }
308
342
}
309
343
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 = {
311
357
tag : "script" | "style" | "template" ;
358
+ originalTag : string ;
312
359
attrs : AttributeToken [ ] ;
313
- contentRange : [ number , number ] ;
360
+ selfClosing : true ;
361
+ startTagRange : [ number , number ] ;
314
362
} ;
315
363
316
364
/** Extract <script> blocks */
@@ -325,23 +373,32 @@ function* extractBlocks(code: string): IterableIterator<Block> {
325
373
if ( ! tag ) {
326
374
continue ;
327
375
}
376
+ const startTagStart = startTagOpenMatch . index ;
328
377
let startTagEnd = startTagOpenRe . lastIndex ;
329
378
379
+ const lowerTag = tag . toLowerCase ( ) as "script" | "style" | "template" ;
380
+
330
381
let attrs : AttributeToken [ ] = [ ] ;
331
382
if ( ! nextChar . trim ( ) ) {
332
383
const attrsData = parseAttributes ( code , startTagOpenRe . lastIndex ) ;
333
384
attrs = attrsData . attributes ;
334
385
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 ;
337
395
}
338
396
if ( code [ startTagEnd ] === ">" ) {
339
397
startTagEnd ++ ;
340
398
} else {
341
399
continue ;
342
400
}
343
401
}
344
- const lowerTag = tag . toLowerCase ( ) as "script" | "style" | "template" ;
345
402
const endTagRe =
346
403
lowerTag === "script"
347
404
? endScriptTagRe
@@ -352,13 +409,16 @@ function* extractBlocks(code: string): IterableIterator<Block> {
352
409
const endTagMatch = endTagRe . exec ( code ) ;
353
410
if ( endTagMatch ) {
354
411
const endTagStart = endTagMatch . index ;
355
- const contentRange : [ number , number ] = [ startTagEnd , endTagStart ] ;
412
+ const endTagEnd = endTagRe . lastIndex ;
356
413
yield {
357
- contentRange,
358
- attrs,
359
414
tag : lowerTag ,
415
+ originalTag : tag ,
416
+ attrs,
417
+ startTagRange : [ startTagStart , startTagEnd ] ,
418
+ contentRange : [ startTagEnd , endTagStart ] ,
419
+ endTagRange : [ endTagStart , endTagEnd ] ,
360
420
} ;
361
- startTagOpenRe . lastIndex = endTagRe . lastIndex ;
421
+ startTagOpenRe . lastIndex = endTagEnd ;
362
422
}
363
423
}
364
424
}
0 commit comments