1
1
import { new_block , get_translation } from './block.js' ;
2
2
import { processor_options } from './processor_options.js' ;
3
+ import { get_line_offsets } from './utils.js' ;
3
4
import { state } from './state.js' ;
4
5
6
+ var charToInteger = { } ;
7
+ var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' ;
8
+ for ( var i = 0 ; i < chars . length ; i ++ ) {
9
+ charToInteger [ chars . charCodeAt ( i ) ] = i ;
10
+ }
11
+ function decode ( mappings ) {
12
+ var generatedCodeColumn = 0 ; // first field
13
+ var sourceFileIndex = 0 ; // second field
14
+ var sourceCodeLine = 0 ; // third field
15
+ var sourceCodeColumn = 0 ; // fourth field
16
+ var nameIndex = 0 ; // fifth field
17
+ var decoded = [ ] ;
18
+ var line = [ ] ;
19
+ var segment = [ ] ;
20
+ for ( var i = 0 , j = 0 , shift = 0 , value = 0 , len = mappings . length ; i < len ; i ++ ) {
21
+ var c = mappings . charCodeAt ( i ) ;
22
+ if ( c === 44 ) { // ","
23
+ if ( segment . length )
24
+ line . push ( segment ) ;
25
+ segment = [ ] ;
26
+ j = 0 ;
27
+ }
28
+ else if ( c === 59 ) { // ";"
29
+ if ( segment . length )
30
+ line . push ( segment ) ;
31
+ segment = [ ] ;
32
+ j = 0 ;
33
+ decoded . push ( line ) ;
34
+ line = [ ] ;
35
+ generatedCodeColumn = 0 ;
36
+ }
37
+ else {
38
+ var integer = charToInteger [ c ] ;
39
+ if ( integer === undefined ) {
40
+ throw new Error ( 'Invalid character (' + String . fromCharCode ( c ) + ')' ) ;
41
+ }
42
+ var hasContinuationBit = integer & 32 ;
43
+ integer &= 31 ;
44
+ value += integer << shift ;
45
+ if ( hasContinuationBit ) {
46
+ shift += 5 ;
47
+ }
48
+ else {
49
+ var shouldNegate = value & 1 ;
50
+ value >>>= 1 ;
51
+ if ( shouldNegate ) {
52
+ value = - value ;
53
+ if ( value === 0 )
54
+ value = - 0x80000000 ;
55
+ }
56
+ if ( j == 0 ) {
57
+ generatedCodeColumn += value ;
58
+ segment . push ( generatedCodeColumn ) ;
59
+ }
60
+ else if ( j === 1 ) {
61
+ sourceFileIndex += value ;
62
+ segment . push ( sourceFileIndex ) ;
63
+ }
64
+ else if ( j === 2 ) {
65
+ sourceCodeLine += value ;
66
+ segment . push ( sourceCodeLine ) ;
67
+ }
68
+ else if ( j === 3 ) {
69
+ sourceCodeColumn += value ;
70
+ segment . push ( sourceCodeColumn ) ;
71
+ }
72
+ else if ( j === 4 ) {
73
+ nameIndex += value ;
74
+ segment . push ( nameIndex ) ;
75
+ }
76
+ j ++ ;
77
+ value = shift = 0 ; // reset
78
+ }
79
+ }
80
+ }
81
+ if ( segment . length )
82
+ line . push ( segment ) ;
83
+ decoded . push ( line ) ;
84
+ return decoded ;
85
+ }
86
+
5
87
let default_compiler ;
6
88
7
89
// find the contextual name or names described by a particular node in the AST
@@ -23,7 +105,7 @@ const find_contextual_names = (compiler, node) => {
23
105
} ;
24
106
25
107
// extract scripts to lint from component definition
26
- export const preprocess = text => {
108
+ export const preprocess = ( text , filename ) => {
27
109
const compiler = processor_options . custom_compiler || default_compiler || ( default_compiler = require ( 'svelte/compiler' ) ) ;
28
110
if ( processor_options . ignore_styles ) {
29
111
// wipe the appropriate <style> tags in the file
@@ -40,10 +122,104 @@ export const preprocess = text => {
40
122
return processor_options . ignore_styles ( attrs ) ? match . replace ( / \S / g, ' ' ) : match ;
41
123
} ) ;
42
124
}
43
- // get information about the component
44
125
let result ;
126
+ let processedResult ;
127
+ let processedModule ;
128
+ let processedInstance ;
129
+ let processedStyle ;
130
+ let processedMarkup ;
131
+ let moduleExt = 'js' ;
132
+ let instanceExt = 'js' ;
45
133
try {
46
- result = compiler . compile ( text , { generate : false , ...processor_options . compiler_options } ) ;
134
+ // run preprocessor if present
135
+ if ( processor_options . svelte_preprocess ) {
136
+ const result = processor_options . svelte_preprocess ( text , filename ) ;
137
+ if ( result ) {
138
+ state . pre_line_offsets = get_line_offsets ( text ) ;
139
+ processedResult = result . code ;
140
+ state . post_line_offsets = get_line_offsets ( processedResult ) ;
141
+ if ( result . mappings ) {
142
+ state . mappings = decode ( result . mappings ) ;
143
+ }
144
+
145
+ processedMarkup = result . markup ;
146
+
147
+ if ( result . module ) {
148
+ processedModule = result . module ;
149
+ moduleExt = result . module . ext ;
150
+ }
151
+ if ( result . instance ) {
152
+ processedInstance = result . instance ;
153
+ instanceExt = result . instance . ext ;
154
+ }
155
+
156
+ processedStyle = result . style ;
157
+
158
+ processor_options . named_blocks = true ;
159
+ }
160
+ }
161
+ // get information about the component
162
+ result = compiler . compile ( processedResult || text , { generate : false , ...processor_options . compiler_options } ) ;
163
+ if ( processedResult ) {
164
+ const { html, css, instance, module } = result . ast ;
165
+
166
+ let styleDiff = processedStyle ? processedStyle . diff : 0 ;
167
+ let markupDiff = processedMarkup ? processedMarkup . diff : 0 ;
168
+ let moduleDiff = processedModule ? processedModule . diff : 0 ;
169
+ let instanceDiff = processedInstance ? processedInstance . diff : 0 ;
170
+
171
+ let modulePreOffset = 0 ;
172
+ let modulePostOffset = 0 ;
173
+ if ( module ) {
174
+ if ( module . start > html . start ) {
175
+ modulePreOffset += markupDiff ;
176
+ }
177
+ if ( module . start > css . start ) {
178
+ modulePreOffset += styleDiff ;
179
+ }
180
+ if ( instance && module . start > instance . start ) {
181
+ modulePreOffset += instanceDiff ;
182
+ }
183
+
184
+ modulePostOffset = modulePreOffset + moduleDiff ;
185
+ }
186
+
187
+ let instancePreOffset = 0 ;
188
+ let instancePostOffset = 0 ;
189
+ if ( instance ) {
190
+ if ( instance . start > html . start ) {
191
+ instancePreOffset += markupDiff ;
192
+ }
193
+ if ( instance . start > css . start ) {
194
+ instancePreOffset += styleDiff ;
195
+ }
196
+ if ( module && instance . start > module . start ) {
197
+ instancePreOffset += moduleDiff ;
198
+ }
199
+
200
+ instancePostOffset = instancePreOffset + instanceDiff ;
201
+ }
202
+
203
+ if ( module ) {
204
+ module . content . body = processedModule . ast . body ;
205
+
206
+ module . start += modulePreOffset ;
207
+ module . end += modulePostOffset ;
208
+
209
+ module . content . start += modulePreOffset ;
210
+ module . content . end += modulePostOffset ;
211
+ }
212
+
213
+ if ( instance ) {
214
+ instance . content . body = processedInstance . ast . body ;
215
+
216
+ instance . start += instancePreOffset ;
217
+ instance . end += instancePostOffset ;
218
+
219
+ instance . content . start += instancePreOffset ;
220
+ instance . content . end += instancePostOffset ;
221
+ }
222
+ }
47
223
} catch ( { name, message, start, end } ) {
48
224
// convert the error to a linting message, store it, and return
49
225
state . messages = [
@@ -79,12 +255,14 @@ export const preprocess = text => {
79
255
if ( ast . module ) {
80
256
// block for <script context='module'>
81
257
const block = new_block ( ) ;
82
- state . blocks . set ( ' module.js' , block ) ;
258
+ state . blocks . set ( ` module.${ moduleExt } ` , block ) ;
83
259
84
260
get_translation ( text , block , ast . module . content ) ;
85
261
86
262
if ( ast . instance ) {
87
- block . transformed_code += text . slice ( ast . instance . content . start , ast . instance . content . end ) ;
263
+ block . transformed_code += processedResult
264
+ ? processedInstance . original
265
+ : text . slice ( ast . instance . content . start , ast . instance . content . end ) ;
88
266
}
89
267
90
268
block . transformed_code += references_and_reassignments ;
@@ -93,7 +271,7 @@ export const preprocess = text => {
93
271
if ( ast . instance ) {
94
272
// block for <script context='instance'>
95
273
const block = new_block ( ) ;
96
- state . blocks . set ( ' instance.js' , block ) ;
274
+ state . blocks . set ( ` instance.${ instanceExt } ` , block ) ;
97
275
98
276
block . transformed_code = vars . filter ( v => v . injected || v . module ) . map ( v => `let ${ v . name } ;` ) . join ( '' ) ;
99
277
@@ -111,11 +289,13 @@ export const preprocess = text => {
111
289
112
290
const nodes_with_contextual_scope = new WeakSet ( ) ;
113
291
let in_quoted_attribute = false ;
292
+ const htmlText = processedResult || text ;
293
+
114
294
compiler . walk ( ast . html , {
115
295
enter ( node , parent , prop ) {
116
296
if ( prop === 'expression' ) {
117
297
return this . skip ( ) ;
118
- } else if ( prop === 'attributes' && '\'"' . includes ( text [ node . end - 1 ] ) ) {
298
+ } else if ( prop === 'attributes' && '\'"' . includes ( htmlText [ node . end - 1 ] ) ) {
119
299
in_quoted_attribute = true ;
120
300
}
121
301
contextual_names . length = 0 ;
@@ -136,7 +316,7 @@ export const preprocess = text => {
136
316
if ( node . expression && typeof node . expression === 'object' ) {
137
317
// add the expression in question to the constructed string
138
318
block . transformed_code += '(' ;
139
- get_translation ( text , block , node . expression , { template : true , in_quoted_attribute } ) ;
319
+ get_translation ( htmlText , block , node . expression , { template : true , in_quoted_attribute } ) ;
140
320
block . transformed_code += ');' ;
141
321
}
142
322
} ,
0 commit comments