@tenphi/eslint-plugin-tasty 0.3.1 → 0.4.0
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/dist/config.js +100 -20
- package/dist/config.js.map +1 -1
- package/dist/configs.js +5 -4
- package/dist/configs.js.map +1 -1
- package/dist/constants.js +55 -1
- package/dist/constants.js.map +1 -1
- package/dist/context.js +37 -6
- package/dist/context.js.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/parsers/state-key-parser.js +486 -0
- package/dist/parsers/state-key-parser.js.map +1 -0
- package/dist/parsers/utils.js +128 -0
- package/dist/parsers/utils.js.map +1 -0
- package/dist/parsers/value-parser.js +613 -0
- package/dist/parsers/value-parser.js.map +1 -0
- package/dist/rules/consistent-token-usage.js +20 -19
- package/dist/rules/consistent-token-usage.js.map +1 -1
- package/dist/rules/known-property.js +31 -30
- package/dist/rules/known-property.js.map +1 -1
- package/dist/rules/no-duplicate-state.js +12 -11
- package/dist/rules/no-duplicate-state.js.map +1 -1
- package/dist/rules/no-important.js +12 -11
- package/dist/rules/no-important.js.map +1 -1
- package/dist/rules/no-nested-selector.js +15 -14
- package/dist/rules/no-nested-selector.js.map +1 -1
- package/dist/rules/no-nested-state-map.js +19 -18
- package/dist/rules/no-nested-state-map.js.map +1 -1
- package/dist/rules/no-raw-color-values.js +15 -14
- package/dist/rules/no-raw-color-values.js.map +1 -1
- package/dist/rules/no-runtime-styles-mutation.js +6 -5
- package/dist/rules/no-runtime-styles-mutation.js.map +1 -1
- package/dist/rules/no-unknown-state-alias.js +12 -11
- package/dist/rules/no-unknown-state-alias.js.map +1 -1
- package/dist/rules/prefer-shorthand-property.js +19 -18
- package/dist/rules/prefer-shorthand-property.js.map +1 -1
- package/dist/rules/require-default-state.js +22 -21
- package/dist/rules/require-default-state.js.map +1 -1
- package/dist/rules/static-no-dynamic-values.js +7 -6
- package/dist/rules/static-no-dynamic-values.js.map +1 -1
- package/dist/rules/static-valid-selector.js +1 -1
- package/dist/rules/valid-boolean-property.js +19 -18
- package/dist/rules/valid-boolean-property.js.map +1 -1
- package/dist/rules/valid-color-token.js +33 -21
- package/dist/rules/valid-color-token.js.map +1 -1
- package/dist/rules/valid-custom-property.js +31 -19
- package/dist/rules/valid-custom-property.js.map +1 -1
- package/dist/rules/valid-custom-unit.js +12 -16
- package/dist/rules/valid-custom-unit.js.map +1 -1
- package/dist/rules/valid-directional-modifier.js +21 -20
- package/dist/rules/valid-directional-modifier.js.map +1 -1
- package/dist/rules/valid-preset.js +5 -2
- package/dist/rules/valid-preset.js.map +1 -1
- package/dist/rules/valid-radius-shape.js +19 -18
- package/dist/rules/valid-radius-shape.js.map +1 -1
- package/dist/rules/valid-recipe.js +5 -2
- package/dist/rules/valid-recipe.js.map +1 -1
- package/dist/rules/valid-state-definition.js +70 -0
- package/dist/rules/valid-state-definition.js.map +1 -0
- package/dist/rules/valid-state-key.js +39 -102
- package/dist/rules/valid-state-key.js.map +1 -1
- package/dist/rules/valid-styles-structure.js +39 -38
- package/dist/rules/valid-styles-structure.js.map +1 -1
- package/dist/rules/valid-sub-element.js +21 -20
- package/dist/rules/valid-sub-element.js.map +1 -1
- package/dist/rules/valid-transition.js +19 -18
- package/dist/rules/valid-transition.js.map +1 -1
- package/dist/rules/valid-value.js +115 -64
- package/dist/rules/valid-value.js.map +1 -1
- package/package.json +1 -8
- package/dist/parser.js +0 -46
- package/dist/parser.js.map +0 -1
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
//#region src/parsers/utils.ts
|
|
2
|
+
function isWhitespace(ch) {
|
|
3
|
+
return ch === " " || ch === "\n" || ch === " " || ch === "\r" || ch === "\f";
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Check that all brackets/parentheses are balanced in a source string.
|
|
7
|
+
* Returns null if balanced, or an error with position if not.
|
|
8
|
+
*/
|
|
9
|
+
function checkBracketBalance(src) {
|
|
10
|
+
let depth = 0;
|
|
11
|
+
let inQuote = 0;
|
|
12
|
+
for (let i = 0; i < src.length; i++) {
|
|
13
|
+
const ch = src[i];
|
|
14
|
+
if (inQuote) {
|
|
15
|
+
if (ch === inQuote && src[i - 1] !== "\\") inQuote = 0;
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (ch === "\"" || ch === "'") {
|
|
19
|
+
inQuote = ch;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (ch === "(") depth++;
|
|
23
|
+
if (ch === ")") {
|
|
24
|
+
depth--;
|
|
25
|
+
if (depth < 0) return {
|
|
26
|
+
position: i,
|
|
27
|
+
message: "Unexpected closing parenthesis"
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (depth !== 0) return {
|
|
32
|
+
position: src.length - 1,
|
|
33
|
+
message: "Unbalanced parentheses: missing closing parenthesis"
|
|
34
|
+
};
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Tokenize a style value string following tasty's scan() semantics:
|
|
39
|
+
* - Whitespace splits tokens
|
|
40
|
+
* - Commas separate groups
|
|
41
|
+
* - Spaced slashes (`a / b`) separate parts
|
|
42
|
+
* - Non-spaced slashes (`center/cover`) stay inside the token
|
|
43
|
+
* - Parenthesized content stays as a single token
|
|
44
|
+
* - Quoted strings stay as a single token
|
|
45
|
+
* - `url(...)` content is never split
|
|
46
|
+
*/
|
|
47
|
+
function scanTokens(src) {
|
|
48
|
+
const result = [];
|
|
49
|
+
let depth = 0;
|
|
50
|
+
let inUrl = false;
|
|
51
|
+
let inQuote = 0;
|
|
52
|
+
let start = 0;
|
|
53
|
+
let i = 0;
|
|
54
|
+
let pendingSlash = false;
|
|
55
|
+
const flush = (isComma, isSlash) => {
|
|
56
|
+
const actualSlash = isSlash || pendingSlash;
|
|
57
|
+
pendingSlash = false;
|
|
58
|
+
if (start < i) result.push({
|
|
59
|
+
value: src.slice(start, i),
|
|
60
|
+
isComma,
|
|
61
|
+
isSlash: actualSlash,
|
|
62
|
+
offset: start
|
|
63
|
+
});
|
|
64
|
+
else if (isComma) result.push({
|
|
65
|
+
value: "",
|
|
66
|
+
isComma: true,
|
|
67
|
+
isSlash: false,
|
|
68
|
+
offset: i
|
|
69
|
+
});
|
|
70
|
+
else if (actualSlash) result.push({
|
|
71
|
+
value: "",
|
|
72
|
+
isComma: false,
|
|
73
|
+
isSlash: true,
|
|
74
|
+
offset: i
|
|
75
|
+
});
|
|
76
|
+
start = i + 1;
|
|
77
|
+
};
|
|
78
|
+
for (; i < src.length; i++) {
|
|
79
|
+
const ch = src[i];
|
|
80
|
+
if (inQuote) {
|
|
81
|
+
if (ch === inQuote && src[i - 1] !== "\\") inQuote = 0;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (ch === "\"" || ch === "'") {
|
|
85
|
+
inQuote = ch;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (ch === "(") {
|
|
89
|
+
if (!depth) {
|
|
90
|
+
if (src.slice(Math.max(0, i - 3), i + 1) === "url(") inUrl = true;
|
|
91
|
+
}
|
|
92
|
+
depth++;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (ch === ")") {
|
|
96
|
+
depth = Math.max(0, depth - 1);
|
|
97
|
+
if (inUrl && depth === 0) inUrl = false;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (inUrl) continue;
|
|
101
|
+
if (!depth) {
|
|
102
|
+
if (ch === ",") {
|
|
103
|
+
flush(true, false);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (ch === "/") {
|
|
107
|
+
const prevIsWs = isWhitespace(src[i - 1]);
|
|
108
|
+
const nextIsWs = isWhitespace(src[i + 1]);
|
|
109
|
+
if (prevIsWs && nextIsWs) {
|
|
110
|
+
pendingSlash = true;
|
|
111
|
+
start = i + 1;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (isWhitespace(ch)) {
|
|
117
|
+
flush(false, false);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
flush(false, false);
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
//#endregion
|
|
127
|
+
export { checkBracketBalance, scanTokens };
|
|
128
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../../src/parsers/utils.ts"],"sourcesContent":["export function isWhitespace(ch: string | undefined): boolean {\n return (\n ch === ' ' || ch === '\\n' || ch === '\\t' || ch === '\\r' || ch === '\\f'\n );\n}\n\nexport function isDigit(ch: string): boolean {\n return ch >= '0' && ch <= '9';\n}\n\nexport function isAlpha(ch: string): boolean {\n return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');\n}\n\nexport interface BracketError {\n position: number;\n message: string;\n}\n\n/**\n * Check that all brackets/parentheses are balanced in a source string.\n * Returns null if balanced, or an error with position if not.\n */\nexport function checkBracketBalance(src: string): BracketError | null {\n let depth = 0;\n let inQuote: string | 0 = 0;\n\n for (let i = 0; i < src.length; i++) {\n const ch = src[i];\n\n if (inQuote) {\n if (ch === inQuote && src[i - 1] !== '\\\\') inQuote = 0;\n continue;\n }\n if (ch === '\"' || ch === \"'\") {\n inQuote = ch;\n continue;\n }\n\n if (ch === '(') depth++;\n if (ch === ')') {\n depth--;\n if (depth < 0) {\n return { position: i, message: 'Unexpected closing parenthesis' };\n }\n }\n }\n\n if (depth !== 0) {\n return {\n position: src.length - 1,\n message: 'Unbalanced parentheses: missing closing parenthesis',\n };\n }\n\n return null;\n}\n\nexport interface ScannedToken {\n value: string;\n isComma: boolean;\n isSlash: boolean;\n offset: number;\n}\n\n/**\n * Tokenize a style value string following tasty's scan() semantics:\n * - Whitespace splits tokens\n * - Commas separate groups\n * - Spaced slashes (`a / b`) separate parts\n * - Non-spaced slashes (`center/cover`) stay inside the token\n * - Parenthesized content stays as a single token\n * - Quoted strings stay as a single token\n * - `url(...)` content is never split\n */\nexport function scanTokens(src: string): ScannedToken[] {\n const result: ScannedToken[] = [];\n let depth = 0;\n let inUrl = false;\n let inQuote: string | 0 = 0;\n let start = 0;\n let i = 0;\n let pendingSlash = false;\n\n const flush = (isComma: boolean, isSlash: boolean) => {\n const actualSlash = isSlash || pendingSlash;\n pendingSlash = false;\n\n if (start < i) {\n result.push({\n value: src.slice(start, i),\n isComma,\n isSlash: actualSlash,\n offset: start,\n });\n } else if (isComma) {\n result.push({ value: '', isComma: true, isSlash: false, offset: i });\n } else if (actualSlash) {\n result.push({ value: '', isComma: false, isSlash: true, offset: i });\n }\n start = i + 1;\n };\n\n for (; i < src.length; i++) {\n const ch = src[i];\n\n if (inQuote) {\n if (ch === inQuote && src[i - 1] !== '\\\\') inQuote = 0;\n continue;\n }\n if (ch === '\"' || ch === \"'\") {\n inQuote = ch;\n continue;\n }\n\n if (ch === '(') {\n if (!depth) {\n const maybe = src.slice(Math.max(0, i - 3), i + 1);\n if (maybe === 'url(') inUrl = true;\n }\n depth++;\n continue;\n }\n if (ch === ')') {\n depth = Math.max(0, depth - 1);\n if (inUrl && depth === 0) inUrl = false;\n continue;\n }\n\n if (inUrl) continue;\n\n if (!depth) {\n if (ch === ',') {\n flush(true, false);\n continue;\n }\n if (ch === '/') {\n const prevIsWs = isWhitespace(src[i - 1]);\n const nextIsWs = isWhitespace(src[i + 1]);\n if (prevIsWs && nextIsWs) {\n pendingSlash = true;\n start = i + 1;\n continue;\n }\n continue;\n }\n if (isWhitespace(ch)) {\n flush(false, false);\n continue;\n }\n }\n }\n flush(false, false);\n\n return result;\n}\n"],"mappings":";AAAA,SAAgB,aAAa,IAAiC;AAC5D,QACE,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAQ,OAAO,QAAQ,OAAO;;;;;;AAqBtE,SAAgB,oBAAoB,KAAkC;CACpE,IAAI,QAAQ;CACZ,IAAI,UAAsB;AAE1B,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;EACnC,MAAM,KAAK,IAAI;AAEf,MAAI,SAAS;AACX,OAAI,OAAO,WAAW,IAAI,IAAI,OAAO,KAAM,WAAU;AACrD;;AAEF,MAAI,OAAO,QAAO,OAAO,KAAK;AAC5B,aAAU;AACV;;AAGF,MAAI,OAAO,IAAK;AAChB,MAAI,OAAO,KAAK;AACd;AACA,OAAI,QAAQ,EACV,QAAO;IAAE,UAAU;IAAG,SAAS;IAAkC;;;AAKvE,KAAI,UAAU,EACZ,QAAO;EACL,UAAU,IAAI,SAAS;EACvB,SAAS;EACV;AAGH,QAAO;;;;;;;;;;;;AAoBT,SAAgB,WAAW,KAA6B;CACtD,MAAM,SAAyB,EAAE;CACjC,IAAI,QAAQ;CACZ,IAAI,QAAQ;CACZ,IAAI,UAAsB;CAC1B,IAAI,QAAQ;CACZ,IAAI,IAAI;CACR,IAAI,eAAe;CAEnB,MAAM,SAAS,SAAkB,YAAqB;EACpD,MAAM,cAAc,WAAW;AAC/B,iBAAe;AAEf,MAAI,QAAQ,EACV,QAAO,KAAK;GACV,OAAO,IAAI,MAAM,OAAO,EAAE;GAC1B;GACA,SAAS;GACT,QAAQ;GACT,CAAC;WACO,QACT,QAAO,KAAK;GAAE,OAAO;GAAI,SAAS;GAAM,SAAS;GAAO,QAAQ;GAAG,CAAC;WAC3D,YACT,QAAO,KAAK;GAAE,OAAO;GAAI,SAAS;GAAO,SAAS;GAAM,QAAQ;GAAG,CAAC;AAEtE,UAAQ,IAAI;;AAGd,QAAO,IAAI,IAAI,QAAQ,KAAK;EAC1B,MAAM,KAAK,IAAI;AAEf,MAAI,SAAS;AACX,OAAI,OAAO,WAAW,IAAI,IAAI,OAAO,KAAM,WAAU;AACrD;;AAEF,MAAI,OAAO,QAAO,OAAO,KAAK;AAC5B,aAAU;AACV;;AAGF,MAAI,OAAO,KAAK;AACd,OAAI,CAAC,OAEH;QADc,IAAI,MAAM,KAAK,IAAI,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KACpC,OAAQ,SAAQ;;AAEhC;AACA;;AAEF,MAAI,OAAO,KAAK;AACd,WAAQ,KAAK,IAAI,GAAG,QAAQ,EAAE;AAC9B,OAAI,SAAS,UAAU,EAAG,SAAQ;AAClC;;AAGF,MAAI,MAAO;AAEX,MAAI,CAAC,OAAO;AACV,OAAI,OAAO,KAAK;AACd,UAAM,MAAM,MAAM;AAClB;;AAEF,OAAI,OAAO,KAAK;IACd,MAAM,WAAW,aAAa,IAAI,IAAI,GAAG;IACzC,MAAM,WAAW,aAAa,IAAI,IAAI,GAAG;AACzC,QAAI,YAAY,UAAU;AACxB,oBAAe;AACf,aAAQ,IAAI;AACZ;;AAEF;;AAEF,OAAI,aAAa,GAAG,EAAE;AACpB,UAAM,OAAO,MAAM;AACnB;;;;AAIN,OAAM,OAAO,MAAM;AAEnB,QAAO"}
|