Skip to content

Commit c33ed5f

Browse files
authored
feat(enforce-logical-properties): add ignore option (#383)
1 parent aa2cfad commit c33ed5f

3 files changed

Lines changed: 74 additions & 0 deletions

File tree

docs/rules/enforce-logical-properties.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,17 @@ The rule reports physical classes and auto-fixes them to their logical equivalen
5858

5959
<br/>
6060

61+
### `ignore`
62+
63+
List of regex patterns for classes that should not report logical property suggestions.
64+
65+
This can be useful for classes that intentionally use physical directions.
66+
67+
**Type**: `string[]`
68+
**Default**: `[]`
69+
70+
<br/>
71+
6172
<details>
6273
<summary>Common options</summary>
6374

src/rules/enforce-logical-properties.test.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,47 @@ describe.runIf(getTailwindCSSVersion().major >= 4)(enforceLogicalProperties.name
244244
);
245245
});
246246

247+
it("should ignore configured classes", () => {
248+
lint(
249+
enforceLogicalProperties,
250+
{
251+
invalid: [
252+
{
253+
angular: `<img class="pl-4 pr-4" />`,
254+
angularOutput: `<img class="ps-4 pr-4" />`,
255+
html: `<img class="pl-4 pr-4" />`,
256+
htmlOutput: `<img class="ps-4 pr-4" />`,
257+
jsx: `() => <img class="pl-4 pr-4" />`,
258+
jsxOutput: `() => <img class="ps-4 pr-4" />`,
259+
svelte: `<img class="pl-4 pr-4" />`,
260+
svelteOutput: `<img class="ps-4 pr-4" />`,
261+
vue: `<template><img class="pl-4 pr-4" /></template>`,
262+
vueOutput: `<template><img class="ps-4 pr-4" /></template>`,
263+
264+
errors: 1,
265+
266+
options: [{
267+
ignore: ["^pr-"]
268+
}]
269+
}
270+
],
271+
valid: [
272+
{
273+
angular: `<img class="pl-4 pr-4" />`,
274+
html: `<img class="pl-4 pr-4" />`,
275+
jsx: `() => <img class="pl-4 pr-4" />`,
276+
svelte: `<img class="pl-4 pr-4" />`,
277+
vue: `<template><img class="pl-4 pr-4" /></template>`,
278+
279+
options: [{
280+
ignore: ["^pl-", "^pr-"]
281+
}]
282+
}
283+
]
284+
}
285+
);
286+
});
287+
247288
it.each(testCases)(`should report "%s"`, (input, output) => {
248289
lint(
249290
enforceLogicalProperties,

src/rules/enforce-logical-properties.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
import { array, description, optional, pipe, strictObject, string } from "valibot";
2+
13
import { createGetDissectedClasses, getDissectedClasses } from "better-tailwindcss:tailwindcss/dissect-classes.js";
24
import { createGetUnknownClasses, getUnknownClasses } from "better-tailwindcss:tailwindcss/unknown-classes.js";
35
import { buildClass } from "better-tailwindcss:utils/class.js";
46
import { async } from "better-tailwindcss:utils/context.js";
57
import { lintClasses } from "better-tailwindcss:utils/lint.js";
8+
import { getCachedRegex } from "better-tailwindcss:utils/regex.js";
69
import { createRule } from "better-tailwindcss:utils/rule.js";
710
import { replacePlaceholders, splitClasses } from "better-tailwindcss:utils/utils.js";
811

@@ -18,6 +21,18 @@ export const enforceLogicalProperties = createRule({
1821
name: "enforce-logical-properties",
1922
recommended: false,
2023

24+
schema: strictObject({
25+
ignore: optional(
26+
pipe(
27+
array(
28+
string()
29+
),
30+
description("A list of regular expression patterns for classes that should be ignored by the rule.")
31+
),
32+
[]
33+
)
34+
}),
35+
2136
messages: {
2237
multiple: "Physical class detected. Replace \"{{ className }}\" with logical classes \"{{fix}}\".",
2338
single: "Physical class detected. Replace \"{{ className }}\" with logical class \"{{fix}}\"."
@@ -96,6 +111,9 @@ const mappings = [
96111

97112

98113
function lintLiterals(ctx: Context<typeof enforceLogicalProperties>, literals: Literal[]) {
114+
const { ignore } = ctx.options;
115+
const ignoredClassRegexes = ignore.map(ignoredClass => getCachedRegex(ignoredClass));
116+
99117
for(const literal of literals){
100118
const classes = splitClasses(literal.content);
101119

@@ -114,6 +132,10 @@ function lintLiterals(ctx: Context<typeof enforceLogicalProperties>, literals: L
114132
const { unknownClasses } = getUnknownClasses(async(ctx), possibleFixes);
115133

116134
lintClasses(ctx, literal, className => {
135+
if(ignoredClassRegexes.some(ignoredClassRegex => ignoredClassRegex.test(className))){
136+
return;
137+
}
138+
117139
const dissectedClass = dissectedClasses[className];
118140

119141
if(!dissectedClass){

0 commit comments

Comments
 (0)