Skip to content

Commit

Permalink
feat(biome_css_analyze): implement noIrregularWhitespaceCss (#3428)
Browse files Browse the repository at this point in the history
  • Loading branch information
DerTimonius committed Aug 1, 2024
1 parent 74397eb commit 3229b32
Show file tree
Hide file tree
Showing 12 changed files with 762 additions and 92 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b
Contributed by @Conaclos

- Add [nursery/noIrregularWhitespace](https://biomejs.dev/linter/rules/no-irregular-whitespace). Contributed by @michellocana
- Implement `noIrreguluarWhitespace` for CSS. Contributed by @DerTimonius
- Add [nursery/useTrimStartEnd](https://biomejs.dev/linter/rules/use-trim-start-end/). Contributed by @chansuke

#### Enhancements
Expand Down
203 changes: 111 additions & 92 deletions crates/biome_configuration/src/linter/rules.rs

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions crates/biome_css_analyze/src/lint/nursery.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use biome_analyze::{
context::RuleContext, declare_lint_rule, Ast, Rule, RuleDiagnostic, RuleSource,
};
use biome_console::markup;
use biome_css_syntax::{AnyCssRule, CssLanguage};
use biome_rowan::{AstNode, Direction, SyntaxToken, TextRange};

const IRREGULAR_WHITESPACES: &[char; 22] = &[
'\u{c}', '\u{b}', '\u{85}', '\u{feff}', '\u{a0}', '\u{1680}', '\u{180e}', '\u{2000}',
'\u{2001}', '\u{2002}', '\u{2003}', '\u{2004}', '\u{2005}', '\u{2006}', '\u{2007}', '\u{2008}',
'\u{2009}', '\u{200a}', '\u{200b}', '\u{202f}', '\u{205f}', '\u{3000}',
];

declare_lint_rule! {
/// Disallows the use of irregular whitespace.
///
/// Using irregular whitespace would lead to the failure of selecting the correct target.
///
/// ## Examples
///
/// ### Invalid
///
/// ```css,expect_diagnostic
/// .firstClass .secondClass {
/// color: red;
/// }
/// ```
///
/// ```css,expect_diagnostic
/// .firstClass .secondClass {
/// color: red;
/// }
/// ```
/// ### Valid
///
/// ```css
/// .firstClass .secondClass {
/// color: red;
/// }
/// ```
///
pub NoIrregularWhitespaceCss {
version: "next",
name: "noIrregularWhitespaceCss",
language: "css",
recommended: false,
sources: &[RuleSource::Stylelint("no-irregular-whitespace")],
}
}

impl Rule for NoIrregularWhitespaceCss {
type Query = Ast<AnyCssRule>;
type State = TextRange;
type Signals = Vec<Self::State>;
type Options = ();

fn run(ctx: &RuleContext<Self>) -> Self::Signals {
let node = ctx.query();
get_irregular_whitespace(node)
}

fn diagnostic(_: &RuleContext<Self>, range: &Self::State) -> Option<RuleDiagnostic> {
Some(
RuleDiagnostic::new(
rule_category!(),
range,
markup! {
"Irregular whitespace found."
},
)
.note(markup! {
"Replace the irregular whitespace with normal whitespaces."
}),
)
}
}

fn get_irregular_whitespace(node: &AnyCssRule) -> Vec<TextRange> {
let syntax = node.syntax();
let mut all_whitespaces_token: Vec<TextRange> = vec![];
let matches_irregular_whitespace = |token: &SyntaxToken<CssLanguage>| {
!token.has_leading_comments()
&& !token.has_trailing_comments()
&& token.text().chars().any(|char| {
IRREGULAR_WHITESPACES
.iter()
.any(|irregular_whitespace| &char == irregular_whitespace)
})
};

for token in syntax.descendants_tokens(Direction::Next) {
if matches_irregular_whitespace(&token) {
all_whitespaces_token.push(token.text_range());
}
}

all_whitespaces_token
}
1 change: 1 addition & 0 deletions crates/biome_css_analyze/src/options.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/* \u{b} */
@import 'a.css';
/* \u{c} */
@layer module, state;
/* \u{feff} */
.firstClass.secondClass {
padding: 10px;
}
/* \u{a0} */
.firstClass .secondClass {
padding: 10px;
}
/* \u{1680} */
.firstClass .secondClass {
padding: 10px;
}
/* \u{2000} */
.firstClass .secondClass {
padding: 10px;
}
/* \u{2001} */
.firstClass .secondClass {
flex: 11 100px;
}
/* \u{2002} */
.firstClass.secondClass {
padding: 10px;
}
/* \u{2003} */
.firstClass .secondClass  {
padding: 10px;
}
/* \u{2004} */
.firstClass .secondClass {
padding: 10px;
}
/* \u{2005} */
.firstClass .secondClass {
padding: 10px;
}
/* \u{2006} */
.firstClass .secondClass {
padding: 10px;
}
/* \u{2007} */
.firstClass .secondClass {
padding: 10px;
}
/* \u{2008} */
@view-transition {
navigation: auto;
}
/* \u{2009} */
@layer state {
body {
padding:10px;
}
}
/* \u{200a} */
@layer state {
body {
padding: 10px;
}
}
/* \u{200b} */
@keyframes slidein {
from​{
transform: translateX(0%);
}

to {
transform: translateX(100%);
}
}
/* \u{202f} */
@font-face {
font-family: "Trickster";
src:
local("Trickster"),
url("trickster-COLRv1.otf") format("opentype") tech(color-COLRv1),
url("trickster-outline.otf") format("opentype"),
url("trickster-outline.woff") format("woff");
}
/* \u{205f} */
@keyframes slidein {
from {
transform: translateX(0%);
}

to {
transform: translateX(100%);
}
}
/* \u{3000} */
@container (width < 15rem) {
color: blue;
}
Loading

0 comments on commit 3229b32

Please sign in to comment.