@master/css-tooling 0.0.0-site.1793659883.g69c9aebcf628
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/README.md +58 -0
- package/dist/browser.d.ts +2 -0
- package/dist/browser.js +1 -0
- package/dist/css-tree-version.d.ts +2 -0
- package/dist/css-tree-version.js +4 -0
- package/dist/css.d.ts +32 -0
- package/dist/css.js +120 -0
- package/dist/immutable.d.ts +2 -0
- package/dist/immutable.js +7 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/language/binding-session.d.ts +6 -0
- package/dist/language/binding-session.js +8 -0
- package/dist/language/browser.d.ts +10 -0
- package/dist/language/browser.js +12 -0
- package/dist/language/common.d.ts +12 -0
- package/dist/language/common.js +55 -0
- package/dist/language/contracts.d.ts +197 -0
- package/dist/language/contracts.js +1 -0
- package/dist/language/index.d.ts +29 -0
- package/dist/language/index.js +39 -0
- package/dist/language/master-css.d.ts +13 -0
- package/dist/language/master-css.js +35 -0
- package/dist/language/node.d.ts +21 -0
- package/dist/language/node.js +36 -0
- package/dist/language/semantic/scopes.d.ts +55 -0
- package/dist/language/semantic/scopes.js +73 -0
- package/dist/language/semantic/types.d.ts +11 -0
- package/dist/language/semantic/types.js +1 -0
- package/dist/language/session.d.ts +37 -0
- package/dist/language/session.js +87 -0
- package/dist/language/settings.d.ts +13 -0
- package/dist/language/settings.js +19 -0
- package/dist/language/utils/mdn-css-data.d.ts +5 -0
- package/dist/language/utils/mdn-css-data.js +63 -0
- package/dist/lexer/browser.d.ts +6 -0
- package/dist/lexer/browser.js +11 -0
- package/dist/lexer/contracts.d.ts +41 -0
- package/dist/lexer/contracts.js +1 -0
- package/dist/lexer/index.d.ts +8 -0
- package/dist/lexer/index.js +11 -0
- package/dist/lexer/node.d.ts +7 -0
- package/dist/lexer/node.js +11 -0
- package/dist/lexer/session.d.ts +17 -0
- package/dist/lexer/session.js +25 -0
- package/dist/lint/analysis.d.ts +90 -0
- package/dist/lint/analysis.js +1 -0
- package/dist/lint/binding-session.d.ts +21 -0
- package/dist/lint/binding-session.js +97 -0
- package/dist/lint/constants.d.ts +7 -0
- package/dist/lint/constants.js +18 -0
- package/dist/lint/contracts.d.ts +17 -0
- package/dist/lint/contracts.js +6 -0
- package/dist/lint/diagnostic-format.d.ts +5 -0
- package/dist/lint/diagnostic-format.js +15 -0
- package/dist/lint/diagnostics.d.ts +42 -0
- package/dist/lint/diagnostics.js +1 -0
- package/dist/lint/index.d.ts +21 -0
- package/dist/lint/index.js +30 -0
- package/dist/lint/node.d.ts +6 -0
- package/dist/lint/node.js +11 -0
- package/dist/lint/rule-signatures.d.ts +23 -0
- package/dist/lint/rule-signatures.js +27 -0
- package/dist/lint/source.d.ts +70 -0
- package/dist/lint/source.js +261 -0
- package/dist/math-types.d.ts +11 -0
- package/dist/math-types.js +236 -0
- package/dist/math-validation.d.ts +7 -0
- package/dist/math-validation.js +74 -0
- package/dist/node.d.ts +12 -0
- package/dist/node.js +32 -0
- package/dist/scanner/binding-session.d.ts +29 -0
- package/dist/scanner/binding-session.js +37 -0
- package/dist/scanner/core.d.ts +130 -0
- package/dist/scanner/core.js +480 -0
- package/dist/scanner/index.d.ts +3 -0
- package/dist/scanner/index.js +3 -0
- package/dist/scanner/node.d.ts +5 -0
- package/dist/scanner/node.js +4 -0
- package/dist/scanner/options/index.d.ts +16 -0
- package/dist/scanner/options/index.js +57 -0
- package/dist/scanner/source-policy.d.ts +15 -0
- package/dist/scanner/source-policy.js +131 -0
- package/dist/source/adapters/optional-peer.d.ts +5 -0
- package/dist/source/adapters/optional-peer.js +29 -0
- package/dist/source/adapters/oxc.d.ts +2 -0
- package/dist/source/adapters/oxc.js +6 -0
- package/dist/source/adapters/svelte.d.ts +5 -0
- package/dist/source/adapters/svelte.js +82 -0
- package/dist/source/adapters/types.d.ts +11 -0
- package/dist/source/adapters/types.js +9 -0
- package/dist/source/adapters/vue.d.ts +5 -0
- package/dist/source/adapters/vue.js +50 -0
- package/dist/source/browser.d.ts +7 -0
- package/dist/source/browser.js +11 -0
- package/dist/source/contracts.d.ts +35 -0
- package/dist/source/contracts.js +1 -0
- package/dist/source/index.d.ts +8 -0
- package/dist/source/index.js +11 -0
- package/dist/source/native.d.ts +5 -0
- package/dist/source/native.js +53 -0
- package/dist/source/node.d.ts +7 -0
- package/dist/source/node.js +11 -0
- package/dist/source/session.d.ts +25 -0
- package/dist/source/session.js +37 -0
- package/dist/syntax-validation.d.ts +10 -0
- package/dist/syntax-validation.js +54 -0
- package/dist/tooling-session.d.ts +66 -0
- package/dist/tooling-session.js +188 -0
- package/dist/validator/binding-session.d.ts +17 -0
- package/dist/validator/binding-session.js +29 -0
- package/dist/validator/contracts.d.ts +24 -0
- package/dist/validator/contracts.js +1 -0
- package/dist/validator/index.d.ts +10 -0
- package/dist/validator/index.js +13 -0
- package/dist/validator/node.d.ts +6 -0
- package/dist/validator/node.js +11 -0
- package/dist/validator/types/syntax-error.d.ts +22 -0
- package/dist/validator/types/syntax-error.js +1 -0
- package/dist/value-validation.d.ts +46 -0
- package/dist/value-validation.js +162 -0
- package/package.json +127 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { validateMathTypes } from "./math-types.js";
|
|
2
|
+
import { mathFunctionStatus } from "./math-validation.js";
|
|
3
|
+
import { cssTreeVersion } from "./css-tree-version.js";
|
|
4
|
+
import { CSS_SYNTAX_CHECK, cssSyntaxStatus } from "./syntax-validation.js";
|
|
5
|
+
import { definitionSyntax, generate, lexer, parse, property, walk } from "@eslint/css-tree";
|
|
6
|
+
// src/value-validation.ts
|
|
7
|
+
const CSS_VALUE_CHECK = Object.freeze({
|
|
8
|
+
name: "@eslint/css-tree",
|
|
9
|
+
version: cssTreeVersion,
|
|
10
|
+
phase: "css-value",
|
|
11
|
+
scope: "expanded-declarations-and-known-math-grammar-and-static-types-v1"
|
|
12
|
+
});
|
|
13
|
+
const units = new Set(Object.values(lexer.units).flat().map((unit) => unit.toLowerCase()));
|
|
14
|
+
const cache = /* @__PURE__ */ new Map();
|
|
15
|
+
let knownKeywords;
|
|
16
|
+
function isKnownKeyword(name) {
|
|
17
|
+
if (!knownKeywords) {
|
|
18
|
+
knownKeywords = /* @__PURE__ */ new Set();
|
|
19
|
+
const grammar = lexer.dump(false, false);
|
|
20
|
+
for (const syntax of [...Object.values(grammar.properties), ...Object.values(grammar.types)]) {
|
|
21
|
+
if (typeof syntax !== "string") continue;
|
|
22
|
+
definitionSyntax.walk(definitionSyntax.parse(syntax), (node) => {
|
|
23
|
+
if (node.type === "Keyword") knownKeywords.add(node.name.toLowerCase());
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return knownKeywords.has(name.toLowerCase());
|
|
28
|
+
}
|
|
29
|
+
/** Grammar knowledge is a report, never permission to generate a declaration. */
|
|
30
|
+
function cssValueStatus(property, value) {
|
|
31
|
+
return validateValue(property, value);
|
|
32
|
+
}
|
|
33
|
+
function validateValue(property$1, value, atRule) {
|
|
34
|
+
const key = `${atRule ?? ""}\0${property$1}\0${value}`;
|
|
35
|
+
const cached = cache.get(key);
|
|
36
|
+
if (cached) return cached;
|
|
37
|
+
if (property(property$1).custom) return "unknown";
|
|
38
|
+
let status;
|
|
39
|
+
try {
|
|
40
|
+
const ast = parse(value, { context: "value" });
|
|
41
|
+
let dependent = property(property$1).custom;
|
|
42
|
+
const descriptor = atRule ? lexer.getAtrule(atRule)?.descriptors?.[property$1] : void 0;
|
|
43
|
+
const pageContext = atRule === "page" || /^(?:top|bottom)-(?:left|center|right)(?:-corner)?$|^(?:left|right)-(?:top|middle|bottom)$/.test(atRule ?? "");
|
|
44
|
+
const useDescriptor = Boolean(atRule && (descriptor || !pageContext));
|
|
45
|
+
let unresolved = dependent || (useDescriptor ? !descriptor : !lexer.getProperty(property$1));
|
|
46
|
+
let unknownCapability = false;
|
|
47
|
+
let invalidRepeat = false;
|
|
48
|
+
let invalidMath = false;
|
|
49
|
+
let unknownMath = false;
|
|
50
|
+
walk(ast, (node) => {
|
|
51
|
+
if (node.type === "Function") {
|
|
52
|
+
const name = node.name.toLowerCase();
|
|
53
|
+
const math = mathFunctionStatus(node);
|
|
54
|
+
invalidMath ||= math === "invalid";
|
|
55
|
+
unknownMath ||= math === "unknown";
|
|
56
|
+
if ([
|
|
57
|
+
"var",
|
|
58
|
+
"env",
|
|
59
|
+
"attr"
|
|
60
|
+
].includes(name)) dependent = true;
|
|
61
|
+
if (dependent || !lexer.getType(`${name}()`)) unresolved = true;
|
|
62
|
+
if (name === "repeat" && /^grid-template-(?:columns|rows)$/.test(property$1)) {
|
|
63
|
+
const count = node.children.first;
|
|
64
|
+
if (count?.type === "Number") invalidRepeat ||= !Number.isInteger(Number(count.value)) || Number(count.value) <= 0;
|
|
65
|
+
else if (count?.type === "Identifier") invalidRepeat ||= !["auto-fill", "auto-fit"].includes(count.name);
|
|
66
|
+
}
|
|
67
|
+
} else if (node.type === "Identifier" && !isKnownKeyword(node.name)) unresolved = true;
|
|
68
|
+
else if (node.type === "Dimension" && !units.has(node.unit.toLowerCase())) {
|
|
69
|
+
unresolved = true;
|
|
70
|
+
unknownCapability = true;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
const matches = (value) => !(useDescriptor ? lexer.matchAtruleDescriptor(atRule, property$1, value) : lexer.matchProperty(property$1, value)).error;
|
|
74
|
+
const math = validateMathTypes(ast, matches);
|
|
75
|
+
invalidMath ||= math.status === "invalid";
|
|
76
|
+
unknownMath ||= math.status === "unknown";
|
|
77
|
+
const knownMatch = matches(math.ast);
|
|
78
|
+
if (math.status === "valid" && !knownMatch && !unresolved && !unknownCapability) invalidMath = true;
|
|
79
|
+
status = invalidRepeat || invalidMath ? "invalid" : dependent || unknownMath || unknownCapability ? "unknown" : knownMatch ? "valid" : unresolved ? "unknown" : "invalid";
|
|
80
|
+
} catch {
|
|
81
|
+
status = "invalid";
|
|
82
|
+
}
|
|
83
|
+
if (cache.size >= 4096) cache.delete(cache.keys().next().value);
|
|
84
|
+
cache.set(key, status);
|
|
85
|
+
return status;
|
|
86
|
+
}
|
|
87
|
+
function validateRuleDeclarations(text) {
|
|
88
|
+
const declarations = [];
|
|
89
|
+
let ast;
|
|
90
|
+
try {
|
|
91
|
+
ast = parse(text, {
|
|
92
|
+
positions: true,
|
|
93
|
+
parseAtrulePrelude: false,
|
|
94
|
+
parseRulePrelude: false,
|
|
95
|
+
parseCustomProperty: false
|
|
96
|
+
});
|
|
97
|
+
} catch {
|
|
98
|
+
return declarations;
|
|
99
|
+
}
|
|
100
|
+
walk(ast, {
|
|
101
|
+
visit: "Declaration",
|
|
102
|
+
enter(node) {
|
|
103
|
+
if (node.type !== "Declaration") return;
|
|
104
|
+
const value = generate(node.value);
|
|
105
|
+
const atRule = this.atrule && !this.rule ? this.atrule.name.toLowerCase() : void 0;
|
|
106
|
+
declarations.push({
|
|
107
|
+
property: node.property,
|
|
108
|
+
value,
|
|
109
|
+
...atRule ? { atRule } : {},
|
|
110
|
+
status: validateValue(node.property, value, atRule),
|
|
111
|
+
...node.loc ? { range: {
|
|
112
|
+
start: node.loc.start.offset,
|
|
113
|
+
end: node.loc.end.offset
|
|
114
|
+
} } : {}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
return declarations;
|
|
119
|
+
}
|
|
120
|
+
function withCSSValueValidation(result) {
|
|
121
|
+
const declarations = result.rules.flatMap((rule) => validateRuleDeclarations(rule.text));
|
|
122
|
+
const diagnostics = [...result.diagnostics || []];
|
|
123
|
+
for (const declaration of declarations) {
|
|
124
|
+
if (declaration.status !== "invalid" && declaration.status !== "unknown") continue;
|
|
125
|
+
diagnostics.push({
|
|
126
|
+
code: declaration.status === "invalid" ? "CSS_VALUE_INVALID" : "CSS_VALUE_UNKNOWN",
|
|
127
|
+
phase: "css-value",
|
|
128
|
+
severity: declaration.status === "invalid" ? "error" : "info",
|
|
129
|
+
message: declaration.status === "invalid" ? `Invalid CSS value: ${declaration.property}:${declaration.value}` : `CSS value cannot be fully checked: ${declaration.property}:${declaration.value}`,
|
|
130
|
+
range: {
|
|
131
|
+
start: 0,
|
|
132
|
+
end: result.className.length
|
|
133
|
+
},
|
|
134
|
+
notes: []
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
const cssValueStatus = declarations.some((d) => d.status === "invalid") ? "invalid" : declarations.some((d) => d.status === "unknown") ? "unknown" : declarations.length ? "valid" : "not-checked";
|
|
138
|
+
const syntax = result.rules.map((rule) => cssSyntaxStatus(rule.text));
|
|
139
|
+
const syntaxStatus = result.cssSyntaxStatus === "invalid" || syntax.includes("invalid") ? "invalid" : syntax.includes("unknown") ? "unknown" : syntax.length ? "valid" : result.cssSyntaxStatus ?? "not-checked";
|
|
140
|
+
if (syntax.includes("invalid")) diagnostics.push({
|
|
141
|
+
code: "CSS_PARSE_ERROR",
|
|
142
|
+
phase: "css-syntax",
|
|
143
|
+
severity: "error",
|
|
144
|
+
message: "Invalid CSS token structure in expanded declarations, selectors or queries",
|
|
145
|
+
range: {
|
|
146
|
+
start: 0,
|
|
147
|
+
end: result.className.length
|
|
148
|
+
},
|
|
149
|
+
notes: []
|
|
150
|
+
});
|
|
151
|
+
const checks = [...syntax.length ? [CSS_SYNTAX_CHECK] : [], ...declarations.length ? [CSS_VALUE_CHECK] : []];
|
|
152
|
+
return {
|
|
153
|
+
...result,
|
|
154
|
+
cssSyntaxStatus: syntaxStatus,
|
|
155
|
+
cssValueStatus,
|
|
156
|
+
browserSupport: "not-checked",
|
|
157
|
+
checks,
|
|
158
|
+
declarations,
|
|
159
|
+
diagnostics
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
export { CSS_VALUE_CHECK, cssValueStatus, validateRuleDeclarations, withCSSValueValidation };
|
package/package.json
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@master/css-tooling",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"engines": {
|
|
5
|
+
"node": "^24"
|
|
6
|
+
},
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"description": "Rust-backed extraction, scanning, linting, language, validation, and diagnostics sessions for Master CSS",
|
|
9
|
+
"author": "Aoyue Design LLC.",
|
|
10
|
+
"homepage": "https://css.master.co",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/master-co/css/issues"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/master-co/css.git",
|
|
17
|
+
"directory": "packages/tooling"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"tooling",
|
|
21
|
+
"scanner",
|
|
22
|
+
"lint",
|
|
23
|
+
"language-service",
|
|
24
|
+
"css",
|
|
25
|
+
"mastercss"
|
|
26
|
+
],
|
|
27
|
+
"sideEffects": false,
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"import": "./dist/index.js",
|
|
33
|
+
"default": "./dist/index.js"
|
|
34
|
+
},
|
|
35
|
+
"./node": {
|
|
36
|
+
"types": "./dist/node.d.ts",
|
|
37
|
+
"import": "./dist/node.js",
|
|
38
|
+
"default": "./dist/node.js"
|
|
39
|
+
},
|
|
40
|
+
"./lexer": {
|
|
41
|
+
"types": "./dist/lexer/index.d.ts",
|
|
42
|
+
"import": "./dist/lexer/index.js",
|
|
43
|
+
"default": "./dist/lexer/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./lexer/node": {
|
|
46
|
+
"types": "./dist/lexer/node.d.ts",
|
|
47
|
+
"import": "./dist/lexer/node.js",
|
|
48
|
+
"default": "./dist/lexer/node.js"
|
|
49
|
+
},
|
|
50
|
+
"./source": {
|
|
51
|
+
"types": "./dist/source/index.d.ts",
|
|
52
|
+
"import": "./dist/source/index.js",
|
|
53
|
+
"default": "./dist/source/index.js"
|
|
54
|
+
},
|
|
55
|
+
"./source/node": {
|
|
56
|
+
"types": "./dist/source/node.d.ts",
|
|
57
|
+
"import": "./dist/source/node.js",
|
|
58
|
+
"default": "./dist/source/node.js"
|
|
59
|
+
},
|
|
60
|
+
"./scanner/node": {
|
|
61
|
+
"types": "./dist/scanner/node.d.ts",
|
|
62
|
+
"import": "./dist/scanner/node.js",
|
|
63
|
+
"default": "./dist/scanner/node.js"
|
|
64
|
+
},
|
|
65
|
+
"./validator": {
|
|
66
|
+
"types": "./dist/validator/index.d.ts",
|
|
67
|
+
"import": "./dist/validator/index.js",
|
|
68
|
+
"default": "./dist/validator/index.js"
|
|
69
|
+
},
|
|
70
|
+
"./validator/node": {
|
|
71
|
+
"types": "./dist/validator/node.d.ts",
|
|
72
|
+
"import": "./dist/validator/node.js",
|
|
73
|
+
"default": "./dist/validator/node.js"
|
|
74
|
+
},
|
|
75
|
+
"./lint": {
|
|
76
|
+
"types": "./dist/lint/index.d.ts",
|
|
77
|
+
"import": "./dist/lint/index.js",
|
|
78
|
+
"default": "./dist/lint/index.js"
|
|
79
|
+
},
|
|
80
|
+
"./lint/node": {
|
|
81
|
+
"types": "./dist/lint/node.d.ts",
|
|
82
|
+
"import": "./dist/lint/node.js",
|
|
83
|
+
"default": "./dist/lint/node.js"
|
|
84
|
+
},
|
|
85
|
+
"./language": {
|
|
86
|
+
"types": "./dist/language/index.d.ts",
|
|
87
|
+
"import": "./dist/language/index.js",
|
|
88
|
+
"default": "./dist/language/index.js"
|
|
89
|
+
},
|
|
90
|
+
"./language/node": {
|
|
91
|
+
"types": "./dist/language/node.d.ts",
|
|
92
|
+
"import": "./dist/language/node.js",
|
|
93
|
+
"default": "./dist/language/node.js"
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"files": [
|
|
97
|
+
"dist"
|
|
98
|
+
],
|
|
99
|
+
"publishConfig": {
|
|
100
|
+
"access": "public",
|
|
101
|
+
"provenance": true
|
|
102
|
+
},
|
|
103
|
+
"dependencies": {
|
|
104
|
+
"@eslint/css-tree": "^4.1.2",
|
|
105
|
+
"@master/css-binding": "0.0.0-site.1793659883.g69c9aebcf628",
|
|
106
|
+
"@master/css-schema": "0.0.0-site.1793659883.g69c9aebcf628",
|
|
107
|
+
"consola": "^3.4.2",
|
|
108
|
+
"defu": "^6.1.7",
|
|
109
|
+
"ignore": "^7.0.14",
|
|
110
|
+
"mdn-data": "^2.37.2",
|
|
111
|
+
"minimatch": "^10.2.6"
|
|
112
|
+
},
|
|
113
|
+
"peerDependencies": {
|
|
114
|
+
"svelte": ">=4",
|
|
115
|
+
"vue": ">=3"
|
|
116
|
+
},
|
|
117
|
+
"peerDependenciesMeta": {
|
|
118
|
+
"svelte": {
|
|
119
|
+
"optional": true
|
|
120
|
+
},
|
|
121
|
+
"vue": {
|
|
122
|
+
"optional": true
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
"version": "0.0.0-site.1793659883.g69c9aebcf628",
|
|
126
|
+
"gitHead": "69c9aebcf628eb529001b9fa1b3536306f1b139e"
|
|
127
|
+
}
|