11
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+ }
343
444 /**
545 * Parse stylesheet.
@@ -27,7 +67,7 @@ module.exports = function(css){
2767 */
2868
2969 function close ( ) {
30- return match ( / ^ } \s * / ) ;
70+ return match ( / ^ } / ) ;
3171 }
3272
3373 /**
@@ -53,7 +93,9 @@ module.exports = function(css){
5393 function match ( re ) {
5494 var m = re . exec ( css ) ;
5595 if ( ! m ) return ;
56- css = css . slice ( m [ 0 ] . length ) ;
96+ var str = m [ 0 ] ;
97+ updatePosition ( str ) ;
98+ css = css . slice ( str . length ) ;
5799 return m ;
58100 }
59101
@@ -81,20 +123,22 @@ module.exports = function(css){
81123 */
82124
83125 function comment ( ) {
126+ var pos = position ( ) ;
84127 if ( '/' != css [ 0 ] || '*' != css [ 1 ] ) return ;
85128
86129 var i = 2 ;
87130 while ( null != css [ i ] && ( '*' != css [ i ] || '/' != css [ i + 1 ] ) ) ++ i ;
88131 i += 2 ;
89132
90133 var str = css . slice ( 2 , i - 2 ) ;
134+ column += 2 ;
135+ updatePosition ( str ) ;
91136 css = css . slice ( i ) ;
92- whitespace ( ) ;
93-
94- return {
137+ column += 2 ;
138+ return pos ( {
95139 type : 'comment' ,
96140 comment : str
97- } ;
141+ } ) ;
98142 }
99143
100144 /**
@@ -112,6 +156,8 @@ module.exports = function(css){
112156 */
113157
114158 function declaration ( ) {
159+ var pos = position ( ) ;
160+
115161 // prop
116162 var prop = match ( / ^ ( \* ? [ - \w ] + ) \s * / ) ;
117163 if ( ! prop ) return ;
@@ -121,18 +167,18 @@ module.exports = function(css){
121167 if ( ! match ( / ^ : \s * / ) ) return ;
122168
123169 // val
124- var val = match ( / ^ ( (?: ' (?: \\ ' | .) * ?' | " (?: \\ " | .) * ?" | \( [ ^ \) ] * ?\) | [ ^ } ; ] ) + ) \s * / ) ;
170+ var val = match ( / ^ ( (?: ' (?: \\ ' | .) * ?' | " (?: \\ " | .) * ?" | \( [ ^ \) ] * ?\) | [ ^ } ; ] ) + ) / ) ;
125171 if ( ! val ) return ;
126- val = val [ 0 ] . trim ( ) ;
127-
128- // ;
129- match ( / ^ [ ; \s ] * / ) ;
130172
131- return {
173+ var ret = pos ( {
132174 type : 'declaration' ,
133175 property : prop ,
134- value : val
135- } ;
176+ value : val [ 0 ] . trim ( )
177+ } ) ;
178+
179+ // ;
180+ match ( / ^ [ ; \s ] * / ) ;
181+ return ret ;
136182 }
137183
138184 /**
@@ -163,6 +209,7 @@ module.exports = function(css){
163209 function keyframe ( ) {
164210 var m ;
165211 var vals = [ ] ;
212+ var pos = position ( ) ;
166213
167214 while ( m = match ( / ^ ( f r o m | t o | \d + % | \. \d + % | \d + \. \d + % ) \s * / ) ) {
168215 vals . push ( m [ 1 ] ) ;
@@ -171,19 +218,21 @@ module.exports = function(css){
171218
172219 if ( ! vals . length ) return ;
173220
174- return {
221+ return pos ( {
175222 type : 'keyframe' ,
176223 values : vals ,
177224 declarations : declarations ( )
178- } ;
225+ } ) ;
179226 }
180227
181228 /**
182229 * Parse keyframes.
183230 */
184231
185232 function atkeyframes ( ) {
233+ var pos = position ( ) ;
186234 var m = match ( / ^ @ ( [ - \w ] + ) ? k e y f r a m e s * / ) ;
235+
187236 if ( ! m ) return ;
188237 var vendor = m [ 1 ] ;
189238
@@ -204,20 +253,22 @@ module.exports = function(css){
204253
205254 if ( ! close ( ) ) return ;
206255
207- return {
256+ return pos ( {
208257 type : 'keyframes' ,
209258 name : name ,
210259 vendor : vendor ,
211260 keyframes : frames
212- } ;
261+ } ) ;
213262 }
214263
215264 /**
216265 * Parse supports.
217266 */
218267
219268 function atsupports ( ) {
269+ var pos = position ( ) ;
220270 var m = match ( / ^ @ s u p p o r t s * ( [ ^ { ] + ) / ) ;
271+
221272 if ( ! m ) return ;
222273 var supports = m [ 1 ] . trim ( ) ;
223274
@@ -228,19 +279,21 @@ module.exports = function(css){
228279
229280 if ( ! close ( ) ) return ;
230281
231- return {
282+ return pos ( {
232283 type : 'supports' ,
233284 supports : supports ,
234285 rules : style
235- } ;
286+ } ) ;
2
8026
36287 }
237288
238289 /**
239290 * Parse media.
240291 */
241292
242293 function atmedia ( ) {
294+ var pos = position ( ) ;
243295 var m = match ( / ^ @ m e d i a * ( [ ^ { ] + ) / ) ;
296+
244297 if ( ! m ) return ;
245298 var media = m [ 1 ] . trim ( ) ;
246299
@@ -251,18 +304,19 @@ module.exports = function(css){
251304
252305 if ( ! close ( ) ) return ;
253306
254- return {
307+ return pos ( {
255308 type : 'media' ,
256309 media : media ,
257310 rules : style
258- } ;
311+ } ) ;
259312 }
260313
261314 /**
262315 * Parse paged media.
263316 */
264317
265318 function atpage ( ) {
319+ var pos = position ( ) ;
266320 var m = match ( / ^ @ p a g e * / ) ;
267321 if ( ! m ) return ;
268322
@@ -281,20 +335,22 @@ module.exports = function(css){
281335
282336 if ( ! close ( ) ) return ;
283337
284- return {
338+ return pos ( {
285339 type : 'page' ,
286340 selectors : sel ,
287341 declarations : decls
288- } ;
342+ } ) ;
289343 }
290344
291345 /**
292346 * Parse document.
293347 */
294348
295349 function atdocument ( ) {
350+ var pos = position ( ) ;
296351 var m = match ( / ^ @ ( [ - \w ] + ) ? d o c u m e n t * ( [ ^ { ] + ) / ) ;
297352 if ( ! m ) return ;
353+
298354 var vendor = m [ 1 ] . trim ( ) ;
299355 var doc = m [ 2 ] . trim ( ) ;
300356
@@ -305,12 +361,12 @@ module.exports = function(css){
305361
306362 if ( ! close ( ) ) return ;
307363
308- return {
364+ return pos ( {
309365 type : 'document' ,
310366 document : doc ,
311367 vendor : vendor ,
312368 rules : style
313- } ;
369+ } ) ;
314370 }
315371
316372 /**
@@ -342,11 +398,12 @@ module.exports = function(css){
342398 */
343399
344400 function _atrule ( name ) {
345- var m = match ( new RegExp ( '^@' + name + ' *([^;\\n]+);\\s*' ) ) ;
401+ var pos = position ( ) ;
402+ var m = match ( new RegExp ( '^@' + name + ' *([^;\\n]+);' ) ) ;
346403 if ( ! m ) return ;
347404 var ret = { type : name } ;
348405 ret [ name ] = m [ 1 ] . trim ( ) ;
349- return ret ;
406+ return pos ( ret ) ;
350407 }
351408
352409 /**
@@ -369,15 +426,19 @@ module.exports = function(css){
369426 */
370427
371428 function rule ( ) {
429+ var pos = position ( ) ;
372430 var sel = selector ( ) ;
431+
373432 if ( ! sel ) return ;
374433 comments ( ) ;
375- return {
434+
435+ return pos ( {
376436 type : 'rule' ,
377437 selectors : sel ,
378438 declarations : declarations ( )
379- } ;
439+ } ) ;
380440 }
381441
382442 return stylesheet ( ) ;
383443} ;
444+
0 commit comments