chore: add design tokens\css lint rules
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
// Rule: NO TOKEN-CATEGORY MISMATCH IN COMPONENTS.
|
||||
// A size property (padding, gap, font-size ...) must use a SIZE token
|
||||
// (--space-*, --size-*, --text-*, --radius-*, --bp-*, --z-*). A color property
|
||||
// (color, background, border-color ...) must use a COLOR token
|
||||
// (--color-*, --brand-*). Crossing categories (e.g. padding: var(--color-x))
|
||||
// is a sign the wrong token is being reused.
|
||||
|
||||
import { COLOR_PROPS, COLOR_TOKEN, SIZE_PROPS, SIZE_TOKEN } from "./lists.js";
|
||||
import { getStyleNodeLoc, getStyleRoot } from "./style-context.js";
|
||||
|
||||
// Collect the token names referenced by var() in a value.
|
||||
const collectVars = (value) =>
|
||||
Array.from(value.matchAll(/var\(\s*(--[\w-]+)/g), (m) => m[1]);
|
||||
|
||||
export default {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
docs: {
|
||||
description:
|
||||
"Ban using a color token in size properties and a size token in color properties; each property must use tokens of its own category.",
|
||||
category: "Design tokens",
|
||||
recommended: true,
|
||||
},
|
||||
messages: {
|
||||
categoryMismatch:
|
||||
"Token '{{token}}' in '{{prop}}' belongs to the {{category}} category; expected a {{expected}} token.",
|
||||
},
|
||||
schema: [],
|
||||
},
|
||||
create(context) {
|
||||
const root = getStyleRoot(context);
|
||||
if (!root) return {};
|
||||
const styleNodeLoc = getStyleNodeLoc(context);
|
||||
|
||||
return {
|
||||
"Program:exit"(programNode) {
|
||||
const report = (node, ruleId, data) => {
|
||||
if (!styleNodeLoc) return;
|
||||
const loc = styleNodeLoc(node);
|
||||
context.report({
|
||||
node: programNode,
|
||||
loc,
|
||||
ruleId,
|
||||
messageId: ruleId,
|
||||
data,
|
||||
});
|
||||
};
|
||||
|
||||
root.walkDecls((decl) => {
|
||||
const prop = decl.prop ?? "";
|
||||
const value = decl.value ?? "";
|
||||
|
||||
const isSizeProp = SIZE_PROPS.test(prop);
|
||||
const isColorProp = COLOR_PROPS.test(prop);
|
||||
if (!isSizeProp && !isColorProp) return;
|
||||
|
||||
for (const token of collectVars(value)) {
|
||||
// A size property that holds a COLOR token.
|
||||
if (isSizeProp && COLOR_TOKEN.test(token)) {
|
||||
report(decl, "categoryMismatch", {
|
||||
token,
|
||||
prop,
|
||||
category: "color",
|
||||
expected: "size",
|
||||
});
|
||||
}
|
||||
// A color property that holds a SIZE token (z-radius/space/text...).
|
||||
if (isColorProp && SIZE_TOKEN.test(token)) {
|
||||
report(decl, "categoryMismatch", {
|
||||
token,
|
||||
prop,
|
||||
category: "size",
|
||||
expected: "color",
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user