@jay-framework/design-system-validator 0.23.1 → 0.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent-kit/designer/design-system.md +16 -2
- package/dist/index.d.ts +3 -1
- package/dist/index.js +63 -6
- package/package.json +11 -11
- package/plugin.yaml +4 -0
|
@@ -97,7 +97,7 @@ Use the token values directly in your `<style>` blocks:
|
|
|
97
97
|
}
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
CSS custom properties (`var(--name)`) are resolved statically when defined in
|
|
100
|
+
CSS custom properties (`var(--name)`) are resolved statically when defined in the page's CSS (inline `<style>` or linked local stylesheets). Variables that are used but never defined are flagged as warnings.
|
|
101
101
|
|
|
102
102
|
## Breakpoints
|
|
103
103
|
|
|
@@ -132,12 +132,18 @@ The `components` section defines expected styles for HTML elements (matched by c
|
|
|
132
132
|
|
|
133
133
|
When a value intentionally breaks the design system, exempt it:
|
|
134
134
|
|
|
135
|
-
**In CSS** — add a comment after the declaration:
|
|
135
|
+
**In CSS** — add a comment on the same line or the line immediately after the declaration:
|
|
136
136
|
|
|
137
137
|
```css
|
|
138
138
|
.hero {
|
|
139
139
|
padding: 7.5rem 0; /* design-system: allow */
|
|
140
140
|
}
|
|
141
|
+
|
|
142
|
+
/* or on the next line: */
|
|
143
|
+
.hero {
|
|
144
|
+
padding: 7.5rem 0;
|
|
145
|
+
/* design-system: allow */
|
|
146
|
+
}
|
|
141
147
|
```
|
|
142
148
|
|
|
143
149
|
**On elements** — add the `jay-design="allow"` attribute:
|
|
@@ -213,6 +219,14 @@ These are the errors the validator produces. Use them to align your CSS with the
|
|
|
213
219
|
Suggestion: Use a DESIGN.md breakpoint: mobile (600px), tablet (768px), desktop (1024px)
|
|
214
220
|
```
|
|
215
221
|
|
|
222
|
+
**Undefined CSS variable:**
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
⚠ CSS variable "--color-surface-tint" is used but never defined
|
|
226
|
+
Suggestion: Define --color-surface-tint in a :root block, or replace with a DESIGN.md token value directly.
|
|
227
|
+
To suppress: add /* design-system: allow */ on the same line or the line after the declaration.
|
|
228
|
+
```
|
|
229
|
+
|
|
216
230
|
**Low contrast:**
|
|
217
231
|
|
|
218
232
|
```
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ declare const validateContrast: JayHtmlValidatorFn;
|
|
|
15
15
|
|
|
16
16
|
declare const validateFontFallbacks: JayHtmlValidatorFn;
|
|
17
17
|
|
|
18
|
+
declare const validateUndefinedVars: JayHtmlValidatorFn;
|
|
19
|
+
|
|
18
20
|
interface FontFallbackInput {
|
|
19
21
|
primary: string;
|
|
20
22
|
fallback: string;
|
|
@@ -106,4 +108,4 @@ declare const regenerateDesignSystemAddMenu: _jay_framework_fullstack_component.
|
|
|
106
108
|
message: any;
|
|
107
109
|
}, []>;
|
|
108
110
|
|
|
109
|
-
export { ADD_MENU_GENERATED_REL, fontFallback, generateDesignSystemAgentKit, getDesignSystemSettingsStatus, loadDesignSystemAddMenuCatalog, regenerateDesignSystemAddMenu, runDesignSystemAnalysisAction as runDesignSystemAnalysis, saveDesignSystemAddMenuCatalog, validateComponents, validateContrast, validateFontFallbacks, validateStructure, validateTokens };
|
|
111
|
+
export { ADD_MENU_GENERATED_REL, fontFallback, generateDesignSystemAgentKit, getDesignSystemSettingsStatus, loadDesignSystemAddMenuCatalog, regenerateDesignSystemAddMenu, runDesignSystemAnalysisAction as runDesignSystemAnalysis, saveDesignSystemAddMenuCatalog, validateComponents, validateContrast, validateFontFallbacks, validateStructure, validateTokens, validateUndefinedVars };
|
package/dist/index.js
CHANGED
|
@@ -91,7 +91,7 @@ function findDesignMd(filePath, projectRoot) {
|
|
|
91
91
|
}
|
|
92
92
|
return null;
|
|
93
93
|
}
|
|
94
|
-
const ALLOW_COMMENT = "design-system: allow";
|
|
94
|
+
const ALLOW_COMMENT$1 = "design-system: allow";
|
|
95
95
|
function computeSpecificity(selector) {
|
|
96
96
|
let result = [0, 0, 0];
|
|
97
97
|
selectorParser((selectors) => {
|
|
@@ -103,15 +103,15 @@ function computeSpecificity(selector) {
|
|
|
103
103
|
}).processSync(selector);
|
|
104
104
|
return result;
|
|
105
105
|
}
|
|
106
|
-
function hasAllowComment(decl) {
|
|
106
|
+
function hasAllowComment$1(decl) {
|
|
107
107
|
const next = decl.next();
|
|
108
|
-
if (next?.type === "comment" && next.text.trim() === ALLOW_COMMENT) {
|
|
108
|
+
if (next?.type === "comment" && next.text.trim() === ALLOW_COMMENT$1) {
|
|
109
109
|
return true;
|
|
110
110
|
}
|
|
111
111
|
const raw = decl.raws.value;
|
|
112
112
|
if (raw && typeof raw === "object" && "raw" in raw) {
|
|
113
113
|
const rawStr = raw.raw;
|
|
114
|
-
if (rawStr.includes(`/*${ALLOW_COMMENT}*/`) || rawStr.includes(`/* ${ALLOW_COMMENT} */`)) {
|
|
114
|
+
if (rawStr.includes(`/*${ALLOW_COMMENT$1}*/`) || rawStr.includes(`/* ${ALLOW_COMMENT$1} */`)) {
|
|
115
115
|
return true;
|
|
116
116
|
}
|
|
117
117
|
}
|
|
@@ -148,7 +148,7 @@ function parseRules(css, sourceIndexOffset = 0, customProperties) {
|
|
|
148
148
|
property: decl.prop,
|
|
149
149
|
value: decl.value,
|
|
150
150
|
important: decl.important,
|
|
151
|
-
allowed: hasAllowComment(decl)
|
|
151
|
+
allowed: hasAllowComment$1(decl)
|
|
152
152
|
});
|
|
153
153
|
});
|
|
154
154
|
const mediaQuery = getMediaQuery(rule);
|
|
@@ -1181,6 +1181,62 @@ const validateFontFallbacks = (ctx) => {
|
|
|
1181
1181
|
}
|
|
1182
1182
|
return findings;
|
|
1183
1183
|
};
|
|
1184
|
+
const ALLOW_COMMENT = "design-system: allow";
|
|
1185
|
+
const VAR_REGEX = /var\(\s*(--[a-zA-Z0-9-]+)(?:\s*,\s*([^)]+))?\s*\)/g;
|
|
1186
|
+
function hasAllowComment(decl) {
|
|
1187
|
+
const next = decl.next();
|
|
1188
|
+
if (next?.type === "comment" && next.text.trim() === ALLOW_COMMENT) {
|
|
1189
|
+
return true;
|
|
1190
|
+
}
|
|
1191
|
+
const raw = decl.raws.value;
|
|
1192
|
+
if (raw && typeof raw === "object" && "raw" in raw) {
|
|
1193
|
+
const rawStr = raw.raw;
|
|
1194
|
+
if (rawStr.includes(`/*${ALLOW_COMMENT}*/`) || rawStr.includes(`/* ${ALLOW_COMMENT} */`)) {
|
|
1195
|
+
return true;
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
return false;
|
|
1199
|
+
}
|
|
1200
|
+
const validateUndefinedVars = (ctx) => {
|
|
1201
|
+
if (!ctx.css) return [];
|
|
1202
|
+
const findings = [];
|
|
1203
|
+
const definedVars = /* @__PURE__ */ new Set();
|
|
1204
|
+
const usedVars = /* @__PURE__ */ new Map();
|
|
1205
|
+
const root = postcss.parse(ctx.css);
|
|
1206
|
+
root.walkDecls((decl) => {
|
|
1207
|
+
if (decl.prop.startsWith("--")) {
|
|
1208
|
+
definedVars.add(decl.prop);
|
|
1209
|
+
}
|
|
1210
|
+
if (decl.value.includes("var(") && !hasAllowComment(decl)) {
|
|
1211
|
+
const selector = decl.parent && "selector" in decl.parent ? decl.parent.selector : "[unknown]";
|
|
1212
|
+
let match;
|
|
1213
|
+
VAR_REGEX.lastIndex = 0;
|
|
1214
|
+
while ((match = VAR_REGEX.exec(decl.value)) !== null) {
|
|
1215
|
+
const varName = match[1];
|
|
1216
|
+
if (!usedVars.has(varName)) {
|
|
1217
|
+
usedVars.set(varName, {
|
|
1218
|
+
property: decl.prop,
|
|
1219
|
+
selector,
|
|
1220
|
+
hasFallback: match[2] !== void 0,
|
|
1221
|
+
fallbackValue: match[2]?.trim()
|
|
1222
|
+
});
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
});
|
|
1227
|
+
for (const [varName, usage] of usedVars) {
|
|
1228
|
+
if (definedVars.has(varName)) continue;
|
|
1229
|
+
const fallbackNote = usage.hasFallback ? ` (falls back to "${usage.fallbackValue}")` : "";
|
|
1230
|
+
findings.push({
|
|
1231
|
+
severity: "warning",
|
|
1232
|
+
message: `CSS variable "${varName}" is used but never defined${fallbackNote}`,
|
|
1233
|
+
suggestion: `Define ${varName} in a :root block, or replace with a DESIGN.md token value directly.
|
|
1234
|
+
To suppress: add /* design-system: allow */ on the same line or the line after the declaration.
|
|
1235
|
+
See agent-kit/designer/design-system.md for usage guide.`
|
|
1236
|
+
});
|
|
1237
|
+
}
|
|
1238
|
+
return findings;
|
|
1239
|
+
};
|
|
1184
1240
|
async function loadMetrics(familyName) {
|
|
1185
1241
|
const camelCase = fontFamilyToCamelCase(familyName);
|
|
1186
1242
|
try {
|
|
@@ -1823,5 +1879,6 @@ export {
|
|
|
1823
1879
|
validateContrast,
|
|
1824
1880
|
validateFontFallbacks,
|
|
1825
1881
|
validateStructure,
|
|
1826
|
-
validateTokens
|
|
1882
|
+
validateTokens,
|
|
1883
|
+
validateUndefinedVars
|
|
1827
1884
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jay-framework/design-system-validator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Design system validation plugin for Jay Framework — validates jay-html CSS against DESIGN.md tokens",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -36,21 +36,21 @@
|
|
|
36
36
|
"@capsizecss/metrics": "^4.2.0",
|
|
37
37
|
"@capsizecss/unpack": "^4.0.1",
|
|
38
38
|
"@csstools/selector-specificity": "^5.0.0",
|
|
39
|
-
"@jay-framework/compiler-jay-html": "^0.
|
|
40
|
-
"@jay-framework/compiler-shared": "^0.
|
|
41
|
-
"@jay-framework/component": "^0.
|
|
42
|
-
"@jay-framework/fullstack-component": "^0.
|
|
43
|
-
"@jay-framework/plugin-validator": "^0.
|
|
44
|
-
"@jay-framework/stack-server-runtime": "^0.
|
|
39
|
+
"@jay-framework/compiler-jay-html": "^0.24.1",
|
|
40
|
+
"@jay-framework/compiler-shared": "^0.24.1",
|
|
41
|
+
"@jay-framework/component": "^0.24.1",
|
|
42
|
+
"@jay-framework/fullstack-component": "^0.24.1",
|
|
43
|
+
"@jay-framework/plugin-validator": "^0.24.1",
|
|
44
|
+
"@jay-framework/stack-server-runtime": "^0.24.1",
|
|
45
45
|
"js-yaml": "^4.1.0",
|
|
46
46
|
"postcss": "^8.5.6",
|
|
47
47
|
"postcss-selector-parser": "^7.1.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@jay-framework/compiler-jay-stack": "^0.
|
|
51
|
-
"@jay-framework/dev-environment": "^0.
|
|
52
|
-
"@jay-framework/jay-cli": "^0.
|
|
53
|
-
"@jay-framework/jay-stack-cli": "^0.
|
|
50
|
+
"@jay-framework/compiler-jay-stack": "^0.24.1",
|
|
51
|
+
"@jay-framework/dev-environment": "^0.24.1",
|
|
52
|
+
"@jay-framework/jay-cli": "^0.24.1",
|
|
53
|
+
"@jay-framework/jay-stack-cli": "^0.24.1",
|
|
54
54
|
"@types/js-yaml": "^4.0.9",
|
|
55
55
|
"@types/node": "^22.15.21",
|
|
56
56
|
"node-html-parser": "^6.1.0",
|
package/plugin.yaml
CHANGED
|
@@ -39,3 +39,7 @@ validators:
|
|
|
39
39
|
- name: font-fallbacks
|
|
40
40
|
handler: validateFontFallbacks
|
|
41
41
|
description: Detects web fonts loaded via @font-face URL without a metric-matched local fallback (causes CLS)
|
|
42
|
+
|
|
43
|
+
- name: undefined-vars
|
|
44
|
+
handler: validateUndefinedVars
|
|
45
|
+
description: Flags CSS var(--name) references that are never defined as custom properties
|