Skip to content

Commit 6819f6d

Browse files
committed
feat: add allow-list options for at-rules, properties, and selectors
fixes #210
1 parent 3c6937a commit 6819f6d

File tree

3 files changed

+108
-1
lines changed

3 files changed

+108
-1
lines changed

docs/rules/use-baseline.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,46 @@ This rule accepts an option object with the following properties:
104104
- `available` (default: `"widely"`)
105105
- change to `"newly"` to allow features that are at the Baseline newly available stage: features that have been supported on all core browsers for less than 30 months
106106
- set to a numeric baseline year, such as `2023`, to allow features that became Baseline newly available that year, or earlier
107+
- `allowAtRules` (default: `[]`) - Specify an array of at-rules that are allowed to be used.
108+
109+
Examples of **correct** code with `{ allowAtRules: ["container"] }`:
110+
111+
```css
112+
/* eslint css/use-baseline: ["error", { allowAtRules: ["container"] }] */
113+
114+
@container (width > 400px) {
115+
h2 {
116+
font-size: 1.5em;
117+
}
118+
}
119+
```
120+
121+
- `allowProperties` (default: `[]`) - Specify an array of properties that are allowed to be used.
122+
123+
Examples of **correct** code with `{ allowProperties: ["user-select"] }`:
124+
125+
```css
126+
/* eslint css/use-baseline: ["error", { allowProperties: ["user-select"] }] */
127+
128+
.unselectable {
129+
user-select: none;
130+
}
131+
```
132+
133+
- `allowSelectors` (default: `[]`) - Specify an array of selectors that are allowed to be used.
134+
135+
Examples of **correct** code with `{ allowSelectors: ["nesting", "has"] }`:
136+
137+
```css
138+
/* eslint css/use-baseline: ["error", { allowSelectors: ["nesting", "has"] }] */
139+
140+
h1 {
141+
margin: 0 0 1rem 0;
142+
&:has(+ h2) {
143+
margin: 0 0 0.25rem 0;
144+
}
145+
}
146+
```
107147

108148
## When Not to Use It
109149

src/rules/use-baseline.js

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ import { namedColors } from "../data/colors.js";
2828
* @import { Identifier, FunctionNodePlain } from "@eslint/css-tree"
2929
* @typedef {"notBaselineProperty" | "notBaselinePropertyValue" | "notBaselineAtRule" | "notBaselineType" | "notBaselineMediaCondition" | "notBaselineSelector"} UseBaselineMessageIds
3030
* @typedef {[{
31-
* available?: "widely" | "newly" | number
31+
* available?: "widely" | "newly" | number,
32+
* allowAtRules?: string[],
33+
* allowProperties?: string[],
34+
* allowSelectors?: string[]
3235
* }]} UseBaselineOptions
3336
* @typedef {CSSRuleDefinition<{ RuleOptions: UseBaselineOptions, MessageIds: UseBaselineMessageIds }>} UseBaselineRuleDefinition
3437
*/
@@ -430,6 +433,27 @@ export default {
430433
},
431434
],
432435
},
436+
allowAtRules: {
437+
type: "array",
438+
items: {
439+
type: "string",
440+
},
441+
uniqueItems: true,
442+
},
443+
allowProperties: {
444+
type: "array",
445+
items: {
446+
type: "string",
447+
},
448+
uniqueItems: true,
449+
},
450+
allowSelectors: {
451+
type: "array",
452+
items: {
453+
type: "string",
454+
},
455+
uniqueItems: true,
456+
},
433457
},
434458
additionalProperties: false,
435459
},
@@ -438,6 +462,9 @@ export default {
438462
defaultOptions: [
439463
{
440464
available: "widely",
465+
allowAtRules: [],
466+
allowProperties: [],
467+
allowSelectors: [],
441468
},
442469
],
443470

@@ -462,6 +489,9 @@ export default {
462489
context.options[0].available,
463490
);
464491
const supportsRules = new SupportsRules();
492+
const allowAtRules = new Set(context.options[0].allowAtRules);
493+
const allowProperties = new Set(context.options[0].allowProperties);
494+
const allowSelectors = new Set(context.options[0].allowSelectors);
465495

466496
/**
467497
* Checks a property value identifier to see if it's a baseline feature.
@@ -587,6 +617,10 @@ export default {
587617
return;
588618
}
589619

620+
if (allowProperties.has(property)) {
621+
return;
622+
}
623+
590624
/*
591625
* Step 1: Check that the property is in the baseline.
592626
*
@@ -723,6 +757,10 @@ export default {
723757
return;
724758
}
725759

760+
if (allowAtRules.has(node.name)) {
761+
return;
762+
}
763+
726764
const featureStatus = atRules.get(node.name);
727765

728766
if (!baselineAvailability.isSupported(featureStatus)) {
@@ -756,6 +794,10 @@ export default {
756794
return;
757795
}
758796

797+
if (allowSelectors.has(selector)) {
798+
return;
799+
}
800+
759801
// if the selector has been tested in a @supports rule, don't check it
760802
if (supportsRules.hasSelector(selector)) {
761803
return;
@@ -799,6 +841,11 @@ export default {
799841
NestingSelector(node) {
800842
// NestingSelector implies CSS nesting
801843
const selector = "nesting";
844+
845+
if (allowSelectors.has(selector)) {
846+
return;
847+
}
848+
802849
const featureStatus = selectors.get(selector);
803850
if (baselineAvailability.isSupported(featureStatus)) {
804851
return;

tests/rules/use-baseline.test.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,26 @@ ruleTester.run("use-baseline", rule, {
8888
code: ".box { backdrop-filter: blur(10px); }",
8989
options: [{ available: 2024 }],
9090
},
91+
{
92+
code: "h1:has(+ h2) { margin: 0 0 0.25rem 0; }",
93+
options: [{ allowSelectors: ["has"] }],
94+
},
95+
{
96+
code: `label {
97+
& input {
98+
border: blue 2px dashed;
99+
}
100+
}`,
101+
options: [{ available: 2022, allowSelectors: ["nesting"] }],
102+
},
103+
{
104+
code: "@container (min-width: 800px) { a { color: red; } }",
105+
options: [{ available: 2022, allowAtRules: ["container"] }],
106+
},
107+
{
108+
code: "a { accent-color: bar; backdrop-filter: auto }",
109+
options: [{ allowProperties: ["accent-color", "backdrop-filter"] }],
110+
},
91111
],
92112
invalid: [
93113
{

0 commit comments

Comments
 (0)