1
1
2
- module . exports = function ( css ) {
2
+ module . exports = function ( css , options ) {
3
+ options = options || { } ;
4
+
5
+ /**
6
+ * Positional.
7
+ */
8
+
9
+ var lineno = 1 ;
10
+ var column = 1 ;
11
+
12
+ /**
13
+ * Update lineno and column based on `str`.
14
+ */
15
+
16
+ function updatePosition ( str ) {
17
+ var lines = str . match ( / \n / g) ;
18
+ if ( lines ) lineno += lines . length ;
19
+ var i = str . lastIndexOf ( '\n' ) ;
20
+ column = ~ i ? str . length - i : column + str . length ;
21
+ }
22
+
23
+ function position ( ) {
24
+ var start = { line : lineno , column : column } ;
25
+ if ( ! options . position ) return positionNoop ;
26
+ return function ( node ) {
27
+ node . position = {
28
+ start : start ,
29
+ end : { line : lineno , column : column }
30
+ } ;
31
+ whitespace ( ) ;
32
+ return node ;
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Return `node`.
38
+ */
39
+ function positionNoop ( node ) {
40
+ whitespace ( ) ;
41
+ return node ;
42
+ }
3
43
4
44
/**
5
45
* Parse stylesheet.
@@ -27,7 +67,7 @@ module.exports = function(css){
27
67
*/
28
68
29
69
function close ( ) {
30
- return match ( / ^ } \s * / ) ;
70
+ return match ( / ^ } / ) ;
31
71
}
32
72
33
73
/**
@@ -53,7 +93,9 @@ module.exports = function(css){
53
93
function match ( re ) {
54
94
var m = re . exec ( css ) ;
55
95
if ( ! m ) return ;
56
- css = css . slice ( m [ 0 ] . length ) ;
96
+ var str = m [ 0 ] ;
97
+ updatePosition ( str ) ;
98
+ css = css . slice ( str . length ) ;
57
99
return m ;
58
100
}
59
101
@@ -81,20 +123,22 @@ module.exports = function(css){
81
123
*/
82
124
83
125
function comment ( ) {
126
+ var pos = position ( ) ;
84
127
if ( '/' != css [ 0 ] || '*' != css [ 1 ] ) return ;
85
128
86
129
var i = 2 ;
87
130
while ( null != css [ i ] && ( '*' != css [ i ] || '/' != css [ i + 1 ] ) ) ++ i ;
88
131
i += 2 ;
89
132
90
133
var str = css . slice ( 2 , i - 2 ) ;
134
+ column += 2 ;
135
+ updatePosition ( str ) ;
91
136
css = css . slice ( i ) ;
92
- whitespace ( ) ;
93
-
94
- return {
137
+ column += 2 ;
138
+ return pos ( {
95
139
type : 'comment' ,
96
140
comment : str
97
- } ;
141
+ } ) ;
98
142
}
99
143
100
144
/**
@@ -112,6 +156,8 @@ module.exports = function(css){
112
156
*/
113
157
114
158
function declaration ( ) {
159
+ var pos = position ( ) ;
160
+
115
161
// prop
116
162
var prop = match ( / ^ ( \* ? [ - \w ] + ) \s * / ) ;
117
163
if ( ! prop ) return ;
@@ -121,18 +167,18 @@ module.exports = function(css){
121
167
if ( ! match ( / ^ : \s * / ) ) return ;
122
168
123
169
// val
124
- var val = match ( / ^ ( (?: ' (?: \\ ' | .) * ?' | " (?: \\ " | .) * ?" | \( [ ^ \) ] * ?\) | [ ^ } ; ] ) + ) \s * / ) ;
170
+ var val = match ( / ^ ( (?: ' (?: \\ ' | .) * ?' | " (?: \\ " | .) * ?" | \( [ ^ \) ] * ?\) | [ ^ } ; ] ) + ) / ) ;
125
171
if ( ! val ) return ;
126
- val = val [ 0 ] . trim ( ) ;
127
-
128
- // ;
129
- match ( / ^ [ ; \s ] * / ) ;
130
172
131
- return {
173
+ var ret = pos ( {
132
174
type : 'declaration' ,
133
175
property : prop ,
134
- value : val
135
- } ;
176
+ value : val [ 0 ] . trim ( )
177
+ } ) ;
178
+
179
+ // ;
180
+ match ( / ^ [ ; \s ] * / ) ;
181
+ return ret ;
136
182
}
137
183
138
184
/**
@@ -163,6 +209,7 @@ module.exports = function(css){
163
209
function keyframe ( ) {
164
210
var m ;
165
211
var vals = [ ] ;
212
+ var pos = position ( ) ;
166
213
167
214
while ( m = match ( / ^ ( f r o m | t o | \d + % | \. \d + % | \d + \. \d + % ) \s * / ) ) {
168
215
vals . push ( m [ 1 ] ) ;
@@ -171,19 +218,21 @@ module.exports = function(css){
171
218
172
219
if ( ! vals . length ) return ;
173
220
174
- return {
221
+ return pos ( {
175
222
type : 'keyframe' ,
176
223
values : vals ,
177
224
declarations : declarations ( )
178
- } ;
225
+ } ) ;
179
226
}
180
227
181
228
/**
182
229
* Parse keyframes.
183
230
*/
184
231
185
232
function atkeyframes ( ) {
233
+ var pos = position ( ) ;
186
234
var m = match ( / ^ @ ( [ - \w ] + ) ? k e y f r a m e s * / ) ;
235
+
187
236
if ( ! m ) return ;
188
237
var vendor = m [ 1 ] ;
189
238
@@ -204,20 +253,22 @@ module.exports = function(css){
204
253
205
254
if ( ! close ( ) ) return ;
206
255
207
- return {
256
+ return pos ( {
208
257
type : 'keyframes' ,
209
258
name : name ,
210
259
vendor : vendor ,
211
260
keyframes : frames
212
- } ;
261
+ } ) ;
213
262
}
214
263
215
264
/**
216
265
* Parse supports.
217
266
*/
218
267
219
268
function atsupports ( ) {
269
+ var pos = position ( ) ;
220
270
var m = match ( / ^ @ s u p p o r t s * ( [ ^ { ] + ) / ) ;
271
+
221
272
if ( ! m ) return ;
222
273
var supports = m [ 1 ] . trim ( ) ;
223
274
@@ -228,19 +279,21 @@ module.exports = function(css){
228
279
229
280
if ( ! close ( ) ) return ;
230
281
231
- return {
282
+ return pos ( {
232
283
type : 'supports' ,
233
284
supports : supports ,
234
285
rules : style
235
- } ;
286
+ } ) ;
236
287
}
237
288
238
289
/**
239
290
* Parse media.
240
291
*/
241
292
242
293
function atmedia ( ) {
294
+ var pos = position ( ) ;
243
295
var m = match ( / ^ @ m e d i a * ( [ ^ { ] + ) / ) ;
296
+
244
297
if ( ! m ) return ;
245
298
var media = m [ 1 ] . trim ( ) ;
246
299
@@ -251,18 +304,19 @@ module.exports = function(css){
251
304
252
305
if ( ! close ( ) ) return ;
253
306
254
- return {
307
+ return pos ( {
255
308
type : 'media' ,
256
309
media : media ,
257
310
rules : style
258
- } ;
311
+ } ) ;
259
312
}
260
313
261
314
/**
262
315
* Parse paged media.
263
316
*/
264
317
265
318
function atpage ( ) {
319
+ var pos = position ( ) ;
266
320
var m = match ( / ^ @ p a g e * / ) ;
267
321
if ( ! m ) return ;
268
322
@@ -281,20 +335,22 @@ module.exports = function(css){
281
335
282
336
if ( ! close ( ) ) return ;
283
337
284
- return {
338
+ return pos ( {
285
339
type : 'page' ,
286
340
selectors : sel ,
287
341
declarations : decls
288
- } ;
342
+ } ) ;
289
343
}
290
344
291
345
/**
292
346
* Parse document.
293
347
*/
294
348
295
349
function atdocument ( ) {
350
+ var pos = position ( ) ;
296
351
var m = match ( / ^ @ ( [ - \w ] + ) ? d o c u m e n t * ( [ ^ { ] + ) / ) ;
297
352
if ( ! m ) return ;
353
+
298
354
var vendor = m [ 1 ] . trim ( ) ;
299
355
var doc = m [ 2 ] . trim ( ) ;
300
356
@@ -305,12 +361,12 @@ module.exports = function(css){
305
361
306
362
if ( ! close ( ) ) return ;
307
363
308
- return {
364
+ return pos ( {
309
365
type : 'document' ,
310
366
document : doc ,
311
367
vendor : vendor ,
312
368
rules : style
313
- } ;
369
+ } ) ;
314
370
}
315
371
316
372
/**
@@ -342,11 +398,12 @@ module.exports = function(css){
342
398
*/
343
399
344
400
function _atrule ( name ) {
345
- var m = match ( new RegExp ( '^@' + name + ' *([^;\\n]+);\\s*' ) ) ;
401
+ var pos = position ( ) ;
402
+ var m = match ( new RegExp ( '^@' + name + ' *([^;\\n]+);' ) ) ;
346
403
if ( ! m ) return ;
347
404
var ret = { type : name } ;
348
405
ret [ name ] = m [ 1 ] . trim ( ) ;
349
- return ret ;
406
+ return pos ( ret ) ;
350
407
}
351
408
352
409
/**
@@ -369,15 +426,19 @@ module.exports = function(css){
369
426
*/
370
427
371
428
function rule ( ) {
429
+ var pos = position ( ) ;
372
430
var sel = selector ( ) ;
431
+
373
432
if ( ! sel ) return ;
374
433
comments ( ) ;
375
- return {
434
+
435
+ return pos ( {
376
436
type : 'rule' ,
377
437
selectors : sel ,
378
438
declarations : declarations ( )
379
- } ;
439
+ } ) ;
380
440
}
381
441
382
442
return stylesheet ( ) ;
383
443
} ;
444
+
0 commit comments