From 0638d150c08f246af2546735afcc897f2d9e904e Mon Sep 17 00:00:00 2001 From: togami <togami2864@gmail.com> Date: Sun, 1 Dec 2024 23:02:08 +0900 Subject: [PATCH 01/12] chore: init rule --- .../src/analyzer/linter/rules.rs | 137 ++++++++++-------- crates/biome_css_analyze/src/lint/nursery.rs | 2 + .../src/lint/nursery/no_unknown_at_rule.rs | 73 ++++++++++ crates/biome_css_analyze/src/options.rs | 2 + .../specs/nursery/noUnknownAtRule/invalid.css | 3 + .../specs/nursery/noUnknownAtRule/valid.css | 2 + .../src/categories.rs | 5 +- .../@biomejs/backend-jsonrpc/src/workspace.ts | 9 +- .../@biomejs/biome/configuration_schema.json | 7 + 9 files changed, 177 insertions(+), 63 deletions(-) create mode 100644 crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css diff --git a/crates/biome_configuration/src/analyzer/linter/rules.rs b/crates/biome_configuration/src/analyzer/linter/rules.rs index 08f5da401271..cd9c232477f5 100644 --- a/crates/biome_configuration/src/analyzer/linter/rules.rs +++ b/crates/biome_configuration/src/analyzer/linter/rules.rs @@ -3365,6 +3365,9 @@ pub struct Nursery { #[serde(skip_serializing_if = "Option::is_none")] pub no_template_curly_in_string: Option<RuleConfiguration<biome_js_analyze::options::NoTemplateCurlyInString>>, + #[doc = "Succinct description of the rule."] + #[serde(skip_serializing_if = "Option::is_none")] + pub no_unknown_at_rule: Option<RuleConfiguration<biome_css_analyze::options::NoUnknownAtRule>>, #[doc = "Disallow unknown pseudo-class selectors."] #[serde(skip_serializing_if = "Option::is_none")] pub no_unknown_pseudo_class: @@ -3510,6 +3513,7 @@ impl Nursery { "noStaticElementInteractions", "noSubstr", "noTemplateCurlyInString", + "noUnknownAtRule", "noUnknownPseudoClass", "noUnknownPseudoElement", "noUnknownTypeSelector", @@ -3562,15 +3566,15 @@ impl Nursery { RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[6]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[7]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[16]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[27]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[29]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[34]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[39]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[30]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[35]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[40]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[47]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[50]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[41]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[48]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[51]), ]; const ALL_RULES_AS_FILTERS: &'static [RuleFilter<'static>] = &[ RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[0]), @@ -3626,6 +3630,7 @@ impl Nursery { RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[50]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[51]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[52]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[53]), ]; #[doc = r" Retrieves the recommended rules"] pub(crate) fn is_recommended_true(&self) -> bool { @@ -3772,141 +3777,146 @@ impl Nursery { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[25])); } } - if let Some(rule) = self.no_unknown_pseudo_class.as_ref() { + if let Some(rule) = self.no_unknown_at_rule.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26])); } } - if let Some(rule) = self.no_unknown_pseudo_element.as_ref() { + if let Some(rule) = self.no_unknown_pseudo_class.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[27])); } } - if let Some(rule) = self.no_unknown_type_selector.as_ref() { + if let Some(rule) = self.no_unknown_pseudo_element.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28])); } } - if let Some(rule) = self.no_useless_escape_in_regex.as_ref() { + if let Some(rule) = self.no_unknown_type_selector.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[29])); } } - if let Some(rule) = self.no_useless_string_raw.as_ref() { + if let Some(rule) = self.no_useless_escape_in_regex.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[30])); } } - if let Some(rule) = self.no_useless_undefined.as_ref() { + if let Some(rule) = self.no_useless_string_raw.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[31])); } } - if let Some(rule) = self.no_value_at_rule.as_ref() { + if let Some(rule) = self.no_useless_undefined.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[32])); } } - if let Some(rule) = self.use_adjacent_overload_signatures.as_ref() { + if let Some(rule) = self.no_value_at_rule.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[33])); } } - if let Some(rule) = self.use_aria_props_supported_by_role.as_ref() { + if let Some(rule) = self.use_adjacent_overload_signatures.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[34])); } } - if let Some(rule) = self.use_at_index.as_ref() { + if let Some(rule) = self.use_aria_props_supported_by_role.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[35])); } } - if let Some(rule) = self.use_collapsed_if.as_ref() { + if let Some(rule) = self.use_at_index.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[36])); } } - if let Some(rule) = self.use_component_export_only_modules.as_ref() { + if let Some(rule) = self.use_collapsed_if.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[37])); } } - if let Some(rule) = self.use_consistent_curly_braces.as_ref() { + if let Some(rule) = self.use_component_export_only_modules.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[38])); } } - if let Some(rule) = self.use_consistent_member_accessibility.as_ref() { + if let Some(rule) = self.use_consistent_curly_braces.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[39])); } } - if let Some(rule) = self.use_deprecated_reason.as_ref() { + if let Some(rule) = self.use_consistent_member_accessibility.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[40])); } } - if let Some(rule) = self.use_explicit_type.as_ref() { + if let Some(rule) = self.use_deprecated_reason.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[41])); } } - if let Some(rule) = self.use_exports_last.as_ref() { + if let Some(rule) = self.use_explicit_type.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[42])); } } - if let Some(rule) = self.use_google_font_display.as_ref() { + if let Some(rule) = self.use_exports_last.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[43])); } } - if let Some(rule) = self.use_google_font_preconnect.as_ref() { + if let Some(rule) = self.use_google_font_display.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[44])); } } - if let Some(rule) = self.use_guard_for_in.as_ref() { + if let Some(rule) = self.use_google_font_preconnect.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[45])); } } - if let Some(rule) = self.use_import_restrictions.as_ref() { + if let Some(rule) = self.use_guard_for_in.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[46])); } } - if let Some(rule) = self.use_named_operation.as_ref() { + if let Some(rule) = self.use_import_restrictions.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[47])); } } - if let Some(rule) = self.use_naming_convention.as_ref() { + if let Some(rule) = self.use_named_operation.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[48])); } } - if let Some(rule) = self.use_sorted_classes.as_ref() { + if let Some(rule) = self.use_naming_convention.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[49])); } } - if let Some(rule) = self.use_strict_mode.as_ref() { + if let Some(rule) = self.use_sorted_classes.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[50])); } } - if let Some(rule) = self.use_trim_start_end.as_ref() { + if let Some(rule) = self.use_strict_mode.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[51])); } } - if let Some(rule) = self.use_valid_autocomplete.as_ref() { + if let Some(rule) = self.use_trim_start_end.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[52])); } } + if let Some(rule) = self.use_valid_autocomplete.as_ref() { + if rule.is_enabled() { + index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[53])); + } + } index_set } pub(crate) fn get_disabled_rules(&self) -> FxHashSet<RuleFilter<'static>> { @@ -4041,141 +4051,146 @@ impl Nursery { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[25])); } } - if let Some(rule) = self.no_unknown_pseudo_class.as_ref() { + if let Some(rule) = self.no_unknown_at_rule.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26])); } } - if let Some(rule) = self.no_unknown_pseudo_element.as_ref() { + if let Some(rule) = self.no_unknown_pseudo_class.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[27])); } } - if let Some(rule) = self.no_unknown_type_selector.as_ref() { + if let Some(rule) = self.no_unknown_pseudo_element.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28])); } } - if let Some(rule) = self.no_useless_escape_in_regex.as_ref() { + if let Some(rule) = self.no_unknown_type_selector.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[29])); } } - if let Some(rule) = self.no_useless_string_raw.as_ref() { + if let Some(rule) = self.no_useless_escape_in_regex.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[30])); } } - if let Some(rule) = self.no_useless_undefined.as_ref() { + if let Some(rule) = self.no_useless_string_raw.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[31])); } } - if let Some(rule) = self.no_value_at_rule.as_ref() { + if let Some(rule) = self.no_useless_undefined.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[32])); } } - if let Some(rule) = self.use_adjacent_overload_signatures.as_ref() { + if let Some(rule) = self.no_value_at_rule.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[33])); } } - if let Some(rule) = self.use_aria_props_supported_by_role.as_ref() { + if let Some(rule) = self.use_adjacent_overload_signatures.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[34])); } } - if let Some(rule) = self.use_at_index.as_ref() { + if let Some(rule) = self.use_aria_props_supported_by_role.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[35])); } } - if let Some(rule) = self.use_collapsed_if.as_ref() { + if let Some(rule) = self.use_at_index.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[36])); } } - if let Some(rule) = self.use_component_export_only_modules.as_ref() { + if let Some(rule) = self.use_collapsed_if.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[37])); } } - if let Some(rule) = self.use_consistent_curly_braces.as_ref() { + if let Some(rule) = self.use_component_export_only_modules.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[38])); } } - if let Some(rule) = self.use_consistent_member_accessibility.as_ref() { + if let Some(rule) = self.use_consistent_curly_braces.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[39])); } } - if let Some(rule) = self.use_deprecated_reason.as_ref() { + if let Some(rule) = self.use_consistent_member_accessibility.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[40])); } } - if let Some(rule) = self.use_explicit_type.as_ref() { + if let Some(rule) = self.use_deprecated_reason.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[41])); } } - if let Some(rule) = self.use_exports_last.as_ref() { + if let Some(rule) = self.use_explicit_type.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[42])); } } - if let Some(rule) = self.use_google_font_display.as_ref() { + if let Some(rule) = self.use_exports_last.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[43])); } } - if let Some(rule) = self.use_google_font_preconnect.as_ref() { + if let Some(rule) = self.use_google_font_display.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[44])); } } - if let Some(rule) = self.use_guard_for_in.as_ref() { + if let Some(rule) = self.use_google_font_preconnect.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[45])); } } - if let Some(rule) = self.use_import_restrictions.as_ref() { + if let Some(rule) = self.use_guard_for_in.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[46])); } } - if let Some(rule) = self.use_named_operation.as_ref() { + if let Some(rule) = self.use_import_restrictions.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[47])); } } - if let Some(rule) = self.use_naming_convention.as_ref() { + if let Some(rule) = self.use_named_operation.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[48])); } } - if let Some(rule) = self.use_sorted_classes.as_ref() { + if let Some(rule) = self.use_naming_convention.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[49])); } } - if let Some(rule) = self.use_strict_mode.as_ref() { + if let Some(rule) = self.use_sorted_classes.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[50])); } } - if let Some(rule) = self.use_trim_start_end.as_ref() { + if let Some(rule) = self.use_strict_mode.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[51])); } } - if let Some(rule) = self.use_valid_autocomplete.as_ref() { + if let Some(rule) = self.use_trim_start_end.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[52])); } } + if let Some(rule) = self.use_valid_autocomplete.as_ref() { + if rule.is_disabled() { + index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[53])); + } + } index_set } #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"] @@ -4316,6 +4331,10 @@ impl Nursery { .no_template_curly_in_string .as_ref() .map(|conf| (conf.level(), conf.get_options())), + "noUnknownAtRule" => self + .no_unknown_at_rule + .as_ref() + .map(|conf| (conf.level(), conf.get_options())), "noUnknownPseudoClass" => self .no_unknown_pseudo_class .as_ref() diff --git a/crates/biome_css_analyze/src/lint/nursery.rs b/crates/biome_css_analyze/src/lint/nursery.rs index 6d16b3056165..b816124eb3c4 100644 --- a/crates/biome_css_analyze/src/lint/nursery.rs +++ b/crates/biome_css_analyze/src/lint/nursery.rs @@ -7,6 +7,7 @@ pub mod no_duplicate_custom_properties; pub mod no_duplicate_properties; pub mod no_irregular_whitespace; pub mod no_missing_var_function; +pub mod no_unknown_at_rule; pub mod no_unknown_pseudo_class; pub mod no_unknown_pseudo_element; pub mod no_unknown_type_selector; @@ -21,6 +22,7 @@ declare_lint_group! { self :: no_duplicate_properties :: NoDuplicateProperties , self :: no_irregular_whitespace :: NoIrregularWhitespace , self :: no_missing_var_function :: NoMissingVarFunction , + self :: no_unknown_at_rule :: NoUnknownAtRule , self :: no_unknown_pseudo_class :: NoUnknownPseudoClass , self :: no_unknown_pseudo_element :: NoUnknownPseudoElement , self :: no_unknown_type_selector :: NoUnknownTypeSelector , diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs new file mode 100644 index 000000000000..d1d0b69cf2a5 --- /dev/null +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs @@ -0,0 +1,73 @@ +use biome_analyze::{context::RuleContext, declare_lint_rule, Ast, Rule, RuleDiagnostic}; +use biome_console::markup; +use biome_css_syntax::CssDeclarationOrRuleBlock; +use biome_rowan::AstNode; + +declare_lint_rule! { + /// Succinct description of the rule. + /// + /// Put context and details about the rule. + /// As a starting point, you can take the description of the corresponding _ESLint_ rule (if any). + /// + /// Try to stay consistent with the descriptions of implemented rules. + /// + /// Add a link to the corresponding stylelint rule (if any): + /// + /// ## Examples + /// + /// ### Invalid + /// + /// ```css,expect_diagnostic + /// p {} + /// ``` + /// + /// ### Valid + /// + /// ```css + /// p { + /// color: red; + /// } + /// ``` + /// + pub NoUnknownAtRule { + version: "next", + name: "noUnknownAtRule", + language: "css", + recommended: false, + } +} + +impl Rule for NoUnknownAtRule { + type Query = Ast<CssDeclarationOrRuleBlock>; + type State = CssDeclarationOrRuleBlock; + type Signals = Option<Self::State>; + type Options = (); + + fn run(ctx: &RuleContext<Self>) -> Option<Self::State> { + let node = ctx.query(); + if node.items().into_iter().next().is_none() { + return Some(node.clone()); + } + None + } + + fn diagnostic(_: &RuleContext<Self>, node: &Self::State) -> Option<RuleDiagnostic> { + // + // Read our guidelines to write great diagnostics: + // https://docs.rs/biome_analyze/latest/biome_analyze/#what-a-rule-should-say-to-the-user + // + let span = node.range(); + Some( + RuleDiagnostic::new( + rule_category!(), + span, + markup! { + "Unexpected empty block is not allowed" + }, + ) + .note(markup! { + "This note will give you more information." + }), + ) + } +} diff --git a/crates/biome_css_analyze/src/options.rs b/crates/biome_css_analyze/src/options.rs index 2edbb3a490ae..069d6c5acdf5 100644 --- a/crates/biome_css_analyze/src/options.rs +++ b/crates/biome_css_analyze/src/options.rs @@ -21,6 +21,8 @@ pub type NoIrregularWhitespace = pub type NoMissingVarFunction = <lint::nursery::no_missing_var_function::NoMissingVarFunction as biome_analyze::Rule>::Options; pub type NoShorthandPropertyOverrides = < lint :: suspicious :: no_shorthand_property_overrides :: NoShorthandPropertyOverrides as biome_analyze :: Rule > :: Options ; +pub type NoUnknownAtRule = + <lint::nursery::no_unknown_at_rule::NoUnknownAtRule as biome_analyze::Rule>::Options; pub type NoUnknownFunction = <lint::correctness::no_unknown_function::NoUnknownFunction as biome_analyze::Rule>::Options; pub type NoUnknownMediaFeatureName = < lint :: correctness :: no_unknown_media_feature_name :: NoUnknownMediaFeatureName as biome_analyze :: Rule > :: Options ; diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css new file mode 100644 index 000000000000..d58e4390e601 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css @@ -0,0 +1,3 @@ +var a = 1; +a = 2; +a = 3; \ No newline at end of file diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css new file mode 100644 index 000000000000..f299f876959a --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css @@ -0,0 +1,2 @@ +/* should not generate diagnostics */ +// var a = 1; \ No newline at end of file diff --git a/crates/biome_diagnostics_categories/src/categories.rs b/crates/biome_diagnostics_categories/src/categories.rs index 85a71c6d1024..943b39285873 100644 --- a/crates/biome_diagnostics_categories/src/categories.rs +++ b/crates/biome_diagnostics_categories/src/categories.rs @@ -157,7 +157,6 @@ define_categories! { "lint/nursery/noInvalidGridAreas": "https://biomejs.dev/linter/rules/use-consistent-grid-areas", "lint/nursery/noInvalidPositionAtImportRule": "https://biomejs.dev/linter/rules/no-invalid-position-at-import-rule", "lint/nursery/noIrregularWhitespace": "https://biomejs.dev/linter/rules/no-irregular-whitespace", - "lint/nursery/useNamingConvention": "https://biomejs.dev/linter/rules/use-naming-convention", "lint/nursery/noMissingGenericFamilyKeyword": "https://biomejs.dev/linter/rules/no-missing-generic-family-keyword", "lint/nursery/noMissingVarFunction": "https://biomejs.dev/linter/rules/no-missing-var-function", "lint/nursery/noNestedTernary": "https://biomejs.dev/linter/rules/no-nested-ternary", @@ -172,6 +171,7 @@ define_categories! { "lint/nursery/noSubstr": "https://biomejs.dev/linter/rules/no-substr", "lint/nursery/noTemplateCurlyInString": "https://biomejs.dev/linter/rules/no-template-curly-in-string", "lint/nursery/noUndeclaredDependencies": "https://biomejs.dev/linter/rules/no-undeclared-dependencies", + "lint/nursery/noUnknownAtRule": "https://biomejs.dev/linter/rules/no-unknown-at-rule", "lint/nursery/noUnknownFunction": "https://biomejs.dev/linter/rules/no-unknown-function", "lint/nursery/noUnknownMediaFeatureName": "https://biomejs.dev/linter/rules/no-unknown-media-feature-name", "lint/nursery/noUnknownProperty": "https://biomejs.dev/linter/rules/no-unknown-property", @@ -198,13 +198,14 @@ define_categories! { "lint/nursery/useDeprecatedReason": "https://biomejs.dev/linter/rules/use-deprecated-reason", "lint/nursery/useExplicitFunctionReturnType": "https://biomejs.dev/linter/rules/use-explicit-function-return-type", "lint/nursery/useExplicitType": "https://biomejs.dev/linter/rules/use-explicit-function-return-type", + "lint/nursery/useExportsLast": "https://biomejs.dev/linter/rules/use-exports-last", "lint/nursery/useGoogleFontDisplay": "https://biomejs.dev/linter/rules/use-google-font-display", "lint/nursery/useGoogleFontPreconnect": "https://biomejs.dev/linter/rules/use-google-font-preconnect", - "lint/nursery/useExportsLast": "https://biomejs.dev/linter/rules/use-exports-last", "lint/nursery/useGuardForIn": "https://biomejs.dev/linter/rules/use-guard-for-in", "lint/nursery/useImportRestrictions": "https://biomejs.dev/linter/rules/use-import-restrictions", "lint/nursery/useJsxCurlyBraceConvention": "https://biomejs.dev/linter/rules/use-jsx-curly-brace-convention", "lint/nursery/useNamedOperation": "https://biomejs.dev/linter/rules/use-named-operation", + "lint/nursery/useNamingConvention": "https://biomejs.dev/linter/rules/use-naming-convention", "lint/nursery/useSortedClasses": "https://biomejs.dev/linter/rules/use-sorted-classes", "lint/nursery/useStrictMode": "https://biomejs.dev/linter/rules/use-strict-mode", "lint/nursery/useTrimStartEnd": "https://biomejs.dev/linter/rules/use-trim-start-end", diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index 77c49ed39316..a35172da9f70 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -1330,6 +1330,10 @@ export interface Nursery { * Disallow template literal placeholder syntax in regular strings. */ noTemplateCurlyInString?: RuleConfiguration_for_Null; + /** + * Succinct description of the rule. + */ + noUnknownAtRule?: RuleConfiguration_for_Null; /** * Disallow unknown pseudo-class selectors. */ @@ -3097,7 +3101,6 @@ export type Category = | "lint/nursery/noInvalidGridAreas" | "lint/nursery/noInvalidPositionAtImportRule" | "lint/nursery/noIrregularWhitespace" - | "lint/nursery/useNamingConvention" | "lint/nursery/noMissingGenericFamilyKeyword" | "lint/nursery/noMissingVarFunction" | "lint/nursery/noNestedTernary" @@ -3112,6 +3115,7 @@ export type Category = | "lint/nursery/noSubstr" | "lint/nursery/noTemplateCurlyInString" | "lint/nursery/noUndeclaredDependencies" + | "lint/nursery/noUnknownAtRule" | "lint/nursery/noUnknownFunction" | "lint/nursery/noUnknownMediaFeatureName" | "lint/nursery/noUnknownProperty" @@ -3138,13 +3142,14 @@ export type Category = | "lint/nursery/useDeprecatedReason" | "lint/nursery/useExplicitFunctionReturnType" | "lint/nursery/useExplicitType" + | "lint/nursery/useExportsLast" | "lint/nursery/useGoogleFontDisplay" | "lint/nursery/useGoogleFontPreconnect" - | "lint/nursery/useExportsLast" | "lint/nursery/useGuardForIn" | "lint/nursery/useImportRestrictions" | "lint/nursery/useJsxCurlyBraceConvention" | "lint/nursery/useNamedOperation" + | "lint/nursery/useNamingConvention" | "lint/nursery/useSortedClasses" | "lint/nursery/useStrictMode" | "lint/nursery/useTrimStartEnd" diff --git a/packages/@biomejs/biome/configuration_schema.json b/packages/@biomejs/biome/configuration_schema.json index 1a24ccabcbec..c71f616bb943 100644 --- a/packages/@biomejs/biome/configuration_schema.json +++ b/packages/@biomejs/biome/configuration_schema.json @@ -2372,6 +2372,13 @@ { "type": "null" } ] }, + "noUnknownAtRule": { + "description": "Succinct description of the rule.", + "anyOf": [ + { "$ref": "#/definitions/RuleConfiguration" }, + { "type": "null" } + ] + }, "noUnknownPseudoClass": { "description": "Disallow unknown pseudo-class selectors.", "anyOf": [ From cd9d434e5ca1ee5f615f20db7ceea64b49e14a11 Mon Sep 17 00:00:00 2001 From: togami <togami2864@gmail.com> Date: Sun, 1 Dec 2024 23:08:23 +0900 Subject: [PATCH 02/12] chore: tests --- .../specs/nursery/noUnknownAtRule/invalid.css | 9 +- .../specs/nursery/noUnknownAtRule/valid.css | 124 +++++++++++++++++- 2 files changed, 128 insertions(+), 5 deletions(-) diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css index d58e4390e601..8b8b1508e5dd 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css @@ -1,3 +1,6 @@ -var a = 1; -a = 2; -a = 3; \ No newline at end of file +@uNkNoWn {} +@UNKNOWN {} +@unknown-at-rule {} +@unknown { @unknown-at-rule { font-size: 14px; } } +@MY-other-at-rule {} +@not-my-at-rule {} \ No newline at end of file diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css index f299f876959a..4dc61a38a255 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css @@ -1,2 +1,122 @@ -/* should not generate diagnostics */ -// var a = 1; \ No newline at end of file +@position-try --foo {} +@starting-style { + opacity: 0; +} +@charset 'UTF-8'; +@container (min-width: 700px) +@CONTAINER (min-width: 500px) +@CHARSET 'UTF-8'; +@charset 'iso-8859-15'; +@import url("fineprint.css") print; +@import 'custom.css' +@import url('landscape.css') screen and (orientation:landscape); +@namespace url(http://www.w3.org/1999/xhtml); +@namespace prefix url(XML-namespace-URL); +@media print { + body { + font-size: 10pt + } +} +@media (max-width: 960px) { + body { + font-size: 13px + } +} +@media screen, +print { + body { + line-height: 1.2 + } +} +@supports (--foo: green) { + body { + color: green; + } +} +@supports ((perspective: 10px) or (-webkit-perspective: 10px)) { + font-size: 10pt +} +@counter-style win-list { + system: fixed; + symbols: url(gold-medal.svg); + suffix: ' '; +} +@document url(http://www.w3.org/), +url-prefix(http: //www.w3.org/Style/), domain(mozilla.org), regexp('https:.*') +@page :left { + margin-left: 4cm; +} +@page { + @top-center { + content: none + } +} +@font-face { + font-family: MyHelvetica; + src: local("Helvetica"), url(MgOpenModern.ttf); +} +@keyframes identifier { + 0% { + top: 0; + left: 0; + } + + 30% { + top: 50px; + } + + 68%, + 100% { + top: 100px; + left: 100%; + } +} +@-webkit-keyframes identifier { + 0% { + top: 0; + left: 0; + } + + 30% { + top: 50px; + } + + 68%, + 100% { + top: 100px; + left: 100%; + } +} +@viewport { + min-width: 640px; + max-width: 800px; +} +@viewport { + orientation: landscape; +} + +@counter-style winners-list { + system: fixed; + symbols: url(gold-medal.svg); + suffix: " "; +} + +@font-feature-values Font One { + @styleset { + nice-style: 12; + } +} +.foo { + color: red; + + @nest .parent & { + color: blue; + } +} + +@layer framework { + h1 { + background: white; + } +} +@scroll-timeline foo {} From 33b16a6f373ef2f1378493e0eeaaff842e043908 Mon Sep 17 00:00:00 2001 From: togami <togami2864@gmail.com> Date: Sun, 1 Dec 2024 23:20:11 +0900 Subject: [PATCH 03/12] feat: define keywords --- crates/biome_css_analyze/src/keywords.rs | 99 ++++++++++++++++++++++++ crates/biome_css_analyze/src/utils.rs | 28 ++++--- 2 files changed, 117 insertions(+), 10 deletions(-) diff --git a/crates/biome_css_analyze/src/keywords.rs b/crates/biome_css_analyze/src/keywords.rs index c323f1fe7823..d972fd5b3a76 100644 --- a/crates/biome_css_analyze/src/keywords.rs +++ b/crates/biome_css_analyze/src/keywords.rs @@ -5735,6 +5735,70 @@ pub(crate) const MATH_ML_TAGS: [&str; 32] = [ "semantics", ]; +// https://www.w3.org/TR/css-nesting-1/#conditionals +pub(crate) const CONDITIONAL_AT_RULES: [&str; 6] = [ + "container", + "layer", + "media", + "scope", + "starting-style", + "supports", +]; + +// https://www.w3.org/TR/css-page-3/#syntax-page-selector +pub const PAGE_MARGIN_AT_KEYWORDS: [&str; 16] = [ + "top-left-corner", + "top-left", + "top-center", + "top-right", + "top-right-corner", + "bottom-left-corner", + "bottom-left", + "bottom-center", + "bottom-right", + "bottom-right-corner", + "left-top", + "left-middle", + "left-bottom", + "right-top", + "right-middle", + "right-bottom", +]; + +// https://www.w3.org/TR/css-fonts-4/#font-feature-values-font-feature-value-type +pub const FONT_FEATURE_VALUE_TYPES: [&str; 7] = [ + "annotation", + "character-variant", + "historical-forms", + "ornaments", + "styleset", + "stylistic", + "swash", +]; + +// https://developer.mozilla.org/en/docs/Web/CSS/At-rule +pub const AT_RULES_KEYWORDS: [&str; 19] = [ + "apply", + "charset", + "counter-style", + "custom-media", + "custom-selector", + "document", + "font-face", + "font-feature-values", + "font-palette-values", + "import", + "keyframes", + "namespace", + "nest", + "page", + "position-try", + "property", + "scroll-timeline", + "view-transition", + "viewport", +]; + #[cfg(test)] mod tests { use std::collections::HashSet; @@ -6126,4 +6190,39 @@ mod tests { assert!(items[0] < items[1], "{} < {}", items[0], items[1]); } } + + #[test] + fn test_conditional_at_rules_sorted() { + let sorted = CONDITIONAL_AT_RULES.to_vec(); + let _ = sorted.is_sorted(); + assert_eq!(CONDITIONAL_AT_RULES, sorted.as_slice()); + } + + #[test] + fn test_page_margin_at_keywords_sorted() { + let sorted = PAGE_MARGIN_AT_KEYWORDS.to_vec(); + let _ = sorted.is_sorted(); + assert_eq!(PAGE_MARGIN_AT_KEYWORDS, sorted.as_slice()); + } + + #[test] + fn test_font_feature_value_types_sorted() { + let sorted = FONT_FEATURE_VALUE_TYPES.to_vec(); + let _ = sorted.is_sorted(); + assert_eq!(FONT_FEATURE_VALUE_TYPES, sorted.as_slice()); + } + + #[test] + fn test_font_feature_value_types_unique() { + let mut set = HashSet::new(); + let has_duplicates = FONT_FEATURE_VALUE_TYPES.iter().any(|&x| !set.insert(x)); + assert!(!has_duplicates); + } + + #[test] + fn test_at_rules_keywords_sorted() { + let sorted = AT_RULES_KEYWORDS.to_vec(); + let _ = sorted.is_sorted(); + assert_eq!(AT_RULES_KEYWORDS, sorted.as_slice()); + } } diff --git a/crates/biome_css_analyze/src/utils.rs b/crates/biome_css_analyze/src/utils.rs index b349a3bea246..ed4b0ef5d183 100644 --- a/crates/biome_css_analyze/src/utils.rs +++ b/crates/biome_css_analyze/src/utils.rs @@ -1,22 +1,30 @@ use crate::keywords::{ - AT_RULE_PAGE_PSEUDO_CLASSES, A_NPLUS_BNOTATION_PSEUDO_CLASSES, - A_NPLUS_BOF_SNOTATION_PSEUDO_CLASSES, BASIC_KEYWORDS, FONT_FAMILY_KEYWORDS, FONT_SIZE_KEYWORDS, - FONT_STRETCH_KEYWORDS, FONT_STYLE_KEYWORDS, FONT_VARIANTS_KEYWORDS, - FONT_WEIGHT_ABSOLUTE_KEYWORDS, FONT_WEIGHT_NUMERIC_KEYWORDS, FUNCTION_KEYWORDS, HTML_TAGS, - KNOWN_CHROME_PROPERTIES, KNOWN_EDGE_PROPERTIES, KNOWN_EXPLORER_PROPERTIES, - KNOWN_FIREFOX_PROPERTIES, KNOWN_PROPERTIES, KNOWN_SAFARI_PROPERTIES, - KNOWN_SAMSUNG_INTERNET_PROPERTIES, KNOWN_US_BROWSER_PROPERTIES, + AT_RULES_KEYWORDS, AT_RULE_PAGE_PSEUDO_CLASSES, A_NPLUS_BNOTATION_PSEUDO_CLASSES, + A_NPLUS_BOF_SNOTATION_PSEUDO_CLASSES, BASIC_KEYWORDS, CONDITIONAL_AT_RULES, + FONT_FAMILY_KEYWORDS, FONT_FEATURE_VALUE_TYPES, FONT_SIZE_KEYWORDS, FONT_STRETCH_KEYWORDS, + FONT_STYLE_KEYWORDS, FONT_VARIANTS_KEYWORDS, FONT_WEIGHT_ABSOLUTE_KEYWORDS, + FONT_WEIGHT_NUMERIC_KEYWORDS, FUNCTION_KEYWORDS, HTML_TAGS, KNOWN_CHROME_PROPERTIES, + KNOWN_EDGE_PROPERTIES, KNOWN_EXPLORER_PROPERTIES, KNOWN_FIREFOX_PROPERTIES, KNOWN_PROPERTIES, + KNOWN_SAFARI_PROPERTIES, KNOWN_SAMSUNG_INTERNET_PROPERTIES, KNOWN_US_BROWSER_PROPERTIES, LEVEL_ONE_AND_TWO_PSEUDO_ELEMENTS, LINE_HEIGHT_KEYWORDS, LINGUISTIC_PSEUDO_CLASSES, LOGICAL_COMBINATIONS_PSEUDO_CLASSES, LONGHAND_SUB_PROPERTIES_OF_SHORTHAND_PROPERTIES, MATH_ML_TAGS, MEDIA_FEATURE_NAMES, OTHER_PSEUDO_CLASSES, OTHER_PSEUDO_ELEMENTS, - RESET_TO_INITIAL_PROPERTIES_BY_BORDER, RESET_TO_INITIAL_PROPERTIES_BY_FONT, - RESOURCE_STATE_PSEUDO_CLASSES, SHADOW_TREE_PSEUDO_ELEMENTS, SHORTHAND_PROPERTIES, SVG_TAGS, - SYSTEM_FAMILY_NAME_KEYWORDS, VENDOR_PREFIXES, VENDOR_SPECIFIC_PSEUDO_ELEMENTS, + PAGE_MARGIN_AT_KEYWORDS, RESET_TO_INITIAL_PROPERTIES_BY_BORDER, + RESET_TO_INITIAL_PROPERTIES_BY_FONT, RESOURCE_STATE_PSEUDO_CLASSES, + SHADOW_TREE_PSEUDO_ELEMENTS, SHORTHAND_PROPERTIES, SVG_TAGS, SYSTEM_FAMILY_NAME_KEYWORDS, + VENDOR_PREFIXES, VENDOR_SPECIFIC_PSEUDO_ELEMENTS, }; use biome_css_syntax::{AnyCssGenericComponentValue, AnyCssValue, CssGenericComponentValueList}; use biome_rowan::{AstNode, SyntaxNodeCast}; use biome_string_case::{StrLikeExtension, StrOnlyExtension}; +pub fn is_at_rule_keywords(value: &str) -> bool { + CONDITIONAL_AT_RULES.binary_search(&value).is_ok() + || PAGE_MARGIN_AT_KEYWORDS.binary_search(&value).is_ok() + || FONT_FEATURE_VALUE_TYPES.binary_search(&value).is_ok() + || AT_RULES_KEYWORDS.binary_search(&value).is_ok() +} + pub fn is_font_family_keyword(value: &str) -> bool { BASIC_KEYWORDS.binary_search(&value).is_ok() || FONT_FAMILY_KEYWORDS.binary_search(&value).is_ok() From 3e8a78e8f494135e8c784cc4693976bc0a960099 Mon Sep 17 00:00:00 2001 From: togami <togami2864@gmail.com> Date: Sun, 1 Dec 2024 23:51:59 +0900 Subject: [PATCH 04/12] feat: impl rule --- .../src/lint/nursery/no_unknown_at_rule.rs | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs index d1d0b69cf2a5..66d82fd61b8b 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs @@ -1,7 +1,7 @@ use biome_analyze::{context::RuleContext, declare_lint_rule, Ast, Rule, RuleDiagnostic}; use biome_console::markup; -use biome_css_syntax::CssDeclarationOrRuleBlock; -use biome_rowan::AstNode; +use biome_css_syntax::{CssUnknownBlockAtRule, CssUnknownValueAtRule}; +use biome_rowan::{declare_node_union, AstNode, TextRange}; declare_lint_rule! { /// Succinct description of the rule. @@ -37,36 +37,48 @@ declare_lint_rule! { } } +declare_node_union! { + pub AnyUnknownAtRule = CssUnknownBlockAtRule | CssUnknownValueAtRule +} + +pub struct NoUnknownAtRuleState { + range: TextRange, + name: String, +} + impl Rule for NoUnknownAtRule { - type Query = Ast<CssDeclarationOrRuleBlock>; - type State = CssDeclarationOrRuleBlock; + type Query = Ast<AnyUnknownAtRule>; + type State = NoUnknownAtRuleState; type Signals = Option<Self::State>; type Options = (); fn run(ctx: &RuleContext<Self>) -> Option<Self::State> { let node = ctx.query(); - if node.items().into_iter().next().is_none() { - return Some(node.clone()); - } - None + let rule = match node { + AnyUnknownAtRule::CssUnknownBlockAtRule(rule) => rule.name().ok()?, + AnyUnknownAtRule::CssUnknownValueAtRule(rule) => rule.name().ok()?, + }; + Some(NoUnknownAtRuleState { + range: rule.range(), + name: rule.text().to_string(), + }) } fn diagnostic(_: &RuleContext<Self>, node: &Self::State) -> Option<RuleDiagnostic> { - // - // Read our guidelines to write great diagnostics: - // https://docs.rs/biome_analyze/latest/biome_analyze/#what-a-rule-should-say-to-the-user - // - let span = node.range(); + let span = node.range; + let name = &node.name; Some( RuleDiagnostic::new( rule_category!(), span, markup! { - "Unexpected empty block is not allowed" + "Unexpected unknown at-rule "<Emphasis>{ name }</Emphasis>" " }, ) .note(markup! { - "This note will give you more information." + ""<Emphasis>{ name }</Emphasis>" is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended." + }).note(markup! { + "See "<Hyperlink href="https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule">"MDN web docs"</Hyperlink>" for more details." }), ) } From 82e9842db541a620a3b6a2eee9bdab0045215ae9 Mon Sep 17 00:00:00 2001 From: togami <togami2864@gmail.com> Date: Sun, 1 Dec 2024 23:58:18 +0900 Subject: [PATCH 05/12] chore: snapshot --- .../src/lint/nursery/no_unknown_at_rule.rs | 2 +- .../nursery/noUnknownAtRule/invalid.css.snap | 141 +++++++++++ .../nursery/noUnknownAtRule/valid.css.snap | 223 ++++++++++++++++++ 3 files changed, 365 insertions(+), 1 deletion(-) create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css.snap create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css.snap diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs index 66d82fd61b8b..7258794f53b8 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs @@ -72,7 +72,7 @@ impl Rule for NoUnknownAtRule { rule_category!(), span, markup! { - "Unexpected unknown at-rule "<Emphasis>{ name }</Emphasis>" " + "Unexpected unknown at-rule: "<Emphasis>{ name }</Emphasis>" " }, ) .note(markup! { diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css.snap new file mode 100644 index 000000000000..d7eb6a88fad7 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css.snap @@ -0,0 +1,141 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +expression: invalid.css +--- +# Input +```css +@uNkNoWn {} +@UNKNOWN {} +@unknown-at-rule {} +@unknown { @unknown-at-rule { font-size: 14px; } } +@MY-other-at-rule {} +@not-my-at-rule {} +``` + +# Diagnostics +``` +invalid.css:1:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown at-rule: uNkNoWn + + > 1 │ @uNkNoWn {} + │ ^^^^^^^ + 2 │ @UNKNOWN {} + 3 │ @unknown-at-rule {} + + i uNkNoWn is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. + + i See MDN web docs for more details. + + +``` + +``` +invalid.css:2:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown at-rule: UNKNOWN + + 1 │ @uNkNoWn {} + > 2 │ @UNKNOWN {} + │ ^^^^^^^ + 3 │ @unknown-at-rule {} + 4 │ @unknown { @unknown-at-rule { font-size: 14px; } } + + i UNKNOWN is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. + + i See MDN web docs for more details. + + +``` + +``` +invalid.css:3:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown at-rule: unknown-at-rule + + 1 │ @uNkNoWn {} + 2 │ @UNKNOWN {} + > 3 │ @unknown-at-rule {} + │ ^^^^^^^^^^^^^^^ + 4 │ @unknown { @unknown-at-rule { font-size: 14px; } } + 5 │ @MY-other-at-rule {} + + i unknown-at-rule is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. + + i See MDN web docs for more details. + + +``` + +``` +invalid.css:4:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown at-rule: unknown + + 2 │ @UNKNOWN {} + 3 │ @unknown-at-rule {} + > 4 │ @unknown { @unknown-at-rule { font-size: 14px; } } + │ ^^^^^^^ + 5 │ @MY-other-at-rule {} + 6 │ @not-my-at-rule {} + + i unknown is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. + + i See MDN web docs for more details. + + +``` + +``` +invalid.css:4:13 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown at-rule: unknown-at-rule + + 2 │ @UNKNOWN {} + 3 │ @unknown-at-rule {} + > 4 │ @unknown { @unknown-at-rule { font-size: 14px; } } + │ ^^^^^^^^^^^^^^^ + 5 │ @MY-other-at-rule {} + 6 │ @not-my-at-rule {} + + i unknown-at-rule is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. + + i See MDN web docs for more details. + + +``` + +``` +invalid.css:5:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown at-rule: MY-other-at-rule + + 3 │ @unknown-at-rule {} + 4 │ @unknown { @unknown-at-rule { font-size: 14px; } } + > 5 │ @MY-other-at-rule {} + │ ^^^^^^^^^^^^^^^^ + 6 │ @not-my-at-rule {} + + i MY-other-at-rule is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. + + i See MDN web docs for more details. + + +``` + +``` +invalid.css:6:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown at-rule: not-my-at-rule + + 4 │ @unknown { @unknown-at-rule { font-size: 14px; } } + 5 │ @MY-other-at-rule {} + > 6 │ @not-my-at-rule {} + │ ^^^^^^^^^^^^^^ + + i not-my-at-rule is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. + + i See MDN web docs for more details. + + +``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css.snap new file mode 100644 index 000000000000..1e8749971ad9 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css.snap @@ -0,0 +1,223 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +expression: valid.css +--- +# Input +```css +@position-try --foo {} +@starting-style { + opacity: 0; +} +@charset 'UTF-8'; +@container (min-width: 700px) +@CONTAINER (min-width: 500px) +@CHARSET 'UTF-8'; +@charset 'iso-8859-15'; +@import url("fineprint.css") print; +@import 'custom.css' +@import url('landscape.css') screen and (orientation:landscape); +@namespace url(http://www.w3.org/1999/xhtml); +@namespace prefix url(XML-namespace-URL); +@media print { + body { + font-size: 10pt + } +} +@media (max-width: 960px) { + body { + font-size: 13px + } +} +@media screen, +print { + body { + line-height: 1.2 + } +} +@supports (--foo: green) { + body { + color: green; + } +} +@supports ((perspective: 10px) or (-webkit-perspective: 10px)) { + font-size: 10pt +} +@counter-style win-list { + system: fixed; + symbols: url(gold-medal.svg); + suffix: ' '; +} +@document url(http://www.w3.org/), +url-prefix(http: //www.w3.org/Style/), domain(mozilla.org), regexp('https:.*') +@page :left { + margin-left: 4cm; +} +@page { + @top-center { + content: none + } +} +@font-face { + font-family: MyHelvetica; + src: local("Helvetica"), url(MgOpenModern.ttf); +} +@keyframes identifier { + 0% { + top: 0; + left: 0; + } + + 30% { + top: 50px; + } + + 68%, + 100% { + top: 100px; + left: 100%; + } +} +@-webkit-keyframes identifier { + 0% { + top: 0; + left: 0; + } + + 30% { + top: 50px; + } + + 68%, + 100% { + top: 100px; + left: 100%; + } +} +@viewport { + min-width: 640px; + max-width: 800px; +} +@viewport { + orientation: landscape; +} + +@counter-style winners-list { + system: fixed; + symbols: url(gold-medal.svg); + suffix: " "; +} + +@font-feature-values Font One { + @styleset { + nice-style: 12; + } +} +.foo { + color: red; + + @nest .parent & { + color: blue; + } +} + +@layer framework { + h1 { + background: white; + } +} +@scroll-timeline foo {} + +``` + +# Diagnostics +``` +valid.css:1:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown at-rule: position-try + + > 1 │ @position-try --foo {} + │ ^^^^^^^^^^^^ + 2 │ @starting-style { + 3 │ opacity: 0; + + i position-try is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. + + i See MDN web docs for more details. + + +``` + +``` +valid.css:90:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown at-rule: viewport + + 88 │ } + 89 │ } + > 90 │ @viewport { + │ ^^^^^^^^ + 91 │ min-width: 640px; + 92 │ max-width: 800px; + + i viewport is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. + + i See MDN web docs for more details. + + +``` + +``` +valid.css:94:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown at-rule: viewport + + 92 │ max-width: 800px; + 93 │ } + > 94 │ @viewport { + │ ^^^^^^^^ + 95 │ orientation: landscape; + 96 │ } + + i viewport is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. + + i See MDN web docs for more details. + + +``` + +``` +valid.css:112:6 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown at-rule: nest + + 110 │ color: red; + 111 │ + > 112 │ @nest .parent & { + │ ^^^^ + 113 │ color: blue; + 114 │ } + + i nest is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. + + i See MDN web docs for more details. + + +``` + +``` +valid.css:122:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown at-rule: scroll-timeline + + 120 │ } + 121 │ } + > 122 │ @scroll-timeline foo {} + │ ^^^^^^^^^^^^^^^ + 123 │ + + i scroll-timeline is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. + + i See MDN web docs for more details. + + +``` From d7bb543b2107d322b3aec4e6dff7f89dd064ce1e Mon Sep 17 00:00:00 2001 From: togami <togami2864@gmail.com> Date: Mon, 2 Dec 2024 00:05:19 +0900 Subject: [PATCH 06/12] chore: gen lint --- .../src/analyzer/linter/rules.rs | 4 ++- .../src/lint/nursery/no_unknown_at_rule.rs | 36 ++++++++++++------- .../@biomejs/backend-jsonrpc/src/workspace.ts | 2 +- .../@biomejs/biome/configuration_schema.json | 2 +- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/crates/biome_configuration/src/analyzer/linter/rules.rs b/crates/biome_configuration/src/analyzer/linter/rules.rs index cd9c232477f5..364831501b2e 100644 --- a/crates/biome_configuration/src/analyzer/linter/rules.rs +++ b/crates/biome_configuration/src/analyzer/linter/rules.rs @@ -3365,7 +3365,7 @@ pub struct Nursery { #[serde(skip_serializing_if = "Option::is_none")] pub no_template_curly_in_string: Option<RuleConfiguration<biome_js_analyze::options::NoTemplateCurlyInString>>, - #[doc = "Succinct description of the rule."] + #[doc = "Disallow unknown at-rules."] #[serde(skip_serializing_if = "Option::is_none")] pub no_unknown_at_rule: Option<RuleConfiguration<biome_css_analyze::options::NoUnknownAtRule>>, #[doc = "Disallow unknown pseudo-class selectors."] @@ -3549,6 +3549,7 @@ impl Nursery { "noDuplicateProperties", "noDuplicatedFields", "noMissingVarFunction", + "noUnknownAtRule", "noUnknownPseudoClass", "noUnknownPseudoElement", "noUnknownTypeSelector", @@ -3566,6 +3567,7 @@ impl Nursery { RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[6]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[7]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[16]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[27]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[29]), diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs index 7258794f53b8..04196ef77235 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs @@ -1,39 +1,49 @@ -use biome_analyze::{context::RuleContext, declare_lint_rule, Ast, Rule, RuleDiagnostic}; +use biome_analyze::{ + context::RuleContext, declare_lint_rule, Ast, Rule, RuleDiagnostic, RuleSource, +}; use biome_console::markup; use biome_css_syntax::{CssUnknownBlockAtRule, CssUnknownValueAtRule}; use biome_rowan::{declare_node_union, AstNode, TextRange}; declare_lint_rule! { - /// Succinct description of the rule. + /// Disallow unknown at-rules. /// - /// Put context and details about the rule. - /// As a starting point, you can take the description of the corresponding _ESLint_ rule (if any). - /// - /// Try to stay consistent with the descriptions of implemented rules. - /// - /// Add a link to the corresponding stylelint rule (if any): + /// This rule considers at-rules defined in the CSS Specifications, up to and including Editor's Drafts, to be known. + /// For details on known at-rules, see the [MDN web docs](https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule). /// /// ## Examples /// /// ### Invalid /// /// ```css,expect_diagnostic - /// p {} + /// @uNkNoWn {} + /// ``` + /// + /// ```css,expect_diagnostic + /// @unknown-at-rule { + /// font-size: 14px; + /// } /// ``` /// /// ### Valid /// /// ```css - /// p { - /// color: red; - /// } + /// @charset 'UTF-8'; /// ``` /// + /// ```css + /// @media (max-width: 960px) { + /// body { + /// font-size: 13px; + /// } + /// } + /// ``` pub NoUnknownAtRule { version: "next", name: "noUnknownAtRule", language: "css", - recommended: false, + recommended: true, + sources: &[RuleSource::Stylelint("at-rule-no-unknown")], } } diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index a35172da9f70..168017bc4a96 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -1331,7 +1331,7 @@ export interface Nursery { */ noTemplateCurlyInString?: RuleConfiguration_for_Null; /** - * Succinct description of the rule. + * Disallow unknown at-rules. */ noUnknownAtRule?: RuleConfiguration_for_Null; /** diff --git a/packages/@biomejs/biome/configuration_schema.json b/packages/@biomejs/biome/configuration_schema.json index c71f616bb943..ccbbc8c6be8a 100644 --- a/packages/@biomejs/biome/configuration_schema.json +++ b/packages/@biomejs/biome/configuration_schema.json @@ -2373,7 +2373,7 @@ ] }, "noUnknownAtRule": { - "description": "Succinct description of the rule.", + "description": "Disallow unknown at-rules.", "anyOf": [ { "$ref": "#/definitions/RuleConfiguration" }, { "type": "null" } From 791fe9f7a39c19c45998b304e0c48828fdbf49e6 Mon Sep 17 00:00:00 2001 From: togami <togami2864@gmail.com> Date: Mon, 2 Dec 2024 00:15:47 +0900 Subject: [PATCH 07/12] feat: register new at-rule keywords --- crates/biome_css_parser/src/lexer/mod.rs | 4 ++++ crates/biome_css_parser/src/syntax/parse_error.rs | 3 +++ crates/biome_css_syntax/src/generated/kind.rs | 14 +++++++++++++- xtask/codegen/src/css_kinds_src.rs | 4 ++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/crates/biome_css_parser/src/lexer/mod.rs b/crates/biome_css_parser/src/lexer/mod.rs index 1ab710860676..663b56ffb719 100644 --- a/crates/biome_css_parser/src/lexer/mod.rs +++ b/crates/biome_css_parser/src/lexer/mod.rs @@ -913,6 +913,10 @@ impl<'src> CssLexer<'src> { b"import" => IMPORT_KW, b"namespace" => NAMESPACE_KW, b"starting-style" => STARTING_STYLE_KW, + b"scroll-timeline" => SCROLL_TIMELINE_KW, + b"nest" => NEST_KW, + b"position-try" => POSITION_TRY_KW, + b"viewport" => VIEWPORT_KW, b"document" => DOCUMENT_KW, b"-moz-document" => DOCUMENT_KW, b"url-prefix" => URL_PREFIX_KW, diff --git a/crates/biome_css_parser/src/syntax/parse_error.rs b/crates/biome_css_parser/src/syntax/parse_error.rs index 59854d6ac3a6..b639932e4686 100644 --- a/crates/biome_css_parser/src/syntax/parse_error.rs +++ b/crates/biome_css_parser/src/syntax/parse_error.rs @@ -196,8 +196,11 @@ pub(crate) fn expected_any_at_rule(p: &CssParser, range: TextRange) -> ParseDiag "layer", "media", "namespace", + "nest", "page", + "position-try", "property", + "scroll-timeline", "supports", "viewport", "scope", diff --git a/crates/biome_css_syntax/src/generated/kind.rs b/crates/biome_css_syntax/src/generated/kind.rs index 4ebc23ac9ae2..2e4ffc48e816 100644 --- a/crates/biome_css_syntax/src/generated/kind.rs +++ b/crates/biome_css_syntax/src/generated/kind.rs @@ -223,6 +223,10 @@ pub enum CssSyntaxKind { IMPORT_KW, NAMESPACE_KW, STARTING_STYLE_KW, + SCROLL_TIMELINE_KW, + NEST_KW, + POSITION_TRY_KW, + VIEWPORT_KW, DOCUMENT_KW, URL_PREFIX_KW, DOMAIN_KW, @@ -722,6 +726,10 @@ impl CssSyntaxKind { "import" => IMPORT_KW, "namespace" => NAMESPACE_KW, "starting-style" => STARTING_STYLE_KW, + "scroll-timeline" => SCROLL_TIMELINE_KW, + "nest" => NEST_KW, + "position-try" => POSITION_TRY_KW, + "viewport" => VIEWPORT_KW, "document" => DOCUMENT_KW, "url-prefix" => URL_PREFIX_KW, "domain" => DOMAIN_KW, @@ -947,6 +955,10 @@ impl CssSyntaxKind { IMPORT_KW => "import", NAMESPACE_KW => "namespace", STARTING_STYLE_KW => "starting-style", + SCROLL_TIMELINE_KW => "scroll-timeline", + NEST_KW => "nest", + POSITION_TRY_KW => "position-try", + VIEWPORT_KW => "viewport", DOCUMENT_KW => "document", URL_PREFIX_KW => "url-prefix", DOMAIN_KW => "domain", @@ -964,4 +976,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 :: CDO } ; [U+] => { $ crate :: CssSyntaxKind :: UNICODE } ; [media] => { $ crate :: CssSyntaxKind :: MEDIA_KW } ; [keyframes] => { $ crate :: CssSyntaxKind :: KEYFRAMES_KW } ; [not] => { $ crate :: CssSyntaxKind :: NOT_KW } ; [and] => { $ crate :: CssSyntaxKind :: AND_KW } ; [only] => { $ crate :: CssSyntaxKind :: ONLY_KW } ; [or] => { $ crate :: CssSyntaxKind :: OR_KW } ; [i] => { $ crate :: CssSyntaxKind :: I_KW } ; [important] => { $ crate :: CssSyntaxKind :: IMPORTANT_KW } ; [highlight] => { $ crate :: CssSyntaxKind :: HIGHLIGHT_KW } ; [part] => { $ crate :: CssSyntaxKind :: PART_KW } ; [dir] => { $ crate :: CssSyntaxKind :: DIR_KW } ; [local] => { $ crate :: CssSyntaxKind :: LOCAL_KW } ; [global] => { $ crate :: CssSyntaxKind :: GLOBAL_KW } ; [any] => { $ crate :: CssSyntaxKind :: ANY_KW } ; [current] => { $ crate :: CssSyntaxKind :: CURRENT_KW } ; [past] => { $ crate :: CssSyntaxKind :: PAST_KW } ; [future] => { $ crate :: CssSyntaxKind :: FUTURE_KW } ; [host] => { $ crate :: CssSyntaxKind :: HOST_KW } ; [host_context] => { $ crate :: CssSyntaxKind :: HOST_CONTEXT_KW } ; [matches] => { $ crate :: CssSyntaxKind :: MATCHES_KW } ; [is] => { $ crate :: CssSyntaxKind :: IS_KW } ; [where] => { $ crate :: CssSyntaxKind :: WHERE_KW } ; [has] => { $ crate :: CssSyntaxKind :: HAS_KW } ; [lang] => { $ crate :: CssSyntaxKind :: LANG_KW } ; [nth_child] => { $ crate :: CssSyntaxKind :: NTH_CHILD_KW } ; [nth_last_child] => { $ crate :: CssSyntaxKind :: NTH_LAST_CHILD_KW } ; [nth_of_type] => { $ crate :: CssSyntaxKind :: NTH_OF_TYPE_KW } ; [nth_last_of_type] => { $ crate :: CssSyntaxKind :: NTH_LAST_OF_TYPE_KW } ; [nth_col] => { $ crate :: CssSyntaxKind :: NTH_COL_KW } ; [nth_last_col] => { $ crate :: CssSyntaxKind :: NTH_LAST_COL_KW } ; [charset] => { $ crate :: CssSyntaxKind :: CHARSET_KW } ; [color_profile] => { $ crate :: CssSyntaxKind :: COLOR_PROFILE_KW } ; [counter_style] => { $ crate :: CssSyntaxKind :: COUNTER_STYLE_KW } ; [property] => { $ crate :: CssSyntaxKind :: PROPERTY_KW } ; [container] => { $ crate :: CssSyntaxKind :: CONTAINER_KW } ; [style] => { $ crate :: CssSyntaxKind :: STYLE_KW } ; [ltr] => { $ crate :: CssSyntaxKind :: LTR_KW } ; [rtl] => { $ crate :: CssSyntaxKind :: RTL_KW } ; [n] => { $ crate :: CssSyntaxKind :: N_KW } ; [even] => { $ crate :: CssSyntaxKind :: EVEN_KW } ; [odd] => { $ crate :: CssSyntaxKind :: ODD_KW } ; [of] => { $ crate :: CssSyntaxKind :: OF_KW } ; [from] => { $ crate :: CssSyntaxKind :: FROM_KW } ; [to] => { $ crate :: CssSyntaxKind :: TO_KW } ; [var] => { $ crate :: CssSyntaxKind :: VAR_KW } ; [url] => { $ crate :: CssSyntaxKind :: URL_KW } ; [src] => { $ crate :: CssSyntaxKind :: SRC_KW } ; [font_palette_values] => { $ crate :: CssSyntaxKind :: FONT_PALETTE_VALUES_KW } ; [font_feature_values] => { $ crate :: CssSyntaxKind :: FONT_FEATURE_VALUES_KW } ; [stylistic] => { $ crate :: CssSyntaxKind :: STYLISTIC_KW } ; [historical_forms] => { $ crate :: CssSyntaxKind :: HISTORICAL_FORMS_KW } ; [styleset] => { $ crate :: CssSyntaxKind :: STYLESET_KW } ; [character_variant] => { $ crate :: CssSyntaxKind :: CHARACTER_VARIANT_KW } ; [swash] => { $ crate :: CssSyntaxKind :: SWASH_KW } ; [ornaments] => { $ crate :: CssSyntaxKind :: ORNAMENTS_KW } ; [annotation] => { $ crate :: CssSyntaxKind :: ANNOTATION_KW } ; [auto] => { $ crate :: CssSyntaxKind :: AUTO_KW } ; [thin] => { $ crate :: CssSyntaxKind :: THIN_KW } ; [medium] => { $ crate :: CssSyntaxKind :: MEDIUM_KW } ; [thick] => { $ crate :: CssSyntaxKind :: THICK_KW } ; [none] => { $ crate :: CssSyntaxKind :: NONE_KW } ; [hidden] => { $ crate :: CssSyntaxKind :: HIDDEN_KW } ; [dotted] => { $ crate :: CssSyntaxKind :: DOTTED_KW } ; [dashed] => { $ crate :: CssSyntaxKind :: DASHED_KW } ; [solid] => { $ crate :: CssSyntaxKind :: SOLID_KW } ; [double] => { $ crate :: CssSyntaxKind :: DOUBLE_KW } ; [groove] => { $ crate :: CssSyntaxKind :: GROOVE_KW } ; [ridge] => { $ crate :: CssSyntaxKind :: RIDGE_KW } ; [inset] => { $ crate :: CssSyntaxKind :: INSET_KW } ; [outset] => { $ crate :: CssSyntaxKind :: OUTSET_KW } ; [initial] => { $ crate :: CssSyntaxKind :: INITIAL_KW } ; [inherit] => { $ crate :: CssSyntaxKind :: INHERIT_KW } ; [unset] => { $ crate :: CssSyntaxKind :: UNSET_KW } ; [revert] => { $ crate :: CssSyntaxKind :: REVERT_KW } ; [revert_layer] => { $ crate :: CssSyntaxKind :: REVERT_LAYER_KW } ; [default] => { $ crate :: CssSyntaxKind :: DEFAULT_KW } ; [em] => { $ crate :: CssSyntaxKind :: EM_KW } ; [rem] => { $ crate :: CssSyntaxKind :: REM_KW } ; [ex] => { $ crate :: CssSyntaxKind :: EX_KW } ; [rex] => { $ crate :: CssSyntaxKind :: REX_KW } ; [cap] => { $ crate :: CssSyntaxKind :: CAP_KW } ; [rcap] => { $ crate :: CssSyntaxKind :: RCAP_KW } ; [ch] => { $ crate :: CssSyntaxKind :: CH_KW } ; [rch] => { $ crate :: CssSyntaxKind :: RCH_KW } ; [ic] => { $ crate :: CssSyntaxKind :: IC_KW } ; [ric] => { $ crate :: CssSyntaxKind :: RIC_KW } ; [lh] => { $ crate :: CssSyntaxKind :: LH_KW } ; [rlh] => { $ crate :: CssSyntaxKind :: RLH_KW } ; [vw] => { $ crate :: CssSyntaxKind :: VW_KW } ; [svw] => { $ crate :: CssSyntaxKind :: SVW_KW } ; [lvw] => { $ crate :: CssSyntaxKind :: LVW_KW } ; [dvw] => { $ crate :: CssSyntaxKind :: DVW_KW } ; [vh] => { $ crate :: CssSyntaxKind :: VH_KW } ; [svh] => { $ crate :: CssSyntaxKind :: SVH_KW } ; [lvh] => { $ crate :: CssSyntaxKind :: LVH_KW } ; [dvh] => { $ crate :: CssSyntaxKind :: DVH_KW } ; [vi] => { $ crate :: CssSyntaxKind :: VI_KW } ; [svi] => { $ crate :: CssSyntaxKind :: SVI_KW } ; [lvi] => { $ crate :: CssSyntaxKind :: LVI_KW } ; [dvi] => { $ crate :: CssSyntaxKind :: DVI_KW } ; [vb] => { $ crate :: CssSyntaxKind :: VB_KW } ; [svb] => { $ crate :: CssSyntaxKind :: SVB_KW } ; [lvb] => { $ crate :: CssSyntaxKind :: LVB_KW } ; [dvb] => { $ crate :: CssSyntaxKind :: DVB_KW } ; [vmin] => { $ crate :: CssSyntaxKind :: VMIN_KW } ; [svmin] => { $ crate :: CssSyntaxKind :: SVMIN_KW } ; [lvmin] => { $ crate :: CssSyntaxKind :: LVMIN_KW } ; [dvmin] => { $ crate :: CssSyntaxKind :: DVMIN_KW } ; [vmax] => { $ crate :: CssSyntaxKind :: VMAX_KW } ; [svmax] => { $ crate :: CssSyntaxKind :: SVMAX_KW } ; [lvmax] => { $ crate :: CssSyntaxKind :: LVMAX_KW } ; [dvmax] => { $ crate :: CssSyntaxKind :: DVMAX_KW } ; [cm] => { $ crate :: CssSyntaxKind :: CM_KW } ; [mm] => { $ crate :: CssSyntaxKind :: MM_KW } ; [q] => { $ crate :: CssSyntaxKind :: Q_KW } ; [in] => { $ crate :: CssSyntaxKind :: IN_KW } ; [pc] => { $ crate :: CssSyntaxKind :: PC_KW } ; [pt] => { $ crate :: CssSyntaxKind :: PT_KW } ; [px] => { $ crate :: CssSyntaxKind :: PX_KW } ; [mozmm] => { $ crate :: CssSyntaxKind :: MOZMM_KW } ; [rpx] => { $ crate :: CssSyntaxKind :: RPX_KW } ; [cqw] => { $ crate :: CssSyntaxKind :: CQW_KW } ; [cqh] => { $ crate :: CssSyntaxKind :: CQH_KW } ; [cqi] => { $ crate :: CssSyntaxKind :: CQI_KW } ; [cqb] => { $ crate :: CssSyntaxKind :: CQB_KW } ; [cqmin] => { $ crate :: CssSyntaxKind :: CQMIN_KW } ; [cqmax] => { $ crate :: CssSyntaxKind :: CQMAX_KW } ; [deg] => { $ crate :: CssSyntaxKind :: DEG_KW } ; [grad] => { $ crate :: CssSyntaxKind :: GRAD_KW } ; [rad] => { $ crate :: CssSyntaxKind :: RAD_KW } ; [turn] => { $ crate :: CssSyntaxKind :: TURN_KW } ; [s] => { $ crate :: CssSyntaxKind :: S_KW } ; [ms] => { $ crate :: CssSyntaxKind :: MS_KW } ; [hz] => { $ crate :: CssSyntaxKind :: HZ_KW } ; [khz] => { $ crate :: CssSyntaxKind :: KHZ_KW } ; [dpi] => { $ crate :: CssSyntaxKind :: DPI_KW } ; [dpcm] => { $ crate :: CssSyntaxKind :: DPCM_KW } ; [dppx] => { $ crate :: CssSyntaxKind :: DPPX_KW } ; [x] => { $ crate :: CssSyntaxKind :: X_KW } ; [fr] => { $ crate :: CssSyntaxKind :: FR_KW } ; [page] => { $ crate :: CssSyntaxKind :: PAGE_KW } ; [left] => { $ crate :: CssSyntaxKind :: LEFT_KW } ; [right] => { $ crate :: CssSyntaxKind :: RIGHT_KW } ; [first] => { $ crate :: CssSyntaxKind :: FIRST_KW } ; [blank] => { $ crate :: CssSyntaxKind :: BLANK_KW } ; [top_left_corner] => { $ crate :: CssSyntaxKind :: TOP_LEFT_CORNER_KW } ; [top_left] => { $ crate :: CssSyntaxKind :: TOP_LEFT_KW } ; [top_center] => { $ crate :: CssSyntaxKind :: TOP_CENTER_KW } ; [top_right] => { $ crate :: CssSyntaxKind :: TOP_RIGHT_KW } ; [top_right_corner] => { $ crate :: CssSyntaxKind :: TOP_RIGHT_CORNER_KW } ; [bottom_left_corner] => { $ crate :: CssSyntaxKind :: BOTTOM_LEFT_CORNER_KW } ; [bottom_left] => { $ crate :: CssSyntaxKind :: BOTTOM_LEFT_KW } ; [bottom_center] => { $ crate :: CssSyntaxKind :: BOTTOM_CENTER_KW } ; [bottom_right] => { $ crate :: CssSyntaxKind :: BOTTOM_RIGHT_KW } ; [bottom_right_corner] => { $ crate :: CssSyntaxKind :: BOTTOM_RIGHT_CORNER_KW } ; [left_top] => { $ crate :: CssSyntaxKind :: LEFT_TOP_KW } ; [left_middle] => { $ crate :: CssSyntaxKind :: LEFT_MIDDLE_KW } ; [left_bottom] => { $ crate :: CssSyntaxKind :: LEFT_BOTTOM_KW } ; [right_top] => { $ crate :: CssSyntaxKind :: RIGHT_TOP_KW } ; [right_middle] => { $ crate :: CssSyntaxKind :: RIGHT_MIDDLE_KW } ; [right_bottom] => { $ crate :: CssSyntaxKind :: RIGHT_BOTTOM_KW } ; [layer] => { $ crate :: CssSyntaxKind :: LAYER_KW } ; [scope] => { $ crate :: CssSyntaxKind :: SCOPE_KW } ; [supports] => { $ crate :: CssSyntaxKind :: SUPPORTS_KW } ; [selector] => { $ crate :: CssSyntaxKind :: SELECTOR_KW } ; [import] => { $ crate :: CssSyntaxKind :: IMPORT_KW } ; [namespace] => { $ crate :: CssSyntaxKind :: NAMESPACE_KW } ; [starting_style] => { $ crate :: CssSyntaxKind :: STARTING_STYLE_KW } ; [document] => { $ crate :: CssSyntaxKind :: DOCUMENT_KW } ; [url_prefix] => { $ crate :: CssSyntaxKind :: URL_PREFIX_KW } ; [domain] => { $ crate :: CssSyntaxKind :: DOMAIN_KW } ; [media_document] => { $ crate :: CssSyntaxKind :: MEDIA_DOCUMENT_KW } ; [regexp] => { $ crate :: CssSyntaxKind :: REGEXP_KW } ; [value] => { $ crate :: CssSyntaxKind :: VALUE_KW } ; [as] => { $ crate :: CssSyntaxKind :: AS_KW } ; [composes] => { $ crate :: CssSyntaxKind :: COMPOSES_KW } ; [font_face] => { $ crate :: CssSyntaxKind :: FONT_FACE_KW } ; [ident] => { $ crate :: CssSyntaxKind :: IDENT } ; [EOF] => { $ crate :: CssSyntaxKind :: EOF } ; [UNICODE_BOM] => { $ crate :: CssSyntaxKind :: UNICODE_BOM } ; [#] => { $ crate :: CssSyntaxKind :: HASH } ; } +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 :: CDO } ; [U+] => { $ crate :: CssSyntaxKind :: UNICODE } ; [media] => { $ crate :: CssSyntaxKind :: MEDIA_KW } ; [keyframes] => { $ crate :: CssSyntaxKind :: KEYFRAMES_KW } ; [not] => { $ crate :: CssSyntaxKind :: NOT_KW } ; [and] => { $ crate :: CssSyntaxKind :: AND_KW } ; [only] => { $ crate :: CssSyntaxKind :: ONLY_KW } ; [or] => { $ crate :: CssSyntaxKind :: OR_KW } ; [i] => { $ crate :: CssSyntaxKind :: I_KW } ; [important] => { $ crate :: CssSyntaxKind :: IMPORTANT_KW } ; [highlight] => { $ crate :: CssSyntaxKind :: HIGHLIGHT_KW } ; [part] => { $ crate :: CssSyntaxKind :: PART_KW } ; [dir] => { $ crate :: CssSyntaxKind :: DIR_KW } ; [local] => { $ crate :: CssSyntaxKind :: LOCAL_KW } ; [global] => { $ crate :: CssSyntaxKind :: GLOBAL_KW } ; [any] => { $ crate :: CssSyntaxKind :: ANY_KW } ; [current] => { $ crate :: CssSyntaxKind :: CURRENT_KW } ; [past] => { $ crate :: CssSyntaxKind :: PAST_KW } ; [future] => { $ crate :: CssSyntaxKind :: FUTURE_KW } ; [host] => { $ crate :: CssSyntaxKind :: HOST_KW } ; [host_context] => { $ crate :: CssSyntaxKind :: HOST_CONTEXT_KW } ; [matches] => { $ crate :: CssSyntaxKind :: MATCHES_KW } ; [is] => { $ crate :: CssSyntaxKind :: IS_KW } ; [where] => { $ crate :: CssSyntaxKind :: WHERE_KW } ; [has] => { $ crate :: CssSyntaxKind :: HAS_KW } ; [lang] => { $ crate :: CssSyntaxKind :: LANG_KW } ; [nth_child] => { $ crate :: CssSyntaxKind :: NTH_CHILD_KW } ; [nth_last_child] => { $ crate :: CssSyntaxKind :: NTH_LAST_CHILD_KW } ; [nth_of_type] => { $ crate :: CssSyntaxKind :: NTH_OF_TYPE_KW } ; [nth_last_of_type] => { $ crate :: CssSyntaxKind :: NTH_LAST_OF_TYPE_KW } ; [nth_col] => { $ crate :: CssSyntaxKind :: NTH_COL_KW } ; [nth_last_col] => { $ crate :: CssSyntaxKind :: NTH_LAST_COL_KW } ; [charset] => { $ crate :: CssSyntaxKind :: CHARSET_KW } ; [color_profile] => { $ crate :: CssSyntaxKind :: COLOR_PROFILE_KW } ; [counter_style] => { $ crate :: CssSyntaxKind :: COUNTER_STYLE_KW } ; [property] => { $ crate :: CssSyntaxKind :: PROPERTY_KW } ; [container] => { $ crate :: CssSyntaxKind :: CONTAINER_KW } ; [style] => { $ crate :: CssSyntaxKind :: STYLE_KW } ; [ltr] => { $ crate :: CssSyntaxKind :: LTR_KW } ; [rtl] => { $ crate :: CssSyntaxKind :: RTL_KW } ; [n] => { $ crate :: CssSyntaxKind :: N_KW } ; [even] => { $ crate :: CssSyntaxKind :: EVEN_KW } ; [odd] => { $ crate :: CssSyntaxKind :: ODD_KW } ; [of] => { $ crate :: CssSyntaxKind :: OF_KW } ; [from] => { $ crate :: CssSyntaxKind :: FROM_KW } ; [to] => { $ crate :: CssSyntaxKind :: TO_KW } ; [var] => { $ crate :: CssSyntaxKind :: VAR_KW } ; [url] => { $ crate :: CssSyntaxKind :: URL_KW } ; [src] => { $ crate :: CssSyntaxKind :: SRC_KW } ; [font_palette_values] => { $ crate :: CssSyntaxKind :: FONT_PALETTE_VALUES_KW } ; [font_feature_values] => { $ crate :: CssSyntaxKind :: FONT_FEATURE_VALUES_KW } ; [stylistic] => { $ crate :: CssSyntaxKind :: STYLISTIC_KW } ; [historical_forms] => { $ crate :: CssSyntaxKind :: HISTORICAL_FORMS_KW } ; [styleset] => { $ crate :: CssSyntaxKind :: STYLESET_KW } ; [character_variant] => { $ crate :: CssSyntaxKind :: CHARACTER_VARIANT_KW } ; [swash] => { $ crate :: CssSyntaxKind :: SWASH_KW } ; [ornaments] => { $ crate :: CssSyntaxKind :: ORNAMENTS_KW } ; [annotation] => { $ crate :: CssSyntaxKind :: ANNOTATION_KW } ; [auto] => { $ crate :: CssSyntaxKind :: AUTO_KW } ; [thin] => { $ crate :: CssSyntaxKind :: THIN_KW } ; [medium] => { $ crate :: CssSyntaxKind :: MEDIUM_KW } ; [thick] => { $ crate :: CssSyntaxKind :: THICK_KW } ; [none] => { $ crate :: CssSyntaxKind :: NONE_KW } ; [hidden] => { $ crate :: CssSyntaxKind :: HIDDEN_KW } ; [dotted] => { $ crate :: CssSyntaxKind :: DOTTED_KW } ; [dashed] => { $ crate :: CssSyntaxKind :: DASHED_KW } ; [solid] => { $ crate :: CssSyntaxKind :: SOLID_KW } ; [double] => { $ crate :: CssSyntaxKind :: DOUBLE_KW } ; [groove] => { $ crate :: CssSyntaxKind :: GROOVE_KW } ; [ridge] => { $ crate :: CssSyntaxKind :: RIDGE_KW } ; [inset] => { $ crate :: CssSyntaxKind :: INSET_KW } ; [outset] => { $ crate :: CssSyntaxKind :: OUTSET_KW } ; [initial] => { $ crate :: CssSyntaxKind :: INITIAL_KW } ; [inherit] => { $ crate :: CssSyntaxKind :: INHERIT_KW } ; [unset] => { $ crate :: CssSyntaxKind :: UNSET_KW } ; [revert] => { $ crate :: CssSyntaxKind :: REVERT_KW } ; [revert_layer] => { $ crate :: CssSyntaxKind :: REVERT_LAYER_KW } ; [default] => { $ crate :: CssSyntaxKind :: DEFAULT_KW } ; [em] => { $ crate :: CssSyntaxKind :: EM_KW } ; [rem] => { $ crate :: CssSyntaxKind :: REM_KW } ; [ex] => { $ crate :: CssSyntaxKind :: EX_KW } ; [rex] => { $ crate :: CssSyntaxKind :: REX_KW } ; [cap] => { $ crate :: CssSyntaxKind :: CAP_KW } ; [rcap] => { $ crate :: CssSyntaxKind :: RCAP_KW } ; [ch] => { $ crate :: CssSyntaxKind :: CH_KW } ; [rch] => { $ crate :: CssSyntaxKind :: RCH_KW } ; [ic] => { $ crate :: CssSyntaxKind :: IC_KW } ; [ric] => { $ crate :: CssSyntaxKind :: RIC_KW } ; [lh] => { $ crate :: CssSyntaxKind :: LH_KW } ; [rlh] => { $ crate :: CssSyntaxKind :: RLH_KW } ; [vw] => { $ crate :: CssSyntaxKind :: VW_KW } ; [svw] => { $ crate :: CssSyntaxKind :: SVW_KW } ; [lvw] => { $ crate :: CssSyntaxKind :: LVW_KW } ; [dvw] => { $ crate :: CssSyntaxKind :: DVW_KW } ; [vh] => { $ crate :: CssSyntaxKind :: VH_KW } ; [svh] => { $ crate :: CssSyntaxKind :: SVH_KW } ; [lvh] => { $ crate :: CssSyntaxKind :: LVH_KW } ; [dvh] => { $ crate :: CssSyntaxKind :: DVH_KW } ; [vi] => { $ crate :: CssSyntaxKind :: VI_KW } ; [svi] => { $ crate :: CssSyntaxKind :: SVI_KW } ; [lvi] => { $ crate :: CssSyntaxKind :: LVI_KW } ; [dvi] => { $ crate :: CssSyntaxKind :: DVI_KW } ; [vb] => { $ crate :: CssSyntaxKind :: VB_KW } ; [svb] => { $ crate :: CssSyntaxKind :: SVB_KW } ; [lvb] => { $ crate :: CssSyntaxKind :: LVB_KW } ; [dvb] => { $ crate :: CssSyntaxKind :: DVB_KW } ; [vmin] => { $ crate :: CssSyntaxKind :: VMIN_KW } ; [svmin] => { $ crate :: CssSyntaxKind :: SVMIN_KW } ; [lvmin] => { $ crate :: CssSyntaxKind :: LVMIN_KW } ; [dvmin] => { $ crate :: CssSyntaxKind :: DVMIN_KW } ; [vmax] => { $ crate :: CssSyntaxKind :: VMAX_KW } ; [svmax] => { $ crate :: CssSyntaxKind :: SVMAX_KW } ; [lvmax] => { $ crate :: CssSyntaxKind :: LVMAX_KW } ; [dvmax] => { $ crate :: CssSyntaxKind :: DVMAX_KW } ; [cm] => { $ crate :: CssSyntaxKind :: CM_KW } ; [mm] => { $ crate :: CssSyntaxKind :: MM_KW } ; [q] => { $ crate :: CssSyntaxKind :: Q_KW } ; [in] => { $ crate :: CssSyntaxKind :: IN_KW } ; [pc] => { $ crate :: CssSyntaxKind :: PC_KW } ; [pt] => { $ crate :: CssSyntaxKind :: PT_KW } ; [px] => { $ crate :: CssSyntaxKind :: PX_KW } ; [mozmm] => { $ crate :: CssSyntaxKind :: MOZMM_KW } ; [rpx] => { $ crate :: CssSyntaxKind :: RPX_KW } ; [cqw] => { $ crate :: CssSyntaxKind :: CQW_KW } ; [cqh] => { $ crate :: CssSyntaxKind :: CQH_KW } ; [cqi] => { $ crate :: CssSyntaxKind :: CQI_KW } ; [cqb] => { $ crate :: CssSyntaxKind :: CQB_KW } ; [cqmin] => { $ crate :: CssSyntaxKind :: CQMIN_KW } ; [cqmax] => { $ crate :: CssSyntaxKind :: CQMAX_KW } ; [deg] => { $ crate :: CssSyntaxKind :: DEG_KW } ; [grad] => { $ crate :: CssSyntaxKind :: GRAD_KW } ; [rad] => { $ crate :: CssSyntaxKind :: RAD_KW } ; [turn] => { $ crate :: CssSyntaxKind :: TURN_KW } ; [s] => { $ crate :: CssSyntaxKind :: S_KW } ; [ms] => { $ crate :: CssSyntaxKind :: MS_KW } ; [hz] => { $ crate :: CssSyntaxKind :: HZ_KW } ; [khz] => { $ crate :: CssSyntaxKind :: KHZ_KW } ; [dpi] => { $ crate :: CssSyntaxKind :: DPI_KW } ; [dpcm] => { $ crate :: CssSyntaxKind :: DPCM_KW } ; [dppx] => { $ crate :: CssSyntaxKind :: DPPX_KW } ; [x] => { $ crate :: CssSyntaxKind :: X_KW } ; [fr] => { $ crate :: CssSyntaxKind :: FR_KW } ; [page] => { $ crate :: CssSyntaxKind :: PAGE_KW } ; [left] => { $ crate :: CssSyntaxKind :: LEFT_KW } ; [right] => { $ crate :: CssSyntaxKind :: RIGHT_KW } ; [first] => { $ crate :: CssSyntaxKind :: FIRST_KW } ; [blank] => { $ crate :: CssSyntaxKind :: BLANK_KW } ; [top_left_corner] => { $ crate :: CssSyntaxKind :: TOP_LEFT_CORNER_KW } ; [top_left] => { $ crate :: CssSyntaxKind :: TOP_LEFT_KW } ; [top_center] => { $ crate :: CssSyntaxKind :: TOP_CENTER_KW } ; [top_right] => { $ crate :: CssSyntaxKind :: TOP_RIGHT_KW } ; [top_right_corner] => { $ crate :: CssSyntaxKind :: TOP_RIGHT_CORNER_KW } ; [bottom_left_corner] => { $ crate :: CssSyntaxKind :: BOTTOM_LEFT_CORNER_KW } ; [bottom_left] => { $ crate :: CssSyntaxKind :: BOTTOM_LEFT_KW } ; [bottom_center] => { $ crate :: CssSyntaxKind :: BOTTOM_CENTER_KW } ; [bottom_right] => { $ crate :: CssSyntaxKind :: BOTTOM_RIGHT_KW } ; [bottom_right_corner] => { $ crate :: CssSyntaxKind :: BOTTOM_RIGHT_CORNER_KW } ; [left_top] => { $ crate :: CssSyntaxKind :: LEFT_TOP_KW } ; [left_middle] => { $ crate :: CssSyntaxKind :: LEFT_MIDDLE_KW } ; [left_bottom] => { $ crate :: CssSyntaxKind :: LEFT_BOTTOM_KW } ; [right_top] => { $ crate :: CssSyntaxKind :: RIGHT_TOP_KW } ; [right_middle] => { $ crate :: CssSyntaxKind :: RIGHT_MIDDLE_KW } ; [right_bottom] => { $ crate :: CssSyntaxKind :: RIGHT_BOTTOM_KW } ; [layer] => { $ crate :: CssSyntaxKind :: LAYER_KW } ; [scope] => { $ crate :: CssSyntaxKind :: SCOPE_KW } ; [supports] => { $ crate :: CssSyntaxKind :: SUPPORTS_KW } ; [selector] => { $ crate :: CssSyntaxKind :: SELECTOR_KW } ; [import] => { $ crate :: CssSyntaxKind :: IMPORT_KW } ; [namespace] => { $ crate :: CssSyntaxKind :: NAMESPACE_KW } ; [starting_style] => { $ crate :: CssSyntaxKind :: STARTING_STYLE_KW } ; [scroll_timeline] => { $ crate :: CssSyntaxKind :: SCROLL_TIMELINE_KW } ; [nest] => { $ crate :: CssSyntaxKind :: NEST_KW } ; [position_try] => { $ crate :: CssSyntaxKind :: POSITION_TRY_KW } ; [viewport] => { $ crate :: CssSyntaxKind :: VIEWPORT_KW } ; [document] => { $ crate :: CssSyntaxKind :: DOCUMENT_KW } ; [url_prefix] => { $ crate :: CssSyntaxKind :: URL_PREFIX_KW } ; [domain] => { $ crate :: CssSyntaxKind :: DOMAIN_KW } ; [media_document] => { $ crate :: CssSyntaxKind :: MEDIA_DOCUMENT_KW } ; [regexp] => { $ crate :: CssSyntaxKind :: REGEXP_KW } ; [value] => { $ crate :: CssSyntaxKind :: VALUE_KW } ; [as] => { $ crate :: CssSyntaxKind :: AS_KW } ; [composes] => { $ crate :: CssSyntaxKind :: COMPOSES_KW } ; [font_face] => { $ crate :: CssSyntaxKind :: FONT_FACE_KW } ; [ident] => { $ crate :: CssSyntaxKind :: IDENT } ; [EOF] => { $ crate :: CssSyntaxKind :: EOF } ; [UNICODE_BOM] => { $ crate :: CssSyntaxKind :: UNICODE_BOM } ; [#] => { $ crate :: CssSyntaxKind :: HASH } ; } diff --git a/xtask/codegen/src/css_kinds_src.rs b/xtask/codegen/src/css_kinds_src.rs index 7cffa42b7e6d..e63c496c07ca 100644 --- a/xtask/codegen/src/css_kinds_src.rs +++ b/xtask/codegen/src/css_kinds_src.rs @@ -233,6 +233,10 @@ pub const CSS_KINDS_SRC: KindsSrc = KindsSrc { "import", "namespace", "starting-style", + "scroll-timeline", + "nest", + "position-try", + "viewport", "document", "url-prefix", "domain", From 2c4f0acb5ed4bd4f6272deb9f13a6d20609418d6 Mon Sep 17 00:00:00 2001 From: togami <togami2864@gmail.com> Date: Mon, 2 Dec 2024 00:34:55 +0900 Subject: [PATCH 08/12] chore: update snapshot --- .../specs/nursery/noUnknownAtRule/valid.css | 35 ++--- .../nursery/noUnknownAtRule/valid.css.snap | 122 +++--------------- 2 files changed, 35 insertions(+), 122 deletions(-) diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css index 4dc61a38a255..9046d4e99ccc 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css @@ -1,4 +1,3 @@ -@position-try --foo {} @starting-style { opacity: 0; } @@ -87,13 +86,6 @@ url-prefix(http: //www.w3.org/Style/), domain(mozilla.org), regexp('https:.*') left: 100%; } } -@viewport { - min-width: 640px; - max-width: 800px; -} -@viewport { - orientation: landscape; -} @counter-style winners-list { system: fixed; @@ -106,17 +98,28 @@ url-prefix(http: //www.w3.org/Style/), domain(mozilla.org), regexp('https:.*') nice-style: 12; } } -.foo { - color: red; - - @nest .parent & { - color: blue; - } -} @layer framework { h1 { background: white; } } -@scroll-timeline foo {} +/* TODO: the parser not supported yet */ +/* @scroll-timeline foo {} */ +/* .foo { + color: red; + + @nest .parent & { + color: blue; + } +} */ + /* @position-try --foo {} */ + /* @viewport { + min-width: 640px; + max-width: 800px; + } + + @viewport { + orientation: landscape; + } */ + diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css.snap index 1e8749971ad9..69b46f2b534b 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css.snap +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css.snap @@ -4,7 +4,6 @@ expression: valid.css --- # Input ```css -@position-try --foo {} @starting-style { opacity: 0; } @@ -93,13 +92,6 @@ url-prefix(http: //www.w3.org/Style/), domain(mozilla.org), regexp('https:.*') left: 100%; } } -@viewport { - min-width: 640px; - max-width: 800px; -} -@viewport { - orientation: landscape; -} @counter-style winners-list { system: fixed; @@ -112,112 +104,30 @@ url-prefix(http: //www.w3.org/Style/), domain(mozilla.org), regexp('https:.*') nice-style: 12; } } -.foo { - color: red; - - @nest .parent & { - color: blue; - } -} @layer framework { h1 { background: white; } } -@scroll-timeline foo {} - -``` - -# Diagnostics -``` -valid.css:1:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown at-rule: position-try - - > 1 │ @position-try --foo {} - │ ^^^^^^^^^^^^ - 2 │ @starting-style { - 3 │ opacity: 0; - - i position-try is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. - - i See MDN web docs for more details. - - -``` - -``` -valid.css:90:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown at-rule: viewport - - 88 │ } - 89 │ } - > 90 │ @viewport { - │ ^^^^^^^^ - 91 │ min-width: 640px; - 92 │ max-width: 800px; - - i viewport is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. - - i See MDN web docs for more details. - - -``` - -``` -valid.css:94:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown at-rule: viewport - - 92 │ max-width: 800px; - 93 │ } - > 94 │ @viewport { - │ ^^^^^^^^ - 95 │ orientation: landscape; - 96 │ } - - i viewport is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. - - i See MDN web docs for more details. - - -``` - -``` -valid.css:112:6 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown at-rule: nest - - 110 │ color: red; - 111 │ - > 112 │ @nest .parent & { - │ ^^^^ - 113 │ color: blue; - 114 │ } - - i nest is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. - - i See MDN web docs for more details. - +/* TODO: the parser not supported yet */ +/* @scroll-timeline foo {} */ +/* .foo { + color: red; -``` + @nest .parent & { + color: blue; + } +} */ + /* @position-try --foo {} */ + /* @viewport { + min-width: 640px; + max-width: 800px; + } -``` -valid.css:122:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + @viewport { + orientation: landscape; + } */ - ! Unexpected unknown at-rule: scroll-timeline - - 120 │ } - 121 │ } - > 122 │ @scroll-timeline foo {} - │ ^^^^^^^^^^^^^^^ - 123 │ - - i scroll-timeline is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. - - i See MDN web docs for more details. - ``` From 75394ad95cf7f86cd4a4e79139144be19a0cab28 Mon Sep 17 00:00:00 2001 From: togami <togami2864@gmail.com> Date: Mon, 2 Dec 2024 00:35:37 +0900 Subject: [PATCH 09/12] Revert "feat: define keywords" This reverts commit 33b16a6f373ef2f1378493e0eeaaff842e043908. --- crates/biome_css_analyze/src/keywords.rs | 99 ------------------------ crates/biome_css_analyze/src/utils.rs | 28 +++---- 2 files changed, 10 insertions(+), 117 deletions(-) diff --git a/crates/biome_css_analyze/src/keywords.rs b/crates/biome_css_analyze/src/keywords.rs index d972fd5b3a76..c323f1fe7823 100644 --- a/crates/biome_css_analyze/src/keywords.rs +++ b/crates/biome_css_analyze/src/keywords.rs @@ -5735,70 +5735,6 @@ pub(crate) const MATH_ML_TAGS: [&str; 32] = [ "semantics", ]; -// https://www.w3.org/TR/css-nesting-1/#conditionals -pub(crate) const CONDITIONAL_AT_RULES: [&str; 6] = [ - "container", - "layer", - "media", - "scope", - "starting-style", - "supports", -]; - -// https://www.w3.org/TR/css-page-3/#syntax-page-selector -pub const PAGE_MARGIN_AT_KEYWORDS: [&str; 16] = [ - "top-left-corner", - "top-left", - "top-center", - "top-right", - "top-right-corner", - "bottom-left-corner", - "bottom-left", - "bottom-center", - "bottom-right", - "bottom-right-corner", - "left-top", - "left-middle", - "left-bottom", - "right-top", - "right-middle", - "right-bottom", -]; - -// https://www.w3.org/TR/css-fonts-4/#font-feature-values-font-feature-value-type -pub const FONT_FEATURE_VALUE_TYPES: [&str; 7] = [ - "annotation", - "character-variant", - "historical-forms", - "ornaments", - "styleset", - "stylistic", - "swash", -]; - -// https://developer.mozilla.org/en/docs/Web/CSS/At-rule -pub const AT_RULES_KEYWORDS: [&str; 19] = [ - "apply", - "charset", - "counter-style", - "custom-media", - "custom-selector", - "document", - "font-face", - "font-feature-values", - "font-palette-values", - "import", - "keyframes", - "namespace", - "nest", - "page", - "position-try", - "property", - "scroll-timeline", - "view-transition", - "viewport", -]; - #[cfg(test)] mod tests { use std::collections::HashSet; @@ -6190,39 +6126,4 @@ mod tests { assert!(items[0] < items[1], "{} < {}", items[0], items[1]); } } - - #[test] - fn test_conditional_at_rules_sorted() { - let sorted = CONDITIONAL_AT_RULES.to_vec(); - let _ = sorted.is_sorted(); - assert_eq!(CONDITIONAL_AT_RULES, sorted.as_slice()); - } - - #[test] - fn test_page_margin_at_keywords_sorted() { - let sorted = PAGE_MARGIN_AT_KEYWORDS.to_vec(); - let _ = sorted.is_sorted(); - assert_eq!(PAGE_MARGIN_AT_KEYWORDS, sorted.as_slice()); - } - - #[test] - fn test_font_feature_value_types_sorted() { - let sorted = FONT_FEATURE_VALUE_TYPES.to_vec(); - let _ = sorted.is_sorted(); - assert_eq!(FONT_FEATURE_VALUE_TYPES, sorted.as_slice()); - } - - #[test] - fn test_font_feature_value_types_unique() { - let mut set = HashSet::new(); - let has_duplicates = FONT_FEATURE_VALUE_TYPES.iter().any(|&x| !set.insert(x)); - assert!(!has_duplicates); - } - - #[test] - fn test_at_rules_keywords_sorted() { - let sorted = AT_RULES_KEYWORDS.to_vec(); - let _ = sorted.is_sorted(); - assert_eq!(AT_RULES_KEYWORDS, sorted.as_slice()); - } } diff --git a/crates/biome_css_analyze/src/utils.rs b/crates/biome_css_analyze/src/utils.rs index ed4b0ef5d183..b349a3bea246 100644 --- a/crates/biome_css_analyze/src/utils.rs +++ b/crates/biome_css_analyze/src/utils.rs @@ -1,30 +1,22 @@ use crate::keywords::{ - AT_RULES_KEYWORDS, AT_RULE_PAGE_PSEUDO_CLASSES, A_NPLUS_BNOTATION_PSEUDO_CLASSES, - A_NPLUS_BOF_SNOTATION_PSEUDO_CLASSES, BASIC_KEYWORDS, CONDITIONAL_AT_RULES, - FONT_FAMILY_KEYWORDS, FONT_FEATURE_VALUE_TYPES, FONT_SIZE_KEYWORDS, FONT_STRETCH_KEYWORDS, - FONT_STYLE_KEYWORDS, FONT_VARIANTS_KEYWORDS, FONT_WEIGHT_ABSOLUTE_KEYWORDS, - FONT_WEIGHT_NUMERIC_KEYWORDS, FUNCTION_KEYWORDS, HTML_TAGS, KNOWN_CHROME_PROPERTIES, - KNOWN_EDGE_PROPERTIES, KNOWN_EXPLORER_PROPERTIES, KNOWN_FIREFOX_PROPERTIES, KNOWN_PROPERTIES, - KNOWN_SAFARI_PROPERTIES, KNOWN_SAMSUNG_INTERNET_PROPERTIES, KNOWN_US_BROWSER_PROPERTIES, + AT_RULE_PAGE_PSEUDO_CLASSES, A_NPLUS_BNOTATION_PSEUDO_CLASSES, + A_NPLUS_BOF_SNOTATION_PSEUDO_CLASSES, BASIC_KEYWORDS, FONT_FAMILY_KEYWORDS, FONT_SIZE_KEYWORDS, + FONT_STRETCH_KEYWORDS, FONT_STYLE_KEYWORDS, FONT_VARIANTS_KEYWORDS, + FONT_WEIGHT_ABSOLUTE_KEYWORDS, FONT_WEIGHT_NUMERIC_KEYWORDS, FUNCTION_KEYWORDS, HTML_TAGS, + KNOWN_CHROME_PROPERTIES, KNOWN_EDGE_PROPERTIES, KNOWN_EXPLORER_PROPERTIES, + KNOWN_FIREFOX_PROPERTIES, KNOWN_PROPERTIES, KNOWN_SAFARI_PROPERTIES, + KNOWN_SAMSUNG_INTERNET_PROPERTIES, KNOWN_US_BROWSER_PROPERTIES, LEVEL_ONE_AND_TWO_PSEUDO_ELEMENTS, LINE_HEIGHT_KEYWORDS, LINGUISTIC_PSEUDO_CLASSES, LOGICAL_COMBINATIONS_PSEUDO_CLASSES, LONGHAND_SUB_PROPERTIES_OF_SHORTHAND_PROPERTIES, MATH_ML_TAGS, MEDIA_FEATURE_NAMES, OTHER_PSEUDO_CLASSES, OTHER_PSEUDO_ELEMENTS, - PAGE_MARGIN_AT_KEYWORDS, RESET_TO_INITIAL_PROPERTIES_BY_BORDER, - RESET_TO_INITIAL_PROPERTIES_BY_FONT, RESOURCE_STATE_PSEUDO_CLASSES, - SHADOW_TREE_PSEUDO_ELEMENTS, SHORTHAND_PROPERTIES, SVG_TAGS, SYSTEM_FAMILY_NAME_KEYWORDS, - VENDOR_PREFIXES, VENDOR_SPECIFIC_PSEUDO_ELEMENTS, + RESET_TO_INITIAL_PROPERTIES_BY_BORDER, RESET_TO_INITIAL_PROPERTIES_BY_FONT, + RESOURCE_STATE_PSEUDO_CLASSES, SHADOW_TREE_PSEUDO_ELEMENTS, SHORTHAND_PROPERTIES, SVG_TAGS, + SYSTEM_FAMILY_NAME_KEYWORDS, VENDOR_PREFIXES, VENDOR_SPECIFIC_PSEUDO_ELEMENTS, }; use biome_css_syntax::{AnyCssGenericComponentValue, AnyCssValue, CssGenericComponentValueList}; use biome_rowan::{AstNode, SyntaxNodeCast}; use biome_string_case::{StrLikeExtension, StrOnlyExtension}; -pub fn is_at_rule_keywords(value: &str) -> bool { - CONDITIONAL_AT_RULES.binary_search(&value).is_ok() - || PAGE_MARGIN_AT_KEYWORDS.binary_search(&value).is_ok() - || FONT_FEATURE_VALUE_TYPES.binary_search(&value).is_ok() - || AT_RULES_KEYWORDS.binary_search(&value).is_ok() -} - pub fn is_font_family_keyword(value: &str) -> bool { BASIC_KEYWORDS.binary_search(&value).is_ok() || FONT_FAMILY_KEYWORDS.binary_search(&value).is_ok() From e2bf92a3ee8f6553d44559465c19754e5d4f37bd Mon Sep 17 00:00:00 2001 From: togami <togami2864@gmail.com> Date: Wed, 4 Dec 2024 00:02:01 +0900 Subject: [PATCH 10/12] chore: fix test cases --- .../src/lint/nursery/no_unknown_at_rule.rs | 1 - .../specs/nursery/noUnknownAtRule/invalid.css | 1 + .../nursery/noUnknownAtRule/invalid.css.snap | 90 +++++++++++-------- .../specs/nursery/noUnknownAtRule/valid.css | 16 ++-- .../nursery/noUnknownAtRule/valid.css.snap | 16 ++-- 5 files changed, 70 insertions(+), 54 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs index 04196ef77235..243c3985df84 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs @@ -8,7 +8,6 @@ use biome_rowan::{declare_node_union, AstNode, TextRange}; declare_lint_rule! { /// Disallow unknown at-rules. /// - /// This rule considers at-rules defined in the CSS Specifications, up to and including Editor's Drafts, to be known. /// For details on known at-rules, see the [MDN web docs](https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule). /// /// ## Examples diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css index 8b8b1508e5dd..43d139851b86 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css @@ -1,3 +1,4 @@ +@unknown-rule 'UTF-8'; @uNkNoWn {} @UNKNOWN {} @unknown-at-rule {} diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css.snap index d7eb6a88fad7..9d0f4e8ec523 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css.snap +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css.snap @@ -4,6 +4,7 @@ expression: invalid.css --- # Input ```css +@unknown-rule 'UTF-8'; @uNkNoWn {} @UNKNOWN {} @unknown-at-rule {} @@ -16,12 +17,30 @@ expression: invalid.css ``` invalid.css:1:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + ! Unexpected unknown at-rule: unknown-rule + + > 1 │ @unknown-rule 'UTF-8'; + │ ^^^^^^^^^^^^ + 2 │ @uNkNoWn {} + 3 │ @UNKNOWN {} + + i unknown-rule is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. + + i See MDN web docs for more details. + + +``` + +``` +invalid.css:2:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + ! Unexpected unknown at-rule: uNkNoWn - > 1 │ @uNkNoWn {} + 1 │ @unknown-rule 'UTF-8'; + > 2 │ @uNkNoWn {} │ ^^^^^^^ - 2 │ @UNKNOWN {} - 3 │ @unknown-at-rule {} + 3 │ @UNKNOWN {} + 4 │ @unknown-at-rule {} i uNkNoWn is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. @@ -31,15 +50,16 @@ invalid.css:1:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━ ``` ``` -invalid.css:2:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.css:3:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Unexpected unknown at-rule: UNKNOWN - 1 │ @uNkNoWn {} - > 2 │ @UNKNOWN {} + 1 │ @unknown-rule 'UTF-8'; + 2 │ @uNkNoWn {} + > 3 │ @UNKNOWN {} │ ^^^^^^^ - 3 │ @unknown-at-rule {} - 4 │ @unknown { @unknown-at-rule { font-size: 14px; } } + 4 │ @unknown-at-rule {} + 5 │ @unknown { @unknown-at-rule { font-size: 14px; } } i UNKNOWN is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. @@ -49,16 +69,16 @@ invalid.css:2:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━ ``` ``` -invalid.css:3:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.css:4:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Unexpected unknown at-rule: unknown-at-rule - 1 │ @uNkNoWn {} - 2 │ @UNKNOWN {} - > 3 │ @unknown-at-rule {} + 2 │ @uNkNoWn {} + 3 │ @UNKNOWN {} + > 4 │ @unknown-at-rule {} │ ^^^^^^^^^^^^^^^ - 4 │ @unknown { @unknown-at-rule { font-size: 14px; } } - 5 │ @MY-other-at-rule {} + 5 │ @unknown { @unknown-at-rule { font-size: 14px; } } + 6 │ @MY-other-at-rule {} i unknown-at-rule is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. @@ -68,16 +88,16 @@ invalid.css:3:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━ ``` ``` -invalid.css:4:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.css:5:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Unexpected unknown at-rule: unknown - 2 │ @UNKNOWN {} - 3 │ @unknown-at-rule {} - > 4 │ @unknown { @unknown-at-rule { font-size: 14px; } } + 3 │ @UNKNOWN {} + 4 │ @unknown-at-rule {} + > 5 │ @unknown { @unknown-at-rule { font-size: 14px; } } │ ^^^^^^^ - 5 │ @MY-other-at-rule {} - 6 │ @not-my-at-rule {} + 6 │ @MY-other-at-rule {} + 7 │ @not-my-at-rule {} i unknown is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. @@ -87,16 +107,16 @@ invalid.css:4:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━ ``` ``` -invalid.css:4:13 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.css:5:13 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Unexpected unknown at-rule: unknown-at-rule - 2 │ @UNKNOWN {} - 3 │ @unknown-at-rule {} - > 4 │ @unknown { @unknown-at-rule { font-size: 14px; } } + 3 │ @UNKNOWN {} + 4 │ @unknown-at-rule {} + > 5 │ @unknown { @unknown-at-rule { font-size: 14px; } } │ ^^^^^^^^^^^^^^^ - 5 │ @MY-other-at-rule {} - 6 │ @not-my-at-rule {} + 6 │ @MY-other-at-rule {} + 7 │ @not-my-at-rule {} i unknown-at-rule is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. @@ -106,15 +126,15 @@ invalid.css:4:13 lint/nursery/noUnknownAtRule ━━━━━━━━━━━ ``` ``` -invalid.css:5:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.css:6:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Unexpected unknown at-rule: MY-other-at-rule - 3 │ @unknown-at-rule {} - 4 │ @unknown { @unknown-at-rule { font-size: 14px; } } - > 5 │ @MY-other-at-rule {} + 4 │ @unknown-at-rule {} + 5 │ @unknown { @unknown-at-rule { font-size: 14px; } } + > 6 │ @MY-other-at-rule {} │ ^^^^^^^^^^^^^^^^ - 6 │ @not-my-at-rule {} + 7 │ @not-my-at-rule {} i MY-other-at-rule is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. @@ -124,13 +144,13 @@ invalid.css:5:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━ ``` ``` -invalid.css:6:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.css:7:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Unexpected unknown at-rule: not-my-at-rule - 4 │ @unknown { @unknown-at-rule { font-size: 14px; } } - 5 │ @MY-other-at-rule {} - > 6 │ @not-my-at-rule {} + 5 │ @unknown { @unknown-at-rule { font-size: 14px; } } + 6 │ @MY-other-at-rule {} + > 7 │ @not-my-at-rule {} │ ^^^^^^^^^^^^^^ i not-my-at-rule is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css index 9046d4e99ccc..a702e5ea94f6 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css @@ -105,16 +105,14 @@ url-prefix(http: //www.w3.org/Style/), domain(mozilla.org), regexp('https:.*') } } /* TODO: the parser not supported yet */ -/* @scroll-timeline foo {} */ -/* .foo { - color: red; - - @nest .parent & { - color: blue; - } +/* @position-try --foo {} +@view-transition { + navigation: auto; } */ - /* @position-try --foo {} */ - /* @viewport { + +/* These at-rules have already been removed from the draft. Support will be provided if there's strong demand*/ +/* @scroll-timeline foo {} +@viewport { min-width: 640px; max-width: 800px; } diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css.snap index 69b46f2b534b..a19019e117e7 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css.snap +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/valid.css.snap @@ -111,16 +111,14 @@ url-prefix(http: //www.w3.org/Style/), domain(mozilla.org), regexp('https:.*') } } /* TODO: the parser not supported yet */ -/* @scroll-timeline foo {} */ -/* .foo { - color: red; - - @nest .parent & { - color: blue; - } +/* @position-try --foo {} +@view-transition { + navigation: auto; } */ - /* @position-try --foo {} */ - /* @viewport { + +/* These at-rules have already been removed from the draft. Support will be provided if there's strong demand*/ +/* @scroll-timeline foo {} +@viewport { min-width: 640px; max-width: 800px; } From 06788fb4c81e0d0d9d4b5ae040a20693a87955b1 Mon Sep 17 00:00:00 2001 From: togami <togami2864@gmail.com> Date: Wed, 4 Dec 2024 00:15:02 +0900 Subject: [PATCH 11/12] chore: revert --- crates/biome_css_parser/src/lexer/mod.rs | 4 ---- crates/biome_css_parser/src/syntax/parse_error.rs | 3 --- crates/biome_css_syntax/src/generated/kind.rs | 14 +------------- xtask/codegen/src/css_kinds_src.rs | 4 ---- 4 files changed, 1 insertion(+), 24 deletions(-) diff --git a/crates/biome_css_parser/src/lexer/mod.rs b/crates/biome_css_parser/src/lexer/mod.rs index 663b56ffb719..1ab710860676 100644 --- a/crates/biome_css_parser/src/lexer/mod.rs +++ b/crates/biome_css_parser/src/lexer/mod.rs @@ -913,10 +913,6 @@ impl<'src> CssLexer<'src> { b"import" => IMPORT_KW, b"namespace" => NAMESPACE_KW, b"starting-style" => STARTING_STYLE_KW, - b"scroll-timeline" => SCROLL_TIMELINE_KW, - b"nest" => NEST_KW, - b"position-try" => POSITION_TRY_KW, - b"viewport" => VIEWPORT_KW, b"document" => DOCUMENT_KW, b"-moz-document" => DOCUMENT_KW, b"url-prefix" => URL_PREFIX_KW, diff --git a/crates/biome_css_parser/src/syntax/parse_error.rs b/crates/biome_css_parser/src/syntax/parse_error.rs index b639932e4686..59854d6ac3a6 100644 --- a/crates/biome_css_parser/src/syntax/parse_error.rs +++ b/crates/biome_css_parser/src/syntax/parse_error.rs @@ -196,11 +196,8 @@ pub(crate) fn expected_any_at_rule(p: &CssParser, range: TextRange) -> ParseDiag "layer", "media", "namespace", - "nest", "page", - "position-try", "property", - "scroll-timeline", "supports", "viewport", "scope", diff --git a/crates/biome_css_syntax/src/generated/kind.rs b/crates/biome_css_syntax/src/generated/kind.rs index 2e4ffc48e816..4ebc23ac9ae2 100644 --- a/crates/biome_css_syntax/src/generated/kind.rs +++ b/crates/biome_css_syntax/src/generated/kind.rs @@ -223,10 +223,6 @@ pub enum CssSyntaxKind { IMPORT_KW, NAMESPACE_KW, STARTING_STYLE_KW, - SCROLL_TIMELINE_KW, - NEST_KW, - POSITION_TRY_KW, - VIEWPORT_KW, DOCUMENT_KW, URL_PREFIX_KW, DOMAIN_KW, @@ -726,10 +722,6 @@ impl CssSyntaxKind { "import" => IMPORT_KW, "namespace" => NAMESPACE_KW, "starting-style" => STARTING_STYLE_KW, - "scroll-timeline" => SCROLL_TIMELINE_KW, - "nest" => NEST_KW, - "position-try" => POSITION_TRY_KW, - "viewport" => VIEWPORT_KW, "document" => DOCUMENT_KW, "url-prefix" => URL_PREFIX_KW, "domain" => DOMAIN_KW, @@ -955,10 +947,6 @@ impl CssSyntaxKind { IMPORT_KW => "import", NAMESPACE_KW => "namespace", STARTING_STYLE_KW => "starting-style", - SCROLL_TIMELINE_KW => "scroll-timeline", - NEST_KW => "nest", - POSITION_TRY_KW => "position-try", - VIEWPORT_KW => "viewport", DOCUMENT_KW => "document", URL_PREFIX_KW => "url-prefix", DOMAIN_KW => "domain", @@ -976,4 +964,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 :: CDO } ; [U+] => { $ crate :: CssSyntaxKind :: UNICODE } ; [media] => { $ crate :: CssSyntaxKind :: MEDIA_KW } ; [keyframes] => { $ crate :: CssSyntaxKind :: KEYFRAMES_KW } ; [not] => { $ crate :: CssSyntaxKind :: NOT_KW } ; [and] => { $ crate :: CssSyntaxKind :: AND_KW } ; [only] => { $ crate :: CssSyntaxKind :: ONLY_KW } ; [or] => { $ crate :: CssSyntaxKind :: OR_KW } ; [i] => { $ crate :: CssSyntaxKind :: I_KW } ; [important] => { $ crate :: CssSyntaxKind :: IMPORTANT_KW } ; [highlight] => { $ crate :: CssSyntaxKind :: HIGHLIGHT_KW } ; [part] => { $ crate :: CssSyntaxKind :: PART_KW } ; [dir] => { $ crate :: CssSyntaxKind :: DIR_KW } ; [local] => { $ crate :: CssSyntaxKind :: LOCAL_KW } ; [global] => { $ crate :: CssSyntaxKind :: GLOBAL_KW } ; [any] => { $ crate :: CssSyntaxKind :: ANY_KW } ; [current] => { $ crate :: CssSyntaxKind :: CURRENT_KW } ; [past] => { $ crate :: CssSyntaxKind :: PAST_KW } ; [future] => { $ crate :: CssSyntaxKind :: FUTURE_KW } ; [host] => { $ crate :: CssSyntaxKind :: HOST_KW } ; [host_context] => { $ crate :: CssSyntaxKind :: HOST_CONTEXT_KW } ; [matches] => { $ crate :: CssSyntaxKind :: MATCHES_KW } ; [is] => { $ crate :: CssSyntaxKind :: IS_KW } ; [where] => { $ crate :: CssSyntaxKind :: WHERE_KW } ; [has] => { $ crate :: CssSyntaxKind :: HAS_KW } ; [lang] => { $ crate :: CssSyntaxKind :: LANG_KW } ; [nth_child] => { $ crate :: CssSyntaxKind :: NTH_CHILD_KW } ; [nth_last_child] => { $ crate :: CssSyntaxKind :: NTH_LAST_CHILD_KW } ; [nth_of_type] => { $ crate :: CssSyntaxKind :: NTH_OF_TYPE_KW } ; [nth_last_of_type] => { $ crate :: CssSyntaxKind :: NTH_LAST_OF_TYPE_KW } ; [nth_col] => { $ crate :: CssSyntaxKind :: NTH_COL_KW } ; [nth_last_col] => { $ crate :: CssSyntaxKind :: NTH_LAST_COL_KW } ; [charset] => { $ crate :: CssSyntaxKind :: CHARSET_KW } ; [color_profile] => { $ crate :: CssSyntaxKind :: COLOR_PROFILE_KW } ; [counter_style] => { $ crate :: CssSyntaxKind :: COUNTER_STYLE_KW } ; [property] => { $ crate :: CssSyntaxKind :: PROPERTY_KW } ; [container] => { $ crate :: CssSyntaxKind :: CONTAINER_KW } ; [style] => { $ crate :: CssSyntaxKind :: STYLE_KW } ; [ltr] => { $ crate :: CssSyntaxKind :: LTR_KW } ; [rtl] => { $ crate :: CssSyntaxKind :: RTL_KW } ; [n] => { $ crate :: CssSyntaxKind :: N_KW } ; [even] => { $ crate :: CssSyntaxKind :: EVEN_KW } ; [odd] => { $ crate :: CssSyntaxKind :: ODD_KW } ; [of] => { $ crate :: CssSyntaxKind :: OF_KW } ; [from] => { $ crate :: CssSyntaxKind :: FROM_KW } ; [to] => { $ crate :: CssSyntaxKind :: TO_KW } ; [var] => { $ crate :: CssSyntaxKind :: VAR_KW } ; [url] => { $ crate :: CssSyntaxKind :: URL_KW } ; [src] => { $ crate :: CssSyntaxKind :: SRC_KW } ; [font_palette_values] => { $ crate :: CssSyntaxKind :: FONT_PALETTE_VALUES_KW } ; [font_feature_values] => { $ crate :: CssSyntaxKind :: FONT_FEATURE_VALUES_KW } ; [stylistic] => { $ crate :: CssSyntaxKind :: STYLISTIC_KW } ; [historical_forms] => { $ crate :: CssSyntaxKind :: HISTORICAL_FORMS_KW } ; [styleset] => { $ crate :: CssSyntaxKind :: STYLESET_KW } ; [character_variant] => { $ crate :: CssSyntaxKind :: CHARACTER_VARIANT_KW } ; [swash] => { $ crate :: CssSyntaxKind :: SWASH_KW } ; [ornaments] => { $ crate :: CssSyntaxKind :: ORNAMENTS_KW } ; [annotation] => { $ crate :: CssSyntaxKind :: ANNOTATION_KW } ; [auto] => { $ crate :: CssSyntaxKind :: AUTO_KW } ; [thin] => { $ crate :: CssSyntaxKind :: THIN_KW } ; [medium] => { $ crate :: CssSyntaxKind :: MEDIUM_KW } ; [thick] => { $ crate :: CssSyntaxKind :: THICK_KW } ; [none] => { $ crate :: CssSyntaxKind :: NONE_KW } ; [hidden] => { $ crate :: CssSyntaxKind :: HIDDEN_KW } ; [dotted] => { $ crate :: CssSyntaxKind :: DOTTED_KW } ; [dashed] => { $ crate :: CssSyntaxKind :: DASHED_KW } ; [solid] => { $ crate :: CssSyntaxKind :: SOLID_KW } ; [double] => { $ crate :: CssSyntaxKind :: DOUBLE_KW } ; [groove] => { $ crate :: CssSyntaxKind :: GROOVE_KW } ; [ridge] => { $ crate :: CssSyntaxKind :: RIDGE_KW } ; [inset] => { $ crate :: CssSyntaxKind :: INSET_KW } ; [outset] => { $ crate :: CssSyntaxKind :: OUTSET_KW } ; [initial] => { $ crate :: CssSyntaxKind :: INITIAL_KW } ; [inherit] => { $ crate :: CssSyntaxKind :: INHERIT_KW } ; [unset] => { $ crate :: CssSyntaxKind :: UNSET_KW } ; [revert] => { $ crate :: CssSyntaxKind :: REVERT_KW } ; [revert_layer] => { $ crate :: CssSyntaxKind :: REVERT_LAYER_KW } ; [default] => { $ crate :: CssSyntaxKind :: DEFAULT_KW } ; [em] => { $ crate :: CssSyntaxKind :: EM_KW } ; [rem] => { $ crate :: CssSyntaxKind :: REM_KW } ; [ex] => { $ crate :: CssSyntaxKind :: EX_KW } ; [rex] => { $ crate :: CssSyntaxKind :: REX_KW } ; [cap] => { $ crate :: CssSyntaxKind :: CAP_KW } ; [rcap] => { $ crate :: CssSyntaxKind :: RCAP_KW } ; [ch] => { $ crate :: CssSyntaxKind :: CH_KW } ; [rch] => { $ crate :: CssSyntaxKind :: RCH_KW } ; [ic] => { $ crate :: CssSyntaxKind :: IC_KW } ; [ric] => { $ crate :: CssSyntaxKind :: RIC_KW } ; [lh] => { $ crate :: CssSyntaxKind :: LH_KW } ; [rlh] => { $ crate :: CssSyntaxKind :: RLH_KW } ; [vw] => { $ crate :: CssSyntaxKind :: VW_KW } ; [svw] => { $ crate :: CssSyntaxKind :: SVW_KW } ; [lvw] => { $ crate :: CssSyntaxKind :: LVW_KW } ; [dvw] => { $ crate :: CssSyntaxKind :: DVW_KW } ; [vh] => { $ crate :: CssSyntaxKind :: VH_KW } ; [svh] => { $ crate :: CssSyntaxKind :: SVH_KW } ; [lvh] => { $ crate :: CssSyntaxKind :: LVH_KW } ; [dvh] => { $ crate :: CssSyntaxKind :: DVH_KW } ; [vi] => { $ crate :: CssSyntaxKind :: VI_KW } ; [svi] => { $ crate :: CssSyntaxKind :: SVI_KW } ; [lvi] => { $ crate :: CssSyntaxKind :: LVI_KW } ; [dvi] => { $ crate :: CssSyntaxKind :: DVI_KW } ; [vb] => { $ crate :: CssSyntaxKind :: VB_KW } ; [svb] => { $ crate :: CssSyntaxKind :: SVB_KW } ; [lvb] => { $ crate :: CssSyntaxKind :: LVB_KW } ; [dvb] => { $ crate :: CssSyntaxKind :: DVB_KW } ; [vmin] => { $ crate :: CssSyntaxKind :: VMIN_KW } ; [svmin] => { $ crate :: CssSyntaxKind :: SVMIN_KW } ; [lvmin] => { $ crate :: CssSyntaxKind :: LVMIN_KW } ; [dvmin] => { $ crate :: CssSyntaxKind :: DVMIN_KW } ; [vmax] => { $ crate :: CssSyntaxKind :: VMAX_KW } ; [svmax] => { $ crate :: CssSyntaxKind :: SVMAX_KW } ; [lvmax] => { $ crate :: CssSyntaxKind :: LVMAX_KW } ; [dvmax] => { $ crate :: CssSyntaxKind :: DVMAX_KW } ; [cm] => { $ crate :: CssSyntaxKind :: CM_KW } ; [mm] => { $ crate :: CssSyntaxKind :: MM_KW } ; [q] => { $ crate :: CssSyntaxKind :: Q_KW } ; [in] => { $ crate :: CssSyntaxKind :: IN_KW } ; [pc] => { $ crate :: CssSyntaxKind :: PC_KW } ; [pt] => { $ crate :: CssSyntaxKind :: PT_KW } ; [px] => { $ crate :: CssSyntaxKind :: PX_KW } ; [mozmm] => { $ crate :: CssSyntaxKind :: MOZMM_KW } ; [rpx] => { $ crate :: CssSyntaxKind :: RPX_KW } ; [cqw] => { $ crate :: CssSyntaxKind :: CQW_KW } ; [cqh] => { $ crate :: CssSyntaxKind :: CQH_KW } ; [cqi] => { $ crate :: CssSyntaxKind :: CQI_KW } ; [cqb] => { $ crate :: CssSyntaxKind :: CQB_KW } ; [cqmin] => { $ crate :: CssSyntaxKind :: CQMIN_KW } ; [cqmax] => { $ crate :: CssSyntaxKind :: CQMAX_KW } ; [deg] => { $ crate :: CssSyntaxKind :: DEG_KW } ; [grad] => { $ crate :: CssSyntaxKind :: GRAD_KW } ; [rad] => { $ crate :: CssSyntaxKind :: RAD_KW } ; [turn] => { $ crate :: CssSyntaxKind :: TURN_KW } ; [s] => { $ crate :: CssSyntaxKind :: S_KW } ; [ms] => { $ crate :: CssSyntaxKind :: MS_KW } ; [hz] => { $ crate :: CssSyntaxKind :: HZ_KW } ; [khz] => { $ crate :: CssSyntaxKind :: KHZ_KW } ; [dpi] => { $ crate :: CssSyntaxKind :: DPI_KW } ; [dpcm] => { $ crate :: CssSyntaxKind :: DPCM_KW } ; [dppx] => { $ crate :: CssSyntaxKind :: DPPX_KW } ; [x] => { $ crate :: CssSyntaxKind :: X_KW } ; [fr] => { $ crate :: CssSyntaxKind :: FR_KW } ; [page] => { $ crate :: CssSyntaxKind :: PAGE_KW } ; [left] => { $ crate :: CssSyntaxKind :: LEFT_KW } ; [right] => { $ crate :: CssSyntaxKind :: RIGHT_KW } ; [first] => { $ crate :: CssSyntaxKind :: FIRST_KW } ; [blank] => { $ crate :: CssSyntaxKind :: BLANK_KW } ; [top_left_corner] => { $ crate :: CssSyntaxKind :: TOP_LEFT_CORNER_KW } ; [top_left] => { $ crate :: CssSyntaxKind :: TOP_LEFT_KW } ; [top_center] => { $ crate :: CssSyntaxKind :: TOP_CENTER_KW } ; [top_right] => { $ crate :: CssSyntaxKind :: TOP_RIGHT_KW } ; [top_right_corner] => { $ crate :: CssSyntaxKind :: TOP_RIGHT_CORNER_KW } ; [bottom_left_corner] => { $ crate :: CssSyntaxKind :: BOTTOM_LEFT_CORNER_KW } ; [bottom_left] => { $ crate :: CssSyntaxKind :: BOTTOM_LEFT_KW } ; [bottom_center] => { $ crate :: CssSyntaxKind :: BOTTOM_CENTER_KW } ; [bottom_right] => { $ crate :: CssSyntaxKind :: BOTTOM_RIGHT_KW } ; [bottom_right_corner] => { $ crate :: CssSyntaxKind :: BOTTOM_RIGHT_CORNER_KW } ; [left_top] => { $ crate :: CssSyntaxKind :: LEFT_TOP_KW } ; [left_middle] => { $ crate :: CssSyntaxKind :: LEFT_MIDDLE_KW } ; [left_bottom] => { $ crate :: CssSyntaxKind :: LEFT_BOTTOM_KW } ; [right_top] => { $ crate :: CssSyntaxKind :: RIGHT_TOP_KW } ; [right_middle] => { $ crate :: CssSyntaxKind :: RIGHT_MIDDLE_KW } ; [right_bottom] => { $ crate :: CssSyntaxKind :: RIGHT_BOTTOM_KW } ; [layer] => { $ crate :: CssSyntaxKind :: LAYER_KW } ; [scope] => { $ crate :: CssSyntaxKind :: SCOPE_KW } ; [supports] => { $ crate :: CssSyntaxKind :: SUPPORTS_KW } ; [selector] => { $ crate :: CssSyntaxKind :: SELECTOR_KW } ; [import] => { $ crate :: CssSyntaxKind :: IMPORT_KW } ; [namespace] => { $ crate :: CssSyntaxKind :: NAMESPACE_KW } ; [starting_style] => { $ crate :: CssSyntaxKind :: STARTING_STYLE_KW } ; [scroll_timeline] => { $ crate :: CssSyntaxKind :: SCROLL_TIMELINE_KW } ; [nest] => { $ crate :: CssSyntaxKind :: NEST_KW } ; [position_try] => { $ crate :: CssSyntaxKind :: POSITION_TRY_KW } ; [viewport] => { $ crate :: CssSyntaxKind :: VIEWPORT_KW } ; [document] => { $ crate :: CssSyntaxKind :: DOCUMENT_KW } ; [url_prefix] => { $ crate :: CssSyntaxKind :: URL_PREFIX_KW } ; [domain] => { $ crate :: CssSyntaxKind :: DOMAIN_KW } ; [media_document] => { $ crate :: CssSyntaxKind :: MEDIA_DOCUMENT_KW } ; [regexp] => { $ crate :: CssSyntaxKind :: REGEXP_KW } ; [value] => { $ crate :: CssSyntaxKind :: VALUE_KW } ; [as] => { $ crate :: CssSyntaxKind :: AS_KW } ; [composes] => { $ crate :: CssSyntaxKind :: COMPOSES_KW } ; [font_face] => { $ crate :: CssSyntaxKind :: FONT_FACE_KW } ; [ident] => { $ crate :: CssSyntaxKind :: IDENT } ; [EOF] => { $ crate :: CssSyntaxKind :: EOF } ; [UNICODE_BOM] => { $ crate :: CssSyntaxKind :: UNICODE_BOM } ; [#] => { $ crate :: CssSyntaxKind :: HASH } ; } +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 :: CDO } ; [U+] => { $ crate :: CssSyntaxKind :: UNICODE } ; [media] => { $ crate :: CssSyntaxKind :: MEDIA_KW } ; [keyframes] => { $ crate :: CssSyntaxKind :: KEYFRAMES_KW } ; [not] => { $ crate :: CssSyntaxKind :: NOT_KW } ; [and] => { $ crate :: CssSyntaxKind :: AND_KW } ; [only] => { $ crate :: CssSyntaxKind :: ONLY_KW } ; [or] => { $ crate :: CssSyntaxKind :: OR_KW } ; [i] => { $ crate :: CssSyntaxKind :: I_KW } ; [important] => { $ crate :: CssSyntaxKind :: IMPORTANT_KW } ; [highlight] => { $ crate :: CssSyntaxKind :: HIGHLIGHT_KW } ; [part] => { $ crate :: CssSyntaxKind :: PART_KW } ; [dir] => { $ crate :: CssSyntaxKind :: DIR_KW } ; [local] => { $ crate :: CssSyntaxKind :: LOCAL_KW } ; [global] => { $ crate :: CssSyntaxKind :: GLOBAL_KW } ; [any] => { $ crate :: CssSyntaxKind :: ANY_KW } ; [current] => { $ crate :: CssSyntaxKind :: CURRENT_KW } ; [past] => { $ crate :: CssSyntaxKind :: PAST_KW } ; [future] => { $ crate :: CssSyntaxKind :: FUTURE_KW } ; [host] => { $ crate :: CssSyntaxKind :: HOST_KW } ; [host_context] => { $ crate :: CssSyntaxKind :: HOST_CONTEXT_KW } ; [matches] => { $ crate :: CssSyntaxKind :: MATCHES_KW } ; [is] => { $ crate :: CssSyntaxKind :: IS_KW } ; [where] => { $ crate :: CssSyntaxKind :: WHERE_KW } ; [has] => { $ crate :: CssSyntaxKind :: HAS_KW } ; [lang] => { $ crate :: CssSyntaxKind :: LANG_KW } ; [nth_child] => { $ crate :: CssSyntaxKind :: NTH_CHILD_KW } ; [nth_last_child] => { $ crate :: CssSyntaxKind :: NTH_LAST_CHILD_KW } ; [nth_of_type] => { $ crate :: CssSyntaxKind :: NTH_OF_TYPE_KW } ; [nth_last_of_type] => { $ crate :: CssSyntaxKind :: NTH_LAST_OF_TYPE_KW } ; [nth_col] => { $ crate :: CssSyntaxKind :: NTH_COL_KW } ; [nth_last_col] => { $ crate :: CssSyntaxKind :: NTH_LAST_COL_KW } ; [charset] => { $ crate :: CssSyntaxKind :: CHARSET_KW } ; [color_profile] => { $ crate :: CssSyntaxKind :: COLOR_PROFILE_KW } ; [counter_style] => { $ crate :: CssSyntaxKind :: COUNTER_STYLE_KW } ; [property] => { $ crate :: CssSyntaxKind :: PROPERTY_KW } ; [container] => { $ crate :: CssSyntaxKind :: CONTAINER_KW } ; [style] => { $ crate :: CssSyntaxKind :: STYLE_KW } ; [ltr] => { $ crate :: CssSyntaxKind :: LTR_KW } ; [rtl] => { $ crate :: CssSyntaxKind :: RTL_KW } ; [n] => { $ crate :: CssSyntaxKind :: N_KW } ; [even] => { $ crate :: CssSyntaxKind :: EVEN_KW } ; [odd] => { $ crate :: CssSyntaxKind :: ODD_KW } ; [of] => { $ crate :: CssSyntaxKind :: OF_KW } ; [from] => { $ crate :: CssSyntaxKind :: FROM_KW } ; [to] => { $ crate :: CssSyntaxKind :: TO_KW } ; [var] => { $ crate :: CssSyntaxKind :: VAR_KW } ; [url] => { $ crate :: CssSyntaxKind :: URL_KW } ; [src] => { $ crate :: CssSyntaxKind :: SRC_KW } ; [font_palette_values] => { $ crate :: CssSyntaxKind :: FONT_PALETTE_VALUES_KW } ; [font_feature_values] => { $ crate :: CssSyntaxKind :: FONT_FEATURE_VALUES_KW } ; [stylistic] => { $ crate :: CssSyntaxKind :: STYLISTIC_KW } ; [historical_forms] => { $ crate :: CssSyntaxKind :: HISTORICAL_FORMS_KW } ; [styleset] => { $ crate :: CssSyntaxKind :: STYLESET_KW } ; [character_variant] => { $ crate :: CssSyntaxKind :: CHARACTER_VARIANT_KW } ; [swash] => { $ crate :: CssSyntaxKind :: SWASH_KW } ; [ornaments] => { $ crate :: CssSyntaxKind :: ORNAMENTS_KW } ; [annotation] => { $ crate :: CssSyntaxKind :: ANNOTATION_KW } ; [auto] => { $ crate :: CssSyntaxKind :: AUTO_KW } ; [thin] => { $ crate :: CssSyntaxKind :: THIN_KW } ; [medium] => { $ crate :: CssSyntaxKind :: MEDIUM_KW } ; [thick] => { $ crate :: CssSyntaxKind :: THICK_KW } ; [none] => { $ crate :: CssSyntaxKind :: NONE_KW } ; [hidden] => { $ crate :: CssSyntaxKind :: HIDDEN_KW } ; [dotted] => { $ crate :: CssSyntaxKind :: DOTTED_KW } ; [dashed] => { $ crate :: CssSyntaxKind :: DASHED_KW } ; [solid] => { $ crate :: CssSyntaxKind :: SOLID_KW } ; [double] => { $ crate :: CssSyntaxKind :: DOUBLE_KW } ; [groove] => { $ crate :: CssSyntaxKind :: GROOVE_KW } ; [ridge] => { $ crate :: CssSyntaxKind :: RIDGE_KW } ; [inset] => { $ crate :: CssSyntaxKind :: INSET_KW } ; [outset] => { $ crate :: CssSyntaxKind :: OUTSET_KW } ; [initial] => { $ crate :: CssSyntaxKind :: INITIAL_KW } ; [inherit] => { $ crate :: CssSyntaxKind :: INHERIT_KW } ; [unset] => { $ crate :: CssSyntaxKind :: UNSET_KW } ; [revert] => { $ crate :: CssSyntaxKind :: REVERT_KW } ; [revert_layer] => { $ crate :: CssSyntaxKind :: REVERT_LAYER_KW } ; [default] => { $ crate :: CssSyntaxKind :: DEFAULT_KW } ; [em] => { $ crate :: CssSyntaxKind :: EM_KW } ; [rem] => { $ crate :: CssSyntaxKind :: REM_KW } ; [ex] => { $ crate :: CssSyntaxKind :: EX_KW } ; [rex] => { $ crate :: CssSyntaxKind :: REX_KW } ; [cap] => { $ crate :: CssSyntaxKind :: CAP_KW } ; [rcap] => { $ crate :: CssSyntaxKind :: RCAP_KW } ; [ch] => { $ crate :: CssSyntaxKind :: CH_KW } ; [rch] => { $ crate :: CssSyntaxKind :: RCH_KW } ; [ic] => { $ crate :: CssSyntaxKind :: IC_KW } ; [ric] => { $ crate :: CssSyntaxKind :: RIC_KW } ; [lh] => { $ crate :: CssSyntaxKind :: LH_KW } ; [rlh] => { $ crate :: CssSyntaxKind :: RLH_KW } ; [vw] => { $ crate :: CssSyntaxKind :: VW_KW } ; [svw] => { $ crate :: CssSyntaxKind :: SVW_KW } ; [lvw] => { $ crate :: CssSyntaxKind :: LVW_KW } ; [dvw] => { $ crate :: CssSyntaxKind :: DVW_KW } ; [vh] => { $ crate :: CssSyntaxKind :: VH_KW } ; [svh] => { $ crate :: CssSyntaxKind :: SVH_KW } ; [lvh] => { $ crate :: CssSyntaxKind :: LVH_KW } ; [dvh] => { $ crate :: CssSyntaxKind :: DVH_KW } ; [vi] => { $ crate :: CssSyntaxKind :: VI_KW } ; [svi] => { $ crate :: CssSyntaxKind :: SVI_KW } ; [lvi] => { $ crate :: CssSyntaxKind :: LVI_KW } ; [dvi] => { $ crate :: CssSyntaxKind :: DVI_KW } ; [vb] => { $ crate :: CssSyntaxKind :: VB_KW } ; [svb] => { $ crate :: CssSyntaxKind :: SVB_KW } ; [lvb] => { $ crate :: CssSyntaxKind :: LVB_KW } ; [dvb] => { $ crate :: CssSyntaxKind :: DVB_KW } ; [vmin] => { $ crate :: CssSyntaxKind :: VMIN_KW } ; [svmin] => { $ crate :: CssSyntaxKind :: SVMIN_KW } ; [lvmin] => { $ crate :: CssSyntaxKind :: LVMIN_KW } ; [dvmin] => { $ crate :: CssSyntaxKind :: DVMIN_KW } ; [vmax] => { $ crate :: CssSyntaxKind :: VMAX_KW } ; [svmax] => { $ crate :: CssSyntaxKind :: SVMAX_KW } ; [lvmax] => { $ crate :: CssSyntaxKind :: LVMAX_KW } ; [dvmax] => { $ crate :: CssSyntaxKind :: DVMAX_KW } ; [cm] => { $ crate :: CssSyntaxKind :: CM_KW } ; [mm] => { $ crate :: CssSyntaxKind :: MM_KW } ; [q] => { $ crate :: CssSyntaxKind :: Q_KW } ; [in] => { $ crate :: CssSyntaxKind :: IN_KW } ; [pc] => { $ crate :: CssSyntaxKind :: PC_KW } ; [pt] => { $ crate :: CssSyntaxKind :: PT_KW } ; [px] => { $ crate :: CssSyntaxKind :: PX_KW } ; [mozmm] => { $ crate :: CssSyntaxKind :: MOZMM_KW } ; [rpx] => { $ crate :: CssSyntaxKind :: RPX_KW } ; [cqw] => { $ crate :: CssSyntaxKind :: CQW_KW } ; [cqh] => { $ crate :: CssSyntaxKind :: CQH_KW } ; [cqi] => { $ crate :: CssSyntaxKind :: CQI_KW } ; [cqb] => { $ crate :: CssSyntaxKind :: CQB_KW } ; [cqmin] => { $ crate :: CssSyntaxKind :: CQMIN_KW } ; [cqmax] => { $ crate :: CssSyntaxKind :: CQMAX_KW } ; [deg] => { $ crate :: CssSyntaxKind :: DEG_KW } ; [grad] => { $ crate :: CssSyntaxKind :: GRAD_KW } ; [rad] => { $ crate :: CssSyntaxKind :: RAD_KW } ; [turn] => { $ crate :: CssSyntaxKind :: TURN_KW } ; [s] => { $ crate :: CssSyntaxKind :: S_KW } ; [ms] => { $ crate :: CssSyntaxKind :: MS_KW } ; [hz] => { $ crate :: CssSyntaxKind :: HZ_KW } ; [khz] => { $ crate :: CssSyntaxKind :: KHZ_KW } ; [dpi] => { $ crate :: CssSyntaxKind :: DPI_KW } ; [dpcm] => { $ crate :: CssSyntaxKind :: DPCM_KW } ; [dppx] => { $ crate :: CssSyntaxKind :: DPPX_KW } ; [x] => { $ crate :: CssSyntaxKind :: X_KW } ; [fr] => { $ crate :: CssSyntaxKind :: FR_KW } ; [page] => { $ crate :: CssSyntaxKind :: PAGE_KW } ; [left] => { $ crate :: CssSyntaxKind :: LEFT_KW } ; [right] => { $ crate :: CssSyntaxKind :: RIGHT_KW } ; [first] => { $ crate :: CssSyntaxKind :: FIRST_KW } ; [blank] => { $ crate :: CssSyntaxKind :: BLANK_KW } ; [top_left_corner] => { $ crate :: CssSyntaxKind :: TOP_LEFT_CORNER_KW } ; [top_left] => { $ crate :: CssSyntaxKind :: TOP_LEFT_KW } ; [top_center] => { $ crate :: CssSyntaxKind :: TOP_CENTER_KW } ; [top_right] => { $ crate :: CssSyntaxKind :: TOP_RIGHT_KW } ; [top_right_corner] => { $ crate :: CssSyntaxKind :: TOP_RIGHT_CORNER_KW } ; [bottom_left_corner] => { $ crate :: CssSyntaxKind :: BOTTOM_LEFT_CORNER_KW } ; [bottom_left] => { $ crate :: CssSyntaxKind :: BOTTOM_LEFT_KW } ; [bottom_center] => { $ crate :: CssSyntaxKind :: BOTTOM_CENTER_KW } ; [bottom_right] => { $ crate :: CssSyntaxKind :: BOTTOM_RIGHT_KW } ; [bottom_right_corner] => { $ crate :: CssSyntaxKind :: BOTTOM_RIGHT_CORNER_KW } ; [left_top] => { $ crate :: CssSyntaxKind :: LEFT_TOP_KW } ; [left_middle] => { $ crate :: CssSyntaxKind :: LEFT_MIDDLE_KW } ; [left_bottom] => { $ crate :: CssSyntaxKind :: LEFT_BOTTOM_KW } ; [right_top] => { $ crate :: CssSyntaxKind :: RIGHT_TOP_KW } ; [right_middle] => { $ crate :: CssSyntaxKind :: RIGHT_MIDDLE_KW } ; [right_bottom] => { $ crate :: CssSyntaxKind :: RIGHT_BOTTOM_KW } ; [layer] => { $ crate :: CssSyntaxKind :: LAYER_KW } ; [scope] => { $ crate :: CssSyntaxKind :: SCOPE_KW } ; [supports] => { $ crate :: CssSyntaxKind :: SUPPORTS_KW } ; [selector] => { $ crate :: CssSyntaxKind :: SELECTOR_KW } ; [import] => { $ crate :: CssSyntaxKind :: IMPORT_KW } ; [namespace] => { $ crate :: CssSyntaxKind :: NAMESPACE_KW } ; [starting_style] => { $ crate :: CssSyntaxKind :: STARTING_STYLE_KW } ; [document] => { $ crate :: CssSyntaxKind :: DOCUMENT_KW } ; [url_prefix] => { $ crate :: CssSyntaxKind :: URL_PREFIX_KW } ; [domain] => { $ crate :: CssSyntaxKind :: DOMAIN_KW } ; [media_document] => { $ crate :: CssSyntaxKind :: MEDIA_DOCUMENT_KW } ; [regexp] => { $ crate :: CssSyntaxKind :: REGEXP_KW } ; [value] => { $ crate :: CssSyntaxKind :: VALUE_KW } ; [as] => { $ crate :: CssSyntaxKind :: AS_KW } ; [composes] => { $ crate :: CssSyntaxKind :: COMPOSES_KW } ; [font_face] => { $ crate :: CssSyntaxKind :: FONT_FACE_KW } ; [ident] => { $ crate :: CssSyntaxKind :: IDENT } ; [EOF] => { $ crate :: CssSyntaxKind :: EOF } ; [UNICODE_BOM] => { $ crate :: CssSyntaxKind :: UNICODE_BOM } ; [#] => { $ crate :: CssSyntaxKind :: HASH } ; } diff --git a/xtask/codegen/src/css_kinds_src.rs b/xtask/codegen/src/css_kinds_src.rs index e63c496c07ca..7cffa42b7e6d 100644 --- a/xtask/codegen/src/css_kinds_src.rs +++ b/xtask/codegen/src/css_kinds_src.rs @@ -233,10 +233,6 @@ pub const CSS_KINDS_SRC: KindsSrc = KindsSrc { "import", "namespace", "starting-style", - "scroll-timeline", - "nest", - "position-try", - "viewport", "document", "url-prefix", "domain", From a524cadd0d9a457005ba001f84af6ae8ad5d68f8 Mon Sep 17 00:00:00 2001 From: togami <togami2864@gmail.com> Date: Wed, 4 Dec 2024 00:55:50 +0900 Subject: [PATCH 12/12] chore: add a suggestion to fix the issue --- .../src/lint/nursery/no_unknown_at_rule.rs | 13 +++++--- .../nursery/noUnknownAtRule/invalid.css.snap | 32 ++++++++++++++----- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs index 243c3985df84..3cfd382362e5 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_at_rule.rs @@ -73,9 +73,9 @@ impl Rule for NoUnknownAtRule { }) } - fn diagnostic(_: &RuleContext<Self>, node: &Self::State) -> Option<RuleDiagnostic> { - let span = node.range; - let name = &node.name; + fn diagnostic(_: &RuleContext<Self>, state: &Self::State) -> Option<RuleDiagnostic> { + let span = state.range; + let name = &state.name; Some( RuleDiagnostic::new( rule_category!(), @@ -86,9 +86,12 @@ impl Rule for NoUnknownAtRule { ) .note(markup! { ""<Emphasis>{ name }</Emphasis>" is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended." + }) + .note(markup! { + "See "<Hyperlink href="https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule">"MDN web docs"</Hyperlink>" for a known list of at-rules." }).note(markup! { - "See "<Hyperlink href="https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule">"MDN web docs"</Hyperlink>" for more details." - }), + "To fix this issue, consider removing the unknown at-rule." + }) ) } } diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css.snap index 9d0f4e8ec523..fd79f5aad0be 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css.snap +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownAtRule/invalid.css.snap @@ -26,7 +26,9 @@ invalid.css:1:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━ i unknown-rule is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. - i See MDN web docs for more details. + i See MDN web docs for a known list of at-rules. + + i To fix this issue, consider removing the unknown at-rule. ``` @@ -44,7 +46,9 @@ invalid.css:2:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━ i uNkNoWn is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. - i See MDN web docs for more details. + i See MDN web docs for a known list of at-rules. + + i To fix this issue, consider removing the unknown at-rule. ``` @@ -63,7 +67,9 @@ invalid.css:3:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━ i UNKNOWN is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. - i See MDN web docs for more details. + i See MDN web docs for a known list of at-rules. + + i To fix this issue, consider removing the unknown at-rule. ``` @@ -82,7 +88,9 @@ invalid.css:4:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━ i unknown-at-rule is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. - i See MDN web docs for more details. + i See MDN web docs for a known list of at-rules. + + i To fix this issue, consider removing the unknown at-rule. ``` @@ -101,7 +109,9 @@ invalid.css:5:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━ i unknown is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. - i See MDN web docs for more details. + i See MDN web docs for a known list of at-rules. + + i To fix this issue, consider removing the unknown at-rule. ``` @@ -120,7 +130,9 @@ invalid.css:5:13 lint/nursery/noUnknownAtRule ━━━━━━━━━━━ i unknown-at-rule is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. - i See MDN web docs for more details. + i See MDN web docs for a known list of at-rules. + + i To fix this issue, consider removing the unknown at-rule. ``` @@ -138,7 +150,9 @@ invalid.css:6:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━ i MY-other-at-rule is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. - i See MDN web docs for more details. + i See MDN web docs for a known list of at-rules. + + i To fix this issue, consider removing the unknown at-rule. ``` @@ -155,7 +169,9 @@ invalid.css:7:2 lint/nursery/noUnknownAtRule ━━━━━━━━━━━ i not-my-at-rule is not a standard CSS at-rule, which may lead to unexpected styling results or failure to interpret the styles as intended. - i See MDN web docs for more details. + i See MDN web docs for a known list of at-rules. + + i To fix this issue, consider removing the unknown at-rule. ```