4
4
5
5
// https://drafts.csswg.org/css-syntax/#parsing
6
6
7
- use super :: {
8
- BasicParseError , BasicParseErrorKind , Delimiter , Delimiters , ParseError , Parser , Token ,
9
- } ;
7
+ use super :: { BasicParseError , BasicParseErrorKind , Delimiter , ParseError , Parser , Token } ;
10
8
use crate :: cow_rc_str:: CowRcStr ;
11
9
use crate :: parser:: { parse_nested_block, parse_until_after, ParseUntilErrorBehavior , ParserState } ;
12
10
@@ -293,7 +291,7 @@ where
293
291
& start,
294
292
self . input ,
295
293
& mut * self . parser ,
296
- Delimiter :: Semicolon | Delimiter :: CurlyBracketBlock ,
294
+ /* nested = */ true ,
297
295
) {
298
296
return Some ( Ok ( qual) ) ;
299
297
}
@@ -304,12 +302,8 @@ where
304
302
token => {
305
303
let result = if self . parser . parse_qualified ( ) {
306
304
self . input . reset ( & start) ;
307
- let delimiters = if self . parser . parse_declarations ( ) {
308
- Delimiter :: Semicolon | Delimiter :: CurlyBracketBlock
309
- } else {
310
- Delimiter :: CurlyBracketBlock
311
- } ;
312
- parse_qualified_rule ( & start, self . input , & mut * self . parser , delimiters)
305
+ let nested = self . parser . parse_declarations ( ) ;
306
+ parse_qualified_rule ( & start, self . input , & mut * self . parser , nested)
313
307
} else {
314
308
let token = token. clone ( ) ;
315
309
self . input . parse_until_after ( Delimiter :: Semicolon , |_| {
@@ -398,7 +392,7 @@ where
398
392
& start,
399
393
self . input ,
400
394
& mut * self . parser ,
401
- Delimiter :: CurlyBracketBlock ,
395
+ /* nested = */ false ,
402
396
) ;
403
397
return Some ( result. map_err ( |e| ( e, self . input . slice_from ( start. position ( ) ) ) ) ) ;
404
398
}
@@ -451,7 +445,7 @@ where
451
445
if let Some ( name) = at_keyword {
452
446
parse_at_rule ( & start, name, input, parser) . map_err ( |e| e. 0 )
453
447
} else {
454
- parse_qualified_rule ( & start, input, parser, Delimiter :: CurlyBracketBlock )
448
+ parse_qualified_rule ( & start, input, parser, /* nested = */ false )
455
449
}
456
450
} )
457
451
}
@@ -491,16 +485,53 @@ where
491
485
}
492
486
}
493
487
488
+ // If the first two non-<whitespace-token> values of rule’s prelude are an <ident-token> whose
489
+ // value starts with "--" followed by a <colon-token>, then...
490
+ fn looks_like_a_custom_property ( input : & mut Parser ) -> bool {
491
+ let ident = match input. expect_ident ( ) {
492
+ Ok ( i) => i,
493
+ Err ( ..) => return false ,
494
+ } ;
495
+ ident. starts_with ( "--" ) && input. expect_colon ( ) . is_ok ( )
496
+ }
497
+
498
+ // https://drafts.csswg.org/css-syntax/#consume-a-qualified-rule
494
499
fn parse_qualified_rule < ' i , ' t , P , E > (
495
500
start : & ParserState ,
496
501
input : & mut Parser < ' i , ' t > ,
497
502
parser : & mut P ,
498
- delimiters : Delimiters ,
503
+ nested : bool ,
499
504
) -> Result < <P as QualifiedRuleParser < ' i > >:: QualifiedRule , ParseError < ' i , E > >
500
505
where
501
506
P : QualifiedRuleParser < ' i , Error = E > ,
502
507
{
503
- let prelude = input. parse_until_before ( delimiters, |input| parser. parse_prelude ( input) ) ;
508
+ input. skip_whitespace ( ) ;
509
+ let prelude = {
510
+ let state = input. state ( ) ;
511
+ if looks_like_a_custom_property ( input) {
512
+ let error = Err ( state
513
+ . source_location ( )
514
+ . new_error ( BasicParseErrorKind :: QualifiedRuleInvalid ) ) ;
515
+ // If nested is true, consume the remnants of a bad declaration from input, with
516
+ // nested set to true, and return nothing.
517
+ // If nested is false, consume a block from input, and return nothing.
518
+ let delimiters = if nested {
519
+ Delimiter :: Semicolon
520
+ } else {
521
+ Delimiter :: CurlyBracketBlock
522
+ } ;
523
+ let _: Result < ( ) , ParseError < ( ) > > = input. parse_until_after ( delimiters, |_| Ok ( ( ) ) ) ;
524
+ return error;
525
+ }
526
+ let delimiters = if nested {
527
+ Delimiter :: Semicolon | Delimiter :: CurlyBracketBlock
528
+ } else {
529
+ Delimiter :: CurlyBracketBlock
530
+ } ;
531
+ input. reset ( & state) ;
532
+ input. parse_until_before ( delimiters, |input| parser. parse_prelude ( input) )
533
+ } ;
534
+
504
535
input. expect_curly_bracket_block ( ) ?;
505
536
// Do this here so that we consume the `{` even if the prelude is `Err`.
506
537
let prelude = prelude?;
0 commit comments