44
55// https://drafts.csswg.org/css-syntax/#parsing
66
7- use super :: {
8- BasicParseError , BasicParseErrorKind , Delimiter , Delimiters , ParseError , Parser , Token ,
9- } ;
7+ use super :: { BasicParseError , BasicParseErrorKind , Delimiter , ParseError , Parser , Token } ;
108use crate :: cow_rc_str:: CowRcStr ;
119use crate :: parser:: { parse_nested_block, parse_until_after, ParseUntilErrorBehavior , ParserState } ;
1210
@@ -293,7 +291,7 @@ where
293291 & start,
294292 self . input ,
295293 & mut * self . parser ,
296- Delimiter :: Semicolon | Delimiter :: CurlyBracketBlock ,
294+ /* nested = */ true ,
297295 ) {
298296 return Some ( Ok ( qual) ) ;
299297 }
@@ -304,12 +302,8 @@ where
304302 token => {
305303 let result = if self . parser . parse_qualified ( ) {
306304 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)
313307 } else {
314308 let token = token. clone ( ) ;
315309 self . input . parse_until_after ( Delimiter :: Semicolon , |_| {
@@ -398,7 +392,7 @@ where
398392 & start,
399393 self . input ,
400394 & mut * self . parser ,
401- Delimiter :: CurlyBracketBlock ,
395+ /* nested = */ false ,
402396 ) ;
403397 return Some ( result. map_err ( |e| ( e, self . input . slice_from ( start. position ( ) ) ) ) ) ;
404398 }
@@ -451,7 +445,7 @@ where
451445 if let Some ( name) = at_keyword {
452446 parse_at_rule ( & start, name, input, parser) . map_err ( |e| e. 0 )
453447 } else {
454- parse_qualified_rule ( & start, input, parser, Delimiter :: CurlyBracketBlock )
448+ parse_qualified_rule ( & start, input, parser, /* nested = */ false )
455449 }
456450 } )
457451}
@@ -491,16 +485,52 @@ where
491485 }
492486}
493487
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
494499fn parse_qualified_rule < ' i , ' t , P , E > (
495500 start : & ParserState ,
496501 input : & mut Parser < ' i , ' t > ,
497502 parser : & mut P ,
498- delimiters : Delimiters ,
503+ nested : bool ,
499504) -> Result < <P as QualifiedRuleParser < ' i > >:: QualifiedRule , ParseError < ' i , E > >
500505where
501506 P : QualifiedRuleParser < ' i , Error = E > ,
502507{
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+ // If nested is true, consume the remnants of a bad declaration from input, with
513+ // nested set to true, and return nothing.
514+ // If nested is false, consume a block from input, and return nothing.
515+ let delimiters = if nested {
516+ Delimiter :: Semicolon
517+ } else {
518+ Delimiter :: CurlyBracketBlock
519+ } ;
520+ let _: Result < ( ) , ParseError < ( ) > > = input. parse_until_after ( delimiters, |_| Ok ( ( ) ) ) ;
521+ return Err ( state
522+ . source_location ( )
523+ . new_error ( BasicParseErrorKind :: QualifiedRuleInvalid ) ) ;
524+ }
525+ let delimiters = if nested {
526+ Delimiter :: Semicolon | Delimiter :: CurlyBracketBlock
527+ } else {
528+ Delimiter :: CurlyBracketBlock
529+ } ;
530+ input. reset ( & state) ;
531+ input. parse_until_before ( delimiters, |input| parser. parse_prelude ( input) )
532+ } ;
533+
504534 input. expect_curly_bracket_block ( ) ?;
505535 // Do this here so that we consume the `{` even if the prelude is `Err`.
506536 let prelude = prelude?;
0 commit comments