From 1683c6a2777a84bfdc79c93f1d1f599e9ddd52ec Mon Sep 17 00:00:00 2001 From: neoki Date: Sat, 20 Apr 2024 06:25:22 +0900 Subject: [PATCH 01/24] chore: add noUnknownUnit rule --- .../biome_configuration/src/linter/rules.rs | 27 +++++- crates/biome_css_analyze/src/lint/nursery.rs | 2 + .../src/lint/nursery/no_unknown_unit.rs | 95 +++++++++++++++++++ crates/biome_css_analyze/src/options.rs | 2 + .../src/categories.rs | 1 + .../@biomejs/backend-jsonrpc/src/workspace.ts | 5 + .../@biomejs/biome/configuration_schema.json | 7 ++ 7 files changed, 135 insertions(+), 4 deletions(-) create mode 100644 crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs diff --git a/crates/biome_configuration/src/linter/rules.rs b/crates/biome_configuration/src/linter/rules.rs index ed3495c7e71b..21943770ad8d 100644 --- a/crates/biome_configuration/src/linter/rules.rs +++ b/crates/biome_configuration/src/linter/rules.rs @@ -2689,6 +2689,9 @@ pub struct Nursery { #[doc = "Disallow the use of dependencies that aren't specified in the package.json."] #[serde(skip_serializing_if = "Option::is_none")] pub no_undeclared_dependencies: Option>, + #[doc = "Disallow unknown units."] + #[serde(skip_serializing_if = "Option::is_none")] + pub no_unknown_unit: Option>, #[doc = "Disallows package private imports."] #[serde(skip_serializing_if = "Option::is_none")] pub use_import_restrictions: Option>, @@ -2727,6 +2730,7 @@ impl Nursery { "noReactSpecificProps", "noRestrictedImports", "noUndeclaredDependencies", + "noUnknownUnit", "useImportRestrictions", "useSortedClasses", ]; @@ -2763,6 +2767,7 @@ impl Nursery { RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[13]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[14]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[15]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[16]), ]; #[doc = r" Retrieves the recommended rules"] pub(crate) fn is_recommended_true(&self) -> bool { @@ -2849,16 +2854,21 @@ impl Nursery { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[13])); } } - if let Some(rule) = self.use_import_restrictions.as_ref() { + if let Some(rule) = self.no_unknown_unit.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[14])); } } - if let Some(rule) = self.use_sorted_classes.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[15])); } } + 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[16])); + } + } index_set } pub(crate) fn get_disabled_rules(&self) -> IndexSet { @@ -2933,16 +2943,21 @@ impl Nursery { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[13])); } } - if let Some(rule) = self.use_import_restrictions.as_ref() { + if let Some(rule) = self.no_unknown_unit.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[14])); } } - if let Some(rule) = self.use_sorted_classes.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[15])); } } + 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[16])); + } + } index_set } #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"] @@ -3035,6 +3050,10 @@ impl Nursery { .no_undeclared_dependencies .as_ref() .map(|conf| (conf.level(), conf.get_options())), + "noUnknownUnit" => self + .no_unknown_unit + .as_ref() + .map(|conf| (conf.level(), conf.get_options())), "useImportRestrictions" => self .use_import_restrictions .as_ref() diff --git a/crates/biome_css_analyze/src/lint/nursery.rs b/crates/biome_css_analyze/src/lint/nursery.rs index 75e80277d7fb..4fe83ed6c4c2 100644 --- a/crates/biome_css_analyze/src/lint/nursery.rs +++ b/crates/biome_css_analyze/src/lint/nursery.rs @@ -4,6 +4,7 @@ use biome_analyze::declare_group; pub mod no_color_invalid_hex; pub mod no_duplicate_font_names; +pub mod no_unknown_unit; declare_group! { pub Nursery { @@ -11,6 +12,7 @@ declare_group! { rules : [ self :: no_color_invalid_hex :: NoColorInvalidHex , self :: no_duplicate_font_names :: NoDuplicateFontNames , + self :: no_unknown_unit :: NoUnknownUnit , ] } } diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs new file mode 100644 index 000000000000..523c65498b69 --- /dev/null +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs @@ -0,0 +1,95 @@ +use biome_analyze::{context::RuleContext, declare_rule, Ast, Rule, RuleDiagnostic, RuleSource}; +use biome_console::markup; +use biome_css_syntax::CssDeclarationOrRuleBlock; +use biome_rowan::AstNode; + +declare_rule! { + /// Disallow unknown units. + /// + /// This rule considers units defined in the CSS Specifications, up to and including Editor's Drafts, to be known. + /// + /// + /// ## Examples + /// + /// ### Invalid + /// + /// ```css,expect_diagnostic + /// a { + /// width: 10pixels; + /// } + /// ``` + /// + /// ```css,expect_diagnostic + /// a { + /// width: calc(10px + 10pixels); + /// } + /// ``` + /// + /// ### Valid + /// + /// ```css + /// a { + /// width: 10px; + /// } + /// ``` + /// + /// ```css + /// a { + /// width: 10Px; + /// } + /// ``` + /// + /// ```css + /// a { + /// width: 10pX; + /// } + /// ``` + /// + /// ```css + /// a { + /// width: calc(10px + 10px); + /// } + /// ``` + /// + pub NoUnknownUnit { + version: "next", + name: "noUnknownUnit", + recommended: false, + sources: &[RuleSource::Stylelint("unit-no-unknown")], + } +} + +impl Rule for NoUnknownUnit { + type Query = Ast; + type State = CssDeclarationOrRuleBlock; + type Signals = Option; + type Options = (); + + fn run(ctx: &RuleContext) -> Option { + let node = ctx.query(); + if node.items().into_iter().next().is_none() { + return Some(node.clone()); + } + None + } + + fn diagnostic(_: &RuleContext, node: &Self::State) -> Option { + // + // 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 e3f743001773..0015ea1b770f 100644 --- a/crates/biome_css_analyze/src/options.rs +++ b/crates/biome_css_analyze/src/options.rs @@ -6,3 +6,5 @@ pub type NoColorInvalidHex = ::Options; pub type NoDuplicateFontNames = ::Options; +pub type NoUnknownUnit = + ::Options; diff --git a/crates/biome_diagnostics_categories/src/categories.rs b/crates/biome_diagnostics_categories/src/categories.rs index 603a8ff3cf30..320f4ec807e3 100644 --- a/crates/biome_diagnostics_categories/src/categories.rs +++ b/crates/biome_diagnostics_categories/src/categories.rs @@ -125,6 +125,7 @@ define_categories! { "lint/nursery/noRestrictedImports": "https://biomejs.dev/linter/rules/no-restricted-imports", "lint/nursery/noTypeOnlyImportAttributes": "https://biomejs.dev/linter/rules/no-type-only-import-attributes", "lint/nursery/noUndeclaredDependencies": "https://biomejs.dev/linter/rules/no-undeclared-dependencies", + "lint/nursery/noUnknownUnit": "https://biomejs.dev/linter/rules/no-unknown-unit", "lint/nursery/useBiomeSuppressionComment": "https://biomejs.dev/linter/rules/use-biome-suppression-comment", "lint/nursery/useImportRestrictions": "https://biomejs.dev/linter/rules/use-import-restrictions", "lint/nursery/useSortedClasses": "https://biomejs.dev/linter/rules/use-sorted-classes", diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index bfe10770e117..e7b34f61ee84 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -964,6 +964,10 @@ export interface Nursery { * Disallow the use of dependencies that aren't specified in the package.json. */ noUndeclaredDependencies?: RuleConfiguration_for_Null; + /** + * Disallow unknown units. + */ + noUnknownUnit?: RuleConfiguration_for_Null; /** * It enables the recommended rules for this group */ @@ -1941,6 +1945,7 @@ export type Category = | "lint/nursery/noRestrictedImports" | "lint/nursery/noTypeOnlyImportAttributes" | "lint/nursery/noUndeclaredDependencies" + | "lint/nursery/noUnknownUnit" | "lint/nursery/useBiomeSuppressionComment" | "lint/nursery/useImportRestrictions" | "lint/nursery/useSortedClasses" diff --git a/packages/@biomejs/biome/configuration_schema.json b/packages/@biomejs/biome/configuration_schema.json index 92ffbdec9830..ec95007d6938 100644 --- a/packages/@biomejs/biome/configuration_schema.json +++ b/packages/@biomejs/biome/configuration_schema.json @@ -1519,6 +1519,13 @@ { "type": "null" } ] }, + "noUnknownUnit": { + "description": "Disallow unknown units.", + "anyOf": [ + { "$ref": "#/definitions/RuleConfiguration" }, + { "type": "null" } + ] + }, "recommended": { "description": "It enables the recommended rules for this group", "type": ["boolean", "null"] From b6a5279e9e8c3b7ea949d4ef2588972c013228e0 Mon Sep 17 00:00:00 2001 From: neoki Date: Sat, 20 Apr 2024 06:25:59 +0900 Subject: [PATCH 02/24] test: add no-unknown-unit tests --- .../specs/nursery/noUnknownUnit/invalid.css | 29 ++++++++ .../specs/nursery/noUnknownUnit/valid.css | 73 +++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css new file mode 100644 index 000000000000..603da6e7eb93 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css @@ -0,0 +1,29 @@ +a { font-size: 13pp; } +a { margin: 13xpx; } +a { font-size: .5remm; } +a { font-size: 0.5remm; } +a { color: rgb(255pix, 0, 51); } +a { color: hsl(255pix, 0, 51); } +a { color: rgba(255pix, 0, 51, 1); } +a { color: hsla(255pix, 0, 51, 1); } +a { margin: calc(13pix + 10px); } +a { margin: calc(10pix*2); } +a { margin: calc(2*10pix); } +a { -webkit-transition-delay: 10pix; } +a { margin: -webkit-calc(13pix + 10px); } +a { margin: some-function(13pix + 10px); } +root { --margin: 10pix; } +root { --margin: 10px + 10pix; } +@media (min-width: 13pix) {} +@media (min-width: 10px)\n and (max-width: 20PIX) {} +@media (width < 10.01REMS) {} +a { width: 1e4pz; } +a { flex: 0 9r9 auto; } +a { width: 400x; } +@media (resolution: 2x) and (min-width: 200x) {} +@media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} +a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } +a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } +a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } +@font-face { color: U+0100-024F; } +a { unicode-range: U+0100-024F; } diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css new file mode 100644 index 000000000000..80f3891a367e --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css @@ -0,0 +1,73 @@ +a { line-height: 1; } +a { color: #000; } +a { font-size: 100%; } +a { margin: 1em; } +a { margin: 1Em; } +a { margin: 1EM; } +a { margin: 1ex; } +a { margin: 1%; } +a { margin: 1px; } +a { margin: 1cm; } +a { margin: 1mm; } +a { margin: 1in; } +a { margin: 1pt; } +a { margin: 1pc; } +a { margin: 1ch; } +a { margin: 1rem; } +a { margin: 1vh; } +a { margin: 1vw; } +a { margin: 1vmin; } +a { margin: 1vmax; } +a { font-size: .5rem; } +a { font-size: 0.5rem; } +a { margin: 1vmin 1vmax; } +a { margin: 0 10em 5rem 2in; } +a { background-position: top right, 1em 5vh; } +a { top: calc(10em - 3em); } +a { top: calc(10px*2); } +a { top: calc(10px*2%*2); } +a { top: calc(2*10px); } +a { background-image: linear-gradient(to right, white calc(100% - 50em), silver); } +a { transition-delay: 3s; } +a { transition-delay: 300ms; } +a { transform: rotate(90deg); } +a { transform: rotate(100grad); } +a { transform: rotate(0.25turn); } +a { transform: rotate(1.5708rad); } +a { grid-template-columns: repeat(12, 1fr); } +a { width: 1e4px } +a { width: 1E4px } +a { width: 1e10; } +a { flex: 0 9e9 auto; } +a { color: green; } +a { color: green10pix; } +a { width: /* 100pix */ 1em; } +a::before { content: "10pix"} +a { font-size: $fs10pix; } +a { font-size: @fs10pix; } +a { font-size: var(--some-fs-10pix); } +a { margin: url(13pix); } +a { margin: uRl(13pix); } +a { margin: URL(13pix); } +a { margin10px: 10px; } +a10pix { margin: 10px; } +#a10pix { margin: 10px; } +.a10pix { margin: 10px; } +input[type=10pix] { margin: 10px; } +a:hover10pix { margin: 10px; } +a::before10pix { margin: 10px; } +a { color: #1f1f1f; } +@media (min-width: 10px) {} +@media (min-width: 10px)\n and (max-width: 20px) {} +@media screen and (min-width:0\\0) {} +@import 'foo.css'; +a { background-image: image-set('img-1x.jpg' 1x, 'img-2x.jpg' 2x, 'img-3x.jpg' 3x) } +a { background-image: -webkit-image-set('img-1x.jpg' 1x, 'img-2x.jpg' 2x) } +a { background-image: url('first.png'), image-set(url('second.png') 1x), image-set(url('third.png') 1x) } +a { background-image: url('first.png'), -webkit-image-set(url('second.png') 1x), -webkit-image-set(url('third.png') 1x) } +a { background-image: image-set(url('first.png') calc(1x * 1), url('second.png') calc(1x + 0.5x)); } +@media (resolution: 2x) {} +@media ( resOLution: 2x) {} +a { image-resolution: 1x; } +a { width: 8ic; } +@font-face { unicode-range: U+0100-024F; } From 7eebe23c2143d2bbc6252786060b9a54576723f7 Mon Sep 17 00:00:00 2001 From: neoki Date: Sat, 20 Apr 2024 10:22:19 +0900 Subject: [PATCH 03/24] feat: implement no-unknown-unit rule --- .../src/lint/nursery/no_unknown_unit.rs | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs index 523c65498b69..30b4a5353e2c 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs @@ -1,7 +1,7 @@ use biome_analyze::{context::RuleContext, declare_rule, Ast, Rule, RuleDiagnostic, RuleSource}; use biome_console::markup; -use biome_css_syntax::CssDeclarationOrRuleBlock; -use biome_rowan::AstNode; +use biome_css_syntax::CssUnknownDimension; +use biome_rowan::TextRange; declare_rule! { /// Disallow unknown units. @@ -59,36 +59,50 @@ declare_rule! { } } +pub struct RuleState { + value: String, + span: TextRange, +} + +fn is_css_hack_unit(value: &str) -> bool { + value == "\\0" +} + impl Rule for NoUnknownUnit { - type Query = Ast; - type State = CssDeclarationOrRuleBlock; + type Query = Ast; + type State = RuleState; type Signals = Option; type Options = (); fn run(ctx: &RuleContext) -> Option { let node = ctx.query(); - if node.items().into_iter().next().is_none() { - return Some(node.clone()); + + if let Ok(unit_token) = node.unit_token() { + let value = unit_token.text().to_string(); + let span = unit_token.text_range(); + + if is_css_hack_unit(&value) { + return None; + } + + return Some(RuleState { value, span }); } + None } - fn diagnostic(_: &RuleContext, node: &Self::State) -> Option { - // - // 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(); + fn diagnostic(_: &RuleContext, state: &Self::State) -> Option { + let span = state.span; Some( RuleDiagnostic::new( rule_category!(), span, markup! { - "Unexpected empty block is not allowed" + "Unexpected unknown unit: "{ state.value } }, ) .note(markup! { - "This note will give you more information." + "Fix to a known unit." }), ) } From 4b420a97f0306816d6d32fdb0ca58274d758de98 Mon Sep 17 00:00:00 2001 From: neoki Date: Sat, 20 Apr 2024 10:22:57 +0900 Subject: [PATCH 04/24] test: fix css hack test --- .../tests/specs/nursery/noUnknownUnit/valid.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css index 80f3891a367e..4cd5c044ba49 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css @@ -59,7 +59,7 @@ a::before10pix { margin: 10px; } a { color: #1f1f1f; } @media (min-width: 10px) {} @media (min-width: 10px)\n and (max-width: 20px) {} -@media screen and (min-width:0\\0) {} +@media screen and (min-width:0\0) {} @import 'foo.css'; a { background-image: image-set('img-1x.jpg' 1x, 'img-2x.jpg' 2x, 'img-3x.jpg' 3x) } a { background-image: -webkit-image-set('img-1x.jpg' 1x, 'img-2x.jpg' 2x) } From 5b437d893bd699bf9be9d9e7d869cf5468b69e36 Mon Sep 17 00:00:00 2001 From: neoki Date: Sat, 20 Apr 2024 10:35:34 +0900 Subject: [PATCH 05/24] test: add snapshots --- .../nursery/noUnknownUnit/invalid.css.snap | 425 ++++++++++++++++++ .../nursery/noUnknownUnit/valid.css.snap | 98 ++++ 2 files changed, 523 insertions(+) create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css.snap diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap new file mode 100644 index 000000000000..cc6d01c8c074 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap @@ -0,0 +1,425 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +expression: invalid.css +--- +# Input +```css +a { font-size: 13pp; } +a { margin: 13xpx; } +a { font-size: .5remm; } +a { font-size: 0.5remm; } +a { color: rgb(255pix, 0, 51); } +a { color: hsl(255pix, 0, 51); } +a { color: rgba(255pix, 0, 51, 1); } +a { color: hsla(255pix, 0, 51, 1); } +a { margin: calc(13pix + 10px); } +a { margin: calc(10pix*2); } +a { margin: calc(2*10pix); } +a { -webkit-transition-delay: 10pix; } +a { margin: -webkit-calc(13pix + 10px); } +a { margin: some-function(13pix + 10px); } +root { --margin: 10pix; } +root { --margin: 10px + 10pix; } +@media (min-width: 13pix) {} +@media (min-width: 10px)\n and (max-width: 20PIX) {} +@media (width < 10.01REMS) {} +a { width: 1e4pz; } +a { flex: 0 9r9 auto; } +a { width: 400x; } +@media (resolution: 2x) and (min-width: 200x) {} +@media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} +a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } +a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } +a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } +@font-face { color: U+0100-024F; } +a { unicode-range: U+0100-024F; } + +``` + +# Diagnostics +``` +invalid.css:1:18 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pp + + > 1 │ a { font-size: 13pp; } + │ ^^ + 2 │ a { margin: 13xpx; } + 3 │ a { font-size: .5remm; } + + i Fix to a known unit. + + +``` + +``` +invalid.css:2:15 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: xpx + + 1 │ a { font-size: 13pp; } + > 2 │ a { margin: 13xpx; } + │ ^^^ + 3 │ a { font-size: .5remm; } + 4 │ a { font-size: 0.5remm; } + + i Fix to a known unit. + + +``` + +``` +invalid.css:3:18 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: remm + + 1 │ a { font-size: 13pp; } + 2 │ a { margin: 13xpx; } + > 3 │ a { font-size: .5remm; } + │ ^^^^ + 4 │ a { font-size: 0.5remm; } + 5 │ a { color: rgb(255pix, 0, 51); } + + i Fix to a known unit. + + +``` + +``` +invalid.css:4:19 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: remm + + 2 │ a { margin: 13xpx; } + 3 │ a { font-size: .5remm; } + > 4 │ a { font-size: 0.5remm; } + │ ^^^^ + 5 │ a { color: rgb(255pix, 0, 51); } + 6 │ a { color: hsl(255pix, 0, 51); } + + i Fix to a known unit. + + +``` + +``` +invalid.css:5:19 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 3 │ a { font-size: .5remm; } + 4 │ a { font-size: 0.5remm; } + > 5 │ a { color: rgb(255pix, 0, 51); } + │ ^^^ + 6 │ a { color: hsl(255pix, 0, 51); } + 7 │ a { color: rgba(255pix, 0, 51, 1); } + + i Fix to a known unit. + + +``` + +``` +invalid.css:6:19 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 4 │ a { font-size: 0.5remm; } + 5 │ a { color: rgb(255pix, 0, 51); } + > 6 │ a { color: hsl(255pix, 0, 51); } + │ ^^^ + 7 │ a { color: rgba(255pix, 0, 51, 1); } + 8 │ a { color: hsla(255pix, 0, 51, 1); } + + i Fix to a known unit. + + +``` + +``` +invalid.css:7:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 5 │ a { color: rgb(255pix, 0, 51); } + 6 │ a { color: hsl(255pix, 0, 51); } + > 7 │ a { color: rgba(255pix, 0, 51, 1); } + │ ^^^ + 8 │ a { color: hsla(255pix, 0, 51, 1); } + 9 │ a { margin: calc(13pix + 10px); } + + i Fix to a known unit. + + +``` + +``` +invalid.css:8:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 6 │ a { color: hsl(255pix, 0, 51); } + 7 │ a { color: rgba(255pix, 0, 51, 1); } + > 8 │ a { color: hsla(255pix, 0, 51, 1); } + │ ^^^ + 9 │ a { margin: calc(13pix + 10px); } + 10 │ a { margin: calc(10pix*2); } + + i Fix to a known unit. + + +``` + +``` +invalid.css:9:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 7 │ a { color: rgba(255pix, 0, 51, 1); } + 8 │ a { color: hsla(255pix, 0, 51, 1); } + > 9 │ a { margin: calc(13pix + 10px); } + │ ^^^^ + 10 │ a { margin: calc(10pix*2); } + 11 │ a { margin: calc(2*10pix); } + + i Fix to a known unit. + + +``` + +``` +invalid.css:10:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 8 │ a { color: hsla(255pix, 0, 51, 1); } + 9 │ a { margin: calc(13pix + 10px); } + > 10 │ a { margin: calc(10pix*2); } + │ ^^^ + 11 │ a { margin: calc(2*10pix); } + 12 │ a { -webkit-transition-delay: 10pix; } + + i Fix to a known unit. + + +``` + +``` +invalid.css:11:22 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 9 │ a { margin: calc(13pix + 10px); } + 10 │ a { margin: calc(10pix*2); } + > 11 │ a { margin: calc(2*10pix); } + │ ^^^ + 12 │ a { -webkit-transition-delay: 10pix; } + 13 │ a { margin: -webkit-calc(13pix + 10px); } + + i Fix to a known unit. + + +``` + +``` +invalid.css:12:33 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 10 │ a { margin: calc(10pix*2); } + 11 │ a { margin: calc(2*10pix); } + > 12 │ a { -webkit-transition-delay: 10pix; } + │ ^^^ + 13 │ a { margin: -webkit-calc(13pix + 10px); } + 14 │ a { margin: some-function(13pix + 10px); } + + i Fix to a known unit. + + +``` + +``` +invalid.css:13:28 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 11 │ a { margin: calc(2*10pix); } + 12 │ a { -webkit-transition-delay: 10pix; } + > 13 │ a { margin: -webkit-calc(13pix + 10px); } + │ ^^^^ + 14 │ a { margin: some-function(13pix + 10px); } + 15 │ root { --margin: 10pix; } + + i Fix to a known unit. + + +``` + +``` +invalid.css:14:29 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 12 │ a { -webkit-transition-delay: 10pix; } + 13 │ a { margin: -webkit-calc(13pix + 10px); } + > 14 │ a { margin: some-function(13pix + 10px); } + │ ^^^^ + 15 │ root { --margin: 10pix; } + 16 │ root { --margin: 10px + 10pix; } + + i Fix to a known unit. + + +``` + +``` +invalid.css:15:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 13 │ a { margin: -webkit-calc(13pix + 10px); } + 14 │ a { margin: some-function(13pix + 10px); } + > 15 │ root { --margin: 10pix; } + │ ^^^ + 16 │ root { --margin: 10px + 10pix; } + 17 │ @media (min-width: 13pix) {} + + i Fix to a known unit. + + +``` + +``` +invalid.css:17:22 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 15 │ root { --margin: 10pix; } + 16 │ root { --margin: 10px + 10pix; } + > 17 │ @media (min-width: 13pix) {} + │ ^^^ + 18 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} + 19 │ @media (width < 10.01REMS) {} + + i Fix to a known unit. + + +``` + +``` +invalid.css:18:47 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: PIX + + 16 │ root { --margin: 10px + 10pix; } + 17 │ @media (min-width: 13pix) {} + > 18 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} + │ ^^^ + 19 │ @media (width < 10.01REMS) {} + 20 │ a { width: 1e4pz; } + + i Fix to a known unit. + + +``` + +``` +invalid.css:19:22 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: REMS + + 17 │ @media (min-width: 13pix) {} + 18 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} + > 19 │ @media (width < 10.01REMS) {} + │ ^^^^ + 20 │ a { width: 1e4pz; } + 21 │ a { flex: 0 9r9 auto; } + + i Fix to a known unit. + + +``` + +``` +invalid.css:20:15 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pz + + 18 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} + 19 │ @media (width < 10.01REMS) {} + > 20 │ a { width: 1e4pz; } + │ ^^ + 21 │ a { flex: 0 9r9 auto; } + 22 │ a { width: 400x; } + + i Fix to a known unit. + + +``` + +``` +invalid.css:21:14 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: r9 + + 19 │ @media (width < 10.01REMS) {} + 20 │ a { width: 1e4pz; } + > 21 │ a { flex: 0 9r9 auto; } + │ ^^^ + 22 │ a { width: 400x; } + 23 │ @media (resolution: 2x) and (min-width: 200x) {} + + i Fix to a known unit. + + +``` + +``` +invalid.css:27:46 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 25 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + 26 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + > 27 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } + │ ^^^ + 28 │ @font-face { color: U+0100-024F; } + 29 │ a { unicode-range: U+0100-024F; } + + i Fix to a known unit. + + +``` + +``` +invalid.css:28:31 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: F + + 26 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + 27 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } + > 28 │ @font-face { color: U+0100-024F; } + │ ^ + 29 │ a { unicode-range: U+0100-024F; } + 30 │ + + i Fix to a known unit. + + +``` + +``` +invalid.css:29:30 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: F + + 27 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } + 28 │ @font-face { color: U+0100-024F; } + > 29 │ a { unicode-range: U+0100-024F; } + │ ^ + 30 │ + + i Fix to a known unit. + + +``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css.snap new file mode 100644 index 000000000000..26b7efe0e421 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css.snap @@ -0,0 +1,98 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +expression: valid.css +--- +# Input +```css +a { line-height: 1; } +a { color: #000; } +a { font-size: 100%; } +a { margin: 1em; } +a { margin: 1Em; } +a { margin: 1EM; } +a { margin: 1ex; } +a { margin: 1%; } +a { margin: 1px; } +a { margin: 1cm; } +a { margin: 1mm; } +a { margin: 1in; } +a { margin: 1pt; } +a { margin: 1pc; } +a { margin: 1ch; } +a { margin: 1rem; } +a { margin: 1vh; } +a { margin: 1vw; } +a { margin: 1vmin; } +a { margin: 1vmax; } +a { font-size: .5rem; } +a { font-size: 0.5rem; } +a { margin: 1vmin 1vmax; } +a { margin: 0 10em 5rem 2in; } +a { background-position: top right, 1em 5vh; } +a { top: calc(10em - 3em); } +a { top: calc(10px*2); } +a { top: calc(10px*2%*2); } +a { top: calc(2*10px); } +a { background-image: linear-gradient(to right, white calc(100% - 50em), silver); } +a { transition-delay: 3s; } +a { transition-delay: 300ms; } +a { transform: rotate(90deg); } +a { transform: rotate(100grad); } +a { transform: rotate(0.25turn); } +a { transform: rotate(1.5708rad); } +a { grid-template-columns: repeat(12, 1fr); } +a { width: 1e4px } +a { width: 1E4px } +a { width: 1e10; } +a { flex: 0 9e9 auto; } +a { color: green; } +a { color: green10pix; } +a { width: /* 100pix */ 1em; } +a::before { content: "10pix"} +a { font-size: $fs10pix; } +a { font-size: @fs10pix; } +a { font-size: var(--some-fs-10pix); } +a { margin: url(13pix); } +a { margin: uRl(13pix); } +a { margin: URL(13pix); } +a { margin10px: 10px; } +a10pix { margin: 10px; } +#a10pix { margin: 10px; } +.a10pix { margin: 10px; } +input[type=10pix] { margin: 10px; } +a:hover10pix { margin: 10px; } +a::before10pix { margin: 10px; } +a { color: #1f1f1f; } +@media (min-width: 10px) {} +@media (min-width: 10px)\n and (max-width: 20px) {} +@media screen and (min-width:0\0) {} +@import 'foo.css'; +a { background-image: image-set('img-1x.jpg' 1x, 'img-2x.jpg' 2x, 'img-3x.jpg' 3x) } +a { background-image: -webkit-image-set('img-1x.jpg' 1x, 'img-2x.jpg' 2x) } +a { background-image: url('first.png'), image-set(url('second.png') 1x), image-set(url('third.png') 1x) } +a { background-image: url('first.png'), -webkit-image-set(url('second.png') 1x), -webkit-image-set(url('third.png') 1x) } +a { background-image: image-set(url('first.png') calc(1x * 1), url('second.png') calc(1x + 0.5x)); } +@media (resolution: 2x) {} +@media ( resOLution: 2x) {} +a { image-resolution: 1x; } +a { width: 8ic; } +@font-face { unicode-range: U+0100-024F; } + +``` + +# Diagnostics +``` +valid.css:73:39 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: F + + 71 │ a { image-resolution: 1x; } + 72 │ a { width: 8ic; } + > 73 │ @font-face { unicode-range: U+0100-024F; } + │ ^ + 74 │ + + i Fix to a known unit. + + +``` From bfee475c42d8a115cb99c0a1ea3e8b7267ba0a68 Mon Sep 17 00:00:00 2001 From: neoki Date: Sun, 21 Apr 2024 02:40:44 +0900 Subject: [PATCH 06/24] fix: corresponding to edge cases --- Cargo.lock | 1 + crates/biome_css_analyze/Cargo.toml | 1 + .../src/lint/nursery/no_unknown_unit.rs | 109 +++++++++++++++--- crates/biome_css_analyze/src/utils.rs | 6 + 4 files changed, 102 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dca8fe6b2bc6..11543e52d070 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -262,6 +262,7 @@ dependencies = [ "biome_test_utils", "insta", "lazy_static", + "regex", "tests_macros", ] diff --git a/crates/biome_css_analyze/Cargo.toml b/crates/biome_css_analyze/Cargo.toml index 669af7a91108..0e167f377be1 100644 --- a/crates/biome_css_analyze/Cargo.toml +++ b/crates/biome_css_analyze/Cargo.toml @@ -19,6 +19,7 @@ biome_css_syntax = { workspace = true } biome_diagnostics = { workspace = true } biome_rowan = { workspace = true } lazy_static = { workspace = true } +regex = { workspace = true } [dev-dependencies] biome_css_parser = { path = "../biome_css_parser" } diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs index 30b4a5353e2c..80a2a9988835 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs @@ -1,7 +1,18 @@ use biome_analyze::{context::RuleContext, declare_rule, Ast, Rule, RuleDiagnostic, RuleSource}; use biome_console::markup; -use biome_css_syntax::CssUnknownDimension; -use biome_rowan::TextRange; +use biome_css_syntax::{ + AnyCssDimension, CssFunction, CssGenericProperty, CssQueryFeaturePlain, CssSyntaxKind, +}; +use biome_rowan::{SyntaxNodeCast, TextRange}; + +use crate::utils::strip_vendor_prefix; + +const RESOLUTION_MEDIA_FEATURE_NAMES: [&str; 3] = + ["resolution", "min-resolution", "max-resolution"]; + +fn is_css_hack_unit(value: &str) -> bool { + value == "\\0" +} declare_rule! { /// Disallow unknown units. @@ -64,12 +75,8 @@ pub struct RuleState { span: TextRange, } -fn is_css_hack_unit(value: &str) -> bool { - value == "\\0" -} - impl Rule for NoUnknownUnit { - type Query = Ast; + type Query = Ast; type State = RuleState; type Signals = Option; type Options = (); @@ -77,18 +84,90 @@ impl Rule for NoUnknownUnit { fn run(ctx: &RuleContext) -> Option { let node = ctx.query(); - if let Ok(unit_token) = node.unit_token() { - let value = unit_token.text().to_string(); - let span = unit_token.text_range(); + // dbg!(ctx.root()); - if is_css_hack_unit(&value) { - return None; + match node { + AnyCssDimension::CssUnknownDimension(dimension) => { + let unit_token = dimension.unit_token().ok()?; + let unit = unit_token.text_trimmed().to_string(); + + if is_css_hack_unit(&unit) { + return None; + } + + Some(RuleState { + value: unit, + span: unit_token.text_trimmed_range(), + }) } + AnyCssDimension::CssRegularDimension(dimension) => { + let unit_token = dimension.unit_token().ok()?; + let unit = unit_token.text_trimmed().to_string(); - return Some(RuleState { value, span }); - } + if unit == "x" { + let mut allow_x = false; + + for ancestor in dimension.unit_token().ok()?.ancestors() { + match ancestor.kind() { + CssSyntaxKind::CSS_FUNCTION => { + let function_name = ancestor + .cast::()? + .name() + .ok()? + .value_token() + .ok()? + .text_trimmed() + .to_lowercase(); + + if strip_vendor_prefix(function_name.as_str()) == "image-set" { + allow_x = true; + } + } + CssSyntaxKind::CSS_QUERY_FEATURE_PLAIN => { + let feature_name = ancestor + .cast::()? + .name() + .ok()? + .value_token() + .ok()? + .text_trimmed() + .to_lowercase(); - None + if RESOLUTION_MEDIA_FEATURE_NAMES.contains(&feature_name.as_str()) { + allow_x = true; + } + } + CssSyntaxKind::CSS_GENERIC_PROPERTY => { + let property_name = ancestor + .cast::()? + .name() + .ok()? + .as_css_identifier()? + .value_token() + .ok()? + .text_trimmed() + .to_lowercase(); + + if property_name == "image-resolution" { + allow_x = true; + } + } + _ => {} + } + } + + if !allow_x { + return Some(RuleState { + value: unit, + span: unit_token.text_trimmed_range(), + }); + } + } + + None + } + _ => None, + } } fn diagnostic(_: &RuleContext, state: &Self::State) -> Option { diff --git a/crates/biome_css_analyze/src/utils.rs b/crates/biome_css_analyze/src/utils.rs index a26f4c08ff13..981a822ba439 100644 --- a/crates/biome_css_analyze/src/utils.rs +++ b/crates/biome_css_analyze/src/utils.rs @@ -5,6 +5,7 @@ use crate::keywords::{ }; use biome_css_syntax::{AnyCssGenericComponentValue, AnyCssValue, CssGenericComponentValueList}; use biome_rowan::{AstNode, SyntaxNodeCast}; +use regex::Regex; pub fn is_font_family_keyword(value: &str) -> bool { BASIC_KEYWORDS.contains(&value) || FONT_FAMILY_KEYWORDS.contains(&value) @@ -92,3 +93,8 @@ pub fn find_font_family(value: CssGenericComponentValueList) -> Vec } font_families } + +pub fn strip_vendor_prefix(property: &str) -> String { + let re = Regex::new(r"^-\w+-").unwrap(); + re.replace(property, "").to_string() +} From 306e4a412a2b842641fd02f90faac139c13d5c7d Mon Sep 17 00:00:00 2001 From: neoki Date: Sun, 21 Apr 2024 02:41:01 +0900 Subject: [PATCH 07/24] test: update test cases --- .../specs/nursery/noUnknownUnit/invalid.css | 3 +- .../nursery/noUnknownUnit/invalid.css.snap | 199 ++++++++++++------ .../specs/nursery/noUnknownUnit/valid.css | 3 +- .../nursery/noUnknownUnit/valid.css.snap | 19 -- 4 files changed, 142 insertions(+), 82 deletions(-) diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css index 603da6e7eb93..3366d7d0964a 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css @@ -13,7 +13,6 @@ a { -webkit-transition-delay: 10pix; } a { margin: -webkit-calc(13pix + 10px); } a { margin: some-function(13pix + 10px); } root { --margin: 10pix; } -root { --margin: 10px + 10pix; } @media (min-width: 13pix) {} @media (min-width: 10px)\n and (max-width: 20PIX) {} @media (width < 10.01REMS) {} @@ -26,4 +25,4 @@ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% rep a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } @font-face { color: U+0100-024F; } -a { unicode-range: U+0100-024F; } +a { unicode-range: U+0100-024F; } \ No newline at end of file diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap index cc6d01c8c074..0c6fd3eda977 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap @@ -19,7 +19,6 @@ a { -webkit-transition-delay: 10pix; } a { margin: -webkit-calc(13pix + 10px); } a { margin: some-function(13pix + 10px); } root { --margin: 10pix; } -root { --margin: 10px + 10pix; } @media (min-width: 13pix) {} @media (min-width: 10px)\n and (max-width: 20PIX) {} @media (width < 10.01REMS) {} @@ -33,7 +32,6 @@ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } @font-face { color: U+0100-024F; } a { unicode-range: U+0100-024F; } - ``` # Diagnostics @@ -173,12 +171,12 @@ invalid.css:8:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━ ``` invalid.css:9:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! Unexpected unknown unit: pix + ! Unexpected unknown unit: pix 7 │ a { color: rgba(255pix, 0, 51, 1); } 8 │ a { color: hsla(255pix, 0, 51, 1); } > 9 │ a { margin: calc(13pix + 10px); } - │ ^^^^ + │ ^^^ 10 │ a { margin: calc(10pix*2); } 11 │ a { margin: calc(2*10pix); } @@ -241,12 +239,12 @@ invalid.css:12:33 lint/nursery/noUnknownUnit ━━━━━━━━━━━ ``` invalid.css:13:28 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! Unexpected unknown unit: pix + ! Unexpected unknown unit: pix 11 │ a { margin: calc(2*10pix); } 12 │ a { -webkit-transition-delay: 10pix; } > 13 │ a { margin: -webkit-calc(13pix + 10px); } - │ ^^^^ + │ ^^^ 14 │ a { margin: some-function(13pix + 10px); } 15 │ root { --margin: 10pix; } @@ -258,14 +256,14 @@ invalid.css:13:28 lint/nursery/noUnknownUnit ━━━━━━━━━━━ ``` invalid.css:14:29 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! Unexpected unknown unit: pix + ! Unexpected unknown unit: pix 12 │ a { -webkit-transition-delay: 10pix; } 13 │ a { margin: -webkit-calc(13pix + 10px); } > 14 │ a { margin: some-function(13pix + 10px); } - │ ^^^^ + │ ^^^ 15 │ root { --margin: 10pix; } - 16 │ root { --margin: 10px + 10pix; } + 16 │ @media (min-width: 13pix) {} i Fix to a known unit. @@ -281,8 +279,8 @@ invalid.css:15:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━ 14 │ a { margin: some-function(13pix + 10px); } > 15 │ root { --margin: 10pix; } │ ^^^ - 16 │ root { --margin: 10px + 10pix; } - 17 │ @media (min-width: 13pix) {} + 16 │ @media (min-width: 13pix) {} + 17 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} i Fix to a known unit. @@ -290,16 +288,16 @@ invalid.css:15:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━ ``` ``` -invalid.css:17:22 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.css:16:22 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Unexpected unknown unit: pix + 14 │ a { margin: some-function(13pix + 10px); } 15 │ root { --margin: 10pix; } - 16 │ root { --margin: 10px + 10pix; } - > 17 │ @media (min-width: 13pix) {} + > 16 │ @media (min-width: 13pix) {} │ ^^^ - 18 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} - 19 │ @media (width < 10.01REMS) {} + 17 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} + 18 │ @media (width < 10.01REMS) {} i Fix to a known unit. @@ -307,16 +305,16 @@ invalid.css:17:22 lint/nursery/noUnknownUnit ━━━━━━━━━━━ ``` ``` -invalid.css:18:47 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.css:17:47 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Unexpected unknown unit: PIX - 16 │ root { --margin: 10px + 10pix; } - 17 │ @media (min-width: 13pix) {} - > 18 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} + 15 │ root { --margin: 10pix; } + 16 │ @media (min-width: 13pix) {} + > 17 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} │ ^^^ - 19 │ @media (width < 10.01REMS) {} - 20 │ a { width: 1e4pz; } + 18 │ @media (width < 10.01REMS) {} + 19 │ a { width: 1e4pz; } i Fix to a known unit. @@ -324,16 +322,16 @@ invalid.css:18:47 lint/nursery/noUnknownUnit ━━━━━━━━━━━ ``` ``` -invalid.css:19:22 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.css:18:22 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Unexpected unknown unit: REMS - 17 │ @media (min-width: 13pix) {} - 18 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} - > 19 │ @media (width < 10.01REMS) {} + 16 │ @media (min-width: 13pix) {} + 17 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} + > 18 │ @media (width < 10.01REMS) {} │ ^^^^ - 20 │ a { width: 1e4pz; } - 21 │ a { flex: 0 9r9 auto; } + 19 │ a { width: 1e4pz; } + 20 │ a { flex: 0 9r9 auto; } i Fix to a known unit. @@ -341,16 +339,101 @@ invalid.css:19:22 lint/nursery/noUnknownUnit ━━━━━━━━━━━ ``` ``` -invalid.css:20:15 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.css:19:15 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Unexpected unknown unit: pz - 18 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} - 19 │ @media (width < 10.01REMS) {} - > 20 │ a { width: 1e4pz; } + 17 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} + 18 │ @media (width < 10.01REMS) {} + > 19 │ a { width: 1e4pz; } │ ^^ - 21 │ a { flex: 0 9r9 auto; } - 22 │ a { width: 400x; } + 20 │ a { flex: 0 9r9 auto; } + 21 │ a { width: 400x; } + + i Fix to a known unit. + + +``` + +``` +invalid.css:20:14 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: r9 + + 18 │ @media (width < 10.01REMS) {} + 19 │ a { width: 1e4pz; } + > 20 │ a { flex: 0 9r9 auto; } + │ ^^ + 21 │ a { width: 400x; } + 22 │ @media (resolution: 2x) and (min-width: 200x) {} + + i Fix to a known unit. + + +``` + +``` +invalid.css:21:15 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: x + + 19 │ a { width: 1e4pz; } + 20 │ a { flex: 0 9r9 auto; } + > 21 │ a { width: 400x; } + │ ^ + 22 │ @media (resolution: 2x) and (min-width: 200x) {} + 23 │ @media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} + + i Fix to a known unit. + + +``` + +``` +invalid.css:22:44 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: x + + 20 │ a { flex: 0 9r9 auto; } + 21 │ a { width: 400x; } + > 22 │ @media (resolution: 2x) and (min-width: 200x) {} + │ ^ + 23 │ @media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} + 24 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + + i Fix to a known unit. + + +``` + +``` +invalid.css:23:60 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: x + + 21 │ a { width: 400x; } + 22 │ @media (resolution: 2x) and (min-width: 200x) {} + > 23 │ @media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} + │ ^ + 24 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + 25 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + + i Fix to a known unit. + + +``` + +``` +invalid.css:24:66 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: x + + 22 │ @media (resolution: 2x) and (min-width: 200x) {} + 23 │ @media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} + > 24 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + │ ^ + 25 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + 26 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } i Fix to a known unit. @@ -358,16 +441,16 @@ invalid.css:20:15 lint/nursery/noUnknownUnit ━━━━━━━━━━━ ``` ``` -invalid.css:21:14 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.css:25:80 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! Unexpected unknown unit: r9 + ! Unexpected unknown unit: x - 19 │ @media (width < 10.01REMS) {} - 20 │ a { width: 1e4pz; } - > 21 │ a { flex: 0 9r9 auto; } - │ ^^^ - 22 │ a { width: 400x; } - 23 │ @media (resolution: 2x) and (min-width: 200x) {} + 23 │ @media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} + 24 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + > 25 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + │ ^ + 26 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } + 27 │ @font-face { color: U+0100-024F; } i Fix to a known unit. @@ -375,16 +458,16 @@ invalid.css:21:14 lint/nursery/noUnknownUnit ━━━━━━━━━━━ ``` ``` -invalid.css:27:46 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.css:26:46 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Unexpected unknown unit: pix - 25 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } - 26 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } - > 27 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } + 24 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + 25 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + > 26 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } │ ^^^ - 28 │ @font-face { color: U+0100-024F; } - 29 │ a { unicode-range: U+0100-024F; } + 27 │ @font-face { color: U+0100-024F; } + 28 │ a { unicode-range: U+0100-024F; } i Fix to a known unit. @@ -392,16 +475,15 @@ invalid.css:27:46 lint/nursery/noUnknownUnit ━━━━━━━━━━━ ``` ``` -invalid.css:28:31 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.css:27:31 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Unexpected unknown unit: F - 26 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } - 27 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } - > 28 │ @font-face { color: U+0100-024F; } + 25 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + 26 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } + > 27 │ @font-face { color: U+0100-024F; } │ ^ - 29 │ a { unicode-range: U+0100-024F; } - 30 │ + 28 │ a { unicode-range: U+0100-024F; } i Fix to a known unit. @@ -409,15 +491,14 @@ invalid.css:28:31 lint/nursery/noUnknownUnit ━━━━━━━━━━━ ``` ``` -invalid.css:29:30 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.css:28:30 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Unexpected unknown unit: F - 27 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } - 28 │ @font-face { color: U+0100-024F; } - > 29 │ a { unicode-range: U+0100-024F; } + 26 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } + 27 │ @font-face { color: U+0100-024F; } + > 28 │ a { unicode-range: U+0100-024F; } │ ^ - 30 │ i Fix to a known unit. diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css index 4cd5c044ba49..97d3480f8360 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css @@ -69,5 +69,4 @@ a { background-image: image-set(url('first.png') calc(1x * 1), url('second.png') @media (resolution: 2x) {} @media ( resOLution: 2x) {} a { image-resolution: 1x; } -a { width: 8ic; } -@font-face { unicode-range: U+0100-024F; } +a { width: 8ic; } \ No newline at end of file diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css.snap index 26b7efe0e421..b62a365edd5e 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css.snap +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css.snap @@ -76,23 +76,4 @@ a { background-image: image-set(url('first.png') calc(1x * 1), url('second.png') @media ( resOLution: 2x) {} a { image-resolution: 1x; } a { width: 8ic; } -@font-face { unicode-range: U+0100-024F; } - -``` - -# Diagnostics -``` -valid.css:73:39 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: F - - 71 │ a { image-resolution: 1x; } - 72 │ a { width: 8ic; } - > 73 │ @font-face { unicode-range: U+0100-024F; } - │ ^ - 74 │ - - i Fix to a known unit. - - ``` From 9cb08e4b67a9d897170cae8738d23e861f520779 Mon Sep 17 00:00:00 2001 From: neoki Date: Sun, 21 Apr 2024 02:53:16 +0900 Subject: [PATCH 08/24] fix: break loop when allowing x --- crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs index 80a2a9988835..18529e88280d 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs @@ -121,6 +121,7 @@ impl Rule for NoUnknownUnit { if strip_vendor_prefix(function_name.as_str()) == "image-set" { allow_x = true; + break; } } CssSyntaxKind::CSS_QUERY_FEATURE_PLAIN => { @@ -135,6 +136,7 @@ impl Rule for NoUnknownUnit { if RESOLUTION_MEDIA_FEATURE_NAMES.contains(&feature_name.as_str()) { allow_x = true; + break; } } CssSyntaxKind::CSS_GENERIC_PROPERTY => { @@ -150,6 +152,7 @@ impl Rule for NoUnknownUnit { if property_name == "image-resolution" { allow_x = true; + break; } } _ => {} From f8af9e9b3342c174677c077fd0f62a1faacecc59 Mon Sep 17 00:00:00 2001 From: neoki Date: Sun, 21 Apr 2024 03:11:41 +0900 Subject: [PATCH 09/24] fix: remove dbg macro --- crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs index 18529e88280d..b3507d829eb9 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs @@ -84,8 +84,6 @@ impl Rule for NoUnknownUnit { fn run(ctx: &RuleContext) -> Option { let node = ctx.query(); - // dbg!(ctx.root()); - match node { AnyCssDimension::CssUnknownDimension(dimension) => { let unit_token = dimension.unit_token().ok()?; From ba1aef28e6d52692fac9831c093d2f52260a7505 Mon Sep 17 00:00:00 2001 From: neoki Date: Sun, 21 Apr 2024 04:08:59 +0900 Subject: [PATCH 10/24] refactor: change rule state name --- .../src/lint/nursery/no_unknown_unit.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs index b3507d829eb9..01858a7a7eee 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs @@ -70,14 +70,14 @@ declare_rule! { } } -pub struct RuleState { - value: String, +pub struct NoUnknownUnitState { + unit: String, span: TextRange, } impl Rule for NoUnknownUnit { type Query = Ast; - type State = RuleState; + type State = NoUnknownUnitState; type Signals = Option; type Options = (); @@ -93,8 +93,8 @@ impl Rule for NoUnknownUnit { return None; } - Some(RuleState { - value: unit, + Some(NoUnknownUnitState { + unit, span: unit_token.text_trimmed_range(), }) } @@ -158,8 +158,8 @@ impl Rule for NoUnknownUnit { } if !allow_x { - return Some(RuleState { - value: unit, + return Some(NoUnknownUnitState { + unit, span: unit_token.text_trimmed_range(), }); } @@ -172,13 +172,12 @@ impl Rule for NoUnknownUnit { } fn diagnostic(_: &RuleContext, state: &Self::State) -> Option { - let span = state.span; Some( RuleDiagnostic::new( rule_category!(), - span, + state.span, markup! { - "Unexpected unknown unit: "{ state.value } + "Unexpected unknown unit: "{ state.unit } }, ) .note(markup! { From 1adcd0041c167ddfe07aff4028bcd01df0f05228 Mon Sep 17 00:00:00 2001 From: neoki Date: Sun, 21 Apr 2024 11:44:17 +0900 Subject: [PATCH 11/24] fix: add noUnknownUnit to recommended rules --- crates/biome_configuration/src/linter/rules.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/biome_configuration/src/linter/rules.rs b/crates/biome_configuration/src/linter/rules.rs index eccbdd3eefe5..8527a71ec5d4 100644 --- a/crates/biome_configuration/src/linter/rules.rs +++ b/crates/biome_configuration/src/linter/rules.rs @@ -2752,6 +2752,7 @@ impl Nursery { "noDuplicateSelectorsKeyframeBlock", "noEvolvingAny", "noFlatMapIdentity", + "noUnknownUnit", ]; const RECOMMENDED_RULES_AS_FILTERS: &'static [RuleFilter<'static>] = &[ RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[3]), @@ -2762,6 +2763,7 @@ impl Nursery { RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[8]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[9]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[10]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[16]), ]; const ALL_RULES_AS_FILTERS: &'static [RuleFilter<'static>] = &[ RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[0]), From 4990cb999c8067905cb484e624102260e8d2ee8d Mon Sep 17 00:00:00 2001 From: neoki Date: Sun, 21 Apr 2024 13:33:59 +0900 Subject: [PATCH 12/24] refactor: sort expressions in match statement --- .../src/lint/nursery/no_unknown_unit.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs index 01858a7a7eee..bfb95e304dfc 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs @@ -122,33 +122,33 @@ impl Rule for NoUnknownUnit { break; } } - CssSyntaxKind::CSS_QUERY_FEATURE_PLAIN => { - let feature_name = ancestor - .cast::()? + CssSyntaxKind::CSS_GENERIC_PROPERTY => { + let property_name = ancestor + .cast::()? .name() .ok()? + .as_css_identifier()? .value_token() .ok()? .text_trimmed() .to_lowercase(); - if RESOLUTION_MEDIA_FEATURE_NAMES.contains(&feature_name.as_str()) { + if property_name == "image-resolution" { allow_x = true; break; } } - CssSyntaxKind::CSS_GENERIC_PROPERTY => { - let property_name = ancestor - .cast::()? + CssSyntaxKind::CSS_QUERY_FEATURE_PLAIN => { + let feature_name = ancestor + .cast::()? .name() .ok()? - .as_css_identifier()? .value_token() .ok()? .text_trimmed() .to_lowercase(); - if property_name == "image-resolution" { + if RESOLUTION_MEDIA_FEATURE_NAMES.contains(&feature_name.as_str()) { allow_x = true; break; } From c52e807ebc3beff9703c07dd85654454b25c1484 Mon Sep 17 00:00:00 2001 From: neoki Date: Sun, 21 Apr 2024 14:16:50 +0900 Subject: [PATCH 13/24] fix: set recommended to true --- crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs index bfb95e304dfc..cc7be7abce14 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs @@ -65,7 +65,7 @@ declare_rule! { pub NoUnknownUnit { version: "next", name: "noUnknownUnit", - recommended: false, + recommended: true, sources: &[RuleSource::Stylelint("unit-no-unknown")], } } From 652ca86eab557ce808c7fe5b169a1ae466fd1164 Mon Sep 17 00:00:00 2001 From: neoki Date: Sun, 21 Apr 2024 16:39:41 +0900 Subject: [PATCH 14/24] fix: use ends_with instead of strip_vendor_prefix --- Cargo.lock | 1 - crates/biome_css_analyze/Cargo.toml | 1 - .../biome_css_analyze/src/lint/nursery/no_unknown_unit.rs | 4 +--- crates/biome_css_analyze/src/utils.rs | 6 ------ 4 files changed, 1 insertion(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ee86130c9f0..2b7a1d52c466 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -264,7 +264,6 @@ dependencies = [ "biome_test_utils", "insta", "lazy_static", - "regex", "schemars", "serde", "tests_macros", diff --git a/crates/biome_css_analyze/Cargo.toml b/crates/biome_css_analyze/Cargo.toml index 63c87d6e313f..187489002128 100644 --- a/crates/biome_css_analyze/Cargo.toml +++ b/crates/biome_css_analyze/Cargo.toml @@ -21,7 +21,6 @@ biome_deserialize_macros = { workspace = true } biome_diagnostics = { workspace = true } biome_rowan = { workspace = true } lazy_static = { workspace = true } -regex = { workspace = true } schemars = { workspace = true, optional = true } serde = { workspace = true, features = ["derive"] } diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs index cc7be7abce14..cbfd27e636d6 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs @@ -5,8 +5,6 @@ use biome_css_syntax::{ }; use biome_rowan::{SyntaxNodeCast, TextRange}; -use crate::utils::strip_vendor_prefix; - const RESOLUTION_MEDIA_FEATURE_NAMES: [&str; 3] = ["resolution", "min-resolution", "max-resolution"]; @@ -117,7 +115,7 @@ impl Rule for NoUnknownUnit { .text_trimmed() .to_lowercase(); - if strip_vendor_prefix(function_name.as_str()) == "image-set" { + if function_name.ends_with("image-set") { allow_x = true; break; } diff --git a/crates/biome_css_analyze/src/utils.rs b/crates/biome_css_analyze/src/utils.rs index 981a822ba439..a26f4c08ff13 100644 --- a/crates/biome_css_analyze/src/utils.rs +++ b/crates/biome_css_analyze/src/utils.rs @@ -5,7 +5,6 @@ use crate::keywords::{ }; use biome_css_syntax::{AnyCssGenericComponentValue, AnyCssValue, CssGenericComponentValueList}; use biome_rowan::{AstNode, SyntaxNodeCast}; -use regex::Regex; pub fn is_font_family_keyword(value: &str) -> bool { BASIC_KEYWORDS.contains(&value) || FONT_FAMILY_KEYWORDS.contains(&value) @@ -93,8 +92,3 @@ pub fn find_font_family(value: CssGenericComponentValueList) -> Vec } font_families } - -pub fn strip_vendor_prefix(property: &str) -> String { - let re = Regex::new(r"^-\w+-").unwrap(); - re.replace(property, "").to_string() -} From a47ad861d243f9968c3673a5f70e1706d11e47d3 Mon Sep 17 00:00:00 2001 From: neoki Date: Sun, 21 Apr 2024 17:38:23 +0900 Subject: [PATCH 15/24] refactor: add documentation on CSS hack --- .../biome_css_analyze/src/lint/nursery/no_unknown_unit.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs index cbfd27e636d6..62bcaff228f1 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs @@ -8,7 +8,8 @@ use biome_rowan::{SyntaxNodeCast, TextRange}; const RESOLUTION_MEDIA_FEATURE_NAMES: [&str; 3] = ["resolution", "min-resolution", "max-resolution"]; -fn is_css_hack_unit(value: &str) -> bool { +// Check if the value is a CSS hack used in Internet Explorer. +fn is_css_hack(value: &str) -> bool { value == "\\0" } @@ -87,7 +88,8 @@ impl Rule for NoUnknownUnit { let unit_token = dimension.unit_token().ok()?; let unit = unit_token.text_trimmed().to_string(); - if is_css_hack_unit(&unit) { + // Ignore CSS hack because it's parsed as an unknown unit. + if is_css_hack(&unit) { return None; } From 073f1b7c0d3beffe5bc6530bfb5cbc6c8b9afa23 Mon Sep 17 00:00:00 2001 From: neoki Date: Sun, 21 Apr 2024 17:50:08 +0900 Subject: [PATCH 16/24] refactor: remove ambiguous document --- crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs index 62bcaff228f1..338689ea3cd5 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs @@ -16,8 +16,6 @@ fn is_css_hack(value: &str) -> bool { declare_rule! { /// Disallow unknown units. /// - /// This rule considers units defined in the CSS Specifications, up to and including Editor's Drafts, to be known. - /// /// /// ## Examples /// From 18cb89bd15163465b85f87db1ea11365dcb95c20 Mon Sep 17 00:00:00 2001 From: neoki Date: Mon, 22 Apr 2024 01:29:54 +0900 Subject: [PATCH 17/24] fix: update diagnostic --- .../src/lint/nursery/no_unknown_unit.rs | 11 +- .../noUnknownUnit/invalid.css.snap.new | 703 ++++++++++++++++++ 2 files changed, 712 insertions(+), 2 deletions(-) create mode 100644 crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap.new diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs index 338689ea3cd5..492383ff2eb9 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs @@ -179,8 +179,15 @@ impl Rule for NoUnknownUnit { }, ) .note(markup! { - "Fix to a known unit." - }), + "See ""MDN web docs"" for more details." + }) + .footer_list( + markup! { + "Use a known unit instead, such as:" + }, + &["px", "em", "rem", "etc."], + ), + ) } } diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap.new b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap.new new file mode 100644 index 000000000000..6f9d703cbb07 --- /dev/null +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap.new @@ -0,0 +1,703 @@ +--- +source: crates/biome_css_analyze/tests/spec_tests.rs +assertion_line: 83 +expression: invalid.css +--- +# Input +```css +a { font-size: 13pp; } +a { margin: 13xpx; } +a { font-size: .5remm; } +a { font-size: 0.5remm; } +a { color: rgb(255pix, 0, 51); } +a { color: hsl(255pix, 0, 51); } +a { color: rgba(255pix, 0, 51, 1); } +a { color: hsla(255pix, 0, 51, 1); } +a { margin: calc(13pix + 10px); } +a { margin: calc(10pix*2); } +a { margin: calc(2*10pix); } +a { -webkit-transition-delay: 10pix; } +a { margin: -webkit-calc(13pix + 10px); } +a { margin: some-function(13pix + 10px); } +root { --margin: 10pix; } +@media (min-width: 13pix) {} +@media (min-width: 10px)\n and (max-width: 20PIX) {} +@media (width < 10.01REMS) {} +a { width: 1e4pz; } +a { flex: 0 9r9 auto; } +a { width: 400x; } +@media (resolution: 2x) and (min-width: 200x) {} +@media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} +a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } +a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } +a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } +@font-face { color: U+0100-024F; } +a { unicode-range: U+0100-024F; } +``` + +# Diagnostics +``` +invalid.css:1:18 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pp + + > 1 │ a { font-size: 13pp; } + │ ^^ + 2 │ a { margin: 13xpx; } + 3 │ a { font-size: .5remm; } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:2:15 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: xpx + + 1 │ a { font-size: 13pp; } + > 2 │ a { margin: 13xpx; } + │ ^^^ + 3 │ a { font-size: .5remm; } + 4 │ a { font-size: 0.5remm; } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:3:18 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: remm + + 1 │ a { font-size: 13pp; } + 2 │ a { margin: 13xpx; } + > 3 │ a { font-size: .5remm; } + │ ^^^^ + 4 │ a { font-size: 0.5remm; } + 5 │ a { color: rgb(255pix, 0, 51); } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:4:19 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: remm + + 2 │ a { margin: 13xpx; } + 3 │ a { font-size: .5remm; } + > 4 │ a { font-size: 0.5remm; } + │ ^^^^ + 5 │ a { color: rgb(255pix, 0, 51); } + 6 │ a { color: hsl(255pix, 0, 51); } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:5:19 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 3 │ a { font-size: .5remm; } + 4 │ a { font-size: 0.5remm; } + > 5 │ a { color: rgb(255pix, 0, 51); } + │ ^^^ + 6 │ a { color: hsl(255pix, 0, 51); } + 7 │ a { color: rgba(255pix, 0, 51, 1); } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:6:19 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 4 │ a { font-size: 0.5remm; } + 5 │ a { color: rgb(255pix, 0, 51); } + > 6 │ a { color: hsl(255pix, 0, 51); } + │ ^^^ + 7 │ a { color: rgba(255pix, 0, 51, 1); } + 8 │ a { color: hsla(255pix, 0, 51, 1); } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:7:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 5 │ a { color: rgb(255pix, 0, 51); } + 6 │ a { color: hsl(255pix, 0, 51); } + > 7 │ a { color: rgba(255pix, 0, 51, 1); } + │ ^^^ + 8 │ a { color: hsla(255pix, 0, 51, 1); } + 9 │ a { margin: calc(13pix + 10px); } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:8:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 6 │ a { color: hsl(255pix, 0, 51); } + 7 │ a { color: rgba(255pix, 0, 51, 1); } + > 8 │ a { color: hsla(255pix, 0, 51, 1); } + │ ^^^ + 9 │ a { margin: calc(13pix + 10px); } + 10 │ a { margin: calc(10pix*2); } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:9:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 7 │ a { color: rgba(255pix, 0, 51, 1); } + 8 │ a { color: hsla(255pix, 0, 51, 1); } + > 9 │ a { margin: calc(13pix + 10px); } + │ ^^^ + 10 │ a { margin: calc(10pix*2); } + 11 │ a { margin: calc(2*10pix); } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:10:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 8 │ a { color: hsla(255pix, 0, 51, 1); } + 9 │ a { margin: calc(13pix + 10px); } + > 10 │ a { margin: calc(10pix*2); } + │ ^^^ + 11 │ a { margin: calc(2*10pix); } + 12 │ a { -webkit-transition-delay: 10pix; } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:11:22 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 9 │ a { margin: calc(13pix + 10px); } + 10 │ a { margin: calc(10pix*2); } + > 11 │ a { margin: calc(2*10pix); } + │ ^^^ + 12 │ a { -webkit-transition-delay: 10pix; } + 13 │ a { margin: -webkit-calc(13pix + 10px); } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:12:33 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 10 │ a { margin: calc(10pix*2); } + 11 │ a { margin: calc(2*10pix); } + > 12 │ a { -webkit-transition-delay: 10pix; } + │ ^^^ + 13 │ a { margin: -webkit-calc(13pix + 10px); } + 14 │ a { margin: some-function(13pix + 10px); } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:13:28 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 11 │ a { margin: calc(2*10pix); } + 12 │ a { -webkit-transition-delay: 10pix; } + > 13 │ a { margin: -webkit-calc(13pix + 10px); } + │ ^^^ + 14 │ a { margin: some-function(13pix + 10px); } + 15 │ root { --margin: 10pix; } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:14:29 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 12 │ a { -webkit-transition-delay: 10pix; } + 13 │ a { margin: -webkit-calc(13pix + 10px); } + > 14 │ a { margin: some-function(13pix + 10px); } + │ ^^^ + 15 │ root { --margin: 10pix; } + 16 │ @media (min-width: 13pix) {} + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:15:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 13 │ a { margin: -webkit-calc(13pix + 10px); } + 14 │ a { margin: some-function(13pix + 10px); } + > 15 │ root { --margin: 10pix; } + │ ^^^ + 16 │ @media (min-width: 13pix) {} + 17 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:16:22 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 14 │ a { margin: some-function(13pix + 10px); } + 15 │ root { --margin: 10pix; } + > 16 │ @media (min-width: 13pix) {} + │ ^^^ + 17 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} + 18 │ @media (width < 10.01REMS) {} + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:17:47 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: PIX + + 15 │ root { --margin: 10pix; } + 16 │ @media (min-width: 13pix) {} + > 17 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} + │ ^^^ + 18 │ @media (width < 10.01REMS) {} + 19 │ a { width: 1e4pz; } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:18:22 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: REMS + + 16 │ @media (min-width: 13pix) {} + 17 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} + > 18 │ @media (width < 10.01REMS) {} + │ ^^^^ + 19 │ a { width: 1e4pz; } + 20 │ a { flex: 0 9r9 auto; } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:19:15 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pz + + 17 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} + 18 │ @media (width < 10.01REMS) {} + > 19 │ a { width: 1e4pz; } + │ ^^ + 20 │ a { flex: 0 9r9 auto; } + 21 │ a { width: 400x; } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:20:14 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: r9 + + 18 │ @media (width < 10.01REMS) {} + 19 │ a { width: 1e4pz; } + > 20 │ a { flex: 0 9r9 auto; } + │ ^^ + 21 │ a { width: 400x; } + 22 │ @media (resolution: 2x) and (min-width: 200x) {} + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:21:15 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: x + + 19 │ a { width: 1e4pz; } + 20 │ a { flex: 0 9r9 auto; } + > 21 │ a { width: 400x; } + │ ^ + 22 │ @media (resolution: 2x) and (min-width: 200x) {} + 23 │ @media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:22:44 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: x + + 20 │ a { flex: 0 9r9 auto; } + 21 │ a { width: 400x; } + > 22 │ @media (resolution: 2x) and (min-width: 200x) {} + │ ^ + 23 │ @media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} + 24 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:23:60 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: x + + 21 │ a { width: 400x; } + 22 │ @media (resolution: 2x) and (min-width: 200x) {} + > 23 │ @media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} + │ ^ + 24 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + 25 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:24:66 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: x + + 22 │ @media (resolution: 2x) and (min-width: 200x) {} + 23 │ @media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} + > 24 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + │ ^ + 25 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + 26 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:25:80 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: x + + 23 │ @media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} + 24 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + > 25 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + │ ^ + 26 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } + 27 │ @font-face { color: U+0100-024F; } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:26:46 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: pix + + 24 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + 25 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + > 26 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } + │ ^^^ + 27 │ @font-face { color: U+0100-024F; } + 28 │ a { unicode-range: U+0100-024F; } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:27:31 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: F + + 25 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } + 26 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } + > 27 │ @font-face { color: U+0100-024F; } + │ ^ + 28 │ a { unicode-range: U+0100-024F; } + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` + +``` +invalid.css:28:30 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Unexpected unknown unit: F + + 26 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } + 27 │ @font-face { color: U+0100-024F; } + > 28 │ a { unicode-range: U+0100-024F; } + │ ^ + + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. + + +``` From 1e89e1980e6afbf91d6893de1f9ca7520dc7f8fd Mon Sep 17 00:00:00 2001 From: neoki Date: Mon, 22 Apr 2024 01:51:40 +0900 Subject: [PATCH 18/24] fix: update document texts of rule --- crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs index 492383ff2eb9..bbdeab4f6b66 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs @@ -14,7 +14,9 @@ fn is_css_hack(value: &str) -> bool { } declare_rule! { - /// Disallow unknown units. + /// Disallow unknown CSS units. + /// + /// For details on known CSS units, see the [MDN web docs](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_and_units#lengths). /// /// /// ## Examples From a801b5dacd191cbef86dd1a3a2f6d92e7e5da590 Mon Sep 17 00:00:00 2001 From: neoki Date: Mon, 22 Apr 2024 04:08:33 +0900 Subject: [PATCH 19/24] test: update invalid.css.snap and remove snap.new file --- .../nursery/noUnknownUnit/invalid.css.snap | 252 ++++++- .../noUnknownUnit/invalid.css.snap.new | 703 ------------------ 2 files changed, 224 insertions(+), 731 deletions(-) delete mode 100644 crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap.new diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap index 0c6fd3eda977..a8f04666bac0 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap @@ -45,7 +45,14 @@ invalid.css:1:18 lint/nursery/noUnknownUnit ━━━━━━━━━━━━ 2 │ a { margin: 13xpx; } 3 │ a { font-size: .5remm; } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -61,7 +68,14 @@ invalid.css:2:15 lint/nursery/noUnknownUnit ━━━━━━━━━━━━ 3 │ a { font-size: .5remm; } 4 │ a { font-size: 0.5remm; } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -78,7 +92,14 @@ invalid.css:3:18 lint/nursery/noUnknownUnit ━━━━━━━━━━━━ 4 │ a { font-size: 0.5remm; } 5 │ a { color: rgb(255pix, 0, 51); } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -95,7 +116,14 @@ invalid.css:4:19 lint/nursery/noUnknownUnit ━━━━━━━━━━━━ 5 │ a { color: rgb(255pix, 0, 51); } 6 │ a { color: hsl(255pix, 0, 51); } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -112,7 +140,14 @@ invalid.css:5:19 lint/nursery/noUnknownUnit ━━━━━━━━━━━━ 6 │ a { color: hsl(255pix, 0, 51); } 7 │ a { color: rgba(255pix, 0, 51, 1); } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -129,7 +164,14 @@ invalid.css:6:19 lint/nursery/noUnknownUnit ━━━━━━━━━━━━ 7 │ a { color: rgba(255pix, 0, 51, 1); } 8 │ a { color: hsla(255pix, 0, 51, 1); } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -146,7 +188,14 @@ invalid.css:7:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━ 8 │ a { color: hsla(255pix, 0, 51, 1); } 9 │ a { margin: calc(13pix + 10px); } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -163,7 +212,14 @@ invalid.css:8:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━ 9 │ a { margin: calc(13pix + 10px); } 10 │ a { margin: calc(10pix*2); } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -180,7 +236,14 @@ invalid.css:9:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━ 10 │ a { margin: calc(10pix*2); } 11 │ a { margin: calc(2*10pix); } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -197,7 +260,14 @@ invalid.css:10:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━ 11 │ a { margin: calc(2*10pix); } 12 │ a { -webkit-transition-delay: 10pix; } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -214,7 +284,14 @@ invalid.css:11:22 lint/nursery/noUnknownUnit ━━━━━━━━━━━ 12 │ a { -webkit-transition-delay: 10pix; } 13 │ a { margin: -webkit-calc(13pix + 10px); } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -231,7 +308,14 @@ invalid.css:12:33 lint/nursery/noUnknownUnit ━━━━━━━━━━━ 13 │ a { margin: -webkit-calc(13pix + 10px); } 14 │ a { margin: some-function(13pix + 10px); } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -248,7 +332,14 @@ invalid.css:13:28 lint/nursery/noUnknownUnit ━━━━━━━━━━━ 14 │ a { margin: some-function(13pix + 10px); } 15 │ root { --margin: 10pix; } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -265,7 +356,14 @@ invalid.css:14:29 lint/nursery/noUnknownUnit ━━━━━━━━━━━ 15 │ root { --margin: 10pix; } 16 │ @media (min-width: 13pix) {} - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -282,7 +380,14 @@ invalid.css:15:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━ 16 │ @media (min-width: 13pix) {} 17 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -299,7 +404,14 @@ invalid.css:16:22 lint/nursery/noUnknownUnit ━━━━━━━━━━━ 17 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} 18 │ @media (width < 10.01REMS) {} - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -316,7 +428,14 @@ invalid.css:17:47 lint/nursery/noUnknownUnit ━━━━━━━━━━━ 18 │ @media (width < 10.01REMS) {} 19 │ a { width: 1e4pz; } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -333,7 +452,14 @@ invalid.css:18:22 lint/nursery/noUnknownUnit ━━━━━━━━━━━ 19 │ a { width: 1e4pz; } 20 │ a { flex: 0 9r9 auto; } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -350,7 +476,14 @@ invalid.css:19:15 lint/nursery/noUnknownUnit ━━━━━━━━━━━ 20 │ a { flex: 0 9r9 auto; } 21 │ a { width: 400x; } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -367,7 +500,14 @@ invalid.css:20:14 lint/nursery/noUnknownUnit ━━━━━━━━━━━ 21 │ a { width: 400x; } 22 │ @media (resolution: 2x) and (min-width: 200x) {} - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -384,7 +524,14 @@ invalid.css:21:15 lint/nursery/noUnknownUnit ━━━━━━━━━━━ 22 │ @media (resolution: 2x) and (min-width: 200x) {} 23 │ @media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -401,7 +548,14 @@ invalid.css:22:44 lint/nursery/noUnknownUnit ━━━━━━━━━━━ 23 │ @media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} 24 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -418,7 +572,14 @@ invalid.css:23:60 lint/nursery/noUnknownUnit ━━━━━━━━━━━ 24 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } 25 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -435,7 +596,14 @@ invalid.css:24:66 lint/nursery/noUnknownUnit ━━━━━━━━━━━ 25 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } 26 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -452,7 +620,14 @@ invalid.css:25:80 lint/nursery/noUnknownUnit ━━━━━━━━━━━ 26 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } 27 │ @font-face { color: U+0100-024F; } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -469,7 +644,14 @@ invalid.css:26:46 lint/nursery/noUnknownUnit ━━━━━━━━━━━ 27 │ @font-face { color: U+0100-024F; } 28 │ a { unicode-range: U+0100-024F; } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -485,7 +667,14 @@ invalid.css:27:31 lint/nursery/noUnknownUnit ━━━━━━━━━━━ │ ^ 28 │ a { unicode-range: U+0100-024F; } - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` @@ -500,7 +689,14 @@ invalid.css:28:30 lint/nursery/noUnknownUnit ━━━━━━━━━━━ > 28 │ a { unicode-range: U+0100-024F; } │ ^ - i Fix to a known unit. + i See MDN web docs for more details. + + i Use a known unit instead, such as: + + - px + - em + - rem + - etc. ``` diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap.new b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap.new deleted file mode 100644 index 6f9d703cbb07..000000000000 --- a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/invalid.css.snap.new +++ /dev/null @@ -1,703 +0,0 @@ ---- -source: crates/biome_css_analyze/tests/spec_tests.rs -assertion_line: 83 -expression: invalid.css ---- -# Input -```css -a { font-size: 13pp; } -a { margin: 13xpx; } -a { font-size: .5remm; } -a { font-size: 0.5remm; } -a { color: rgb(255pix, 0, 51); } -a { color: hsl(255pix, 0, 51); } -a { color: rgba(255pix, 0, 51, 1); } -a { color: hsla(255pix, 0, 51, 1); } -a { margin: calc(13pix + 10px); } -a { margin: calc(10pix*2); } -a { margin: calc(2*10pix); } -a { -webkit-transition-delay: 10pix; } -a { margin: -webkit-calc(13pix + 10px); } -a { margin: some-function(13pix + 10px); } -root { --margin: 10pix; } -@media (min-width: 13pix) {} -@media (min-width: 10px)\n and (max-width: 20PIX) {} -@media (width < 10.01REMS) {} -a { width: 1e4pz; } -a { flex: 0 9r9 auto; } -a { width: 400x; } -@media (resolution: 2x) and (min-width: 200x) {} -@media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} -a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } -a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } -a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } -@font-face { color: U+0100-024F; } -a { unicode-range: U+0100-024F; } -``` - -# Diagnostics -``` -invalid.css:1:18 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: pp - - > 1 │ a { font-size: 13pp; } - │ ^^ - 2 │ a { margin: 13xpx; } - 3 │ a { font-size: .5remm; } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:2:15 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: xpx - - 1 │ a { font-size: 13pp; } - > 2 │ a { margin: 13xpx; } - │ ^^^ - 3 │ a { font-size: .5remm; } - 4 │ a { font-size: 0.5remm; } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:3:18 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: remm - - 1 │ a { font-size: 13pp; } - 2 │ a { margin: 13xpx; } - > 3 │ a { font-size: .5remm; } - │ ^^^^ - 4 │ a { font-size: 0.5remm; } - 5 │ a { color: rgb(255pix, 0, 51); } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:4:19 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: remm - - 2 │ a { margin: 13xpx; } - 3 │ a { font-size: .5remm; } - > 4 │ a { font-size: 0.5remm; } - │ ^^^^ - 5 │ a { color: rgb(255pix, 0, 51); } - 6 │ a { color: hsl(255pix, 0, 51); } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:5:19 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: pix - - 3 │ a { font-size: .5remm; } - 4 │ a { font-size: 0.5remm; } - > 5 │ a { color: rgb(255pix, 0, 51); } - │ ^^^ - 6 │ a { color: hsl(255pix, 0, 51); } - 7 │ a { color: rgba(255pix, 0, 51, 1); } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:6:19 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: pix - - 4 │ a { font-size: 0.5remm; } - 5 │ a { color: rgb(255pix, 0, 51); } - > 6 │ a { color: hsl(255pix, 0, 51); } - │ ^^^ - 7 │ a { color: rgba(255pix, 0, 51, 1); } - 8 │ a { color: hsla(255pix, 0, 51, 1); } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:7:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: pix - - 5 │ a { color: rgb(255pix, 0, 51); } - 6 │ a { color: hsl(255pix, 0, 51); } - > 7 │ a { color: rgba(255pix, 0, 51, 1); } - │ ^^^ - 8 │ a { color: hsla(255pix, 0, 51, 1); } - 9 │ a { margin: calc(13pix + 10px); } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:8:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: pix - - 6 │ a { color: hsl(255pix, 0, 51); } - 7 │ a { color: rgba(255pix, 0, 51, 1); } - > 8 │ a { color: hsla(255pix, 0, 51, 1); } - │ ^^^ - 9 │ a { margin: calc(13pix + 10px); } - 10 │ a { margin: calc(10pix*2); } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:9:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: pix - - 7 │ a { color: rgba(255pix, 0, 51, 1); } - 8 │ a { color: hsla(255pix, 0, 51, 1); } - > 9 │ a { margin: calc(13pix + 10px); } - │ ^^^ - 10 │ a { margin: calc(10pix*2); } - 11 │ a { margin: calc(2*10pix); } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:10:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: pix - - 8 │ a { color: hsla(255pix, 0, 51, 1); } - 9 │ a { margin: calc(13pix + 10px); } - > 10 │ a { margin: calc(10pix*2); } - │ ^^^ - 11 │ a { margin: calc(2*10pix); } - 12 │ a { -webkit-transition-delay: 10pix; } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:11:22 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: pix - - 9 │ a { margin: calc(13pix + 10px); } - 10 │ a { margin: calc(10pix*2); } - > 11 │ a { margin: calc(2*10pix); } - │ ^^^ - 12 │ a { -webkit-transition-delay: 10pix; } - 13 │ a { margin: -webkit-calc(13pix + 10px); } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:12:33 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: pix - - 10 │ a { margin: calc(10pix*2); } - 11 │ a { margin: calc(2*10pix); } - > 12 │ a { -webkit-transition-delay: 10pix; } - │ ^^^ - 13 │ a { margin: -webkit-calc(13pix + 10px); } - 14 │ a { margin: some-function(13pix + 10px); } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:13:28 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: pix - - 11 │ a { margin: calc(2*10pix); } - 12 │ a { -webkit-transition-delay: 10pix; } - > 13 │ a { margin: -webkit-calc(13pix + 10px); } - │ ^^^ - 14 │ a { margin: some-function(13pix + 10px); } - 15 │ root { --margin: 10pix; } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:14:29 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: pix - - 12 │ a { -webkit-transition-delay: 10pix; } - 13 │ a { margin: -webkit-calc(13pix + 10px); } - > 14 │ a { margin: some-function(13pix + 10px); } - │ ^^^ - 15 │ root { --margin: 10pix; } - 16 │ @media (min-width: 13pix) {} - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:15:20 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: pix - - 13 │ a { margin: -webkit-calc(13pix + 10px); } - 14 │ a { margin: some-function(13pix + 10px); } - > 15 │ root { --margin: 10pix; } - │ ^^^ - 16 │ @media (min-width: 13pix) {} - 17 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:16:22 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: pix - - 14 │ a { margin: some-function(13pix + 10px); } - 15 │ root { --margin: 10pix; } - > 16 │ @media (min-width: 13pix) {} - │ ^^^ - 17 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} - 18 │ @media (width < 10.01REMS) {} - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:17:47 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: PIX - - 15 │ root { --margin: 10pix; } - 16 │ @media (min-width: 13pix) {} - > 17 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} - │ ^^^ - 18 │ @media (width < 10.01REMS) {} - 19 │ a { width: 1e4pz; } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:18:22 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: REMS - - 16 │ @media (min-width: 13pix) {} - 17 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} - > 18 │ @media (width < 10.01REMS) {} - │ ^^^^ - 19 │ a { width: 1e4pz; } - 20 │ a { flex: 0 9r9 auto; } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:19:15 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: pz - - 17 │ @media (min-width: 10px)\n and (max-width: 20PIX) {} - 18 │ @media (width < 10.01REMS) {} - > 19 │ a { width: 1e4pz; } - │ ^^ - 20 │ a { flex: 0 9r9 auto; } - 21 │ a { width: 400x; } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:20:14 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: r9 - - 18 │ @media (width < 10.01REMS) {} - 19 │ a { width: 1e4pz; } - > 20 │ a { flex: 0 9r9 auto; } - │ ^^ - 21 │ a { width: 400x; } - 22 │ @media (resolution: 2x) and (min-width: 200x) {} - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:21:15 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: x - - 19 │ a { width: 1e4pz; } - 20 │ a { flex: 0 9r9 auto; } - > 21 │ a { width: 400x; } - │ ^ - 22 │ @media (resolution: 2x) and (min-width: 200x) {} - 23 │ @media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:22:44 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: x - - 20 │ a { flex: 0 9r9 auto; } - 21 │ a { width: 400x; } - > 22 │ @media (resolution: 2x) and (min-width: 200x) {} - │ ^ - 23 │ @media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} - 24 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:23:60 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: x - - 21 │ a { width: 400x; } - 22 │ @media (resolution: 2x) and (min-width: 200x) {} - > 23 │ @media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} - │ ^ - 24 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } - 25 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:24:66 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: x - - 22 │ @media (resolution: 2x) and (min-width: 200x) {} - 23 │ @media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} - > 24 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } - │ ^ - 25 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } - 26 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:25:80 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: x - - 23 │ @media ( resolution: /* comment */ 2x ) and (min-width: 200x) {} - 24 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } - > 25 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } - │ ^ - 26 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } - 27 │ @font-face { color: U+0100-024F; } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:26:46 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: pix - - 24 │ a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } - 25 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } - > 26 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } - │ ^^^ - 27 │ @font-face { color: U+0100-024F; } - 28 │ a { unicode-range: U+0100-024F; } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:27:31 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: F - - 25 │ a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; } - 26 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } - > 27 │ @font-face { color: U+0100-024F; } - │ ^ - 28 │ a { unicode-range: U+0100-024F; } - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` - -``` -invalid.css:28:30 lint/nursery/noUnknownUnit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Unexpected unknown unit: F - - 26 │ a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); } - 27 │ @font-face { color: U+0100-024F; } - > 28 │ a { unicode-range: U+0100-024F; } - │ ^ - - i See MDN web docs for more details. - - i Use a known unit instead, such as: - - - px - - em - - rem - - etc. - - -``` From ac189f91c4818d1d92d42c42ed9ba2cac35e1102 Mon Sep 17 00:00:00 2001 From: neoki Date: Mon, 22 Apr 2024 04:11:43 +0900 Subject: [PATCH 20/24] fix: remove processing for css hack --- .../src/lint/nursery/no_unknown_unit.rs | 10 ---------- .../tests/specs/nursery/noUnknownUnit/valid.css | 1 - .../tests/specs/nursery/noUnknownUnit/valid.css.snap | 1 - 3 files changed, 12 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs index bbdeab4f6b66..d339e3791c06 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs @@ -8,11 +8,6 @@ use biome_rowan::{SyntaxNodeCast, TextRange}; const RESOLUTION_MEDIA_FEATURE_NAMES: [&str; 3] = ["resolution", "min-resolution", "max-resolution"]; -// Check if the value is a CSS hack used in Internet Explorer. -fn is_css_hack(value: &str) -> bool { - value == "\\0" -} - declare_rule! { /// Disallow unknown CSS units. /// @@ -88,11 +83,6 @@ impl Rule for NoUnknownUnit { let unit_token = dimension.unit_token().ok()?; let unit = unit_token.text_trimmed().to_string(); - // Ignore CSS hack because it's parsed as an unknown unit. - if is_css_hack(&unit) { - return None; - } - Some(NoUnknownUnitState { unit, span: unit_token.text_trimmed_range(), diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css index 97d3480f8360..01d87750c622 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css @@ -59,7 +59,6 @@ a::before10pix { margin: 10px; } a { color: #1f1f1f; } @media (min-width: 10px) {} @media (min-width: 10px)\n and (max-width: 20px) {} -@media screen and (min-width:0\0) {} @import 'foo.css'; a { background-image: image-set('img-1x.jpg' 1x, 'img-2x.jpg' 2x, 'img-3x.jpg' 3x) } a { background-image: -webkit-image-set('img-1x.jpg' 1x, 'img-2x.jpg' 2x) } diff --git a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css.snap b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css.snap index b62a365edd5e..9d62fab26085 100644 --- a/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css.snap +++ b/crates/biome_css_analyze/tests/specs/nursery/noUnknownUnit/valid.css.snap @@ -65,7 +65,6 @@ a::before10pix { margin: 10px; } a { color: #1f1f1f; } @media (min-width: 10px) {} @media (min-width: 10px)\n and (max-width: 20px) {} -@media screen and (min-width:0\0) {} @import 'foo.css'; a { background-image: image-set('img-1x.jpg' 1x, 'img-2x.jpg' 2x, 'img-3x.jpg' 3x) } a { background-image: -webkit-image-set('img-1x.jpg' 1x, 'img-2x.jpg' 2x) } From c21d091f901241ca147c604429bd04d657972d30 Mon Sep 17 00:00:00 2001 From: neoki Date: Mon, 22 Apr 2024 05:06:58 +0900 Subject: [PATCH 21/24] refactor: add comment as to why `x` is checked --- crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs index d339e3791c06..1518e39bcef2 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs @@ -92,6 +92,9 @@ impl Rule for NoUnknownUnit { let unit_token = dimension.unit_token().ok()?; let unit = unit_token.text_trimmed().to_string(); + // The `x` unit is parsed as `CssRegularDimension`, but it is used for describing resolutions in media queries. + // This check is to disallow the use of the `x` unit outside this specific context. + // See MDN web docs (https://developer.mozilla.org/en-US/docs/Web/CSS/resolution) for more details on the `x` unit. if unit == "x" { let mut allow_x = false; From 4ed73c5e6b9d9c97c3d46107df3ab8cdade111ad Mon Sep 17 00:00:00 2001 From: neoki Date: Mon, 22 Apr 2024 05:31:49 +0900 Subject: [PATCH 22/24] refactor: fix comment as to why `x` is checked --- crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs index 1518e39bcef2..262886ce93c6 100644 --- a/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs +++ b/crates/biome_css_analyze/src/lint/nursery/no_unknown_unit.rs @@ -92,9 +92,8 @@ impl Rule for NoUnknownUnit { let unit_token = dimension.unit_token().ok()?; let unit = unit_token.text_trimmed().to_string(); - // The `x` unit is parsed as `CssRegularDimension`, but it is used for describing resolutions in media queries. + // The `x` unit is parsed as `CssRegularDimension`, but it is used for describing resolutions. // This check is to disallow the use of the `x` unit outside this specific context. - // See MDN web docs (https://developer.mozilla.org/en-US/docs/Web/CSS/resolution) for more details on the `x` unit. if unit == "x" { let mut allow_x = false; From 8685fdfbd1e6bc3da42fbc9a52ce25ff1bbbc7f0 Mon Sep 17 00:00:00 2001 From: neoki Date: Mon, 22 Apr 2024 05:40:20 +0900 Subject: [PATCH 23/24] chore: update auto generated files --- crates/biome_configuration/src/linter/rules.rs | 2 +- packages/@biomejs/backend-jsonrpc/src/workspace.ts | 2 +- packages/@biomejs/biome/configuration_schema.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/biome_configuration/src/linter/rules.rs b/crates/biome_configuration/src/linter/rules.rs index 8527a71ec5d4..63986e739bc4 100644 --- a/crates/biome_configuration/src/linter/rules.rs +++ b/crates/biome_configuration/src/linter/rules.rs @@ -2696,7 +2696,7 @@ pub struct Nursery { #[doc = "Disallow the use of dependencies that aren't specified in the package.json."] #[serde(skip_serializing_if = "Option::is_none")] pub no_undeclared_dependencies: Option>, - #[doc = "Disallow unknown units."] + #[doc = "Disallow unknown CSS units."] #[serde(skip_serializing_if = "Option::is_none")] pub no_unknown_unit: Option>, #[doc = "Disallows package private imports."] diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index caaa34f21959..d54c5c6a7187 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -973,7 +973,7 @@ export interface Nursery { */ noUndeclaredDependencies?: RuleConfiguration_for_Null; /** - * Disallow unknown units. + * Disallow unknown CSS units. */ noUnknownUnit?: RuleConfiguration_for_Null; /** diff --git a/packages/@biomejs/biome/configuration_schema.json b/packages/@biomejs/biome/configuration_schema.json index 2bd6e0858ec7..bd43f6b87b60 100644 --- a/packages/@biomejs/biome/configuration_schema.json +++ b/packages/@biomejs/biome/configuration_schema.json @@ -1546,7 +1546,7 @@ ] }, "noUnknownUnit": { - "description": "Disallow unknown units.", + "description": "Disallow unknown CSS units.", "anyOf": [ { "$ref": "#/definitions/RuleConfiguration" }, { "type": "null" } From 1f077acffc46805201be6c4420332d5f640c4db0 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Mon, 22 Apr 2024 13:01:45 +0100 Subject: [PATCH 24/24] chore: run codegen --- .../biome_configuration/src/linter/rules.rs | 55 +++++++++++++------ crates/biome_css_analyze/src/lint/nursery.rs | 2 + crates/biome_css_analyze/src/options.rs | 1 + 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/crates/biome_configuration/src/linter/rules.rs b/crates/biome_configuration/src/linter/rules.rs index 63986e739bc4..b6463594cb8c 100644 --- a/crates/biome_configuration/src/linter/rules.rs +++ b/crates/biome_configuration/src/linter/rules.rs @@ -2681,6 +2681,9 @@ pub struct Nursery { #[doc = "Disallow to use unnecessary callback on flatMap."] #[serde(skip_serializing_if = "Option::is_none")] pub no_flat_map_identity: Option>, + #[doc = "Disallow invalid !important within keyframe declarations"] + #[serde(skip_serializing_if = "Option::is_none")] + pub no_important_in_keyframe: Option>, #[doc = "Checks that the assertion function, for example expect, is placed inside an it() function call."] #[serde(skip_serializing_if = "Option::is_none")] pub no_misplaced_assertion: Option>, @@ -2734,6 +2737,7 @@ impl Nursery { "noDuplicateSelectorsKeyframeBlock", "noEvolvingAny", "noFlatMapIdentity", + "noImportantInKeyframe", "noMisplacedAssertion", "noNodejsModules", "noReactSpecificProps", @@ -2752,6 +2756,7 @@ impl Nursery { "noDuplicateSelectorsKeyframeBlock", "noEvolvingAny", "noFlatMapIdentity", + "noImportantInKeyframe", "noUnknownUnit", ]; const RECOMMENDED_RULES_AS_FILTERS: &'static [RuleFilter<'static>] = &[ @@ -2763,7 +2768,8 @@ impl Nursery { RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[8]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[9]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[10]), - RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[16]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[11]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[17]), ]; const ALL_RULES_AS_FILTERS: &'static [RuleFilter<'static>] = &[ RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[0]), @@ -2785,6 +2791,7 @@ impl Nursery { RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[16]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[17]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[18]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[19]), ]; #[doc = r" Retrieves the recommended rules"] pub(crate) fn is_recommended_true(&self) -> bool { @@ -2856,46 +2863,51 @@ impl Nursery { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[10])); } } - if let Some(rule) = self.no_misplaced_assertion.as_ref() { + if let Some(rule) = self.no_important_in_keyframe.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[11])); } } - if let Some(rule) = self.no_nodejs_modules.as_ref() { + if let Some(rule) = self.no_misplaced_assertion.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[12])); } } - if let Some(rule) = self.no_react_specific_props.as_ref() { + if let Some(rule) = self.no_nodejs_modules.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[13])); } } - if let Some(rule) = self.no_restricted_imports.as_ref() { + if let Some(rule) = self.no_react_specific_props.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[14])); } } - if let Some(rule) = self.no_undeclared_dependencies.as_ref() { + if let Some(rule) = self.no_restricted_imports.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[15])); } } - if let Some(rule) = self.no_unknown_unit.as_ref() { + if let Some(rule) = self.no_undeclared_dependencies.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[16])); } } - if let Some(rule) = self.use_import_restrictions.as_ref() { + if let Some(rule) = self.no_unknown_unit.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[17])); } } - if let Some(rule) = self.use_sorted_classes.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[18])); } } + 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[19])); + } + } index_set } pub(crate) fn get_disabled_rules(&self) -> IndexSet { @@ -2955,46 +2967,51 @@ impl Nursery { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[10])); } } - if let Some(rule) = self.no_misplaced_assertion.as_ref() { + if let Some(rule) = self.no_important_in_keyframe.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[11])); } } - if let Some(rule) = self.no_nodejs_modules.as_ref() { + if let Some(rule) = self.no_misplaced_assertion.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[12])); } } - if let Some(rule) = self.no_react_specific_props.as_ref() { + if let Some(rule) = self.no_nodejs_modules.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[13])); } } - if let Some(rule) = self.no_restricted_imports.as_ref() { + if let Some(rule) = self.no_react_specific_props.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[14])); } } - if let Some(rule) = self.no_undeclared_dependencies.as_ref() { + if let Some(rule) = self.no_restricted_imports.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[15])); } } - if let Some(rule) = self.no_unknown_unit.as_ref() { + if let Some(rule) = self.no_undeclared_dependencies.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[16])); } } - if let Some(rule) = self.use_import_restrictions.as_ref() { + if let Some(rule) = self.no_unknown_unit.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[17])); } } - if let Some(rule) = self.use_sorted_classes.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[18])); } } + 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[19])); + } + } index_set } #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"] @@ -3075,6 +3092,10 @@ impl Nursery { .no_flat_map_identity .as_ref() .map(|conf| (conf.level(), conf.get_options())), + "noImportantInKeyframe" => self + .no_important_in_keyframe + .as_ref() + .map(|conf| (conf.level(), conf.get_options())), "noMisplacedAssertion" => self .no_misplaced_assertion .as_ref() diff --git a/crates/biome_css_analyze/src/lint/nursery.rs b/crates/biome_css_analyze/src/lint/nursery.rs index 705d07a754d8..6daa2ac3394d 100644 --- a/crates/biome_css_analyze/src/lint/nursery.rs +++ b/crates/biome_css_analyze/src/lint/nursery.rs @@ -6,6 +6,7 @@ pub mod no_color_invalid_hex; pub mod no_css_empty_block; pub mod no_duplicate_font_names; pub mod no_duplicate_selectors_keyframe_block; +pub mod no_important_in_keyframe; pub mod no_unknown_unit; declare_group! { @@ -16,6 +17,7 @@ declare_group! { self :: no_css_empty_block :: NoCssEmptyBlock , self :: no_duplicate_font_names :: NoDuplicateFontNames , self :: no_duplicate_selectors_keyframe_block :: NoDuplicateSelectorsKeyframeBlock , + self :: no_important_in_keyframe :: NoImportantInKeyframe , self :: no_unknown_unit :: NoUnknownUnit , ] } diff --git a/crates/biome_css_analyze/src/options.rs b/crates/biome_css_analyze/src/options.rs index 4a922c656d80..0be8ac2a7afd 100644 --- a/crates/biome_css_analyze/src/options.rs +++ b/crates/biome_css_analyze/src/options.rs @@ -9,5 +9,6 @@ pub type NoCssEmptyBlock = pub type NoDuplicateFontNames = ::Options; pub type NoDuplicateSelectorsKeyframeBlock = < lint :: nursery :: no_duplicate_selectors_keyframe_block :: NoDuplicateSelectorsKeyframeBlock as biome_analyze :: Rule > :: Options ; +pub type NoImportantInKeyframe = < lint :: nursery :: no_important_in_keyframe :: NoImportantInKeyframe as biome_analyze :: Rule > :: Options ; pub type NoUnknownUnit = ::Options;