Skip to content

Commit ca1bf18

Browse files
committed
feat: add allow-list options for at-rules, properties, and selectors
fixes #210
1 parent 0598689 commit ca1bf18

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
*
@@ -724,6 +758,10 @@ export default {
724758
return;
725759
}
726760

761+
if (allowAtRules.has(atRuleName)) {
762+
return;
763+
}
764+
727765
const featureStatus = atRules.get(atRuleName);
728766

729767
if (!baselineAvailability.isSupported(featureStatus)) {
@@ -757,6 +795,10 @@ export default {
757795
return;
758796
}
759797

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

tests/rules/use-baseline.test.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,26 @@ ruleTester.run("use-baseline", rule, {
103103
"@container (min-width: 800px) { a { color: red; } }",
104104
"@media (color-gamut: srgb) { a { color: red; } }",
105105
"@MEDIA (color-gamut: srgb) { a { color: red; } }",
106+
{
107+
code: "h1:has(+ h2) { margin: 0 0 0.25rem 0; }",
108+
options: [{ allowSelectors: ["has"] }],
109+
},
110+
{
111+
code: `label {
112+
& input {
113+
border: blue 2px dashed;
114+
}
115+
}`,
116+
options: [{ available: 2022, allowSelectors: ["nesting"] }],
117+
},
118+
{
119+
code: "@container (min-width: 800px) { a { color: red; } }",
120+
options: [{ available: 2022, allowAtRules: ["container"] }],
121+
},
122+
{
123+
code: "a { accent-color: bar; backdrop-filter: auto }",
124+
options: [{ allowProperties: ["accent-color", "backdrop-filter"] }],
125+
},
106126
],
107127
invalid: [
108128
{

0 commit comments

Comments
 (0)