@@ -10,7 +10,7 @@ import {
1010 type Rule ,
1111} from './ast'
1212import { createLineTable } from './source-maps/line-table'
13- import type { Source } from './source-maps/source'
13+ import type { Source , SourceLocation } from './source-maps/source'
1414
1515const BACKSLASH = 0x5c
1616const SLASH = 0x2f
@@ -41,14 +41,23 @@ export interface ParseOptions {
4141 * CSS syntax error with source location information.
4242 */
4343export class CssSyntaxError extends Error {
44- constructor ( message : string , source : Source | null , position : number ) {
45- if ( ! source ) {
46- super ( message )
47- } else {
48- const { line, column } = createLineTable ( source . code ) . find ( position )
49- super ( `${ message } at ${ source . file } :${ line } :${ column + 1 } ` )
44+ loc : SourceLocation | null
45+
46+ constructor ( message : string , loc : SourceLocation | null ) {
47+ if ( loc ) {
48+ let source = loc [ 0 ]
49+ let start = createLineTable ( source . code ) . find ( loc [ 1 ] )
50+ message = `${ source . file } : ${ start . line } :${ start . column } : ${ message } `
5051 }
52+
53+ super ( message )
54+
5155 this . name = 'CssSyntaxError'
56+ this . loc = loc
57+
58+ if ( Error . captureStackTrace ) {
59+ Error . captureStackTrace ( this , CssSyntaxError )
60+ }
5261 }
5362}
5463
@@ -285,7 +294,12 @@ export function parse(input: string, opts?: ParseOptions) {
285294 }
286295
287296 let declaration = parseDeclaration ( buffer , colonIdx )
288- if ( ! declaration ) throw new CssSyntaxError ( `Invalid custom property, expected a value` , source , start )
297+ if ( ! declaration ) {
298+ throw new CssSyntaxError (
299+ `Invalid custom property, expected a value` ,
300+ source ? [ source , start , i ] : null ,
301+ )
302+ }
289303
290304 if ( source ) {
291305 declaration . src = [ source , start , i ]
@@ -350,7 +364,10 @@ export function parse(input: string, opts?: ParseOptions) {
350364 let declaration = parseDeclaration ( buffer )
351365 if ( ! declaration ) {
352366 if ( buffer . length === 0 ) continue
353- throw new CssSyntaxError ( `Invalid declaration: \`${ buffer . trim ( ) } \`` , source , bufferStart )
367+ throw new CssSyntaxError (
368+ `Invalid declaration: \`${ buffer . trim ( ) } \`` ,
369+ source ? [ source , bufferStart , i ] : null ,
370+ )
354371 }
355372
356373 if ( source ) {
@@ -407,7 +424,7 @@ export function parse(input: string, opts?: ParseOptions) {
407424 closingBracketStack [ closingBracketStack . length - 1 ] !== ')'
408425 ) {
409426 if ( closingBracketStack === '' ) {
410- throw new CssSyntaxError ( 'Missing opening {' , source , i )
427+ throw new CssSyntaxError ( 'Missing opening {' , source ? [ source , i , i ] : null )
411428 }
412429
413430 closingBracketStack = closingBracketStack . slice ( 0 , - 1 )
@@ -469,7 +486,12 @@ export function parse(input: string, opts?: ParseOptions) {
469486 // Attach the declaration to the parent.
470487 if ( parent ) {
471488 let node = parseDeclaration ( buffer , colonIdx )
472- if ( ! node ) throw new CssSyntaxError ( `Invalid declaration: \`${ buffer . trim ( ) } \`` , source , bufferStart )
489+ if ( ! node ) {
490+ throw new CssSyntaxError (
491+ `Invalid declaration: \`${ buffer . trim ( ) } \`` ,
492+ source ? [ source , bufferStart , i ] : null ,
493+ )
494+ }
473495
474496 if ( source ) {
475497 node . src = [ source , bufferStart , i ]
@@ -508,7 +530,7 @@ export function parse(input: string, opts?: ParseOptions) {
508530 // `)`
509531 else if ( currentChar === CLOSE_PAREN ) {
510532 if ( closingBracketStack [ closingBracketStack . length - 1 ] !== ')' ) {
511- throw new CssSyntaxError ( 'Missing opening (' , source , i )
533+ throw new CssSyntaxError ( 'Missing opening (' , source ? [ source , i , i ] : null )
512534 }
513535
514536 closingBracketStack = closingBracketStack . slice ( 0 , - 1 )
@@ -550,10 +572,17 @@ export function parse(input: string, opts?: ParseOptions) {
550572 // have a leftover `parent`, then it means that we have an unterminated block.
551573 if ( closingBracketStack . length > 0 && parent ) {
552574 if ( parent . kind === 'rule' ) {
553- throw new CssSyntaxError ( `Missing closing } at ${ parent . selector } ` , source , input . length )
575+ throw new CssSyntaxError (
576+ `Missing closing } at ${ parent . selector } ` ,
577+ source ? [ source , bufferStart , bufferStart ] : null ,
578+ )
554579 }
580+
555581 if ( parent . kind === 'at-rule' ) {
556- throw new CssSyntaxError ( `Missing closing } at ${ parent . name } ${ parent . params } ` , source , input . length )
582+ throw new CssSyntaxError (
583+ `Missing closing } at ${ parent . name } ${ parent . params } ` ,
584+ source ? [ source , bufferStart , bufferStart ] : null ,
585+ )
557586 }
558587 }
559588
@@ -610,7 +639,12 @@ function parseDeclaration(
610639 )
611640}
612641
613- function parseString ( input : string , startIdx : number , quoteChar : number , source : Source | null = null ) : number {
642+ function parseString (
643+ input : string ,
644+ startIdx : number ,
645+ quoteChar : number ,
646+ source : Source | null = null ,
647+ ) : number {
614648 let peekChar : number
615649
616650 // We need to ensure that the closing quote is the same as the opening
@@ -653,7 +687,8 @@ function parseString(input: string, startIdx: number, quoteChar: number, source:
653687 ( input . charCodeAt ( i + 1 ) === CARRIAGE_RETURN && input . charCodeAt ( i + 2 ) === LINE_BREAK ) )
654688 ) {
655689 throw new CssSyntaxError (
656- `Unterminated string: ${ input . slice ( startIdx , i + 1 ) + String . fromCharCode ( quoteChar ) } ` , source , startIdx
690+ `Unterminated string: ${ input . slice ( startIdx , i + 1 ) + String . fromCharCode ( quoteChar ) } ` ,
691+ source ? [ source , startIdx , i + 1 ] : null ,
657692 )
658693 }
659694
@@ -672,7 +707,8 @@ function parseString(input: string, startIdx: number, quoteChar: number, source:
672707 ( peekChar === CARRIAGE_RETURN && input . charCodeAt ( i + 1 ) === LINE_BREAK )
673708 ) {
674709 throw new CssSyntaxError (
675- `Unterminated string: ${ input . slice ( startIdx , i ) + String . fromCharCode ( quoteChar ) } ` , source , startIdx
710+ `Unterminated string: ${ input . slice ( startIdx , i ) + String . fromCharCode ( quoteChar ) } ` ,
711+ source ? [ source , startIdx , i + 1 ] : null ,
676712 )
677713 }
678714 }
0 commit comments