11'use strict'
22
3+ let lineColumn = require ( 'line-column' )
4+
35let Declaration = require ( './declaration' )
46let tokenizer = require ( './tokenize' )
57let Comment = require ( './comment' )
@@ -10,6 +12,7 @@ let Rule = require('./rule')
1012class Parser {
1113 constructor ( input ) {
1214 this . input = input
15+ this . finder = lineColumn ( this . input . css )
1316
1417 this . root = new Root ( )
1518 this . current = this . root
@@ -18,7 +21,7 @@ class Parser {
1821 this . customProperty = false
1922
2023 this . createTokenizer ( )
21- this . root . source = { input, start : { line : 1 , column : 1 } }
24+ this . root . source = { input, start : { offset : 0 , line : 1 , column : 1 } }
2225 }
2326
2427 createTokenizer ( ) {
@@ -65,8 +68,13 @@ class Parser {
6568
6669 comment ( token ) {
6770 let node = new Comment ( )
68- this . init ( node , token [ 2 ] , token [ 3 ] )
69- node . source . end = { line : token [ 4 ] , column : token [ 5 ] }
71+ this . init ( node , token [ 2 ] )
72+ let pos = this . finder . fromIndex ( token [ 3 ] )
73+ node . source . end = {
74+ offset : token [ 3 ] ,
75+ line : pos . line ,
76+ column : pos . col
77+ }
7078
7179 let text = token [ 1 ] . slice ( 2 , - 2 )
7280 if ( / ^ \s * $ / . test ( text ) ) {
@@ -83,7 +91,7 @@ class Parser {
8391
8492 emptyRule ( token ) {
8593 let node = new Rule ( )
86- this . init ( node , token [ 2 ] , token [ 3 ] )
94+ this . init ( node , token [ 2 ] )
8795 node . selector = ''
8896 node . raws . between = ''
8997 this . current = node
@@ -154,7 +162,7 @@ class Parser {
154162 tokens . pop ( )
155163
156164 let node = new Rule ( )
157- this . init ( node , tokens [ 0 ] [ 2 ] , tokens [ 0 ] [ 3 ] )
165+ this . init ( node , tokens [ 0 ] [ 2 ] )
158166
159167 node . raws . between = this . spacesAndCommentsFromEnd ( tokens )
160168 this . raw ( node , 'selector' , tokens )
@@ -170,17 +178,32 @@ class Parser {
170178 this . semicolon = true
171179 tokens . pop ( )
172180 }
173- if ( last [ 4 ] ) {
174- node . source . end = { line : last [ 4 ] , column : last [ 5 ] }
181+ if ( last [ 3 ] ) {
182+ let pos = this . finder . fromIndex ( last [ 3 ] )
183+ node . source . end = {
184+ offset : last [ 3 ] ,
185+ line : pos . line ,
186+ column : pos . col
187+ }
175188 } else {
176- node . source . end = { line : last [ 2 ] , column : last [ 3 ] }
189+ let pos = this . finder . fromIndex ( last [ 2 ] )
190+ node . source . end = {
191+ offset : last [ 2 ] ,
192+ line : pos . line ,
193+ column : pos . col
194+ }
177195 }
178196
179197 while ( tokens [ 0 ] [ 0 ] !== 'word' ) {
180198 if ( tokens . length === 1 ) this . unknownWord ( tokens )
181199 node . raws . before += tokens . shift ( ) [ 1 ]
182200 }
183- node . source . start = { line : tokens [ 0 ] [ 2 ] , column : tokens [ 0 ] [ 3 ] }
201+ let pos = this . finder . fromIndex ( tokens [ 0 ] [ 2 ] )
202+ node . source . start = {
203+ offset : tokens [ 0 ] [ 2 ] ,
204+ line : pos . line ,
205+ column : pos . col
206+ }
184207
185208 node . prop = ''
186209 while ( tokens . length ) {
@@ -264,7 +287,7 @@ class Parser {
264287 if ( node . name === '' ) {
265288 this . unnamedAtrule ( node , token )
266289 }
267- this . init ( node , token [ 2 ] , token [ 3 ] )
290+ this . init ( node , token [ 2 ] )
268291
269292 let type
270293 let prev
@@ -288,7 +311,12 @@ class Parser {
288311
289312 if ( brackets . length === 0 ) {
290313 if ( type === ';' ) {
291- node . source . end = { line : token [ 2 ] , column : token [ 3 ] }
314+ let pos = this . finder . fromIndex ( token [ 2 ] )
315+ node . source . end = {
316+ offset : token [ 2 ] ,
317+ line : pos . line ,
318+ column : pos . col
319+ }
292320 this . semicolon = true
293321 break
294322 } else if ( type === '{' ) {
@@ -302,7 +330,12 @@ class Parser {
302330 prev = params [ -- shift ]
303331 }
304332 if ( prev ) {
305- node . source . end = { line : prev [ 4 ] , column : prev [ 5 ] }
333+ let pos = this . finder . fromIndex ( prev [ 4 ] )
334+ node . source . end = {
335+ offset : prev [ 4 ] ,
336+ line : pos . line ,
337+ column : pos . col
338+ }
306339 }
307340 }
308341 this . end ( token )
@@ -326,7 +359,12 @@ class Parser {
326359 this . raw ( node , 'params' , params )
327360 if ( last ) {
328361 token = params [ params . length - 1 ]
329- node . source . end = { line : token [ 4 ] , column : token [ 5 ] }
362+ let pos = this . finder . fromIndex ( token [ 3 ] )
363+ node . source . end = {
364+ offset : token [ 3 ] ,
365+ line : pos . line ,
366+ column : pos . col
367+ }
330368 this . spaces = node . raws . between
331369 node . raws . between = ''
332370 }
@@ -351,7 +389,12 @@ class Parser {
351389 this . spaces = ''
352390
353391 if ( this . current . parent ) {
354- this . current . source . end = { line : token [ 2 ] , column : token [ 3 ] }
392+ let pos = this . finder . fromIndex ( token [ 2 ] )
393+ this . current . source . end = {
394+ offset : token [ 2 ] ,
395+ line : pos . line ,
396+ column : pos . col
397+ }
355398 this . current = this . current . parent
356399 } else {
357400 this . unexpectedClose ( token )
@@ -379,10 +422,18 @@ class Parser {
379422
380423 // Helpers
381424
382- init ( node , line , column ) {
425+ init ( node , offset ) {
383426 this . current . push ( node )
384427
385- node . source = { start : { line, column } , input : this . input }
428+ let pos = this . finder . fromIndex ( offset ) || { line : null , column : null }
429+ node . source = {
430+ start : {
431+ offset,
432+ line : pos . line ,
433+ column : pos . col
434+ } ,
435+ input : this . input
436+ }
386437 node . raws . before = this . spaces
387438 this . spaces = ''
388439 if ( node . type !== 'comment' ) this . semicolon = false
@@ -504,15 +555,18 @@ class Parser {
504555 // Errors
505556
506557 unclosedBracket ( bracket ) {
507- throw this . input . error ( 'Unclosed bracket' , bracket [ 2 ] , bracket [ 3 ] )
558+ let pos = this . finder . fromIndex ( bracket [ 2 ] )
559+ throw this . input . error ( 'Unclosed bracket' , pos . line , pos . col )
508560 }
509561
510562 unknownWord ( tokens ) {
511- throw this . input . error ( 'Unknown word' , tokens [ 0 ] [ 2 ] , tokens [ 0 ] [ 3 ] )
563+ let pos = this . finder . fromIndex ( tokens [ 0 ] [ 2 ] )
564+ throw this . input . error ( 'Unknown word' , pos . line , pos . col )
512565 }
513566
514567 unexpectedClose ( token ) {
515- throw this . input . error ( 'Unexpected }' , token [ 2 ] , token [ 3 ] )
568+ let pos = this . finder . fromIndex ( token [ 2 ] )
569+ throw this . input . error ( 'Unexpected }' , pos . line , pos . col )
516570 }
517571
518572 unclosedBlock ( ) {
@@ -521,11 +575,13 @@ class Parser {
521575 }
522576
523577 doubleColon ( token ) {
524- throw this . input . error ( 'Double colon' , token [ 2 ] , token [ 3 ] )
578+ let pos = this . finder . fromIndex ( token [ 2 ] )
579+ throw this . input . error ( 'Double colon' , pos . line , pos . col )
525580 }
526581
527582 unnamedAtrule ( node , token ) {
528- throw this . input . error ( 'At-rule without name' , token [ 2 ] , token [ 3 ] )
583+ let pos = this . finder . fromIndex ( token [ 2 ] )
584+ throw this . input . error ( 'At-rule without name' , pos . line , pos . col )
529585 }
530586
531587 precheckMissedSemicolon ( /* tokens */ ) {
@@ -545,7 +601,8 @@ class Parser {
545601 if ( founded === 2 ) break
546602 }
547603 }
548- throw this . input . error ( 'Missed semicolon' , token [ 2 ] , token [ 3 ] )
604+ let pos = this . finder . fromIndex ( token [ 2 ] )
605+ throw this . input . error ( 'Missed semicolon' , pos . line , pos . col )
549606 }
550607}
551608
0 commit comments