diff --git a/.changeset/warm-foxes-shine.md b/.changeset/warm-foxes-shine.md new file mode 100644 index 000000000000..3a90d4462270 --- /dev/null +++ b/.changeset/warm-foxes-shine.md @@ -0,0 +1,5 @@ +--- +"@biomejs/biome": patch +--- + +Fixed [#7923](https://github.com/biomejs/biome/issues/7923). Added a new `css.parser.vueScopedCss` option that enables parsing of Vue SFC scoped CSS selectors (`:deep()`, `:slotted()`). diff --git a/crates/biome_configuration/src/css.rs b/crates/biome_configuration/src/css.rs index 0d5cabee9cd6..f53289d3af7a 100644 --- a/crates/biome_configuration/src/css.rs +++ b/crates/biome_configuration/src/css.rs @@ -36,6 +36,7 @@ pub struct CssConfiguration { pub type CssAllowWrongLineCommentsEnabled = Bool; pub type CssModulesEnabled = Bool; pub type CssTailwindDirectivesEnabled = Bool; +pub type CssVueScopedCssEnabled = Bool; /// Options that changes how the CSS parser behaves #[derive( @@ -57,6 +58,11 @@ pub struct CssParserConfiguration { /// Enables parsing of Tailwind CSS 4.0 directives and functions. #[bpaf(long("css-parse-tailwind-directives"), argument("true|false"))] pub tailwind_directives: Option, + + /// Enables parsing of Vue SFC scoped CSS selectors (`:deep()`, `:slotted()`). + #[serde(skip_serializing_if = "Option::is_none")] + #[bpaf(long("css-parse-vue-scoped-css"), argument("true|false"))] + pub vue_scoped_css: Option, } pub type CssFormatterEnabled = Bool; diff --git a/crates/biome_css_parser/src/lexer/mod.rs b/crates/biome_css_parser/src/lexer/mod.rs index fbc0855e16ee..cddbf56689be 100644 --- a/crates/biome_css_parser/src/lexer/mod.rs +++ b/crates/biome_css_parser/src/lexer/mod.rs @@ -749,6 +749,8 @@ impl<'src> CssLexer<'src> { b"dir" => DIR_KW, b"global" => GLOBAL_KW, b"local" => LOCAL_KW, + b"deep" => DEEP_KW, + b"slotted" => SLOTTED_KW, b"-moz-any" => ANY_KW, b"-webkit-any" => ANY_KW, b"past" => PAST_KW, diff --git a/crates/biome_css_parser/src/parser.rs b/crates/biome_css_parser/src/parser.rs index dc95d2e77606..34a935e74ea6 100644 --- a/crates/biome_css_parser/src/parser.rs +++ b/crates/biome_css_parser/src/parser.rs @@ -37,6 +37,10 @@ pub struct CssParserOptions { /// Enables parsing of Tailwind CSS 4.0 directives and functions. /// Defaults to `false`. pub tailwind_directives: bool, + + /// Enables parsing of Vue SFC scoped CSS selectors (`:deep()`, `:slotted()`). + /// Defaults to `false`. + pub vue_scoped_css: bool, } impl CssParserOptions { @@ -64,6 +68,12 @@ impl CssParserOptions { self } + /// Enables parsing of Vue SFC scoped CSS selectors. + pub fn allow_vue_scoped_css(mut self) -> Self { + self.vue_scoped_css = true; + self + } + /// Checks if parsing of CSS Modules features is disabled. pub fn is_css_modules_disabled(&self) -> bool { !self.css_modules @@ -78,6 +88,11 @@ impl CssParserOptions { pub fn is_tailwind_directives_enabled(&self) -> bool { self.tailwind_directives } + + /// Checks if parsing of Vue SFC scoped CSS selectors is enabled. + pub fn is_vue_scoped_css_enabled(&self) -> bool { + self.vue_scoped_css + } } impl<'source> CssParser<'source> { diff --git a/crates/biome_css_parser/src/syntax/mod.rs b/crates/biome_css_parser/src/syntax/mod.rs index d5d1d72eb674..ff1d1e2dcd70 100644 --- a/crates/biome_css_parser/src/syntax/mod.rs +++ b/crates/biome_css_parser/src/syntax/mod.rs @@ -6,6 +6,7 @@ mod property; mod selector; mod util; mod value; +mod vue_scoped_css; use crate::lexer::CssLexContext; use crate::parser::CssParser; diff --git a/crates/biome_css_parser/src/syntax/selector/pseudo_class/function_selector.rs b/crates/biome_css_parser/src/syntax/selector/pseudo_class/function_selector.rs index 61f0d0fc361a..4432e6d733ff 100644 --- a/crates/biome_css_parser/src/syntax/selector/pseudo_class/function_selector.rs +++ b/crates/biome_css_parser/src/syntax/selector/pseudo_class/function_selector.rs @@ -6,6 +6,7 @@ use crate::syntax::selector::{ eat_or_recover_selector_function_close_token, parse_selector, recover_selector_function_parameter, }; +use crate::syntax::vue_scoped_css::{VUE_SCOPED_CSS_SET, vue_scoped_css_not_allowed}; use biome_css_syntax::CssSyntaxKind::*; use biome_css_syntax::CssSyntaxKind::{self, CSS_PSEUDO_CLASS_FUNCTION_SELECTOR}; use biome_css_syntax::T; @@ -13,43 +14,36 @@ use biome_parser::Parser; use biome_parser::parsed_syntax::ParsedSyntax; use biome_parser::parsed_syntax::ParsedSyntax::{Absent, Present}; -/// Checks if the current parser position is at a pseudo-class function selector for CSS Modules. -/// -/// This function determines if the parser is currently positioned at the start of a `:local` or `:global` -/// pseudo-class function selector, which is part of the CSS Modules syntax. +/// Checks if the current parser position is at a pseudo-class function selector +/// (`:local()`, `:global()` for CSS Modules; `:deep()`, `:slotted()` for Vue SFC). #[inline] pub(crate) fn is_at_pseudo_class_function_selector(p: &mut CssParser) -> bool { - p.at_ts(CSS_MODULES_SCOPE_SET) && p.nth_at(1, T!['(']) + (p.at_ts(CSS_MODULES_SCOPE_SET) || p.at_ts(VUE_SCOPED_CSS_SET)) && p.nth_at(1, T!['(']) } -/// Parses a pseudo-class function selector for CSS Modules. +/// Parses a pseudo-class function selector for CSS Modules (`:local()`, `:global()`) +/// or Vue SFC scoped CSS (`:deep()`, `:slotted()`). /// -/// This function parses a pseudo-class function selector, specifically `:local` or `:global`, in CSS Modules. -/// If the `css.parser.cssModules` option is not enabled, it generates a diagnostic error and skips the selector. -/// ```css -/// :local(.className) { -/// color: red; -/// } -/// :global(.globalClass) .nestedClass { -/// padding: 10px; -/// } -/// :local(.className) > :global(.globalClass) { -/// margin: 0; -/// } -/// ``` +/// If the corresponding parser option is not enabled, emits a diagnostic and skips the selector. #[inline] pub(crate) fn parse_pseudo_class_function_selector(p: &mut CssParser) -> ParsedSyntax { if !is_at_pseudo_class_function_selector(p) { return Absent; } - if p.options().is_css_modules_disabled() { - // :local and :global are not standard CSS features - // provide a hint on how to enable parsing of these pseudo-classes - p.error(local_or_global_not_allowed(p, p.cur_range())); + // Determine which feature this selector belongs to and whether it's enabled. + let disabled_error = if p.at_ts(VUE_SCOPED_CSS_SET) { + (!p.options().is_vue_scoped_css_enabled()) + .then(|| vue_scoped_css_not_allowed(p, p.cur_range())) + } else { + p.options() + .is_css_modules_disabled() + .then(|| local_or_global_not_allowed(p, p.cur_range())) + }; + + if let Some(error) = disabled_error { + p.error(error); - // Skip the entire pseudo-class function selector - // Skip until the next closing parenthesis while !p.eat(T![')']) && !p.at(CssSyntaxKind::EOF) { p.bump_any(); } diff --git a/crates/biome_css_parser/src/syntax/vue_scoped_css.rs b/crates/biome_css_parser/src/syntax/vue_scoped_css.rs new file mode 100644 index 000000000000..699b6c388044 --- /dev/null +++ b/crates/biome_css_parser/src/syntax/vue_scoped_css.rs @@ -0,0 +1,20 @@ +use crate::parser::CssParser; +use biome_css_syntax::{CssSyntaxKind, T, TextRange}; +use biome_parser::diagnostic::ParseDiagnostic; +use biome_parser::{Parser, TokenSet, token_set}; + +/// A set of tokens representing the Vue SFC scoped CSS selectors `:deep` and `:slotted`. +/// +/// Note: `:global` is shared with CSS Modules and handled separately. +pub(crate) const VUE_SCOPED_CSS_SET: TokenSet = token_set![T![deep], T![slotted]]; + +/// Generates a parse diagnostic for when Vue SFC scoped CSS selectors are not allowed. +pub(crate) fn vue_scoped_css_not_allowed(p: &CssParser, range: TextRange) -> ParseDiagnostic { + p.err_builder( + "`:deep` and `:slotted` are Vue SFC scoped CSS selectors, not standard CSS features.", + range, + ) + .with_hint( + "You can enable Vue SFC scoped CSS parsing by setting the `css.parser.vueScopedCss` option to `true` in your configuration file.", + ) +} diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector/vue_disabled/pseudo_class_vue_disabled.css b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector/vue_disabled/pseudo_class_vue_disabled.css new file mode 100644 index 000000000000..a2b9f6d356f3 --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector/vue_disabled/pseudo_class_vue_disabled.css @@ -0,0 +1,2 @@ +:deep(.b) { color: red; } +:slotted(.b) { color: red; } diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector/vue_disabled/pseudo_class_vue_disabled.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector/vue_disabled/pseudo_class_vue_disabled.css.snap new file mode 100644 index 000000000000..2335e1cc7a05 --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector/vue_disabled/pseudo_class_vue_disabled.css.snap @@ -0,0 +1,203 @@ +--- +source: crates/biome_css_parser/tests/spec_test.rs +expression: snapshot +--- + +## Input + +```css +:deep(.b) { color: red; } +:slotted(.b) { color: red; } + +``` + + +## AST + +``` +CssRoot { + bom_token: missing (optional), + rules: CssRuleList [ + CssQualifiedRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssBogusSubSelector { + items: [ + COLON@0..1 ":" [] [], + DEEP_KW@1..5 "deep" [] [], + L_PAREN@5..6 "(" [] [], + DOT@6..7 "." [] [], + IDENT@7..8 "b" [] [], + R_PAREN@8..10 ")" [] [Whitespace(" ")], + ], + }, + ], + }, + ], + block: CssDeclarationOrRuleBlock { + l_curly_token: L_CURLY@10..12 "{" [] [Whitespace(" ")], + items: CssDeclarationOrRuleList [ + CssDeclarationWithSemicolon { + declaration: CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@12..17 "color" [] [], + }, + colon_token: COLON@17..19 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@19..22 "red" [] [], + }, + ], + }, + important: missing (optional), + }, + semicolon_token: SEMICOLON@22..24 ";" [] [Whitespace(" ")], + }, + ], + r_curly_token: R_CURLY@24..25 "}" [] [], + }, + }, + CssQualifiedRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssBogusSubSelector { + items: [ + COLON@25..27 ":" [Newline("\n")] [], + SLOTTED_KW@27..34 "slotted" [] [], + L_PAREN@34..35 "(" [] [], + DOT@35..36 "." [] [], + IDENT@36..37 "b" [] [], + R_PAREN@37..39 ")" [] [Whitespace(" ")], + ], + }, + ], + }, + ], + block: CssDeclarationOrRuleBlock { + l_curly_token: L_CURLY@39..41 "{" [] [Whitespace(" ")], + items: CssDeclarationOrRuleList [ + CssDeclarationWithSemicolon { + declaration: CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@41..46 "color" [] [], + }, + colon_token: COLON@46..48 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@48..51 "red" [] [], + }, + ], + }, + important: missing (optional), + }, + semicolon_token: SEMICOLON@51..53 ";" [] [Whitespace(" ")], + }, + ], + r_curly_token: R_CURLY@53..54 "}" [] [], + }, + }, + ], + eof_token: EOF@54..55 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: CSS_ROOT@0..55 + 0: (empty) + 1: CSS_RULE_LIST@0..54 + 0: CSS_QUALIFIED_RULE@0..25 + 0: CSS_SELECTOR_LIST@0..10 + 0: CSS_COMPOUND_SELECTOR@0..10 + 0: CSS_NESTED_SELECTOR_LIST@0..0 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@0..10 + 0: CSS_BOGUS_SUB_SELECTOR@0..10 + 0: COLON@0..1 ":" [] [] + 1: DEEP_KW@1..5 "deep" [] [] + 2: L_PAREN@5..6 "(" [] [] + 3: DOT@6..7 "." [] [] + 4: IDENT@7..8 "b" [] [] + 5: R_PAREN@8..10 ")" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_BLOCK@10..25 + 0: L_CURLY@10..12 "{" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_LIST@12..24 + 0: CSS_DECLARATION_WITH_SEMICOLON@12..24 + 0: CSS_DECLARATION@12..22 + 0: CSS_GENERIC_PROPERTY@12..22 + 0: CSS_IDENTIFIER@12..17 + 0: IDENT@12..17 "color" [] [] + 1: COLON@17..19 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@19..22 + 0: CSS_IDENTIFIER@19..22 + 0: IDENT@19..22 "red" [] [] + 1: (empty) + 1: SEMICOLON@22..24 ";" [] [Whitespace(" ")] + 2: R_CURLY@24..25 "}" [] [] + 1: CSS_QUALIFIED_RULE@25..54 + 0: CSS_SELECTOR_LIST@25..39 + 0: CSS_COMPOUND_SELECTOR@25..39 + 0: CSS_NESTED_SELECTOR_LIST@25..25 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@25..39 + 0: CSS_BOGUS_SUB_SELECTOR@25..39 + 0: COLON@25..27 ":" [Newline("\n")] [] + 1: SLOTTED_KW@27..34 "slotted" [] [] + 2: L_PAREN@34..35 "(" [] [] + 3: DOT@35..36 "." [] [] + 4: IDENT@36..37 "b" [] [] + 5: R_PAREN@37..39 ")" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_BLOCK@39..54 + 0: L_CURLY@39..41 "{" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_LIST@41..53 + 0: CSS_DECLARATION_WITH_SEMICOLON@41..53 + 0: CSS_DECLARATION@41..51 + 0: CSS_GENERIC_PROPERTY@41..51 + 0: CSS_IDENTIFIER@41..46 + 0: IDENT@41..46 "color" [] [] + 1: COLON@46..48 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@48..51 + 0: CSS_IDENTIFIER@48..51 + 0: IDENT@48..51 "red" [] [] + 1: (empty) + 1: SEMICOLON@51..53 ";" [] [Whitespace(" ")] + 2: R_CURLY@53..54 "}" [] [] + 2: EOF@54..55 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +pseudo_class_vue_disabled.css:1:2 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × `:deep` and `:slotted` are Vue SFC scoped CSS selectors, not standard CSS features. + + > 1 │ :deep(.b) { color: red; } + │ ^^^^ + 2 │ :slotted(.b) { color: red; } + 3 │ + + i You can enable Vue SFC scoped CSS parsing by setting the `css.parser.vueScopedCss` option to `true` in your configuration file. + +pseudo_class_vue_disabled.css:2:2 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × `:deep` and `:slotted` are Vue SFC scoped CSS selectors, not standard CSS features. + + 1 │ :deep(.b) { color: red; } + > 2 │ :slotted(.b) { color: red; } + │ ^^^^^^^ + 3 │ + + i You can enable Vue SFC scoped CSS parsing by setting the `css.parser.vueScopedCss` option to `true` in your configuration file. + +``` diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector/vue_enabled/options.json b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector/vue_enabled/options.json new file mode 100644 index 000000000000..02f587b8bce2 --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector/vue_enabled/options.json @@ -0,0 +1,8 @@ +{ + "$schema": "../../../../../../../../../packages/@biomejs/biome/configuration_schema.json", + "css": { + "parser": { + "vueScopedCss": true + } + } +} diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector/vue_enabled/pseudo_class_vue_enabled.css b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector/vue_enabled/pseudo_class_vue_enabled.css new file mode 100644 index 000000000000..11315ebea8aa --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector/vue_enabled/pseudo_class_vue_enabled.css @@ -0,0 +1,12 @@ +:deep( {} +:deep() {} +:deep(.div, .class) {} +:deep(.div, .class {} +:deep(.div .class {} +:deep(.div .class +:slotted( {} +:slotted() {} +:slotted(.div, .class) {} +:slotted(.div, .class {} +:slotted(.div .class {} +:slotted(.div .class diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector/vue_enabled/pseudo_class_vue_enabled.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector/vue_enabled/pseudo_class_vue_enabled.css.snap new file mode 100644 index 000000000000..ca2be9df3751 --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector/vue_enabled/pseudo_class_vue_enabled.css.snap @@ -0,0 +1,1079 @@ +--- +source: crates/biome_css_parser/tests/spec_test.rs +expression: snapshot +--- + +## Input + +```css +:deep( {} +:deep() {} +:deep(.div, .class) {} +:deep(.div, .class {} +:deep(.div .class {} +:deep(.div .class +:slotted( {} +:slotted() {} +:slotted(.div, .class) {} +:slotted(.div, .class {} +:slotted(.div .class {} +:slotted(.div .class + +``` + + +## AST + +``` +CssRoot { + bom_token: missing (optional), + rules: CssRuleList [ + CssQualifiedRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssPseudoClassSelector { + colon_token: COLON@0..1 ":" [] [], + class: CssBogusPseudoClass { + items: [ + CssIdentifier { + value_token: IDENT@1..5 "deep" [] [], + }, + L_PAREN@5..7 "(" [] [Whitespace(" ")], + ], + }, + }, + ], + }, + ], + block: CssDeclarationOrRuleBlock { + l_curly_token: L_CURLY@7..8 "{" [] [], + items: CssDeclarationOrRuleList [], + r_curly_token: R_CURLY@8..9 "}" [] [], + }, + }, + CssQualifiedRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssPseudoClassSelector { + colon_token: COLON@9..11 ":" [Newline("\n")] [], + class: CssBogusPseudoClass { + items: [ + CssIdentifier { + value_token: IDENT@11..15 "deep" [] [], + }, + L_PAREN@15..16 "(" [] [], + R_PAREN@16..18 ")" [] [Whitespace(" ")], + ], + }, + }, + ], + }, + ], + block: CssDeclarationOrRuleBlock { + l_curly_token: L_CURLY@18..19 "{" [] [], + items: CssDeclarationOrRuleList [], + r_curly_token: R_CURLY@19..20 "}" [] [], + }, + }, + CssQualifiedRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssPseudoClassSelector { + colon_token: COLON@20..22 ":" [Newline("\n")] [], + class: CssBogusPseudoClass { + items: [ + CssIdentifier { + value_token: IDENT@22..26 "deep" [] [], + }, + L_PAREN@26..27 "(" [] [], + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssClassSelector { + dot_token: DOT@27..28 "." [] [], + name: CssCustomIdentifier { + value_token: IDENT@28..31 "div" [] [], + }, + }, + ], + }, + CssBogus { + items: [ + COMMA@31..33 "," [] [Whitespace(" ")], + DOT@33..34 "." [] [], + IDENT@34..39 "class" [] [], + ], + }, + R_PAREN@39..41 ")" [] [Whitespace(" ")], + ], + }, + }, + ], + }, + ], + block: CssDeclarationOrRuleBlock { + l_curly_token: L_CURLY@41..42 "{" [] [], + items: CssDeclarationOrRuleList [], + r_curly_token: R_CURLY@42..43 "}" [] [], + }, + }, + CssQualifiedRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssPseudoClassSelector { + colon_token: COLON@43..45 ":" [Newline("\n")] [], + class: CssBogusPseudoClass { + items: [ + CssIdentifier { + value_token: IDENT@45..49 "deep" [] [], + }, + L_PAREN@49..50 "(" [] [], + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssClassSelector { + dot_token: DOT@50..51 "." [] [], + name: CssCustomIdentifier { + value_token: IDENT@51..54 "div" [] [], + }, + }, + ], + }, + CssBogus { + items: [ + COMMA@54..56 "," [] [Whitespace(" ")], + DOT@56..57 "." [] [], + IDENT@57..63 "class" [] [Whitespace(" ")], + ], + }, + ], + }, + }, + ], + }, + ], + block: CssDeclarationOrRuleBlock { + l_curly_token: L_CURLY@63..64 "{" [] [], + items: CssDeclarationOrRuleList [], + r_curly_token: R_CURLY@64..65 "}" [] [], + }, + }, + CssQualifiedRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssPseudoClassSelector { + colon_token: COLON@65..67 ":" [Newline("\n")] [], + class: CssBogusPseudoClass { + items: [ + CssIdentifier { + value_token: IDENT@67..71 "deep" [] [], + }, + L_PAREN@71..72 "(" [] [], + CssComplexSelector { + left: CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssClassSelector { + dot_token: DOT@72..73 "." [] [], + name: CssCustomIdentifier { + value_token: IDENT@73..76 "div" [] [], + }, + }, + ], + }, + combinator: CSS_SPACE_LITERAL@76..77 " " [] [], + right: CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssClassSelector { + dot_token: DOT@77..78 "." [] [], + name: CssCustomIdentifier { + value_token: IDENT@78..84 "class" [] [Whitespace(" ")], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + ], + block: CssDeclarationOrRuleBlock { + l_curly_token: L_CURLY@84..85 "{" [] [], + items: CssDeclarationOrRuleList [], + r_curly_token: R_CURLY@85..86 "}" [] [], + }, + }, + CssQualifiedRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssPseudoClassSelector { + colon_token: COLON@86..88 ":" [Newline("\n")] [], + class: CssBogusPseudoClass { + items: [ + CssIdentifier { + value_token: IDENT@88..92 "deep" [] [], + }, + L_PAREN@92..93 "(" [] [], + CssComplexSelector { + left: CssComplexSelector { + left: CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssClassSelector { + dot_token: DOT@93..94 "." [] [], + name: CssCustomIdentifier { + value_token: IDENT@94..97 "div" [] [], + }, + }, + ], + }, + combinator: CSS_SPACE_LITERAL@97..98 " " [] [], + right: CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssClassSelector { + dot_token: DOT@98..99 "." [] [], + name: CssCustomIdentifier { + value_token: IDENT@99..104 "class" [] [], + }, + }, + ], + }, + }, + combinator: CSS_SPACE_LITERAL@104..105 "\n" [] [], + right: CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssPseudoClassSelector { + colon_token: COLON@105..106 ":" [] [], + class: CssBogusPseudoClass { + items: [ + CssIdentifier { + value_token: IDENT@106..113 "slotted" [] [], + }, + L_PAREN@113..115 "(" [] [Whitespace(" ")], + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + ], + block: CssDeclarationOrRuleBlock { + l_curly_token: L_CURLY@115..116 "{" [] [], + items: CssDeclarationOrRuleList [], + r_curly_token: R_CURLY@116..117 "}" [] [], + }, + }, + CssQualifiedRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssPseudoClassSelector { + colon_token: COLON@117..119 ":" [Newline("\n")] [], + class: CssBogusPseudoClass { + items: [ + CssIdentifier { + value_token: IDENT@119..126 "slotted" [] [], + }, + L_PAREN@126..127 "(" [] [], + R_PAREN@127..129 ")" [] [Whitespace(" ")], + ], + }, + }, + ], + }, + ], + block: CssDeclarationOrRuleBlock { + l_curly_token: L_CURLY@129..130 "{" [] [], + items: CssDeclarationOrRuleList [], + r_curly_token: R_CURLY@130..131 "}" [] [], + }, + }, + CssQualifiedRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssPseudoClassSelector { + colon_token: COLON@131..133 ":" [Newline("\n")] [], + class: CssBogusPseudoClass { + items: [ + CssIdentifier { + value_token: IDENT@133..140 "slotted" [] [], + }, + L_PAREN@140..141 "(" [] [], + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssClassSelector { + dot_token: DOT@141..142 "." [] [], + name: CssCustomIdentifier { + value_token: IDENT@142..145 "div" [] [], + }, + }, + ], + }, + CssBogus { + items: [ + COMMA@145..147 "," [] [Whitespace(" ")], + DOT@147..148 "." [] [], + IDENT@148..153 "class" [] [], + ], + }, + R_PAREN@153..155 ")" [] [Whitespace(" ")], + ], + }, + }, + ], + }, + ], + block: CssDeclarationOrRuleBlock { + l_curly_token: L_CURLY@155..156 "{" [] [], + items: CssDeclarationOrRuleList [], + r_curly_token: R_CURLY@156..157 "}" [] [], + }, + }, + CssQualifiedRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssPseudoClassSelector { + colon_token: COLON@157..159 ":" [Newline("\n")] [], + class: CssBogusPseudoClass { + items: [ + CssIdentifier { + value_token: IDENT@159..166 "slotted" [] [], + }, + L_PAREN@166..167 "(" [] [], + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssClassSelector { + dot_token: DOT@167..168 "." [] [], + name: CssCustomIdentifier { + value_token: IDENT@168..171 "div" [] [], + }, + }, + ], + }, + CssBogus { + items: [ + COMMA@171..173 "," [] [Whitespace(" ")], + DOT@173..174 "." [] [], + IDENT@174..180 "class" [] [Whitespace(" ")], + ], + }, + ], + }, + }, + ], + }, + ], + block: CssDeclarationOrRuleBlock { + l_curly_token: L_CURLY@180..181 "{" [] [], + items: CssDeclarationOrRuleList [], + r_curly_token: R_CURLY@181..182 "}" [] [], + }, + }, + CssQualifiedRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssPseudoClassSelector { + colon_token: COLON@182..184 ":" [Newline("\n")] [], + class: CssBogusPseudoClass { + items: [ + CssIdentifier { + value_token: IDENT@184..191 "slotted" [] [], + }, + L_PAREN@191..192 "(" [] [], + CssComplexSelector { + left: CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssClassSelector { + dot_token: DOT@192..193 "." [] [], + name: CssCustomIdentifier { + value_token: IDENT@193..196 "div" [] [], + }, + }, + ], + }, + combinator: CSS_SPACE_LITERAL@196..197 " " [] [], + right: CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssClassSelector { + dot_token: DOT@197..198 "." [] [], + name: CssCustomIdentifier { + value_token: IDENT@198..204 "class" [] [Whitespace(" ")], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + ], + block: CssDeclarationOrRuleBlock { + l_curly_token: L_CURLY@204..205 "{" [] [], + items: CssDeclarationOrRuleList [], + r_curly_token: R_CURLY@205..206 "}" [] [], + }, + }, + CssQualifiedRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssPseudoClassSelector { + colon_token: COLON@206..208 ":" [Newline("\n")] [], + class: CssBogusPseudoClass { + items: [ + CssIdentifier { + value_token: IDENT@208..215 "slotted" [] [], + }, + L_PAREN@215..216 "(" [] [], + CssComplexSelector { + left: CssComplexSelector { + left: CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssClassSelector { + dot_token: DOT@216..217 "." [] [], + name: CssCustomIdentifier { + value_token: IDENT@217..220 "div" [] [], + }, + }, + ], + }, + combinator: CSS_SPACE_LITERAL@220..221 " " [] [], + right: CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssClassSelector { + dot_token: DOT@221..222 "." [] [], + name: CssCustomIdentifier { + value_token: IDENT@222..227 "class" [] [], + }, + }, + ], + }, + }, + combinator: CSS_SPACE_LITERAL@227..228 "\n" [] [], + right: missing (required), + }, + ], + }, + }, + ], + }, + ], + block: CssBogusBlock { + items: [], + }, + }, + ], + eof_token: EOF@228..228 "" [] [], +} +``` + +## CST + +``` +0: CSS_ROOT@0..228 + 0: (empty) + 1: CSS_RULE_LIST@0..228 + 0: CSS_QUALIFIED_RULE@0..9 + 0: CSS_SELECTOR_LIST@0..7 + 0: CSS_COMPOUND_SELECTOR@0..7 + 0: CSS_NESTED_SELECTOR_LIST@0..0 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@0..7 + 0: CSS_PSEUDO_CLASS_SELECTOR@0..7 + 0: COLON@0..1 ":" [] [] + 1: CSS_BOGUS_PSEUDO_CLASS@1..7 + 0: CSS_IDENTIFIER@1..5 + 0: IDENT@1..5 "deep" [] [] + 1: L_PAREN@5..7 "(" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_BLOCK@7..9 + 0: L_CURLY@7..8 "{" [] [] + 1: CSS_DECLARATION_OR_RULE_LIST@8..8 + 2: R_CURLY@8..9 "}" [] [] + 1: CSS_QUALIFIED_RULE@9..20 + 0: CSS_SELECTOR_LIST@9..18 + 0: CSS_COMPOUND_SELECTOR@9..18 + 0: CSS_NESTED_SELECTOR_LIST@9..9 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@9..18 + 0: CSS_PSEUDO_CLASS_SELECTOR@9..18 + 0: COLON@9..11 ":" [Newline("\n")] [] + 1: CSS_BOGUS_PSEUDO_CLASS@11..18 + 0: CSS_IDENTIFIER@11..15 + 0: IDENT@11..15 "deep" [] [] + 1: L_PAREN@15..16 "(" [] [] + 2: R_PAREN@16..18 ")" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_BLOCK@18..20 + 0: L_CURLY@18..19 "{" [] [] + 1: CSS_DECLARATION_OR_RULE_LIST@19..19 + 2: R_CURLY@19..20 "}" [] [] + 2: CSS_QUALIFIED_RULE@20..43 + 0: CSS_SELECTOR_LIST@20..41 + 0: CSS_COMPOUND_SELECTOR@20..41 + 0: CSS_NESTED_SELECTOR_LIST@20..20 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@20..41 + 0: CSS_PSEUDO_CLASS_SELECTOR@20..41 + 0: COLON@20..22 ":" [Newline("\n")] [] + 1: CSS_BOGUS_PSEUDO_CLASS@22..41 + 0: CSS_IDENTIFIER@22..26 + 0: IDENT@22..26 "deep" [] [] + 1: L_PAREN@26..27 "(" [] [] + 2: CSS_COMPOUND_SELECTOR@27..31 + 0: CSS_NESTED_SELECTOR_LIST@27..27 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@27..31 + 0: CSS_CLASS_SELECTOR@27..31 + 0: DOT@27..28 "." [] [] + 1: CSS_CUSTOM_IDENTIFIER@28..31 + 0: IDENT@28..31 "div" [] [] + 3: CSS_BOGUS@31..39 + 0: COMMA@31..33 "," [] [Whitespace(" ")] + 1: DOT@33..34 "." [] [] + 2: IDENT@34..39 "class" [] [] + 4: R_PAREN@39..41 ")" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_BLOCK@41..43 + 0: L_CURLY@41..42 "{" [] [] + 1: CSS_DECLARATION_OR_RULE_LIST@42..42 + 2: R_CURLY@42..43 "}" [] [] + 3: CSS_QUALIFIED_RULE@43..65 + 0: CSS_SELECTOR_LIST@43..63 + 0: CSS_COMPOUND_SELECTOR@43..63 + 0: CSS_NESTED_SELECTOR_LIST@43..43 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@43..63 + 0: CSS_PSEUDO_CLASS_SELECTOR@43..63 + 0: COLON@43..45 ":" [Newline("\n")] [] + 1: CSS_BOGUS_PSEUDO_CLASS@45..63 + 0: CSS_IDENTIFIER@45..49 + 0: IDENT@45..49 "deep" [] [] + 1: L_PAREN@49..50 "(" [] [] + 2: CSS_COMPOUND_SELECTOR@50..54 + 0: CSS_NESTED_SELECTOR_LIST@50..50 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@50..54 + 0: CSS_CLASS_SELECTOR@50..54 + 0: DOT@50..51 "." [] [] + 1: CSS_CUSTOM_IDENTIFIER@51..54 + 0: IDENT@51..54 "div" [] [] + 3: CSS_BOGUS@54..63 + 0: COMMA@54..56 "," [] [Whitespace(" ")] + 1: DOT@56..57 "." [] [] + 2: IDENT@57..63 "class" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_BLOCK@63..65 + 0: L_CURLY@63..64 "{" [] [] + 1: CSS_DECLARATION_OR_RULE_LIST@64..64 + 2: R_CURLY@64..65 "}" [] [] + 4: CSS_QUALIFIED_RULE@65..86 + 0: CSS_SELECTOR_LIST@65..84 + 0: CSS_COMPOUND_SELECTOR@65..84 + 0: CSS_NESTED_SELECTOR_LIST@65..65 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@65..84 + 0: CSS_PSEUDO_CLASS_SELECTOR@65..84 + 0: COLON@65..67 ":" [Newline("\n")] [] + 1: CSS_BOGUS_PSEUDO_CLASS@67..84 + 0: CSS_IDENTIFIER@67..71 + 0: IDENT@67..71 "deep" [] [] + 1: L_PAREN@71..72 "(" [] [] + 2: CSS_COMPLEX_SELECTOR@72..84 + 0: CSS_COMPOUND_SELECTOR@72..76 + 0: CSS_NESTED_SELECTOR_LIST@72..72 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@72..76 + 0: CSS_CLASS_SELECTOR@72..76 + 0: DOT@72..73 "." [] [] + 1: CSS_CUSTOM_IDENTIFIER@73..76 + 0: IDENT@73..76 "div" [] [] + 1: CSS_SPACE_LITERAL@76..77 " " [] [] + 2: CSS_COMPOUND_SELECTOR@77..84 + 0: CSS_NESTED_SELECTOR_LIST@77..77 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@77..84 + 0: CSS_CLASS_SELECTOR@77..84 + 0: DOT@77..78 "." [] [] + 1: CSS_CUSTOM_IDENTIFIER@78..84 + 0: IDENT@78..84 "class" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_BLOCK@84..86 + 0: L_CURLY@84..85 "{" [] [] + 1: CSS_DECLARATION_OR_RULE_LIST@85..85 + 2: R_CURLY@85..86 "}" [] [] + 5: CSS_QUALIFIED_RULE@86..117 + 0: CSS_SELECTOR_LIST@86..115 + 0: CSS_COMPOUND_SELECTOR@86..115 + 0: CSS_NESTED_SELECTOR_LIST@86..86 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@86..115 + 0: CSS_PSEUDO_CLASS_SELECTOR@86..115 + 0: COLON@86..88 ":" [Newline("\n")] [] + 1: CSS_BOGUS_PSEUDO_CLASS@88..115 + 0: CSS_IDENTIFIER@88..92 + 0: IDENT@88..92 "deep" [] [] + 1: L_PAREN@92..93 "(" [] [] + 2: CSS_COMPLEX_SELECTOR@93..115 + 0: CSS_COMPLEX_SELECTOR@93..104 + 0: CSS_COMPOUND_SELECTOR@93..97 + 0: CSS_NESTED_SELECTOR_LIST@93..93 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@93..97 + 0: CSS_CLASS_SELECTOR@93..97 + 0: DOT@93..94 "." [] [] + 1: CSS_CUSTOM_IDENTIFIER@94..97 + 0: IDENT@94..97 "div" [] [] + 1: CSS_SPACE_LITERAL@97..98 " " [] [] + 2: CSS_COMPOUND_SELECTOR@98..104 + 0: CSS_NESTED_SELECTOR_LIST@98..98 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@98..104 + 0: CSS_CLASS_SELECTOR@98..104 + 0: DOT@98..99 "." [] [] + 1: CSS_CUSTOM_IDENTIFIER@99..104 + 0: IDENT@99..104 "class" [] [] + 1: CSS_SPACE_LITERAL@104..105 "\n" [] [] + 2: CSS_COMPOUND_SELECTOR@105..115 + 0: CSS_NESTED_SELECTOR_LIST@105..105 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@105..115 + 0: CSS_PSEUDO_CLASS_SELECTOR@105..115 + 0: COLON@105..106 ":" [] [] + 1: CSS_BOGUS_PSEUDO_CLASS@106..115 + 0: CSS_IDENTIFIER@106..113 + 0: IDENT@106..113 "slotted" [] [] + 1: L_PAREN@113..115 "(" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_BLOCK@115..117 + 0: L_CURLY@115..116 "{" [] [] + 1: CSS_DECLARATION_OR_RULE_LIST@116..116 + 2: R_CURLY@116..117 "}" [] [] + 6: CSS_QUALIFIED_RULE@117..131 + 0: CSS_SELECTOR_LIST@117..129 + 0: CSS_COMPOUND_SELECTOR@117..129 + 0: CSS_NESTED_SELECTOR_LIST@117..117 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@117..129 + 0: CSS_PSEUDO_CLASS_SELECTOR@117..129 + 0: COLON@117..119 ":" [Newline("\n")] [] + 1: CSS_BOGUS_PSEUDO_CLASS@119..129 + 0: CSS_IDENTIFIER@119..126 + 0: IDENT@119..126 "slotted" [] [] + 1: L_PAREN@126..127 "(" [] [] + 2: R_PAREN@127..129 ")" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_BLOCK@129..131 + 0: L_CURLY@129..130 "{" [] [] + 1: CSS_DECLARATION_OR_RULE_LIST@130..130 + 2: R_CURLY@130..131 "}" [] [] + 7: CSS_QUALIFIED_RULE@131..157 + 0: CSS_SELECTOR_LIST@131..155 + 0: CSS_COMPOUND_SELECTOR@131..155 + 0: CSS_NESTED_SELECTOR_LIST@131..131 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@131..155 + 0: CSS_PSEUDO_CLASS_SELECTOR@131..155 + 0: COLON@131..133 ":" [Newline("\n")] [] + 1: CSS_BOGUS_PSEUDO_CLASS@133..155 + 0: CSS_IDENTIFIER@133..140 + 0: IDENT@133..140 "slotted" [] [] + 1: L_PAREN@140..141 "(" [] [] + 2: CSS_COMPOUND_SELECTOR@141..145 + 0: CSS_NESTED_SELECTOR_LIST@141..141 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@141..145 + 0: CSS_CLASS_SELECTOR@141..145 + 0: DOT@141..142 "." [] [] + 1: CSS_CUSTOM_IDENTIFIER@142..145 + 0: IDENT@142..145 "div" [] [] + 3: CSS_BOGUS@145..153 + 0: COMMA@145..147 "," [] [Whitespace(" ")] + 1: DOT@147..148 "." [] [] + 2: IDENT@148..153 "class" [] [] + 4: R_PAREN@153..155 ")" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_BLOCK@155..157 + 0: L_CURLY@155..156 "{" [] [] + 1: CSS_DECLARATION_OR_RULE_LIST@156..156 + 2: R_CURLY@156..157 "}" [] [] + 8: CSS_QUALIFIED_RULE@157..182 + 0: CSS_SELECTOR_LIST@157..180 + 0: CSS_COMPOUND_SELECTOR@157..180 + 0: CSS_NESTED_SELECTOR_LIST@157..157 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@157..180 + 0: CSS_PSEUDO_CLASS_SELECTOR@157..180 + 0: COLON@157..159 ":" [Newline("\n")] [] + 1: CSS_BOGUS_PSEUDO_CLASS@159..180 + 0: CSS_IDENTIFIER@159..166 + 0: IDENT@159..166 "slotted" [] [] + 1: L_PAREN@166..167 "(" [] [] + 2: CSS_COMPOUND_SELECTOR@167..171 + 0: CSS_NESTED_SELECTOR_LIST@167..167 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@167..171 + 0: CSS_CLASS_SELECTOR@167..171 + 0: DOT@167..168 "." [] [] + 1: CSS_CUSTOM_IDENTIFIER@168..171 + 0: IDENT@168..171 "div" [] [] + 3: CSS_BOGUS@171..180 + 0: COMMA@171..173 "," [] [Whitespace(" ")] + 1: DOT@173..174 "." [] [] + 2: IDENT@174..180 "class" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_BLOCK@180..182 + 0: L_CURLY@180..181 "{" [] [] + 1: CSS_DECLARATION_OR_RULE_LIST@181..181 + 2: R_CURLY@181..182 "}" [] [] + 9: CSS_QUALIFIED_RULE@182..206 + 0: CSS_SELECTOR_LIST@182..204 + 0: CSS_COMPOUND_SELECTOR@182..204 + 0: CSS_NESTED_SELECTOR_LIST@182..182 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@182..204 + 0: CSS_PSEUDO_CLASS_SELECTOR@182..204 + 0: COLON@182..184 ":" [Newline("\n")] [] + 1: CSS_BOGUS_PSEUDO_CLASS@184..204 + 0: CSS_IDENTIFIER@184..191 + 0: IDENT@184..191 "slotted" [] [] + 1: L_PAREN@191..192 "(" [] [] + 2: CSS_COMPLEX_SELECTOR@192..204 + 0: CSS_COMPOUND_SELECTOR@192..196 + 0: CSS_NESTED_SELECTOR_LIST@192..192 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@192..196 + 0: CSS_CLASS_SELECTOR@192..196 + 0: DOT@192..193 "." [] [] + 1: CSS_CUSTOM_IDENTIFIER@193..196 + 0: IDENT@193..196 "div" [] [] + 1: CSS_SPACE_LITERAL@196..197 " " [] [] + 2: CSS_COMPOUND_SELECTOR@197..204 + 0: CSS_NESTED_SELECTOR_LIST@197..197 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@197..204 + 0: CSS_CLASS_SELECTOR@197..204 + 0: DOT@197..198 "." [] [] + 1: CSS_CUSTOM_IDENTIFIER@198..204 + 0: IDENT@198..204 "class" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_BLOCK@204..206 + 0: L_CURLY@204..205 "{" [] [] + 1: CSS_DECLARATION_OR_RULE_LIST@205..205 + 2: R_CURLY@205..206 "}" [] [] + 10: CSS_QUALIFIED_RULE@206..228 + 0: CSS_SELECTOR_LIST@206..228 + 0: CSS_COMPOUND_SELECTOR@206..228 + 0: CSS_NESTED_SELECTOR_LIST@206..206 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@206..228 + 0: CSS_PSEUDO_CLASS_SELECTOR@206..228 + 0: COLON@206..208 ":" [Newline("\n")] [] + 1: CSS_BOGUS_PSEUDO_CLASS@208..228 + 0: CSS_IDENTIFIER@208..215 + 0: IDENT@208..215 "slotted" [] [] + 1: L_PAREN@215..216 "(" [] [] + 2: CSS_COMPLEX_SELECTOR@216..228 + 0: CSS_COMPLEX_SELECTOR@216..227 + 0: CSS_COMPOUND_SELECTOR@216..220 + 0: CSS_NESTED_SELECTOR_LIST@216..216 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@216..220 + 0: CSS_CLASS_SELECTOR@216..220 + 0: DOT@216..217 "." [] [] + 1: CSS_CUSTOM_IDENTIFIER@217..220 + 0: IDENT@217..220 "div" [] [] + 1: CSS_SPACE_LITERAL@220..221 " " [] [] + 2: CSS_COMPOUND_SELECTOR@221..227 + 0: CSS_NESTED_SELECTOR_LIST@221..221 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@221..227 + 0: CSS_CLASS_SELECTOR@221..227 + 0: DOT@221..222 "." [] [] + 1: CSS_CUSTOM_IDENTIFIER@222..227 + 0: IDENT@222..227 "class" [] [] + 1: CSS_SPACE_LITERAL@227..228 "\n" [] [] + 2: (empty) + 1: CSS_BOGUS_BLOCK@228..228 + 2: EOF@228..228 "" [] [] + +``` + +## Diagnostics + +``` +pseudo_class_vue_enabled.css:1:8 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected a selector but instead found '{'. + + > 1 │ :deep( {} + │ ^ + 2 │ :deep() {} + 3 │ :deep(.div, .class) {} + + i Expected a selector here. + + > 1 │ :deep( {} + │ ^ + 2 │ :deep() {} + 3 │ :deep(.div, .class) {} + +pseudo_class_vue_enabled.css:2:7 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected a selector but instead found ')'. + + 1 │ :deep( {} + > 2 │ :deep() {} + │ ^ + 3 │ :deep(.div, .class) {} + 4 │ :deep(.div, .class {} + + i Expected a selector here. + + 1 │ :deep( {} + > 2 │ :deep() {} + │ ^ + 3 │ :deep(.div, .class) {} + 4 │ :deep(.div, .class {} + +pseudo_class_vue_enabled.css:3:7 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected a selector but instead found '.div, .class'. + + 1 │ :deep( {} + 2 │ :deep() {} + > 3 │ :deep(.div, .class) {} + │ ^^^^^^^^^^^^ + 4 │ :deep(.div, .class {} + 5 │ :deep(.div .class {} + + i Expected a selector here. + + 1 │ :deep( {} + 2 │ :deep() {} + > 3 │ :deep(.div, .class) {} + │ ^^^^^^^^^^^^ + 4 │ :deep(.div, .class {} + 5 │ :deep(.div .class {} + +pseudo_class_vue_enabled.css:4:7 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected a selector but instead found '.div, .class'. + + 2 │ :deep() {} + 3 │ :deep(.div, .class) {} + > 4 │ :deep(.div, .class {} + │ ^^^^^^^^^^^^ + 5 │ :deep(.div .class {} + 6 │ :deep(.div .class + + i Expected a selector here. + + 2 │ :deep() {} + 3 │ :deep(.div, .class) {} + > 4 │ :deep(.div, .class {} + │ ^^^^^^^^^^^^ + 5 │ :deep(.div .class {} + 6 │ :deep(.div .class + +pseudo_class_vue_enabled.css:4:20 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × expected `)` but instead found `{` + + 2 │ :deep() {} + 3 │ :deep(.div, .class) {} + > 4 │ :deep(.div, .class {} + │ ^ + 5 │ :deep(.div .class {} + 6 │ :deep(.div .class + + i Remove { + +pseudo_class_vue_enabled.css:5:19 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × expected `)` but instead found `{` + + 3 │ :deep(.div, .class) {} + 4 │ :deep(.div, .class {} + > 5 │ :deep(.div .class {} + │ ^ + 6 │ :deep(.div .class + 7 │ :slotted( {} + + i Remove { + +pseudo_class_vue_enabled.css:7:11 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected a selector but instead found '{'. + + 5 │ :deep(.div .class {} + 6 │ :deep(.div .class + > 7 │ :slotted( {} + │ ^ + 8 │ :slotted() {} + 9 │ :slotted(.div, .class) {} + + i Expected a selector here. + + 5 │ :deep(.div .class {} + 6 │ :deep(.div .class + > 7 │ :slotted( {} + │ ^ + 8 │ :slotted() {} + 9 │ :slotted(.div, .class) {} + +pseudo_class_vue_enabled.css:8:10 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected a selector but instead found ')'. + + 6 │ :deep(.div .class + 7 │ :slotted( {} + > 8 │ :slotted() {} + │ ^ + 9 │ :slotted(.div, .class) {} + 10 │ :slotted(.div, .class {} + + i Expected a selector here. + + 6 │ :deep(.div .class + 7 │ :slotted( {} + > 8 │ :slotted() {} + │ ^ + 9 │ :slotted(.div, .class) {} + 10 │ :slotted(.div, .class {} + +pseudo_class_vue_enabled.css:9:10 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected a selector but instead found '.div, .class'. + + 7 │ :slotted( {} + 8 │ :slotted() {} + > 9 │ :slotted(.div, .class) {} + │ ^^^^^^^^^^^^ + 10 │ :slotted(.div, .class {} + 11 │ :slotted(.div .class {} + + i Expected a selector here. + + 7 │ :slotted( {} + 8 │ :slotted() {} + > 9 │ :slotted(.div, .class) {} + │ ^^^^^^^^^^^^ + 10 │ :slotted(.div, .class {} + 11 │ :slotted(.div .class {} + +pseudo_class_vue_enabled.css:10:10 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected a selector but instead found '.div, .class'. + + 8 │ :slotted() {} + 9 │ :slotted(.div, .class) {} + > 10 │ :slotted(.div, .class {} + │ ^^^^^^^^^^^^ + 11 │ :slotted(.div .class {} + 12 │ :slotted(.div .class + + i Expected a selector here. + + 8 │ :slotted() {} + 9 │ :slotted(.div, .class) {} + > 10 │ :slotted(.div, .class {} + │ ^^^^^^^^^^^^ + 11 │ :slotted(.div .class {} + 12 │ :slotted(.div .class + +pseudo_class_vue_enabled.css:10:23 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × expected `)` but instead found `{` + + 8 │ :slotted() {} + 9 │ :slotted(.div, .class) {} + > 10 │ :slotted(.div, .class {} + │ ^ + 11 │ :slotted(.div .class {} + 12 │ :slotted(.div .class + + i Remove { + +pseudo_class_vue_enabled.css:11:22 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × expected `)` but instead found `{` + + 9 │ :slotted(.div, .class) {} + 10 │ :slotted(.div, .class {} + > 11 │ :slotted(.div .class {} + │ ^ + 12 │ :slotted(.div .class + 13 │ + + i Remove { + +pseudo_class_vue_enabled.css:13:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected a compound selector but instead found the end of the file. + + 11 │ :slotted(.div .class {} + 12 │ :slotted(.div .class + > 13 │ + │ + + i Expected a compound selector here. + + 11 │ :slotted(.div .class {} + 12 │ :slotted(.div .class + > 13 │ + │ + +``` diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_vue/options.json b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_vue/options.json new file mode 100644 index 000000000000..5ab11d31c477 --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_vue/options.json @@ -0,0 +1,8 @@ +{ + "$schema": "../../../../../../../../packages/@biomejs/biome/configuration_schema.json", + "css": { + "parser": { + "vueScopedCss": true + } + } +} diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_vue/pseudo_class_vue.css b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_vue/pseudo_class_vue.css new file mode 100644 index 000000000000..98a3afe330a4 --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_vue/pseudo_class_vue.css @@ -0,0 +1,2 @@ +.a :deep(.b) { color: red; } +.a :slotted(.b) { color: red; } diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_vue/pseudo_class_vue.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_vue/pseudo_class_vue.css.snap new file mode 100644 index 000000000000..a62e4caf8022 --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_vue/pseudo_class_vue.css.snap @@ -0,0 +1,266 @@ +--- +source: crates/biome_css_parser/tests/spec_test.rs +expression: snapshot +--- + +## Input + +```css +.a :deep(.b) { color: red; } +.a :slotted(.b) { color: red; } + +``` + + +## AST + +``` +CssRoot { + bom_token: missing (optional), + rules: CssRuleList [ + CssQualifiedRule { + prelude: CssSelectorList [ + CssComplexSelector { + left: CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssClassSelector { + dot_token: DOT@0..1 "." [] [], + name: CssCustomIdentifier { + value_token: IDENT@1..2 "a" [] [], + }, + }, + ], + }, + combinator: CSS_SPACE_LITERAL@2..3 " " [] [], + right: CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssPseudoClassSelector { + colon_token: COLON@3..4 ":" [] [], + class: CssPseudoClassFunctionSelector { + name: CssIdentifier { + value_token: IDENT@4..8 "deep" [] [], + }, + l_paren_token: L_PAREN@8..9 "(" [] [], + selector: CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssClassSelector { + dot_token: DOT@9..10 "." [] [], + name: CssCustomIdentifier { + value_token: IDENT@10..11 "b" [] [], + }, + }, + ], + }, + r_paren_token: R_PAREN@11..13 ")" [] [Whitespace(" ")], + }, + }, + ], + }, + }, + ], + block: CssDeclarationOrRuleBlock { + l_curly_token: L_CURLY@13..15 "{" [] [Whitespace(" ")], + items: CssDeclarationOrRuleList [ + CssDeclarationWithSemicolon { + declaration: CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@15..20 "color" [] [], + }, + colon_token: COLON@20..22 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@22..25 "red" [] [], + }, + ], + }, + important: missing (optional), + }, + semicolon_token: SEMICOLON@25..27 ";" [] [Whitespace(" ")], + }, + ], + r_curly_token: R_CURLY@27..28 "}" [] [], + }, + }, + CssQualifiedRule { + prelude: CssSelectorList [ + CssComplexSelector { + left: CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssClassSelector { + dot_token: DOT@28..30 "." [Newline("\n")] [], + name: CssCustomIdentifier { + value_token: IDENT@30..31 "a" [] [], + }, + }, + ], + }, + combinator: CSS_SPACE_LITERAL@31..32 " " [] [], + right: CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssPseudoClassSelector { + colon_token: COLON@32..33 ":" [] [], + class: CssPseudoClassFunctionSelector { + name: CssIdentifier { + value_token: IDENT@33..40 "slotted" [] [], + }, + l_paren_token: L_PAREN@40..41 "(" [] [], + selector: CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: missing (optional), + sub_selectors: CssSubSelectorList [ + CssClassSelector { + dot_token: DOT@41..42 "." [] [], + name: CssCustomIdentifier { + value_token: IDENT@42..43 "b" [] [], + }, + }, + ], + }, + r_paren_token: R_PAREN@43..45 ")" [] [Whitespace(" ")], + }, + }, + ], + }, + }, + ], + block: CssDeclarationOrRuleBlock { + l_curly_token: L_CURLY@45..47 "{" [] [Whitespace(" ")], + items: CssDeclarationOrRuleList [ + CssDeclarationWithSemicolon { + declaration: CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@47..52 "color" [] [], + }, + colon_token: COLON@52..54 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@54..57 "red" [] [], + }, + ], + }, + important: missing (optional), + }, + semicolon_token: SEMICOLON@57..59 ";" [] [Whitespace(" ")], + }, + ], + r_curly_token: R_CURLY@59..60 "}" [] [], + }, + }, + ], + eof_token: EOF@60..61 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: CSS_ROOT@0..61 + 0: (empty) + 1: CSS_RULE_LIST@0..60 + 0: CSS_QUALIFIED_RULE@0..28 + 0: CSS_SELECTOR_LIST@0..13 + 0: CSS_COMPLEX_SELECTOR@0..13 + 0: CSS_COMPOUND_SELECTOR@0..2 + 0: CSS_NESTED_SELECTOR_LIST@0..0 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@0..2 + 0: CSS_CLASS_SELECTOR@0..2 + 0: DOT@0..1 "." [] [] + 1: CSS_CUSTOM_IDENTIFIER@1..2 + 0: IDENT@1..2 "a" [] [] + 1: CSS_SPACE_LITERAL@2..3 " " [] [] + 2: CSS_COMPOUND_SELECTOR@3..13 + 0: CSS_NESTED_SELECTOR_LIST@3..3 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@3..13 + 0: CSS_PSEUDO_CLASS_SELECTOR@3..13 + 0: COLON@3..4 ":" [] [] + 1: CSS_PSEUDO_CLASS_FUNCTION_SELECTOR@4..13 + 0: CSS_IDENTIFIER@4..8 + 0: IDENT@4..8 "deep" [] [] + 1: L_PAREN@8..9 "(" [] [] + 2: CSS_COMPOUND_SELECTOR@9..11 + 0: CSS_NESTED_SELECTOR_LIST@9..9 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@9..11 + 0: CSS_CLASS_SELECTOR@9..11 + 0: DOT@9..10 "." [] [] + 1: CSS_CUSTOM_IDENTIFIER@10..11 + 0: IDENT@10..11 "b" [] [] + 3: R_PAREN@11..13 ")" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_BLOCK@13..28 + 0: L_CURLY@13..15 "{" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_LIST@15..27 + 0: CSS_DECLARATION_WITH_SEMICOLON@15..27 + 0: CSS_DECLARATION@15..25 + 0: CSS_GENERIC_PROPERTY@15..25 + 0: CSS_IDENTIFIER@15..20 + 0: IDENT@15..20 "color" [] [] + 1: COLON@20..22 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@22..25 + 0: CSS_IDENTIFIER@22..25 + 0: IDENT@22..25 "red" [] [] + 1: (empty) + 1: SEMICOLON@25..27 ";" [] [Whitespace(" ")] + 2: R_CURLY@27..28 "}" [] [] + 1: CSS_QUALIFIED_RULE@28..60 + 0: CSS_SELECTOR_LIST@28..45 + 0: CSS_COMPLEX_SELECTOR@28..45 + 0: CSS_COMPOUND_SELECTOR@28..31 + 0: CSS_NESTED_SELECTOR_LIST@28..28 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@28..31 + 0: CSS_CLASS_SELECTOR@28..31 + 0: DOT@28..30 "." [Newline("\n")] [] + 1: CSS_CUSTOM_IDENTIFIER@30..31 + 0: IDENT@30..31 "a" [] [] + 1: CSS_SPACE_LITERAL@31..32 " " [] [] + 2: CSS_COMPOUND_SELECTOR@32..45 + 0: CSS_NESTED_SELECTOR_LIST@32..32 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@32..45 + 0: CSS_PSEUDO_CLASS_SELECTOR@32..45 + 0: COLON@32..33 ":" [] [] + 1: CSS_PSEUDO_CLASS_FUNCTION_SELECTOR@33..45 + 0: CSS_IDENTIFIER@33..40 + 0: IDENT@33..40 "slotted" [] [] + 1: L_PAREN@40..41 "(" [] [] + 2: CSS_COMPOUND_SELECTOR@41..43 + 0: CSS_NESTED_SELECTOR_LIST@41..41 + 1: (empty) + 2: CSS_SUB_SELECTOR_LIST@41..43 + 0: CSS_CLASS_SELECTOR@41..43 + 0: DOT@41..42 "." [] [] + 1: CSS_CUSTOM_IDENTIFIER@42..43 + 0: IDENT@42..43 "b" [] [] + 3: R_PAREN@43..45 ")" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_BLOCK@45..60 + 0: L_CURLY@45..47 "{" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_LIST@47..59 + 0: CSS_DECLARATION_WITH_SEMICOLON@47..59 + 0: CSS_DECLARATION@47..57 + 0: CSS_GENERIC_PROPERTY@47..57 + 0: CSS_IDENTIFIER@47..52 + 0: IDENT@47..52 "color" [] [] + 1: COLON@52..54 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@54..57 + 0: CSS_IDENTIFIER@54..57 + 0: IDENT@54..57 "red" [] [] + 1: (empty) + 1: SEMICOLON@57..59 ";" [] [Whitespace(" ")] + 2: R_CURLY@59..60 "}" [] [] + 2: EOF@60..61 "" [Newline("\n")] [] + +``` diff --git a/crates/biome_css_parser/tests/spec_test.rs b/crates/biome_css_parser/tests/spec_test.rs index 986ebfe33de9..378f62a7bd0e 100644 --- a/crates/biome_css_parser/tests/spec_test.rs +++ b/crates/biome_css_parser/tests/spec_test.rs @@ -75,6 +75,10 @@ pub fn run(test_case: &str, _snapshot_name: &str, test_directory: &str, outcome_ options = options.allow_tailwind_directives(); } + if settings.vue_scoped_css_enabled() { + options = options.allow_vue_scoped_css(); + } + if !diagnostics.is_empty() { for diagnostic in diagnostics { println!("{:?}", print_diagnostic_to_string(&diagnostic)); diff --git a/crates/biome_css_syntax/src/generated/kind.rs b/crates/biome_css_syntax/src/generated/kind.rs index 893053e0846b..6c8aff70b974 100644 --- a/crates/biome_css_syntax/src/generated/kind.rs +++ b/crates/biome_css_syntax/src/generated/kind.rs @@ -139,6 +139,8 @@ pub enum CssSyntaxKind { PLUGIN_KW, SLOT_KW, INLINE_KW, + DEEP_KW, + SLOTTED_KW, INITIAL_KW, INHERIT_KW, UNSET_KW, @@ -748,6 +750,8 @@ impl CssSyntaxKind { "plugin" => PLUGIN_KW, "slot" => SLOT_KW, "inline" => INLINE_KW, + "deep" => DEEP_KW, + "slotted" => SLOTTED_KW, "initial" => INITIAL_KW, "inherit" => INHERIT_KW, "unset" => UNSET_KW, @@ -990,6 +994,8 @@ impl CssSyntaxKind { PLUGIN_KW => "plugin", SLOT_KW => "slot", INLINE_KW => "inline", + DEEP_KW => "deep", + SLOTTED_KW => "slotted", INITIAL_KW => "initial", INHERIT_KW => "inherit", UNSET_KW => "unset", @@ -1108,4 +1114,4 @@ impl CssSyntaxKind { } #[doc = r" Utility macro for creating a SyntaxKind through simple macro syntax"] #[macro_export] -macro_rules ! T { [;] => { $ crate :: CssSyntaxKind :: SEMICOLON } ; [,] => { $ crate :: CssSyntaxKind :: COMMA } ; ['('] => { $ crate :: CssSyntaxKind :: L_PAREN } ; [')'] => { $ crate :: CssSyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: CssSyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: CssSyntaxKind :: R_CURLY } ; ['['] => { $ crate :: CssSyntaxKind :: L_BRACK } ; [']'] => { $ crate :: CssSyntaxKind :: R_BRACK } ; [<] => { $ crate :: CssSyntaxKind :: L_ANGLE } ; [>] => { $ crate :: CssSyntaxKind :: R_ANGLE } ; [~] => { $ crate :: CssSyntaxKind :: TILDE } ; [#] => { $ crate :: CssSyntaxKind :: HASH } ; [&] => { $ crate :: CssSyntaxKind :: AMP } ; [|] => { $ crate :: CssSyntaxKind :: PIPE } ; [||] => { $ crate :: CssSyntaxKind :: PIPE2 } ; [+] => { $ crate :: CssSyntaxKind :: PLUS } ; [*] => { $ crate :: CssSyntaxKind :: STAR } ; [/] => { $ crate :: CssSyntaxKind :: SLASH } ; [^] => { $ crate :: CssSyntaxKind :: CARET } ; [%] => { $ crate :: CssSyntaxKind :: PERCENT } ; [.] => { $ crate :: CssSyntaxKind :: DOT } ; [:] => { $ crate :: CssSyntaxKind :: COLON } ; [::] => { $ crate :: CssSyntaxKind :: COLON2 } ; [=] => { $ crate :: CssSyntaxKind :: EQ } ; [!] => { $ crate :: CssSyntaxKind :: BANG } ; [!=] => { $ crate :: CssSyntaxKind :: NEQ } ; [-] => { $ crate :: CssSyntaxKind :: MINUS } ; [<=] => { $ crate :: CssSyntaxKind :: LTEQ } ; [>=] => { $ crate :: CssSyntaxKind :: GTEQ } ; [+=] => { $ crate :: CssSyntaxKind :: PLUSEQ } ; [|=] => { $ crate :: CssSyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: CssSyntaxKind :: AMPEQ } ; [^=] => { $ crate :: CssSyntaxKind :: CARETEQ } ; [/=] => { $ crate :: CssSyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: CssSyntaxKind :: STAREQ } ; [%=] => { $ crate :: CssSyntaxKind :: PERCENTEQ } ; [@] => { $ crate :: CssSyntaxKind :: AT } ; ["$="] => { $ crate :: CssSyntaxKind :: DOLLAR_EQ } ; [~=] => { $ crate :: CssSyntaxKind :: TILDE_EQ } ; [-->] => { $ crate :: CssSyntaxKind :: CDC } ; [] => { $ crate :: CssSyntaxKind :: CDC } ; [