Skip to content

Commit

Permalink
feat(linter): support class sorting for tw.div (#4699)
Browse files Browse the repository at this point in the history
  • Loading branch information
Yz4230 authored Dec 18, 2024
1 parent 383a66a commit ec1e9e8
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 4 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,27 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b

Contributed by @lucasweng

- [useSortedClasses](https://biomejs.dev/linter/rules/use-sorted-classes/) now supports wildcards in the `function` option.

```json
{
"linter": {
"rules": {
"nursery": {
"useSortedClasses": {
"level": "warn",
"options": {
"functions": ["tw.*"]
}
}
}
}
}
}
```

This allows the rule to handle class sorting for tagged template literals like `` tw.div`...` ``, used in libraries such as [twin.macro](https://github.com/ben-rogerson/twin.macro) and [react-twc](https://github.com/gregberge/twc).

#### Enhancements

- `useExportType` and `useImportType` now ignore TypeScript declaration files ([#4416](https://github.com/biomejs/biome/pull/4416)). Contributed by @Conaclos
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ declare_lint_rule! {
/// {
/// "options": {
/// "attributes": ["classList"],
/// "functions": ["clsx", "cva", "tw"]
/// "functions": ["clsx", "cva", "tw", "tw.*"]
/// }
/// }
/// ```
Expand Down Expand Up @@ -111,6 +111,12 @@ declare_lint_rule! {
/// tw`px-2 foo p-4 bar`;
/// ```
///
/// **Since v2.0.0**, tagged template literals like `` tw.div`...` `` are supported by setting `tw.*`:
///
/// ```js,expect_diagnostic,use_options
/// tw.div`px-2 foo p-4 bar`;
/// ```
///
/// ### Sort-related
///
/// :::caution
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ impl AnyClassStringLike {
return Some(true);
}
}
if let Some(AnyJsExpression::JsStaticMemberExpression(tag)) =
template_expression.tag()
{
if options.match_function(tag.text().as_ref()) {
return Some(true);
}
}
} else if let Some(jsx_attribute) = JsxAttribute::cast_ref(&ancestor) {
let attribute_name = get_attribute_name(&jsx_attribute)?;
if options.has_attribute(attribute_name.text()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ impl UtilityClassSortingOptions {
false
}

pub(crate) fn match_function(&self, name: &str) -> bool {
self.functions.iter().flatten().any(|matcher| {
let mut matcher_parts = matcher.split('.');
let mut name_parts = name.split('.');

let all_parts_match = matcher_parts
.by_ref()
.zip(name_parts.by_ref())
.all(|(m, p)| m == "*" || m == p);

all_parts_match && matcher_parts.next().is_none() && name_parts.next().is_none()
})
}

pub(crate) fn has_attribute(&self, name: &str) -> bool {
CLASS_ATTRIBUTES.contains(&name)
|| self.attributes.iter().flatten().any(|v| v.as_ref() == name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"level": "error",
"options": {
"attributes": ["customClassAttribute"],
"functions": ["clsx", "tw"]
"functions": ["clsx", "tw", "tw.*"]
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,30 @@ codeOptionsUnsorted.jsx:27:4 lint/nursery/useSortedClasses FIXABLE ━━━
29 29 │ notClassFunction("px-2 foo p-4 bar");
```

```
codeOptionsUnsorted.jsx:28:8 lint/nursery/useSortedClasses FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! These CSS classes should be sorted.
26 │ clsx("px-2 foo p-4 bar");
27 │ tw`px-2 foo p-4 bar`;
> 28 │ tw.div`px-2 foo p-4 bar`;
│ ^^^^^^^^^^^^^^^^
29 │ notClassFunction("px-2 foo p-4 bar");
30 │ notTemplateFunction`px-2 foo p-4 bar`;
i Unsafe fix: Sort the classes.
26 26 │ clsx("px-2 foo p-4 bar");
27 27 │ tw`px-2 foo p-4 bar`;
28 │ - tw.div`px-2·foo·p-4·bar`;
28 │ + tw.div`foo·bar·p-4·px-2`;
29 29 │ notClassFunction("px-2 foo p-4 bar");
30 30 │ notTemplateFunction`px-2 foo p-4 bar`;
```

```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"level": "error",
"options": {
"attributes": ["customClassAttribute"],
"functions": ["clsx", "tw"]
"functions": ["clsx", "tw", "tw.*"]
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/biome_js_syntax/src/jsx_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ impl JsxSelfClosingElement {

impl JsxAttributeList {
/// Returns the [JsxAttribute] that match the given `names_to_lookup`.
/// Only attributes with name as [JsxName] can be returned.
/// Only attributes with name as [AnyJsxAttributeName::JsxName] can be returned.
///
/// Each name of `names_to_lookup` must be unique.
///
Expand Down

0 comments on commit ec1e9e8

Please sign in to comment.