1
1
import fs from "fs"
2
2
import path from "path"
3
- import type { Comment , Locations , Position , Token } from "../ast"
3
+ import type {
4
+ Comment ,
5
+ Locations ,
6
+ Position ,
7
+ SvelteScriptElement ,
8
+ SvelteStyleElement ,
9
+ Token ,
10
+ } from "../ast"
4
11
import type ESTree from "estree"
5
12
import { ScriptLetContext } from "./script-let"
6
13
import { LetDirectiveCollections } from "./let-directive-collection"
7
14
import { getParserName } from "../parser/resolve-parser"
15
+ import type { AttributeToken } from "../parser/html"
16
+ import { parseAttributes } from "../parser/html"
8
17
9
18
export class ScriptsSourceCode {
10
19
private raw : string
@@ -87,6 +96,8 @@ export class Context {
87
96
88
97
private state : { isTypeScript ?: boolean } = { }
89
98
99
+ private readonly blocks : Block [ ] = [ ]
100
+
90
101
public constructor ( code : string , parserOptions : any ) {
91
102
this . code = code
92
103
this . parserOptions = parserOptions
@@ -96,21 +107,25 @@ export class Context {
96
107
97
108
let templateCode = ""
98
109
let scriptCode = ""
99
- let scriptAttrs : Record < string , string | undefined > = { }
110
+ const scriptAttrs : Record < string , string | undefined > = { }
100
111
101
112
let start = 0
102
113
for ( const block of extractBlocks ( code ) ) {
114
+ this . blocks . push ( block )
103
115
templateCode +=
104
- code . slice ( start , block . codeRange [ 0 ] ) +
105
- spaces . slice ( block . codeRange [ 0 ] , block . codeRange [ 1 ] )
116
+ code . slice ( start , block . contentRange [ 0 ] ) +
117
+ spaces . slice ( block . contentRange [ 0 ] , block . contentRange [ 1 ] )
106
118
if ( block . tag === "script" ) {
107
119
scriptCode +=
108
- spaces . slice ( start , block . codeRange [ 0 ] ) + block . code
109
- scriptAttrs = Object . assign ( scriptAttrs , block . attrs )
120
+ spaces . slice ( start , block . contentRange [ 0 ] ) +
121
+ code . slice ( ...block . contentRange )
122
+ for ( const attr of block . attrs ) {
123
+ scriptAttrs [ attr . key . name ] = attr . value ?. value
124
+ }
110
125
} else {
111
- scriptCode += spaces . slice ( start , block . codeRange [ 1 ] )
126
+ scriptCode += spaces . slice ( start , block . contentRange [ 1 ] )
112
127
}
113
- start = block . codeRange [ 1 ]
128
+ start = block . contentRange [ 1 ]
114
129
}
115
130
templateCode += code . slice ( start )
116
131
scriptCode += spaces . slice ( start )
@@ -223,49 +238,63 @@ export class Context {
223
238
public stripScriptCode ( start : number , end : number ) : void {
224
239
this . sourceCode . scripts . stripCode ( start , end )
225
240
}
241
+
242
+ public findBlock (
243
+ element : SvelteScriptElement | SvelteStyleElement ,
244
+ ) : Block | undefined {
245
+ const tag = element . type === "SvelteScriptElement" ? "script" : "style"
246
+ return this . blocks . find (
247
+ ( block ) =>
248
+ block . tag === tag &&
249
+ element . range [ 0 ] <= block . contentRange [ 0 ] &&
250
+ block . contentRange [ 1 ] <= element . range [ 1 ] ,
251
+ )
252
+ }
226
253
}
227
254
228
- /** Extract <script> blocks */
229
- function * extractBlocks ( code : string ) : IterableIterator < {
230
- code : string
231
- codeRange : [ number , number ]
232
- attrs : Record < string , string | undefined >
255
+ type Block = {
233
256
tag : "script" | "style"
234
- } > {
235
- const startTagRe = / < ( s c r i p t | s t y l e ) ( \s [ \s \S ] * ?) ? > / giu
236
- const endScriptTagRe = / < \/ s c r i p t (?: \s [ \s \S ] * ?) ? > / giu
237
- const endStyleTagRe = / < \/ s t y l e (?: \s [ \s \S ] * ?) ? > / giu
238
- let startTagRes
239
- while ( ( startTagRes = startTagRe . exec ( code ) ) ) {
240
- const [ startTag , tag , attributes = "" ] = startTagRes
241
- const startTagStart = startTagRes . index
242
- const startTagEnd = startTagStart + startTag . length
257
+ attrs : AttributeToken [ ]
258
+ contentRange : [ number , number ]
259
+ }
260
+
261
+ /** Extract <script> blocks */
262
+ function * extractBlocks ( code : string ) : IterableIterator < Block > {
263
+ const startTagOpenRe = / < ( s c r i p t | s t y l e ) ( [ \s > ] ) / giu
264
+ const endScriptTagRe = / < \/ s c r i p t > / giu
265
+ const endStyleTagRe = / < \/ s t y l e > / giu
266
+ let startTagOpenMatch
267
+ while ( ( startTagOpenMatch = startTagOpenRe . exec ( code ) ) ) {
268
+ const [ , tag , nextChar ] = startTagOpenMatch
269
+ let startTagEnd = startTagOpenRe . lastIndex
270
+
271
+ let attrs : AttributeToken [ ] = [ ]
272
+ if ( ! nextChar . trim ( ) ) {
273
+ const attrsData = parseAttributes ( code , startTagOpenRe . lastIndex )
274
+ attrs = attrsData . attributes
275
+ startTagEnd = attrsData . index
276
+ if ( code [ startTagEnd ] === "/" ) {
277
+ startTagEnd ++
278
+ }
279
+ if ( code [ startTagEnd ] === ">" ) {
280
+ startTagEnd ++
281
+ } else {
282
+ continue
283
+ }
284
+ }
243
285
const endTagRe =
244
286
tag . toLowerCase ( ) === "script" ? endScriptTagRe : endStyleTagRe
245
- endTagRe . lastIndex = startTagRe . lastIndex
246
- const endTagRes = endTagRe . exec ( code )
247
- if ( endTagRes ) {
248
- const endTagStart = endTagRes . index
249
- const codeRange : [ number , number ] = [ startTagEnd , endTagStart ]
250
-
251
- const attrRe =
252
- / (?< key > [ ^ \s = ] + ) (?: = (?: " (?< val1 > [ ^ " ] * ) " | ' (?< val2 > [ ^ " ] * ) ' | (?< val3 > [ ^ \s = ] + ) ) ) ? / gu
253
- const attrs : Record < string , string | undefined > = { }
254
- let attrRes
255
- while ( ( attrRes = attrRe . exec ( attributes ) ) ) {
256
- attrs [ attrRes . groups ! . key ] =
257
- ( attrRes . groups ! . val1 ||
258
- attrRes . groups ! . val2 ||
259
- attrRes . groups ! . val3 ) ??
260
- null
261
- }
287
+ endTagRe . lastIndex = startTagEnd
288
+ const endTagMatch = endTagRe . exec ( code )
289
+ if ( endTagMatch ) {
290
+ const endTagStart = endTagMatch . index
291
+ const contentRange : [ number , number ] = [ startTagEnd , endTagStart ]
262
292
yield {
263
- code : code . slice ( ...codeRange ) ,
264
- codeRange,
293
+ contentRange,
265
294
attrs,
266
295
tag : tag as "script" | "style" ,
267
296
}
268
- startTagRe . lastIndex = endTagRe . lastIndex
297
+ startTagOpenRe . lastIndex = endTagRe . lastIndex
269
298
}
270
299
}
271
300
}
0 commit comments