@bamboocss/eslint-plugin 1.12.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/LICENSE.md +16 -0
- package/dist/index.cjs +2287 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +2458 -0
- package/dist/index.mjs.map +1 -0
- package/dist/utils/worker.cjs +6 -0
- package/dist/utils/worker.d.cts +54 -0
- package/dist/utils/worker.d.mts +55 -0
- package/dist/utils/worker.mjs +4 -0
- package/dist/utils-BQiAeXE_.cjs +4455 -0
- package/dist/utils-BQiAeXE_.cjs.map +1 -0
- package/dist/utils-CwjhPHe9.mjs +4433 -0
- package/dist/utils-CwjhPHe9.mjs.map +1 -0
- package/package.json +62 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2458 @@
|
|
|
1
|
+
import { c as __commonJSMin, l as __esmMin, n as init_utils, r as syncAction, t as createRule } from "./utils-CwjhPHe9.mjs";
|
|
2
|
+
import { getArbitraryValue } from "@bamboocss/shared";
|
|
3
|
+
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
4
|
+
import { isNodeOfType, isNodeOfTypes } from "@typescript-eslint/utils/ast-utils";
|
|
5
|
+
import { analyze } from "@typescript-eslint/scope-manager";
|
|
6
|
+
import "@typescript-eslint/utils/ts-eslint";
|
|
7
|
+
|
|
8
|
+
//#region package.json
|
|
9
|
+
var name = "@bamboocss/eslint-plugin";
|
|
10
|
+
var version = "1.12.0";
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/utils/nodes.ts
|
|
14
|
+
var isIdentifier, isLiteral, isTemplateLiteral, isArrayExpression, isObjectExpression, isMemberExpression, isVariableDeclarator, isVariableDeclaration, isJSXMemberExpression, isJSXOpeningElement, isJSXExpressionContainer, isJSXAttribute, isJSXIdentifier, isCallExpression, isImportDeclaration, isImportSpecifier;
|
|
15
|
+
var init_nodes = __esmMin((() => {
|
|
16
|
+
isIdentifier = isNodeOfType(AST_NODE_TYPES.Identifier);
|
|
17
|
+
isLiteral = isNodeOfType(AST_NODE_TYPES.Literal);
|
|
18
|
+
isTemplateLiteral = isNodeOfType(AST_NODE_TYPES.TemplateLiteral);
|
|
19
|
+
isArrayExpression = isNodeOfType(AST_NODE_TYPES.ArrayExpression);
|
|
20
|
+
isObjectExpression = isNodeOfType(AST_NODE_TYPES.ObjectExpression);
|
|
21
|
+
isMemberExpression = isNodeOfType(AST_NODE_TYPES.MemberExpression);
|
|
22
|
+
isVariableDeclarator = isNodeOfType(AST_NODE_TYPES.VariableDeclarator);
|
|
23
|
+
isVariableDeclaration = isNodeOfType(AST_NODE_TYPES.VariableDeclaration);
|
|
24
|
+
isJSXMemberExpression = isNodeOfType(AST_NODE_TYPES.JSXMemberExpression);
|
|
25
|
+
isJSXOpeningElement = isNodeOfType(AST_NODE_TYPES.JSXOpeningElement);
|
|
26
|
+
isJSXExpressionContainer = isNodeOfType(AST_NODE_TYPES.JSXExpressionContainer);
|
|
27
|
+
isJSXAttribute = isNodeOfType(AST_NODE_TYPES.JSXAttribute);
|
|
28
|
+
isJSXIdentifier = isNodeOfType(AST_NODE_TYPES.JSXIdentifier);
|
|
29
|
+
isCallExpression = isNodeOfType(AST_NODE_TYPES.CallExpression);
|
|
30
|
+
isImportDeclaration = isNodeOfType(AST_NODE_TYPES.ImportDeclaration);
|
|
31
|
+
isImportSpecifier = isNodeOfType(AST_NODE_TYPES.ImportSpecifier);
|
|
32
|
+
}));
|
|
33
|
+
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/utils/helpers.ts
|
|
36
|
+
function isRecipeVariant(node, context) {
|
|
37
|
+
const caller = isInBambooFunction(node, context);
|
|
38
|
+
if (!caller) return;
|
|
39
|
+
if (!getImports(context).find((imp) => ["cva", "sva"].includes(imp.name) && imp.alias === caller)) return;
|
|
40
|
+
let currentNode = node;
|
|
41
|
+
let length = 0;
|
|
42
|
+
let styleObjectParent = null;
|
|
43
|
+
while (currentNode) {
|
|
44
|
+
const keyName = currentNode?.key?.name;
|
|
45
|
+
if (keyName && ["base", "variants"].includes(keyName)) styleObjectParent = keyName;
|
|
46
|
+
currentNode = currentNode.parent;
|
|
47
|
+
if (!styleObjectParent) length++;
|
|
48
|
+
}
|
|
49
|
+
if (length < (caller === "cva" ? 2 : 4) + (styleObjectParent === "base" ? 0 : 4)) return true;
|
|
50
|
+
}
|
|
51
|
+
var getAncestor, getSyncOptions, getImportSpecifiers, hasPkgImport, isBambooConfigFunction, rawImportsCache, _getImports, importsCache, getImports, isValidStyledProperty, matchFile, isBambooIsh, scopeCache, findDeclaration, isLocalStyledFactory, isValidFile, isValidProperty, isBambooImport, isBambooProp, isStyledProperty, isInBambooFunction, isInJSXProp, isBambooAttribute, resolveLonghand, resolveShorthands, isColorAttribute, isColorToken, extractTokens, invalidTokensCache, getInvalidTokens, deprecatedTokensCache, getDeprecatedTokens, getTokenImport, getTaggedTemplateCaller, isStyledTaggedTemplate;
|
|
52
|
+
var init_helpers = __esmMin((() => {
|
|
53
|
+
init_utils();
|
|
54
|
+
init_nodes();
|
|
55
|
+
getAncestor = (ofType, for_) => {
|
|
56
|
+
let current = for_.parent;
|
|
57
|
+
while (current) {
|
|
58
|
+
if (ofType(current)) return current;
|
|
59
|
+
current = current.parent;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
getSyncOptions = (context) => {
|
|
63
|
+
return {
|
|
64
|
+
configPath: context.settings["@bamboocss/configPath"],
|
|
65
|
+
currentFile: context.filename
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
getImportSpecifiers = (context) => {
|
|
69
|
+
const specifiers = [];
|
|
70
|
+
for (const node of context.sourceCode?.ast.body) {
|
|
71
|
+
if (!isImportDeclaration(node)) continue;
|
|
72
|
+
const module_ = node.source.value;
|
|
73
|
+
if (!module_) continue;
|
|
74
|
+
for (const specifier of node.specifiers) {
|
|
75
|
+
if (!isImportSpecifier(specifier)) continue;
|
|
76
|
+
specifiers.push({
|
|
77
|
+
mod: module_,
|
|
78
|
+
specifier
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return specifiers;
|
|
83
|
+
};
|
|
84
|
+
hasPkgImport = (context) => {
|
|
85
|
+
return _getImports(context).some(({ mod }) => mod === "@bamboocss/dev");
|
|
86
|
+
};
|
|
87
|
+
isBambooConfigFunction = (context, name) => {
|
|
88
|
+
return _getImports(context).some(({ alias, mod }) => alias === name && mod === "@bamboocss/dev");
|
|
89
|
+
};
|
|
90
|
+
rawImportsCache = /* @__PURE__ */ new WeakMap();
|
|
91
|
+
_getImports = (context) => {
|
|
92
|
+
if (rawImportsCache.has(context)) return rawImportsCache.get(context);
|
|
93
|
+
const imports = getImportSpecifiers(context).map(({ mod, specifier }) => ({
|
|
94
|
+
alias: specifier.local.name,
|
|
95
|
+
mod,
|
|
96
|
+
name: specifier.imported.name
|
|
97
|
+
}));
|
|
98
|
+
rawImportsCache.set(context, imports);
|
|
99
|
+
return imports;
|
|
100
|
+
};
|
|
101
|
+
importsCache = /* @__PURE__ */ new WeakMap();
|
|
102
|
+
getImports = (context) => {
|
|
103
|
+
if (importsCache.has(context)) return importsCache.get(context);
|
|
104
|
+
const imports = _getImports(context);
|
|
105
|
+
const result = syncAction("filterImports", getSyncOptions(context), imports) ?? [];
|
|
106
|
+
importsCache.set(context, result);
|
|
107
|
+
return result;
|
|
108
|
+
};
|
|
109
|
+
isValidStyledProperty = (node, context) => {
|
|
110
|
+
return isJSXIdentifier(node) && isValidProperty(node.name, context);
|
|
111
|
+
};
|
|
112
|
+
matchFile = (name, imports, context) => {
|
|
113
|
+
return syncAction("matchFile", getSyncOptions(context), name, imports);
|
|
114
|
+
};
|
|
115
|
+
isBambooIsh = (name, context) => {
|
|
116
|
+
const imports = getImports(context);
|
|
117
|
+
if (imports.length === 0) return false;
|
|
118
|
+
const jsxFactory = syncAction("getJsxFactory", getSyncOptions(context));
|
|
119
|
+
if (jsxFactory && name === jsxFactory) return imports.some((imp) => imp.name === name || imp.alias === name);
|
|
120
|
+
return matchFile(name, imports, context);
|
|
121
|
+
};
|
|
122
|
+
scopeCache = /* @__PURE__ */ new WeakMap();
|
|
123
|
+
findDeclaration = (name, context) => {
|
|
124
|
+
try {
|
|
125
|
+
const source = context.sourceCode;
|
|
126
|
+
if (!source) {
|
|
127
|
+
console.warn("⚠️ ESLint's sourceCode is not available. Ensure that the rule is invoked with valid code.");
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
let scope = scopeCache.get(source.ast);
|
|
131
|
+
if (!scope) {
|
|
132
|
+
scope = analyze(source.ast, { sourceType: "module" });
|
|
133
|
+
scopeCache.set(source.ast, scope);
|
|
134
|
+
}
|
|
135
|
+
const decl = scope.variables.find((v) => v.name === name)?.defs.find((d) => isIdentifier(d.name) && d.name.name === name)?.node;
|
|
136
|
+
if (isVariableDeclarator(decl)) return decl;
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.error("Error in findDeclaration:", error);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
isLocalStyledFactory = (node, context) => {
|
|
143
|
+
if (!isJSXIdentifier(node.name)) return;
|
|
144
|
+
const decl = findDeclaration(node.name.name, context);
|
|
145
|
+
if (!decl) return;
|
|
146
|
+
if (!isCallExpression(decl.init)) return;
|
|
147
|
+
if (!isIdentifier(decl.init.callee)) return;
|
|
148
|
+
const calleeName = decl.init.callee.name;
|
|
149
|
+
if (!_getImports(context).some((imp) => imp.alias === calleeName && imp.mod.includes("bamboo")) && !isBambooIsh(calleeName, context)) return;
|
|
150
|
+
return true;
|
|
151
|
+
};
|
|
152
|
+
isValidFile = (context) => {
|
|
153
|
+
return syncAction("isValidFile", getSyncOptions(context));
|
|
154
|
+
};
|
|
155
|
+
isValidProperty = (name, context, calleName) => {
|
|
156
|
+
return syncAction("isValidProperty", getSyncOptions(context), name, calleName);
|
|
157
|
+
};
|
|
158
|
+
isBambooImport = (node, context) => {
|
|
159
|
+
return getImports(context).some((imp) => imp.mod === node.source.value);
|
|
160
|
+
};
|
|
161
|
+
isBambooProp = (node, context) => {
|
|
162
|
+
const jsxAncestor = getAncestor(isJSXOpeningElement, node);
|
|
163
|
+
if (!jsxAncestor) return;
|
|
164
|
+
if (!isJSXMemberExpression(jsxAncestor.name) && !isJSXIdentifier(jsxAncestor.name)) return;
|
|
165
|
+
let isBambooComponent = false;
|
|
166
|
+
let componentName;
|
|
167
|
+
if (isJSXMemberExpression(jsxAncestor.name)) {
|
|
168
|
+
const objectName = jsxAncestor.name.object.name;
|
|
169
|
+
componentName = objectName;
|
|
170
|
+
const imports = getImports(context);
|
|
171
|
+
const rawImports = _getImports(context);
|
|
172
|
+
isBambooComponent = imports.some((imp) => imp.alias === objectName) || rawImports.some((imp) => imp.alias === objectName && imp.mod.includes("bamboo")) || isBambooIsh(objectName, context);
|
|
173
|
+
if (isBambooComponent) return true;
|
|
174
|
+
} else if (isJSXIdentifier(jsxAncestor.name)) {
|
|
175
|
+
componentName = jsxAncestor.name.name;
|
|
176
|
+
if (isLocalStyledFactory(jsxAncestor, context)) {
|
|
177
|
+
const property = node.name.name;
|
|
178
|
+
if (property === "css" || typeof property === "string" && property.startsWith("_")) return true;
|
|
179
|
+
if (typeof property !== "string" || !isValidProperty(property, context)) return false;
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
isBambooComponent = isBambooIsh(componentName, context);
|
|
183
|
+
}
|
|
184
|
+
if (!isBambooComponent) return;
|
|
185
|
+
const property = node.name.name;
|
|
186
|
+
if (typeof property !== "string" || !isValidProperty(property, context, componentName)) return;
|
|
187
|
+
return true;
|
|
188
|
+
};
|
|
189
|
+
isStyledProperty = (node, context, calleeName) => {
|
|
190
|
+
if (!isIdentifier(node.key) && !isLiteral(node.key) && !isTemplateLiteral(node.key)) return;
|
|
191
|
+
if (isIdentifier(node.key) && !isValidProperty(node.key.name, context, calleeName)) return;
|
|
192
|
+
if (isLiteral(node.key) && typeof node.key.value === "string" && !isValidProperty(node.key.value, context, calleeName)) return;
|
|
193
|
+
if (isTemplateLiteral(node.key) && !isValidProperty(node.key.quasis[0].value.raw, context, calleeName)) return;
|
|
194
|
+
return true;
|
|
195
|
+
};
|
|
196
|
+
isInBambooFunction = (node, context) => {
|
|
197
|
+
const callAncestor = getAncestor(isCallExpression, node);
|
|
198
|
+
if (!callAncestor) return;
|
|
199
|
+
let calleeName;
|
|
200
|
+
if (isIdentifier(callAncestor.callee)) calleeName = callAncestor.callee.name;
|
|
201
|
+
if (isMemberExpression(callAncestor.callee) && isIdentifier(callAncestor.callee.object)) calleeName = callAncestor.callee.object.name;
|
|
202
|
+
if (!calleeName) return;
|
|
203
|
+
if (!isBambooIsh(calleeName, context)) return;
|
|
204
|
+
return calleeName;
|
|
205
|
+
};
|
|
206
|
+
isInJSXProp = (node, context) => {
|
|
207
|
+
const jsxExprAncestor = getAncestor(isJSXExpressionContainer, node);
|
|
208
|
+
const jsxAttributeAncestor = getAncestor(isJSXAttribute, node);
|
|
209
|
+
if (!jsxExprAncestor || !jsxAttributeAncestor) return;
|
|
210
|
+
const jsxElement = getAncestor(isJSXOpeningElement, jsxAttributeAncestor);
|
|
211
|
+
if (!jsxElement) return;
|
|
212
|
+
let isBambooComponent = false;
|
|
213
|
+
if (isJSXMemberExpression(jsxElement.name)) {
|
|
214
|
+
const objectName = jsxElement.name.object.name;
|
|
215
|
+
isBambooComponent = isBambooIsh(objectName, context);
|
|
216
|
+
} else if (isJSXIdentifier(jsxElement.name)) {
|
|
217
|
+
const componentName = jsxElement.name.name;
|
|
218
|
+
isBambooComponent = isBambooIsh(componentName, context) || Boolean(isLocalStyledFactory(jsxElement, context));
|
|
219
|
+
}
|
|
220
|
+
if (!isBambooComponent) return;
|
|
221
|
+
if (!isJSXIdentifier(jsxAttributeAncestor.name)) return;
|
|
222
|
+
if (!isValidStyledProperty(jsxAttributeAncestor.name, context)) return;
|
|
223
|
+
return true;
|
|
224
|
+
};
|
|
225
|
+
isBambooAttribute = (node, context) => {
|
|
226
|
+
if (getAncestor(isCallExpression, node)) {
|
|
227
|
+
const callee = isInBambooFunction(node, context);
|
|
228
|
+
if (!callee) return;
|
|
229
|
+
return isStyledProperty(node, context, callee);
|
|
230
|
+
}
|
|
231
|
+
return isInJSXProp(node, context) && isStyledProperty(node, context);
|
|
232
|
+
};
|
|
233
|
+
resolveLonghand = (name, context) => {
|
|
234
|
+
return syncAction("resolveLongHand", getSyncOptions(context), name);
|
|
235
|
+
};
|
|
236
|
+
resolveShorthands = (name, context) => {
|
|
237
|
+
return syncAction("resolveShorthands", getSyncOptions(context), name);
|
|
238
|
+
};
|
|
239
|
+
isColorAttribute = (attribute, context) => {
|
|
240
|
+
return syncAction("isColorAttribute", getSyncOptions(context), attribute);
|
|
241
|
+
};
|
|
242
|
+
isColorToken = (value, context) => {
|
|
243
|
+
if (!value) return;
|
|
244
|
+
return syncAction("isColorToken", getSyncOptions(context), value);
|
|
245
|
+
};
|
|
246
|
+
extractTokens = (value) => {
|
|
247
|
+
const regex = /token\(([^"'(),]+)(?:,\s*([^"'(),]+))?\)|\{([^\n\r{}]+)\}/g;
|
|
248
|
+
const matches = [];
|
|
249
|
+
let match;
|
|
250
|
+
while ((match = regex.exec(value)) !== null) {
|
|
251
|
+
const tokenFromFirstSyntax = match[1] || match[2] || match[3];
|
|
252
|
+
const tokensFromSecondSyntax = match[4] && match[4].match(/(\w+\.\w+(\.\w+)?)/g);
|
|
253
|
+
if (tokenFromFirstSyntax) matches.push(tokenFromFirstSyntax);
|
|
254
|
+
if (tokensFromSecondSyntax) matches.push(...tokensFromSecondSyntax);
|
|
255
|
+
}
|
|
256
|
+
return matches.filter(Boolean);
|
|
257
|
+
};
|
|
258
|
+
invalidTokensCache = /* @__PURE__ */ new Map();
|
|
259
|
+
getInvalidTokens = (value, context) => {
|
|
260
|
+
if (invalidTokensCache.has(value)) return invalidTokensCache.get(value);
|
|
261
|
+
const tokens = extractTokens(value);
|
|
262
|
+
if (!tokens.length) return [];
|
|
263
|
+
const invalidTokens = syncAction("filterInvalidTokens", getSyncOptions(context), tokens);
|
|
264
|
+
invalidTokensCache.set(value, invalidTokens);
|
|
265
|
+
return invalidTokens;
|
|
266
|
+
};
|
|
267
|
+
deprecatedTokensCache = /* @__PURE__ */ new Map();
|
|
268
|
+
getDeprecatedTokens = (property, value, context) => {
|
|
269
|
+
const propertyCategory = syncAction("getPropCategory", getSyncOptions(context), property);
|
|
270
|
+
const tokens = extractTokens(value);
|
|
271
|
+
if (!propertyCategory && !tokens.length) return [];
|
|
272
|
+
const values = tokens.length ? tokens : [{
|
|
273
|
+
category: propertyCategory,
|
|
274
|
+
value: value.split("/")[0]
|
|
275
|
+
}];
|
|
276
|
+
if (deprecatedTokensCache.has(value)) return deprecatedTokensCache.get(value);
|
|
277
|
+
const deprecatedTokens = syncAction("filterDeprecatedTokens", getSyncOptions(context), values);
|
|
278
|
+
deprecatedTokensCache.set(value, deprecatedTokens);
|
|
279
|
+
return deprecatedTokens;
|
|
280
|
+
};
|
|
281
|
+
getTokenImport = (context) => {
|
|
282
|
+
return _getImports(context).find((imp) => imp.name === "token");
|
|
283
|
+
};
|
|
284
|
+
getTaggedTemplateCaller = (node) => {
|
|
285
|
+
if (isIdentifier(node.tag)) return node.tag.name;
|
|
286
|
+
if (isMemberExpression(node.tag)) {
|
|
287
|
+
if (!isIdentifier(node.tag.object)) return;
|
|
288
|
+
return node.tag.object.name;
|
|
289
|
+
}
|
|
290
|
+
if (isCallExpression(node.tag)) {
|
|
291
|
+
if (!isIdentifier(node.tag.callee)) return;
|
|
292
|
+
return node.tag.callee.name;
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
isStyledTaggedTemplate = (node, context) => {
|
|
296
|
+
const caller = getTaggedTemplateCaller(node);
|
|
297
|
+
if (!caller) return false;
|
|
298
|
+
return _getImports(context).some((imp) => imp.alias === caller && imp.mod.includes("bamboo")) || isBambooIsh(caller, context);
|
|
299
|
+
};
|
|
300
|
+
}));
|
|
301
|
+
|
|
302
|
+
//#endregion
|
|
303
|
+
//#region src/rules/file-not-included.ts
|
|
304
|
+
var RULE_NAME$18, rule$18;
|
|
305
|
+
var init_file_not_included = __esmMin((() => {
|
|
306
|
+
init_utils();
|
|
307
|
+
init_helpers();
|
|
308
|
+
RULE_NAME$18 = "file-not-included";
|
|
309
|
+
rule$18 = createRule({
|
|
310
|
+
create(context) {
|
|
311
|
+
if (isValidFile(context)) return {};
|
|
312
|
+
let hasReported = false;
|
|
313
|
+
return { ImportDeclaration(node) {
|
|
314
|
+
if (hasReported) return;
|
|
315
|
+
if (!isBambooImport(node, context)) return;
|
|
316
|
+
context.report({
|
|
317
|
+
messageId: "include",
|
|
318
|
+
node
|
|
319
|
+
});
|
|
320
|
+
hasReported = true;
|
|
321
|
+
} };
|
|
322
|
+
},
|
|
323
|
+
defaultOptions: [],
|
|
324
|
+
meta: {
|
|
325
|
+
docs: { description: "Disallow the use of Bamboo CSS in files that are not included in the specified Bamboo CSS `include` config." },
|
|
326
|
+
messages: { include: "The use of Bamboo CSS is not allowed in this file. Please ensure the file is included in the Bamboo CSS `include` configuration." },
|
|
327
|
+
schema: [],
|
|
328
|
+
type: "problem"
|
|
329
|
+
},
|
|
330
|
+
name: RULE_NAME$18
|
|
331
|
+
});
|
|
332
|
+
}));
|
|
333
|
+
|
|
334
|
+
//#endregion
|
|
335
|
+
//#region src/rules/no-config-function-in-source.ts
|
|
336
|
+
var RULE_NAME$17, CONFIG_FUNCTIONS, rule$17;
|
|
337
|
+
var init_no_config_function_in_source = __esmMin((() => {
|
|
338
|
+
init_utils();
|
|
339
|
+
init_helpers();
|
|
340
|
+
init_nodes();
|
|
341
|
+
RULE_NAME$17 = "no-config-function-in-source";
|
|
342
|
+
CONFIG_FUNCTIONS = new Set([
|
|
343
|
+
"defineConfig",
|
|
344
|
+
"defineGlobalStyles",
|
|
345
|
+
"defineKeyframes",
|
|
346
|
+
"defineLayerStyles",
|
|
347
|
+
"defineParts",
|
|
348
|
+
"definePattern",
|
|
349
|
+
"definePreset",
|
|
350
|
+
"defineRecipe",
|
|
351
|
+
"defineSemanticTokens",
|
|
352
|
+
"defineSlotRecipe",
|
|
353
|
+
"defineStyles",
|
|
354
|
+
"defineTextStyles",
|
|
355
|
+
"defineTokens",
|
|
356
|
+
"defineUtility"
|
|
357
|
+
]);
|
|
358
|
+
rule$17 = createRule({
|
|
359
|
+
create(context) {
|
|
360
|
+
if (!hasPkgImport(context)) return {};
|
|
361
|
+
if (!isValidFile(context)) return {};
|
|
362
|
+
return { CallExpression(node) {
|
|
363
|
+
if (!isIdentifier(node.callee)) return;
|
|
364
|
+
const functionName = node.callee.name;
|
|
365
|
+
if (!CONFIG_FUNCTIONS.has(functionName)) return;
|
|
366
|
+
if (!isBambooConfigFunction(context, functionName)) return;
|
|
367
|
+
context.report({
|
|
368
|
+
data: { name: functionName },
|
|
369
|
+
messageId: "configFunction",
|
|
370
|
+
node,
|
|
371
|
+
suggest: [{
|
|
372
|
+
data: { name: functionName },
|
|
373
|
+
fix(fixer) {
|
|
374
|
+
const declaration = getAncestor(isVariableDeclaration, node);
|
|
375
|
+
const importSpec = getImportSpecifiers(context).find((s) => s.specifier.local.name === functionName);
|
|
376
|
+
const fixes = [];
|
|
377
|
+
if (declaration) fixes.push(fixer.remove(declaration));
|
|
378
|
+
else fixes.push(fixer.remove(node));
|
|
379
|
+
if (importSpec?.specifier) fixes.push(fixer.remove(importSpec.specifier));
|
|
380
|
+
return fixes;
|
|
381
|
+
},
|
|
382
|
+
messageId: "delete"
|
|
383
|
+
}]
|
|
384
|
+
});
|
|
385
|
+
} };
|
|
386
|
+
},
|
|
387
|
+
defaultOptions: [],
|
|
388
|
+
meta: {
|
|
389
|
+
docs: { description: "Prohibit the use of config functions outside the Bamboo config file." },
|
|
390
|
+
hasSuggestions: true,
|
|
391
|
+
messages: {
|
|
392
|
+
configFunction: "Unnecessary `{{name}}` call. Config functions should only be used in the Bamboo config file.",
|
|
393
|
+
delete: "Delete `{{name}}` call."
|
|
394
|
+
},
|
|
395
|
+
schema: [],
|
|
396
|
+
type: "problem"
|
|
397
|
+
},
|
|
398
|
+
name: RULE_NAME$17
|
|
399
|
+
});
|
|
400
|
+
}));
|
|
401
|
+
|
|
402
|
+
//#endregion
|
|
403
|
+
//#region src/rules/no-debug.ts
|
|
404
|
+
var RULE_NAME$16, rule$16;
|
|
405
|
+
var init_no_debug = __esmMin((() => {
|
|
406
|
+
init_utils();
|
|
407
|
+
init_helpers();
|
|
408
|
+
init_nodes();
|
|
409
|
+
RULE_NAME$16 = "no-debug";
|
|
410
|
+
rule$16 = createRule({
|
|
411
|
+
create(context) {
|
|
412
|
+
const processedNodes = /* @__PURE__ */ new WeakSet();
|
|
413
|
+
const checkObjectForDebug = (object) => {
|
|
414
|
+
for (const property of object.properties) {
|
|
415
|
+
if (property.type !== "Property") continue;
|
|
416
|
+
if (!property.key || property.key.type !== "Identifier") continue;
|
|
417
|
+
if (property.key.name === "debug") {
|
|
418
|
+
if (processedNodes.has(property)) continue;
|
|
419
|
+
processedNodes.add(property);
|
|
420
|
+
context.report({
|
|
421
|
+
messageId: "debug",
|
|
422
|
+
node: property.key,
|
|
423
|
+
suggest: [{
|
|
424
|
+
fix: (fixer) => fixer.removeRange([property.range[0], property.range[1] + 1]),
|
|
425
|
+
messageId: "property"
|
|
426
|
+
}]
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
if (property.value && property.value.type === "ObjectExpression") checkObjectForDebug(property.value);
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
return {
|
|
433
|
+
JSXAttribute(node) {
|
|
434
|
+
if (!isBambooProp(node, context)) return;
|
|
435
|
+
if (!node.value || !isJSXExpressionContainer(node.value)) return;
|
|
436
|
+
const expr = node.value.expression;
|
|
437
|
+
if (!isObjectExpression(expr)) return;
|
|
438
|
+
checkObjectForDebug(expr);
|
|
439
|
+
},
|
|
440
|
+
"JSXAttribute[name.name=\"debug\"]"(node) {
|
|
441
|
+
if (!isBambooProp(node, context)) return;
|
|
442
|
+
context.report({
|
|
443
|
+
messageId: "debug",
|
|
444
|
+
node,
|
|
445
|
+
suggest: [{
|
|
446
|
+
fix: (fixer) => fixer.remove(node),
|
|
447
|
+
messageId: "prop"
|
|
448
|
+
}]
|
|
449
|
+
});
|
|
450
|
+
},
|
|
451
|
+
"Property[key.name=\"debug\"]"(node) {
|
|
452
|
+
if (processedNodes.has(node)) return;
|
|
453
|
+
if (!isBambooAttribute(node, context)) return;
|
|
454
|
+
if (isRecipeVariant(node, context)) return;
|
|
455
|
+
processedNodes.add(node);
|
|
456
|
+
context.report({
|
|
457
|
+
messageId: "debug",
|
|
458
|
+
node: node.key,
|
|
459
|
+
suggest: [{
|
|
460
|
+
fix: (fixer) => fixer.removeRange([node.range[0], node.range[1] + 1]),
|
|
461
|
+
messageId: "property"
|
|
462
|
+
}]
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
},
|
|
467
|
+
defaultOptions: [],
|
|
468
|
+
meta: {
|
|
469
|
+
docs: { description: "Disallow the inclusion of the debug attribute when shipping code to the production environment." },
|
|
470
|
+
hasSuggestions: true,
|
|
471
|
+
messages: {
|
|
472
|
+
debug: "Unnecessary debug utility.",
|
|
473
|
+
prop: "Remove the debug prop.",
|
|
474
|
+
property: "Remove the debug property."
|
|
475
|
+
},
|
|
476
|
+
schema: [],
|
|
477
|
+
type: "problem"
|
|
478
|
+
},
|
|
479
|
+
name: RULE_NAME$16
|
|
480
|
+
});
|
|
481
|
+
}));
|
|
482
|
+
|
|
483
|
+
//#endregion
|
|
484
|
+
//#region src/rules/no-deprecated-tokens.ts
|
|
485
|
+
var RULE_NAME$15, rule$15;
|
|
486
|
+
var init_no_deprecated_tokens = __esmMin((() => {
|
|
487
|
+
init_utils();
|
|
488
|
+
init_helpers();
|
|
489
|
+
init_nodes();
|
|
490
|
+
RULE_NAME$15 = "no-deprecated-tokens";
|
|
491
|
+
rule$15 = createRule({
|
|
492
|
+
create(context) {
|
|
493
|
+
const deprecatedTokensCache = /* @__PURE__ */ new Map();
|
|
494
|
+
const sendReport = (property, node, value) => {
|
|
495
|
+
if (!value) return;
|
|
496
|
+
let tokens = deprecatedTokensCache.get(value);
|
|
497
|
+
if (!tokens) {
|
|
498
|
+
tokens = getDeprecatedTokens(property, value, context);
|
|
499
|
+
deprecatedTokensCache.set(value, tokens);
|
|
500
|
+
}
|
|
501
|
+
if (!tokens || tokens.length === 0) return;
|
|
502
|
+
for (const token of tokens) context.report({
|
|
503
|
+
data: {
|
|
504
|
+
category: typeof token === "string" ? void 0 : token.category,
|
|
505
|
+
token: typeof token === "string" ? token : token.value
|
|
506
|
+
},
|
|
507
|
+
messageId: typeof token === "string" ? "noDeprecatedTokenPaths" : "noDeprecatedTokens",
|
|
508
|
+
node
|
|
509
|
+
});
|
|
510
|
+
};
|
|
511
|
+
const handleLiteralOrTemplate = (property, node) => {
|
|
512
|
+
if (!node) return;
|
|
513
|
+
if (isLiteral(node)) {
|
|
514
|
+
const value = node.value?.toString();
|
|
515
|
+
sendReport(property, node, value);
|
|
516
|
+
} else if (isTemplateLiteral(node) && node.expressions.length === 0) {
|
|
517
|
+
const value = node.quasis[0].value.raw;
|
|
518
|
+
sendReport(property, node.quasis[0], value);
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
return {
|
|
522
|
+
JSXAttribute(node) {
|
|
523
|
+
if (!node.value || !isBambooProp(node, context)) return;
|
|
524
|
+
const property = node.name.name;
|
|
525
|
+
if (isLiteral(node.value)) handleLiteralOrTemplate(property, node.value);
|
|
526
|
+
else if (isJSXExpressionContainer(node.value)) handleLiteralOrTemplate(property, node.value.expression);
|
|
527
|
+
},
|
|
528
|
+
Property(node) {
|
|
529
|
+
if (!isIdentifier(node.key) || !isNodeOfTypes([AST_NODE_TYPES.Literal, AST_NODE_TYPES.TemplateLiteral])(node.value) || !isBambooAttribute(node, context) || isRecipeVariant(node, context)) return;
|
|
530
|
+
const property = node.key.name;
|
|
531
|
+
handleLiteralOrTemplate(property, node.value);
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
},
|
|
535
|
+
defaultOptions: [],
|
|
536
|
+
meta: {
|
|
537
|
+
docs: { description: "Disallow the use of deprecated tokens within token function syntax." },
|
|
538
|
+
messages: {
|
|
539
|
+
noDeprecatedTokenPaths: "`{{token}}` is a deprecated token.",
|
|
540
|
+
noDeprecatedTokens: "`{{token}}` is a deprecated {{category}} token."
|
|
541
|
+
},
|
|
542
|
+
schema: [],
|
|
543
|
+
type: "problem"
|
|
544
|
+
},
|
|
545
|
+
name: RULE_NAME$15
|
|
546
|
+
});
|
|
547
|
+
}));
|
|
548
|
+
|
|
549
|
+
//#endregion
|
|
550
|
+
//#region src/rules/no-dynamic-styling.ts
|
|
551
|
+
var RULE_NAME$14, rule$14;
|
|
552
|
+
var init_no_dynamic_styling = __esmMin((() => {
|
|
553
|
+
init_utils();
|
|
554
|
+
init_helpers();
|
|
555
|
+
init_nodes();
|
|
556
|
+
RULE_NAME$14 = "no-dynamic-styling";
|
|
557
|
+
rule$14 = createRule({
|
|
558
|
+
create(context) {
|
|
559
|
+
function isStaticValue(node) {
|
|
560
|
+
if (!node) return false;
|
|
561
|
+
if (isLiteral(node)) return true;
|
|
562
|
+
if (isTemplateLiteral(node) && node.expressions.length === 0) return true;
|
|
563
|
+
if (isObjectExpression(node)) return true;
|
|
564
|
+
return false;
|
|
565
|
+
}
|
|
566
|
+
function checkArrayElements(array) {
|
|
567
|
+
for (const element of array.elements) {
|
|
568
|
+
if (!element) continue;
|
|
569
|
+
if (isStaticValue(element)) continue;
|
|
570
|
+
context.report({
|
|
571
|
+
messageId: "dynamic",
|
|
572
|
+
node: element
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
return {
|
|
577
|
+
JSXAttribute(node) {
|
|
578
|
+
if (!node.value) return;
|
|
579
|
+
if (!isBambooProp(node, context)) return;
|
|
580
|
+
if (isLiteral(node.value)) return;
|
|
581
|
+
if (isJSXExpressionContainer(node.value)) {
|
|
582
|
+
const expr = node.value.expression;
|
|
583
|
+
if (isStaticValue(expr)) return;
|
|
584
|
+
if (isArrayExpression(expr)) {
|
|
585
|
+
checkArrayElements(expr);
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
context.report({
|
|
589
|
+
messageId: "dynamic",
|
|
590
|
+
node: node.value
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
},
|
|
594
|
+
Property(node) {
|
|
595
|
+
if (!isIdentifier(node.key)) return;
|
|
596
|
+
if (!isBambooAttribute(node, context)) return;
|
|
597
|
+
if (isRecipeVariant(node, context)) return;
|
|
598
|
+
if (isStaticValue(node.value)) return;
|
|
599
|
+
if (isArrayExpression(node.value)) {
|
|
600
|
+
checkArrayElements(node.value);
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
context.report({
|
|
604
|
+
messageId: "dynamic",
|
|
605
|
+
node: node.value
|
|
606
|
+
});
|
|
607
|
+
},
|
|
608
|
+
"Property[computed=true]": (node) => {
|
|
609
|
+
if (!isInBambooFunction(node, context)) return;
|
|
610
|
+
context.report({
|
|
611
|
+
messageId: isRecipeVariant(node, context) ? "dynamicRecipeVariant" : "dynamicProperty",
|
|
612
|
+
node: node.key
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
};
|
|
616
|
+
},
|
|
617
|
+
defaultOptions: [],
|
|
618
|
+
meta: {
|
|
619
|
+
docs: { description: "Ensure users don't use dynamic styling. Prefer static styles, leverage CSS variables, or recipes for known dynamic styles." },
|
|
620
|
+
messages: {
|
|
621
|
+
dynamic: "Remove dynamic value. Prefer static styles.",
|
|
622
|
+
dynamicProperty: "Remove dynamic property. Prefer static style property.",
|
|
623
|
+
dynamicRecipeVariant: "Remove dynamic variant. Prefer static variant definition."
|
|
624
|
+
},
|
|
625
|
+
schema: [],
|
|
626
|
+
type: "problem"
|
|
627
|
+
},
|
|
628
|
+
name: RULE_NAME$14
|
|
629
|
+
});
|
|
630
|
+
}));
|
|
631
|
+
|
|
632
|
+
//#endregion
|
|
633
|
+
//#region src/rules/no-escape-hatch.ts
|
|
634
|
+
var RULE_NAME$13, rule$13;
|
|
635
|
+
var init_no_escape_hatch = __esmMin((() => {
|
|
636
|
+
init_utils();
|
|
637
|
+
init_helpers();
|
|
638
|
+
init_nodes();
|
|
639
|
+
RULE_NAME$13 = "no-escape-hatch";
|
|
640
|
+
rule$13 = createRule({
|
|
641
|
+
create(context) {
|
|
642
|
+
const removeBrackets = (range) => {
|
|
643
|
+
const [start, end] = range;
|
|
644
|
+
return [start + 1, end - 1];
|
|
645
|
+
};
|
|
646
|
+
const hasEscapeHatch = (value) => {
|
|
647
|
+
if (!value) return false;
|
|
648
|
+
if (!value.includes("[")) return false;
|
|
649
|
+
return getArbitraryValue(value) !== value.trim();
|
|
650
|
+
};
|
|
651
|
+
const handleNodeValue = (node, value) => {
|
|
652
|
+
if (!hasEscapeHatch(value)) return;
|
|
653
|
+
context.report({
|
|
654
|
+
messageId: "escapeHatch",
|
|
655
|
+
node,
|
|
656
|
+
suggest: [{
|
|
657
|
+
fix: (fixer) => {
|
|
658
|
+
return fixer.replaceTextRange(removeBrackets(node.range), getArbitraryValue(value));
|
|
659
|
+
},
|
|
660
|
+
messageId: "remove"
|
|
661
|
+
}]
|
|
662
|
+
});
|
|
663
|
+
};
|
|
664
|
+
return {
|
|
665
|
+
JSXAttribute(node) {
|
|
666
|
+
if (!node.value) return;
|
|
667
|
+
if (!isBambooProp(node, context)) return;
|
|
668
|
+
const { value } = node;
|
|
669
|
+
if (isLiteral(value)) handleNodeValue(value, value.value?.toString() ?? "");
|
|
670
|
+
else if (isJSXExpressionContainer(value)) {
|
|
671
|
+
const expr = value.expression;
|
|
672
|
+
if (isLiteral(expr)) handleNodeValue(expr, expr.value?.toString() ?? "");
|
|
673
|
+
else if (isTemplateLiteral(expr) && expr.expressions.length === 0) {
|
|
674
|
+
const value_ = expr.quasis[0].value.raw;
|
|
675
|
+
handleNodeValue(expr.quasis[0], value_);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
},
|
|
679
|
+
Property(node) {
|
|
680
|
+
if (!isIdentifier(node.key)) return;
|
|
681
|
+
if (!isBambooAttribute(node, context)) return;
|
|
682
|
+
if (isRecipeVariant(node, context)) return;
|
|
683
|
+
const value = node.value;
|
|
684
|
+
if (isLiteral(value)) handleNodeValue(value, value.value?.toString() ?? "");
|
|
685
|
+
else if (isTemplateLiteral(value) && value.expressions.length === 0) {
|
|
686
|
+
const value_ = value.quasis[0].value.raw;
|
|
687
|
+
handleNodeValue(value.quasis[0], value_);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
};
|
|
691
|
+
},
|
|
692
|
+
defaultOptions: [],
|
|
693
|
+
meta: {
|
|
694
|
+
docs: { description: "Prohibit the use of escape hatch syntax in the code." },
|
|
695
|
+
hasSuggestions: true,
|
|
696
|
+
messages: {
|
|
697
|
+
escapeHatch: "Avoid using the escape hatch [value] for undefined tokens. Define a corresponding token in your design system for better consistency and maintainability.",
|
|
698
|
+
remove: "Remove the square brackets (`[]`)."
|
|
699
|
+
},
|
|
700
|
+
schema: [],
|
|
701
|
+
type: "problem"
|
|
702
|
+
},
|
|
703
|
+
name: RULE_NAME$13
|
|
704
|
+
});
|
|
705
|
+
}));
|
|
706
|
+
|
|
707
|
+
//#endregion
|
|
708
|
+
//#region src/rules/no-hardcoded-color.ts
|
|
709
|
+
var RULE_NAME$12, rule$12;
|
|
710
|
+
var init_no_hardcoded_color = __esmMin((() => {
|
|
711
|
+
init_utils();
|
|
712
|
+
init_helpers();
|
|
713
|
+
init_nodes();
|
|
714
|
+
RULE_NAME$12 = "no-hardcoded-color";
|
|
715
|
+
rule$12 = createRule({
|
|
716
|
+
create(context) {
|
|
717
|
+
const noOpacity = context.options[0]?.noOpacity;
|
|
718
|
+
const whitelist = context.options[0]?.whitelist ?? [];
|
|
719
|
+
const colorTokenCache = new Map(whitelist?.map((item) => [item, true]));
|
|
720
|
+
const colorAttributeCache = /* @__PURE__ */ new Map();
|
|
721
|
+
const isColorToken$1 = (token) => {
|
|
722
|
+
if (colorTokenCache.has(token)) return colorTokenCache.get(token);
|
|
723
|
+
const result = isColorToken(token, context);
|
|
724
|
+
colorTokenCache.set(token, result);
|
|
725
|
+
return Boolean(result);
|
|
726
|
+
};
|
|
727
|
+
const isColorAttribute$1 = (attribute) => {
|
|
728
|
+
if (colorAttributeCache.has(attribute)) return colorAttributeCache.get(attribute);
|
|
729
|
+
const result = isColorAttribute(attribute, context);
|
|
730
|
+
colorAttributeCache.set(attribute, result);
|
|
731
|
+
return result;
|
|
732
|
+
};
|
|
733
|
+
const isTokenFunctionUsed = (value) => {
|
|
734
|
+
if (!value) return false;
|
|
735
|
+
return extractTokens(value).length > 0;
|
|
736
|
+
};
|
|
737
|
+
const isValidColorToken = (value) => {
|
|
738
|
+
if (!value) return false;
|
|
739
|
+
const [colorToken, opacity] = value.split("/");
|
|
740
|
+
const hasOpacity = opacity !== void 0 && opacity.length > 0;
|
|
741
|
+
const isValidToken = isColorToken$1(colorToken);
|
|
742
|
+
return noOpacity ? isValidToken && !hasOpacity : isValidToken;
|
|
743
|
+
};
|
|
744
|
+
const reportInvalidColor = (node, color) => {
|
|
745
|
+
context.report({
|
|
746
|
+
data: { color },
|
|
747
|
+
messageId: "invalidColor",
|
|
748
|
+
node
|
|
749
|
+
});
|
|
750
|
+
};
|
|
751
|
+
const checkColorValue = (node, value, attributeName) => {
|
|
752
|
+
if (!isColorAttribute$1(attributeName)) return;
|
|
753
|
+
if (isTokenFunctionUsed(value)) return;
|
|
754
|
+
if (isValidColorToken(value)) return;
|
|
755
|
+
reportInvalidColor(node, value);
|
|
756
|
+
};
|
|
757
|
+
return {
|
|
758
|
+
JSXAttribute(node) {
|
|
759
|
+
if (!isJSXIdentifier(node.name)) return;
|
|
760
|
+
if (!isBambooProp(node, context) || !node.value) return;
|
|
761
|
+
const attributeName = node.name.name;
|
|
762
|
+
const valueNode = node.value;
|
|
763
|
+
if (isLiteral(valueNode)) checkColorValue(valueNode, valueNode.value?.toString() || "", attributeName);
|
|
764
|
+
else if (isJSXExpressionContainer(valueNode)) {
|
|
765
|
+
const expression = valueNode.expression;
|
|
766
|
+
if (isLiteral(expression)) checkColorValue(expression, expression.value?.toString() || "", attributeName);
|
|
767
|
+
else if (isTemplateLiteral(expression) && expression.expressions.length === 0) {
|
|
768
|
+
const value = expression.quasis[0].value.raw;
|
|
769
|
+
checkColorValue(expression.quasis[0], value, attributeName);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
},
|
|
773
|
+
Property(node) {
|
|
774
|
+
if (!isIdentifier(node.key)) return;
|
|
775
|
+
if (!isBambooAttribute(node, context)) return;
|
|
776
|
+
if (isRecipeVariant(node, context)) return;
|
|
777
|
+
const attributeName = node.key.name;
|
|
778
|
+
const valueNode = node.value;
|
|
779
|
+
if (isLiteral(valueNode)) checkColorValue(valueNode, valueNode.value?.toString() || "", attributeName);
|
|
780
|
+
else if (isTemplateLiteral(valueNode) && valueNode.expressions.length === 0) {
|
|
781
|
+
const value = valueNode.quasis[0].value.raw;
|
|
782
|
+
checkColorValue(valueNode.quasis[0], value, attributeName);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
};
|
|
786
|
+
},
|
|
787
|
+
defaultOptions: [{
|
|
788
|
+
noOpacity: false,
|
|
789
|
+
whitelist: []
|
|
790
|
+
}],
|
|
791
|
+
meta: {
|
|
792
|
+
docs: { description: "Enforce the exclusive use of design tokens as values for colors within the codebase." },
|
|
793
|
+
messages: { invalidColor: "`{{color}}` is not a valid color token." },
|
|
794
|
+
schema: [{
|
|
795
|
+
additionalProperties: false,
|
|
796
|
+
properties: {
|
|
797
|
+
noOpacity: { type: "boolean" },
|
|
798
|
+
whitelist: {
|
|
799
|
+
items: {
|
|
800
|
+
minLength: 0,
|
|
801
|
+
type: "string"
|
|
802
|
+
},
|
|
803
|
+
type: "array",
|
|
804
|
+
uniqueItems: true
|
|
805
|
+
}
|
|
806
|
+
},
|
|
807
|
+
type: "object"
|
|
808
|
+
}],
|
|
809
|
+
type: "problem"
|
|
810
|
+
},
|
|
811
|
+
name: RULE_NAME$12
|
|
812
|
+
});
|
|
813
|
+
}));
|
|
814
|
+
|
|
815
|
+
//#endregion
|
|
816
|
+
//#region src/rules/no-important.ts
|
|
817
|
+
var exclamationRegex, importantRegex, RULE_NAME$11, rule$11;
|
|
818
|
+
var init_no_important = __esmMin((() => {
|
|
819
|
+
init_utils();
|
|
820
|
+
init_helpers();
|
|
821
|
+
init_nodes();
|
|
822
|
+
exclamationRegex = /\s*!$/;
|
|
823
|
+
importantRegex = /\s*!important\s*$/;
|
|
824
|
+
RULE_NAME$11 = "no-important";
|
|
825
|
+
rule$11 = createRule({
|
|
826
|
+
create(context) {
|
|
827
|
+
const removeQuotes = (range) => {
|
|
828
|
+
const [start, end] = range;
|
|
829
|
+
return [start + 1, end - 1];
|
|
830
|
+
};
|
|
831
|
+
const bambooPropertyCache = /* @__PURE__ */ new WeakMap();
|
|
832
|
+
const bambooAttributeCache = /* @__PURE__ */ new WeakMap();
|
|
833
|
+
const recipeVariantCache = /* @__PURE__ */ new WeakMap();
|
|
834
|
+
const isCachedBambooProperty = (node) => {
|
|
835
|
+
if (bambooPropertyCache.has(node)) return bambooPropertyCache.get(node);
|
|
836
|
+
const result = isBambooProp(node, context);
|
|
837
|
+
bambooPropertyCache.set(node, result);
|
|
838
|
+
return Boolean(result);
|
|
839
|
+
};
|
|
840
|
+
const isCachedBambooAttribute = (node) => {
|
|
841
|
+
if (bambooAttributeCache.has(node)) return bambooAttributeCache.get(node);
|
|
842
|
+
const result = isBambooAttribute(node, context);
|
|
843
|
+
bambooAttributeCache.set(node, result);
|
|
844
|
+
return Boolean(result);
|
|
845
|
+
};
|
|
846
|
+
const isCachedRecipeVariant = (node) => {
|
|
847
|
+
if (recipeVariantCache.has(node)) return recipeVariantCache.get(node);
|
|
848
|
+
const result = isRecipeVariant(node, context);
|
|
849
|
+
recipeVariantCache.set(node, result);
|
|
850
|
+
return Boolean(result);
|
|
851
|
+
};
|
|
852
|
+
const hasImportantKeyword = (value) => {
|
|
853
|
+
if (!value) return false;
|
|
854
|
+
const arbitraryValue = getArbitraryValue(value);
|
|
855
|
+
return exclamationRegex.test(arbitraryValue) || importantRegex.test(arbitraryValue);
|
|
856
|
+
};
|
|
857
|
+
const removeImportantKeyword = (input) => {
|
|
858
|
+
if (importantRegex.test(input)) return {
|
|
859
|
+
fixed: input.replace(importantRegex, "").trimEnd(),
|
|
860
|
+
keyword: "!important"
|
|
861
|
+
};
|
|
862
|
+
else if (exclamationRegex.test(input)) return {
|
|
863
|
+
fixed: input.replace(exclamationRegex, "").trimEnd(),
|
|
864
|
+
keyword: "!"
|
|
865
|
+
};
|
|
866
|
+
else return {
|
|
867
|
+
fixed: input,
|
|
868
|
+
keyword: null
|
|
869
|
+
};
|
|
870
|
+
};
|
|
871
|
+
const handleNodeValue = (node, value) => {
|
|
872
|
+
if (!hasImportantKeyword(value)) return;
|
|
873
|
+
const { fixed: fixedArbitrary, keyword } = removeImportantKeyword(getArbitraryValue(value));
|
|
874
|
+
let fixed = value;
|
|
875
|
+
if (value.startsWith("[") && value.endsWith("]")) fixed = `[${fixedArbitrary}]`;
|
|
876
|
+
else fixed = fixedArbitrary;
|
|
877
|
+
context.report({
|
|
878
|
+
data: { keyword },
|
|
879
|
+
messageId: "important",
|
|
880
|
+
node,
|
|
881
|
+
suggest: [{
|
|
882
|
+
data: { keyword },
|
|
883
|
+
fix: (fixer) => {
|
|
884
|
+
return fixer.replaceTextRange(removeQuotes(node.range), fixed);
|
|
885
|
+
},
|
|
886
|
+
messageId: "remove"
|
|
887
|
+
}]
|
|
888
|
+
});
|
|
889
|
+
};
|
|
890
|
+
return {
|
|
891
|
+
JSXAttribute(node) {
|
|
892
|
+
if (!node.value) return;
|
|
893
|
+
if (!isCachedBambooProperty(node)) return;
|
|
894
|
+
const valueNode = node.value;
|
|
895
|
+
if (isLiteral(valueNode)) handleNodeValue(valueNode, valueNode.value?.toString() ?? "");
|
|
896
|
+
else if (isJSXExpressionContainer(valueNode)) {
|
|
897
|
+
const expr = valueNode.expression;
|
|
898
|
+
if (isLiteral(expr)) handleNodeValue(expr, expr.value?.toString() ?? "");
|
|
899
|
+
else if (isTemplateLiteral(expr) && expr.expressions.length === 0) {
|
|
900
|
+
const value = expr.quasis[0].value.raw;
|
|
901
|
+
handleNodeValue(expr.quasis[0], value);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
},
|
|
905
|
+
Property(node) {
|
|
906
|
+
if (!isIdentifier(node.key)) return;
|
|
907
|
+
if (!isCachedBambooAttribute(node)) return;
|
|
908
|
+
if (isCachedRecipeVariant(node)) return;
|
|
909
|
+
const valueNode = node.value;
|
|
910
|
+
if (isLiteral(valueNode)) handleNodeValue(valueNode, valueNode.value?.toString() ?? "");
|
|
911
|
+
else if (isTemplateLiteral(valueNode) && valueNode.expressions.length === 0) {
|
|
912
|
+
const value = valueNode.quasis[0].value.raw;
|
|
913
|
+
handleNodeValue(valueNode.quasis[0], value);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
};
|
|
917
|
+
},
|
|
918
|
+
defaultOptions: [],
|
|
919
|
+
meta: {
|
|
920
|
+
docs: { description: "Disallow usage of !important keyword. Prioritize specificity for a maintainable and predictable styling structure." },
|
|
921
|
+
hasSuggestions: true,
|
|
922
|
+
messages: {
|
|
923
|
+
important: "Avoid using the {{keyword}} keyword. Refactor your code to prioritize specificity for predictable styling.",
|
|
924
|
+
remove: "Remove the `{{keyword}}` keyword."
|
|
925
|
+
},
|
|
926
|
+
schema: [],
|
|
927
|
+
type: "problem"
|
|
928
|
+
},
|
|
929
|
+
name: RULE_NAME$11
|
|
930
|
+
});
|
|
931
|
+
}));
|
|
932
|
+
|
|
933
|
+
//#endregion
|
|
934
|
+
//#region src/rules/no-invalid-nesting.ts
|
|
935
|
+
var RULE_NAME$10, rule$10;
|
|
936
|
+
var init_no_invalid_nesting = __esmMin((() => {
|
|
937
|
+
init_utils();
|
|
938
|
+
init_helpers();
|
|
939
|
+
init_nodes();
|
|
940
|
+
RULE_NAME$10 = "no-invalid-nesting";
|
|
941
|
+
rule$10 = createRule({
|
|
942
|
+
create(context) {
|
|
943
|
+
const bambooFunctionCache = /* @__PURE__ */ new WeakMap();
|
|
944
|
+
const jsxPropertyCache = /* @__PURE__ */ new WeakMap();
|
|
945
|
+
const recipeVariantCache = /* @__PURE__ */ new WeakMap();
|
|
946
|
+
const styledPropertyCache = /* @__PURE__ */ new WeakMap();
|
|
947
|
+
const isCachedInBambooFunction = (node) => {
|
|
948
|
+
if (bambooFunctionCache.has(node)) return bambooFunctionCache.get(node);
|
|
949
|
+
const result = Boolean(isInBambooFunction(node, context));
|
|
950
|
+
bambooFunctionCache.set(node, result);
|
|
951
|
+
return Boolean(result);
|
|
952
|
+
};
|
|
953
|
+
const isCachedInJSXProperty = (node) => {
|
|
954
|
+
if (jsxPropertyCache.has(node)) return jsxPropertyCache.get(node);
|
|
955
|
+
const result = isInJSXProp(node, context);
|
|
956
|
+
jsxPropertyCache.set(node, result);
|
|
957
|
+
return Boolean(result);
|
|
958
|
+
};
|
|
959
|
+
const isCachedRecipeVariant = (node) => {
|
|
960
|
+
if (recipeVariantCache.has(node)) return recipeVariantCache.get(node);
|
|
961
|
+
const result = isRecipeVariant(node, context);
|
|
962
|
+
recipeVariantCache.set(node, result);
|
|
963
|
+
return Boolean(result);
|
|
964
|
+
};
|
|
965
|
+
const isCachedStyledProperty = (node) => {
|
|
966
|
+
if (styledPropertyCache.has(node)) return styledPropertyCache.get(node);
|
|
967
|
+
const result = isStyledProperty(node, context);
|
|
968
|
+
styledPropertyCache.set(node, result);
|
|
969
|
+
return Boolean(result);
|
|
970
|
+
};
|
|
971
|
+
const isInvalidNestingSelector = (node) => {
|
|
972
|
+
if (isLiteral(node) && typeof node.value === "string") return !node.value.includes("&");
|
|
973
|
+
else if (isTemplateLiteral(node) && node.expressions.length === 0) return !node.quasis[0].value.raw.includes("&");
|
|
974
|
+
return false;
|
|
975
|
+
};
|
|
976
|
+
return { "Property[key.type!=/Identifier/][value.type=\"ObjectExpression\"]"(node) {
|
|
977
|
+
const inBambooFunction = isCachedInBambooFunction(node);
|
|
978
|
+
const inJSXProperty = isCachedInJSXProperty(node);
|
|
979
|
+
if (!inBambooFunction && !inJSXProperty) return;
|
|
980
|
+
if (isCachedRecipeVariant(node)) return;
|
|
981
|
+
if (isCachedStyledProperty(node)) return;
|
|
982
|
+
const keyNode = node.key;
|
|
983
|
+
if (isInvalidNestingSelector(keyNode)) context.report({
|
|
984
|
+
messageId: "nesting",
|
|
985
|
+
node: keyNode
|
|
986
|
+
});
|
|
987
|
+
} };
|
|
988
|
+
},
|
|
989
|
+
defaultOptions: [],
|
|
990
|
+
meta: {
|
|
991
|
+
docs: { description: "Warn against invalid nesting. Nested styles must contain the `&` character." },
|
|
992
|
+
messages: { nesting: "Invalid style nesting. Nested styles must contain the `&` character." },
|
|
993
|
+
schema: [],
|
|
994
|
+
type: "problem"
|
|
995
|
+
},
|
|
996
|
+
name: RULE_NAME$10
|
|
997
|
+
});
|
|
998
|
+
}));
|
|
999
|
+
|
|
1000
|
+
//#endregion
|
|
1001
|
+
//#region src/rules/no-invalid-token-paths.ts
|
|
1002
|
+
var RULE_NAME$9, rule$9;
|
|
1003
|
+
var init_no_invalid_token_paths = __esmMin((() => {
|
|
1004
|
+
init_utils();
|
|
1005
|
+
init_helpers();
|
|
1006
|
+
init_nodes();
|
|
1007
|
+
RULE_NAME$9 = "no-invalid-token-paths";
|
|
1008
|
+
rule$9 = createRule({
|
|
1009
|
+
create(context) {
|
|
1010
|
+
const invalidTokensCache = /* @__PURE__ */ new Map();
|
|
1011
|
+
const sendReport = (node, value) => {
|
|
1012
|
+
if (!value) return;
|
|
1013
|
+
let tokens = invalidTokensCache.get(value);
|
|
1014
|
+
if (!tokens) {
|
|
1015
|
+
tokens = getInvalidTokens(value, context);
|
|
1016
|
+
invalidTokensCache.set(value, tokens);
|
|
1017
|
+
}
|
|
1018
|
+
if (!tokens || tokens.length === 0) return;
|
|
1019
|
+
for (const token of tokens) context.report({
|
|
1020
|
+
data: { token },
|
|
1021
|
+
messageId: "noInvalidTokenPaths",
|
|
1022
|
+
node
|
|
1023
|
+
});
|
|
1024
|
+
};
|
|
1025
|
+
const handleLiteralOrTemplate = (node) => {
|
|
1026
|
+
if (!node) return;
|
|
1027
|
+
if (isLiteral(node)) {
|
|
1028
|
+
const value = node.value?.toString();
|
|
1029
|
+
sendReport(node, value);
|
|
1030
|
+
} else if (isTemplateLiteral(node) && node.expressions.length === 0) {
|
|
1031
|
+
const value = node.quasis[0].value.raw;
|
|
1032
|
+
sendReport(node.quasis[0], value);
|
|
1033
|
+
}
|
|
1034
|
+
};
|
|
1035
|
+
return {
|
|
1036
|
+
JSXAttribute(node) {
|
|
1037
|
+
if (!node.value || !isBambooProp(node, context)) return;
|
|
1038
|
+
if (isLiteral(node.value)) handleLiteralOrTemplate(node.value);
|
|
1039
|
+
else if (isJSXExpressionContainer(node.value)) handleLiteralOrTemplate(node.value.expression);
|
|
1040
|
+
},
|
|
1041
|
+
Property(node) {
|
|
1042
|
+
if (!isIdentifier(node.key) || !isNodeOfTypes([AST_NODE_TYPES.Literal, AST_NODE_TYPES.TemplateLiteral])(node.value) || !isBambooAttribute(node, context) || isRecipeVariant(node, context)) return;
|
|
1043
|
+
handleLiteralOrTemplate(node.value);
|
|
1044
|
+
},
|
|
1045
|
+
TaggedTemplateExpression(node) {
|
|
1046
|
+
if (!getTaggedTemplateCaller(node)) return;
|
|
1047
|
+
if (!isStyledTaggedTemplate(node, context)) return;
|
|
1048
|
+
const quasis = node.quasi.quasis;
|
|
1049
|
+
for (const quasi of quasis) {
|
|
1050
|
+
const styles = quasi.value.raw;
|
|
1051
|
+
if (!styles) continue;
|
|
1052
|
+
let tokens = invalidTokensCache.get(styles);
|
|
1053
|
+
if (!tokens) {
|
|
1054
|
+
tokens = getInvalidTokens(styles, context);
|
|
1055
|
+
invalidTokensCache.set(styles, tokens);
|
|
1056
|
+
}
|
|
1057
|
+
if (!tokens || tokens.length === 0) continue;
|
|
1058
|
+
for (const token of tokens) {
|
|
1059
|
+
let index = styles.indexOf(token);
|
|
1060
|
+
while (index !== -1) {
|
|
1061
|
+
const start = quasi.range[0] + index + 1;
|
|
1062
|
+
const end = start + token.length;
|
|
1063
|
+
context.report({
|
|
1064
|
+
data: { token },
|
|
1065
|
+
loc: {
|
|
1066
|
+
end: context.sourceCode.getLocFromIndex(end),
|
|
1067
|
+
start: context.sourceCode.getLocFromIndex(start)
|
|
1068
|
+
},
|
|
1069
|
+
messageId: "noInvalidTokenPaths"
|
|
1070
|
+
});
|
|
1071
|
+
index = styles.indexOf(token, index + token.length);
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
};
|
|
1077
|
+
},
|
|
1078
|
+
defaultOptions: [],
|
|
1079
|
+
meta: {
|
|
1080
|
+
docs: { description: "Disallow the use of invalid token paths within token function syntax." },
|
|
1081
|
+
messages: { noInvalidTokenPaths: "`{{token}}` is an invalid token path." },
|
|
1082
|
+
schema: [],
|
|
1083
|
+
type: "problem"
|
|
1084
|
+
},
|
|
1085
|
+
name: RULE_NAME$9
|
|
1086
|
+
});
|
|
1087
|
+
}));
|
|
1088
|
+
|
|
1089
|
+
//#endregion
|
|
1090
|
+
//#region src/rules/no-margin-properties.ts
|
|
1091
|
+
var RULE_NAME$8, rule$8;
|
|
1092
|
+
var init_no_margin_properties = __esmMin((() => {
|
|
1093
|
+
init_utils();
|
|
1094
|
+
init_helpers();
|
|
1095
|
+
init_nodes();
|
|
1096
|
+
RULE_NAME$8 = "no-margin-properties";
|
|
1097
|
+
rule$8 = createRule({
|
|
1098
|
+
create(context) {
|
|
1099
|
+
const whitelist = context.options[0]?.whitelist ?? [];
|
|
1100
|
+
const longhandCache = /* @__PURE__ */ new Map();
|
|
1101
|
+
const getLonghand = (name) => {
|
|
1102
|
+
if (longhandCache.has(name)) return longhandCache.get(name);
|
|
1103
|
+
const longhand = resolveLonghand(name, context) ?? name;
|
|
1104
|
+
longhandCache.set(name, longhand);
|
|
1105
|
+
return longhand;
|
|
1106
|
+
};
|
|
1107
|
+
const marginRegex = /margin/i;
|
|
1108
|
+
const isMarginProperty = (name) => {
|
|
1109
|
+
const longhand = getLonghand(name).toLowerCase();
|
|
1110
|
+
return marginRegex.test(longhand);
|
|
1111
|
+
};
|
|
1112
|
+
const sendReport = (node) => {
|
|
1113
|
+
if (whitelist.includes(node.name)) return;
|
|
1114
|
+
if (!isMarginProperty(node.name)) return;
|
|
1115
|
+
context.report({
|
|
1116
|
+
messageId: "noMargin",
|
|
1117
|
+
node
|
|
1118
|
+
});
|
|
1119
|
+
};
|
|
1120
|
+
const bambooPropertyCache = /* @__PURE__ */ new WeakMap();
|
|
1121
|
+
const isCachedBambooProperty = (node) => {
|
|
1122
|
+
if (bambooPropertyCache.has(node)) return bambooPropertyCache.get(node);
|
|
1123
|
+
const result = isBambooProp(node, context);
|
|
1124
|
+
bambooPropertyCache.set(node, result);
|
|
1125
|
+
return Boolean(result);
|
|
1126
|
+
};
|
|
1127
|
+
const bambooAttributeCache = /* @__PURE__ */ new WeakMap();
|
|
1128
|
+
const isCachedBambooAttribute = (node) => {
|
|
1129
|
+
if (bambooAttributeCache.has(node)) return bambooAttributeCache.get(node);
|
|
1130
|
+
const result = isBambooAttribute(node, context);
|
|
1131
|
+
bambooAttributeCache.set(node, result);
|
|
1132
|
+
return Boolean(result);
|
|
1133
|
+
};
|
|
1134
|
+
const recipeVariantCache = /* @__PURE__ */ new WeakMap();
|
|
1135
|
+
const isCachedRecipeVariant = (node) => {
|
|
1136
|
+
if (recipeVariantCache.has(node)) return recipeVariantCache.get(node);
|
|
1137
|
+
const result = isRecipeVariant(node, context);
|
|
1138
|
+
recipeVariantCache.set(node, result);
|
|
1139
|
+
return Boolean(result);
|
|
1140
|
+
};
|
|
1141
|
+
return {
|
|
1142
|
+
JSXAttribute(node) {
|
|
1143
|
+
if (!isJSXIdentifier(node.name)) return;
|
|
1144
|
+
if (!isCachedBambooProperty(node)) return;
|
|
1145
|
+
sendReport(node.name);
|
|
1146
|
+
},
|
|
1147
|
+
Property(node) {
|
|
1148
|
+
if (!isIdentifier(node.key)) return;
|
|
1149
|
+
if (!isCachedBambooAttribute(node)) return;
|
|
1150
|
+
if (isCachedRecipeVariant(node)) return;
|
|
1151
|
+
sendReport(node.key);
|
|
1152
|
+
}
|
|
1153
|
+
};
|
|
1154
|
+
},
|
|
1155
|
+
defaultOptions: [{ whitelist: [] }],
|
|
1156
|
+
meta: {
|
|
1157
|
+
docs: { description: "Discourage using margin properties for spacing; prefer defining spacing in parent elements with `flex` or `grid` using the `gap` property for a more resilient layout. Margins make components less reusable in other contexts." },
|
|
1158
|
+
messages: { noMargin: "Use flex or grid with the `gap` property to define spacing in parent elements for a more resilient layout." },
|
|
1159
|
+
schema: [{
|
|
1160
|
+
additionalProperties: false,
|
|
1161
|
+
properties: { whitelist: {
|
|
1162
|
+
items: {
|
|
1163
|
+
minLength: 0,
|
|
1164
|
+
type: "string"
|
|
1165
|
+
},
|
|
1166
|
+
type: "array",
|
|
1167
|
+
uniqueItems: true
|
|
1168
|
+
} },
|
|
1169
|
+
type: "object"
|
|
1170
|
+
}],
|
|
1171
|
+
type: "suggestion"
|
|
1172
|
+
},
|
|
1173
|
+
name: RULE_NAME$8
|
|
1174
|
+
});
|
|
1175
|
+
}));
|
|
1176
|
+
|
|
1177
|
+
//#endregion
|
|
1178
|
+
//#region src/utils/physical-properties.ts
|
|
1179
|
+
var physicalProperties, physicalPropertyValues;
|
|
1180
|
+
var init_physical_properties = __esmMin((() => {
|
|
1181
|
+
physicalProperties = {
|
|
1182
|
+
borderBottom: "borderBlockEnd",
|
|
1183
|
+
borderBottomColor: "borderBlockEndColor",
|
|
1184
|
+
borderBottomLeftRadius: "borderEndStartRadius",
|
|
1185
|
+
borderBottomRightRadius: "borderEndEndRadius",
|
|
1186
|
+
borderBottomStyle: "borderBlockEndStyle",
|
|
1187
|
+
borderBottomWidth: "borderBlockEndWidth",
|
|
1188
|
+
borderLeft: "borderInlineStart",
|
|
1189
|
+
borderLeftColor: "borderInlineStartColor",
|
|
1190
|
+
borderLeftStyle: "borderInlineStartStyle",
|
|
1191
|
+
borderLeftWidth: "borderInlineStartWidth",
|
|
1192
|
+
borderRight: "borderInlineEnd",
|
|
1193
|
+
borderRightColor: "borderInlineEndColor",
|
|
1194
|
+
borderRightStyle: "borderInlineEndStyle",
|
|
1195
|
+
borderRightWidth: "borderInlineEndWidth",
|
|
1196
|
+
borderTop: "borderBlockStart",
|
|
1197
|
+
borderTopColor: "borderBlockStartColor",
|
|
1198
|
+
borderTopLeftRadius: "borderStartStartRadius",
|
|
1199
|
+
borderTopRightRadius: "borderStartEndRadius",
|
|
1200
|
+
borderTopStyle: "borderBlockStartStyle",
|
|
1201
|
+
borderTopWidth: "borderBlockStartWidth",
|
|
1202
|
+
bottom: "insetBlockEnd",
|
|
1203
|
+
left: "insetInlineStart",
|
|
1204
|
+
marginBottom: "marginBlockEnd",
|
|
1205
|
+
marginLeft: "marginInlineStart",
|
|
1206
|
+
marginRight: "marginInlineEnd",
|
|
1207
|
+
marginTop: "marginBlockStart",
|
|
1208
|
+
paddingBottom: "paddingBlockEnd",
|
|
1209
|
+
paddingLeft: "paddingInlineStart",
|
|
1210
|
+
paddingRight: "paddingInlineEnd",
|
|
1211
|
+
paddingTop: "paddingBlockStart",
|
|
1212
|
+
right: "insetInlineEnd",
|
|
1213
|
+
top: "insetBlockStart"
|
|
1214
|
+
};
|
|
1215
|
+
physicalPropertyValues = { textAlign: {
|
|
1216
|
+
left: "start",
|
|
1217
|
+
right: "end"
|
|
1218
|
+
} };
|
|
1219
|
+
}));
|
|
1220
|
+
|
|
1221
|
+
//#endregion
|
|
1222
|
+
//#region src/rules/no-physical-properties.ts
|
|
1223
|
+
var RULE_NAME$7, MESSAGES, PropertyCache, extractStringLiteralValue, createPropertyReport, createValueReport, rule$7;
|
|
1224
|
+
var init_no_physical_properties = __esmMin((() => {
|
|
1225
|
+
init_utils();
|
|
1226
|
+
init_helpers();
|
|
1227
|
+
init_nodes();
|
|
1228
|
+
init_physical_properties();
|
|
1229
|
+
RULE_NAME$7 = "no-physical-properties";
|
|
1230
|
+
MESSAGES = {
|
|
1231
|
+
physical: "Use logical property instead of {{physical}}. Prefer `{{logical}}`.",
|
|
1232
|
+
physicalValue: "Use logical value instead of {{physical}}. Prefer `{{logical}}`.",
|
|
1233
|
+
replace: "Replace `{{physical}}` with `{{logical}}`."
|
|
1234
|
+
};
|
|
1235
|
+
PropertyCache = class {
|
|
1236
|
+
longhandCache = /* @__PURE__ */ new Map();
|
|
1237
|
+
bambooAttributeCache = /* @__PURE__ */ new WeakMap();
|
|
1238
|
+
bambooPropCache = /* @__PURE__ */ new WeakMap();
|
|
1239
|
+
recipeVariantCache = /* @__PURE__ */ new WeakMap();
|
|
1240
|
+
getLonghand(name, context) {
|
|
1241
|
+
if (this.longhandCache.has(name)) return this.longhandCache.get(name);
|
|
1242
|
+
const longhand = resolveLonghand(name, context) ?? name;
|
|
1243
|
+
this.longhandCache.set(name, longhand);
|
|
1244
|
+
return longhand;
|
|
1245
|
+
}
|
|
1246
|
+
isBambooAttribute(node, context) {
|
|
1247
|
+
if (this.bambooAttributeCache.has(node)) return this.bambooAttributeCache.get(node);
|
|
1248
|
+
const result = isBambooAttribute(node, context);
|
|
1249
|
+
this.bambooAttributeCache.set(node, result);
|
|
1250
|
+
return Boolean(result);
|
|
1251
|
+
}
|
|
1252
|
+
isBambooProp(node, context) {
|
|
1253
|
+
if (this.bambooPropCache.has(node)) return this.bambooPropCache.get(node);
|
|
1254
|
+
const result = isBambooProp(node, context);
|
|
1255
|
+
this.bambooPropCache.set(node, result);
|
|
1256
|
+
return Boolean(result);
|
|
1257
|
+
}
|
|
1258
|
+
isRecipeVariant(node, context) {
|
|
1259
|
+
if (this.recipeVariantCache.has(node)) return this.recipeVariantCache.get(node);
|
|
1260
|
+
const result = isRecipeVariant(node, context);
|
|
1261
|
+
this.recipeVariantCache.set(node, result);
|
|
1262
|
+
return Boolean(result);
|
|
1263
|
+
}
|
|
1264
|
+
};
|
|
1265
|
+
extractStringLiteralValue = (valueNode) => {
|
|
1266
|
+
if (isLiteral(valueNode) && typeof valueNode.value === "string") return valueNode.value;
|
|
1267
|
+
if (isJSXExpressionContainer(valueNode) && isLiteral(valueNode.expression) && typeof valueNode.expression.value === "string") return valueNode.expression.value;
|
|
1268
|
+
return null;
|
|
1269
|
+
};
|
|
1270
|
+
createPropertyReport = (node, longhandName, logical, context) => {
|
|
1271
|
+
const physicalName = `\`${node.name}\`${longhandName !== node.name ? ` (resolved to \`${longhandName}\`)` : ""}`;
|
|
1272
|
+
context.report({
|
|
1273
|
+
data: {
|
|
1274
|
+
logical,
|
|
1275
|
+
physical: physicalName
|
|
1276
|
+
},
|
|
1277
|
+
messageId: "physical",
|
|
1278
|
+
node,
|
|
1279
|
+
suggest: [{
|
|
1280
|
+
data: {
|
|
1281
|
+
logical,
|
|
1282
|
+
physical: node.name
|
|
1283
|
+
},
|
|
1284
|
+
fix: (fixer) => fixer.replaceText(node, logical),
|
|
1285
|
+
messageId: "replace"
|
|
1286
|
+
}]
|
|
1287
|
+
});
|
|
1288
|
+
};
|
|
1289
|
+
createValueReport = (valueNode, valueText, logical, context) => {
|
|
1290
|
+
context.report({
|
|
1291
|
+
data: {
|
|
1292
|
+
logical: `"${logical}"`,
|
|
1293
|
+
physical: `"${valueText}"`
|
|
1294
|
+
},
|
|
1295
|
+
messageId: "physicalValue",
|
|
1296
|
+
node: valueNode,
|
|
1297
|
+
suggest: [{
|
|
1298
|
+
data: {
|
|
1299
|
+
logical: `"${logical}"`,
|
|
1300
|
+
physical: `"${valueText}"`
|
|
1301
|
+
},
|
|
1302
|
+
fix: (fixer) => {
|
|
1303
|
+
if (isLiteral(valueNode)) return fixer.replaceText(valueNode, `"${logical}"`);
|
|
1304
|
+
if (isJSXExpressionContainer(valueNode) && isLiteral(valueNode.expression)) return fixer.replaceText(valueNode.expression, `"${logical}"`);
|
|
1305
|
+
return null;
|
|
1306
|
+
},
|
|
1307
|
+
messageId: "replace"
|
|
1308
|
+
}]
|
|
1309
|
+
});
|
|
1310
|
+
};
|
|
1311
|
+
rule$7 = createRule({
|
|
1312
|
+
create(context) {
|
|
1313
|
+
const whitelist = context.options[0]?.whitelist ?? [];
|
|
1314
|
+
const cache = new PropertyCache();
|
|
1315
|
+
const checkPropertyName = (node) => {
|
|
1316
|
+
if (whitelist.includes(node.name)) return;
|
|
1317
|
+
const longhandName = cache.getLonghand(node.name, context);
|
|
1318
|
+
if (!(longhandName in physicalProperties)) return;
|
|
1319
|
+
const logical = physicalProperties[longhandName];
|
|
1320
|
+
createPropertyReport(node, longhandName, logical, context);
|
|
1321
|
+
};
|
|
1322
|
+
const checkPropertyValue = (keyNode, valueNode) => {
|
|
1323
|
+
const propertyName = keyNode.name;
|
|
1324
|
+
if (!(propertyName in physicalPropertyValues)) return false;
|
|
1325
|
+
const valueText = extractStringLiteralValue(valueNode);
|
|
1326
|
+
if (valueText === null) return false;
|
|
1327
|
+
const valueMap = physicalPropertyValues[propertyName];
|
|
1328
|
+
if (!valueMap[valueText]) return false;
|
|
1329
|
+
createValueReport(valueNode, valueText, valueMap[valueText], context);
|
|
1330
|
+
return true;
|
|
1331
|
+
};
|
|
1332
|
+
return {
|
|
1333
|
+
JSXAttribute(node) {
|
|
1334
|
+
if (!isJSXIdentifier(node.name)) return;
|
|
1335
|
+
if (!cache.isBambooProp(node, context)) return;
|
|
1336
|
+
checkPropertyName(node.name);
|
|
1337
|
+
if (node.value) checkPropertyValue(node.name, node.value);
|
|
1338
|
+
},
|
|
1339
|
+
Property(node) {
|
|
1340
|
+
if (!isIdentifier(node.key)) return;
|
|
1341
|
+
if (!cache.isBambooAttribute(node, context)) return;
|
|
1342
|
+
if (cache.isRecipeVariant(node, context)) return;
|
|
1343
|
+
checkPropertyName(node.key);
|
|
1344
|
+
if (node.value) checkPropertyValue(node.key, node.value);
|
|
1345
|
+
}
|
|
1346
|
+
};
|
|
1347
|
+
},
|
|
1348
|
+
defaultOptions: [{ whitelist: [] }],
|
|
1349
|
+
meta: {
|
|
1350
|
+
docs: { description: "Encourage the use of logical properties over physical properties to foster a responsive and adaptable user interface." },
|
|
1351
|
+
hasSuggestions: true,
|
|
1352
|
+
messages: MESSAGES,
|
|
1353
|
+
schema: [{
|
|
1354
|
+
additionalProperties: false,
|
|
1355
|
+
properties: { whitelist: {
|
|
1356
|
+
items: {
|
|
1357
|
+
minLength: 0,
|
|
1358
|
+
type: "string"
|
|
1359
|
+
},
|
|
1360
|
+
type: "array",
|
|
1361
|
+
uniqueItems: true
|
|
1362
|
+
} },
|
|
1363
|
+
type: "object"
|
|
1364
|
+
}],
|
|
1365
|
+
type: "suggestion"
|
|
1366
|
+
},
|
|
1367
|
+
name: RULE_NAME$7
|
|
1368
|
+
});
|
|
1369
|
+
}));
|
|
1370
|
+
|
|
1371
|
+
//#endregion
|
|
1372
|
+
//#region src/rules/no-property-renaming.ts
|
|
1373
|
+
var RULE_NAME$6, rule$6;
|
|
1374
|
+
var init_no_property_renaming = __esmMin((() => {
|
|
1375
|
+
init_utils();
|
|
1376
|
+
init_helpers();
|
|
1377
|
+
init_nodes();
|
|
1378
|
+
RULE_NAME$6 = "no-property-renaming";
|
|
1379
|
+
rule$6 = createRule({
|
|
1380
|
+
create(context) {
|
|
1381
|
+
const bambooPropertyCache = /* @__PURE__ */ new WeakMap();
|
|
1382
|
+
const bambooAttributeCache = /* @__PURE__ */ new WeakMap();
|
|
1383
|
+
const recipeVariantCache = /* @__PURE__ */ new WeakMap();
|
|
1384
|
+
const isCachedBambooProperty = (node) => {
|
|
1385
|
+
if (bambooPropertyCache.has(node)) return bambooPropertyCache.get(node);
|
|
1386
|
+
const result = isBambooProp(node, context);
|
|
1387
|
+
bambooPropertyCache.set(node, result);
|
|
1388
|
+
return Boolean(result);
|
|
1389
|
+
};
|
|
1390
|
+
const isCachedBambooAttribute = (node) => {
|
|
1391
|
+
if (bambooAttributeCache.has(node)) return bambooAttributeCache.get(node);
|
|
1392
|
+
const result = isBambooAttribute(node, context);
|
|
1393
|
+
bambooAttributeCache.set(node, result);
|
|
1394
|
+
return Boolean(result);
|
|
1395
|
+
};
|
|
1396
|
+
const isCachedRecipeVariant = (node) => {
|
|
1397
|
+
if (recipeVariantCache.has(node)) return recipeVariantCache.get(node);
|
|
1398
|
+
const result = isRecipeVariant(node, context);
|
|
1399
|
+
recipeVariantCache.set(node, result);
|
|
1400
|
+
return Boolean(result);
|
|
1401
|
+
};
|
|
1402
|
+
const sendReport = (node, expected, property) => {
|
|
1403
|
+
context.report({
|
|
1404
|
+
data: {
|
|
1405
|
+
expected,
|
|
1406
|
+
prop: property
|
|
1407
|
+
},
|
|
1408
|
+
messageId: "noRenaming",
|
|
1409
|
+
node
|
|
1410
|
+
});
|
|
1411
|
+
};
|
|
1412
|
+
const handleReport = (node, value, attribute) => {
|
|
1413
|
+
if (isIdentifier(value) && attribute !== value.name) sendReport(node, attribute, value.name);
|
|
1414
|
+
else if (isMemberExpression(value) && isIdentifier(value.property) && attribute !== value.property.name) sendReport(node, attribute, value.property.name);
|
|
1415
|
+
};
|
|
1416
|
+
return {
|
|
1417
|
+
JSXAttribute(node) {
|
|
1418
|
+
if (!node.value) return;
|
|
1419
|
+
if (!isJSXExpressionContainer(node.value)) return;
|
|
1420
|
+
if (!isCachedBambooProperty(node)) return;
|
|
1421
|
+
const attribute = node.name.name.toString();
|
|
1422
|
+
const expression = node.value.expression;
|
|
1423
|
+
handleReport(node.value, expression, attribute);
|
|
1424
|
+
},
|
|
1425
|
+
Property(node) {
|
|
1426
|
+
if (!isIdentifier(node.key)) return;
|
|
1427
|
+
if (!isIdentifier(node.value) && !isMemberExpression(node.value)) return;
|
|
1428
|
+
if (!isCachedBambooAttribute(node)) return;
|
|
1429
|
+
if (isCachedRecipeVariant(node)) return;
|
|
1430
|
+
const attribute = node.key.name;
|
|
1431
|
+
const value = node.value;
|
|
1432
|
+
handleReport(node.value, value, attribute);
|
|
1433
|
+
}
|
|
1434
|
+
};
|
|
1435
|
+
},
|
|
1436
|
+
defaultOptions: [],
|
|
1437
|
+
meta: {
|
|
1438
|
+
docs: { description: "Ensure that properties for patterns or style props are not renamed, as it prevents proper tracking." },
|
|
1439
|
+
messages: { noRenaming: "Incoming `{{prop}}` prop is different from the expected `{{expected}}` attribute. Bamboo will not track this prop." },
|
|
1440
|
+
schema: [],
|
|
1441
|
+
type: "problem"
|
|
1442
|
+
},
|
|
1443
|
+
name: RULE_NAME$6
|
|
1444
|
+
});
|
|
1445
|
+
}));
|
|
1446
|
+
|
|
1447
|
+
//#endregion
|
|
1448
|
+
//#region src/rules/no-unsafe-token-fn-usage.ts
|
|
1449
|
+
var RULE_NAME$5, rule$5;
|
|
1450
|
+
var init_no_unsafe_token_fn_usage = __esmMin((() => {
|
|
1451
|
+
init_utils();
|
|
1452
|
+
init_helpers();
|
|
1453
|
+
init_nodes();
|
|
1454
|
+
RULE_NAME$5 = "no-unsafe-token-fn-usage";
|
|
1455
|
+
rule$5 = createRule({
|
|
1456
|
+
create(context) {
|
|
1457
|
+
let tokenImportCache;
|
|
1458
|
+
const getCachedTokenImport = () => {
|
|
1459
|
+
if (tokenImportCache !== void 0) return tokenImportCache;
|
|
1460
|
+
tokenImportCache = getTokenImport(context);
|
|
1461
|
+
return tokenImportCache;
|
|
1462
|
+
};
|
|
1463
|
+
const isUnsafeCallExpression = (node) => {
|
|
1464
|
+
const tkImport = getCachedTokenImport();
|
|
1465
|
+
return isIdentifier(node.callee) && node.callee.name === tkImport?.alias;
|
|
1466
|
+
};
|
|
1467
|
+
const tokenWrap = (value) => value ? `token(${value})` : "";
|
|
1468
|
+
const isCompositeValue = (input) => {
|
|
1469
|
+
if (!input) return false;
|
|
1470
|
+
return !/^(?:token\([^)]*\)|\{[^}]*\})$/.test(input);
|
|
1471
|
+
};
|
|
1472
|
+
const sendReport = (node, value) => {
|
|
1473
|
+
const tkImports = extractTokens(value);
|
|
1474
|
+
if (!tkImports.length) return;
|
|
1475
|
+
const token = tkImports[0].replace(/^[^.]*\./, "");
|
|
1476
|
+
context.report({
|
|
1477
|
+
messageId: "noUnsafeTokenFnUsage",
|
|
1478
|
+
node,
|
|
1479
|
+
suggest: [{
|
|
1480
|
+
data: { safe: token },
|
|
1481
|
+
fix: (fixer) => fixer.replaceText(node, `'${token}'`),
|
|
1482
|
+
messageId: "replace"
|
|
1483
|
+
}]
|
|
1484
|
+
});
|
|
1485
|
+
};
|
|
1486
|
+
const handleRuntimeFunction = (node) => {
|
|
1487
|
+
if (!isCallExpression(node)) return;
|
|
1488
|
+
if (!isUnsafeCallExpression(node)) return;
|
|
1489
|
+
const value = node.arguments[0];
|
|
1490
|
+
if (isLiteral(value)) sendReport(node, tokenWrap(getArbitraryValue(value.value?.toString() ?? "")));
|
|
1491
|
+
else if (isTemplateLiteral(value) && value.expressions.length === 0) sendReport(node, tokenWrap(getArbitraryValue(value.quasis[0].value.raw)));
|
|
1492
|
+
};
|
|
1493
|
+
const handleLiteral = (node) => {
|
|
1494
|
+
if (!isLiteral(node)) return;
|
|
1495
|
+
const value = getArbitraryValue(node.value?.toString() ?? "");
|
|
1496
|
+
if (isCompositeValue(value)) return;
|
|
1497
|
+
sendReport(node, value);
|
|
1498
|
+
};
|
|
1499
|
+
const handleTemplateLiteral = (node) => {
|
|
1500
|
+
if (!isTemplateLiteral(node) || node.expressions.length > 0) return;
|
|
1501
|
+
const value = getArbitraryValue(node.quasis[0].value.raw);
|
|
1502
|
+
if (isCompositeValue(value)) return;
|
|
1503
|
+
sendReport(node, value);
|
|
1504
|
+
};
|
|
1505
|
+
const bambooPropertyCache = /* @__PURE__ */ new WeakMap();
|
|
1506
|
+
const isCachedBambooProperty = (node) => {
|
|
1507
|
+
if (bambooPropertyCache.has(node)) return bambooPropertyCache.get(node);
|
|
1508
|
+
const result = isBambooProp(node, context);
|
|
1509
|
+
bambooPropertyCache.set(node, result);
|
|
1510
|
+
return Boolean(result);
|
|
1511
|
+
};
|
|
1512
|
+
const bambooAttributeCache = /* @__PURE__ */ new WeakMap();
|
|
1513
|
+
const isCachedBambooAttribute = (node) => {
|
|
1514
|
+
if (bambooAttributeCache.has(node)) return bambooAttributeCache.get(node);
|
|
1515
|
+
const result = isBambooAttribute(node, context);
|
|
1516
|
+
bambooAttributeCache.set(node, result);
|
|
1517
|
+
return Boolean(result);
|
|
1518
|
+
};
|
|
1519
|
+
const recipeVariantCache = /* @__PURE__ */ new WeakMap();
|
|
1520
|
+
const isCachedRecipeVariant = (node) => {
|
|
1521
|
+
if (recipeVariantCache.has(node)) return recipeVariantCache.get(node);
|
|
1522
|
+
const result = isRecipeVariant(node, context);
|
|
1523
|
+
recipeVariantCache.set(node, result);
|
|
1524
|
+
return Boolean(result);
|
|
1525
|
+
};
|
|
1526
|
+
return {
|
|
1527
|
+
JSXAttribute(node) {
|
|
1528
|
+
if (!node.value) return;
|
|
1529
|
+
if (!isCachedBambooProperty(node)) return;
|
|
1530
|
+
handleLiteral(node.value);
|
|
1531
|
+
if (isJSXExpressionContainer(node.value)) {
|
|
1532
|
+
const expression = node.value.expression;
|
|
1533
|
+
handleLiteral(expression);
|
|
1534
|
+
handleTemplateLiteral(expression);
|
|
1535
|
+
handleRuntimeFunction(expression);
|
|
1536
|
+
}
|
|
1537
|
+
},
|
|
1538
|
+
Property(node) {
|
|
1539
|
+
if (!isCachedBambooAttribute(node)) return;
|
|
1540
|
+
if (isCachedRecipeVariant(node)) return;
|
|
1541
|
+
const valueNode = node.value;
|
|
1542
|
+
if (isCallExpression(valueNode) || isLiteral(valueNode) || isTemplateLiteral(valueNode)) {
|
|
1543
|
+
handleRuntimeFunction(valueNode);
|
|
1544
|
+
handleLiteral(valueNode);
|
|
1545
|
+
handleTemplateLiteral(valueNode);
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
};
|
|
1549
|
+
},
|
|
1550
|
+
defaultOptions: [],
|
|
1551
|
+
meta: {
|
|
1552
|
+
docs: { description: "Prevent users from using the token function in situations where they could simply use the raw design token." },
|
|
1553
|
+
hasSuggestions: true,
|
|
1554
|
+
messages: {
|
|
1555
|
+
noUnsafeTokenFnUsage: "Unnecessary token function usage. Prefer design token.",
|
|
1556
|
+
replace: "Replace token function with `{{safe}}`."
|
|
1557
|
+
},
|
|
1558
|
+
schema: [],
|
|
1559
|
+
type: "suggestion"
|
|
1560
|
+
},
|
|
1561
|
+
name: RULE_NAME$5
|
|
1562
|
+
});
|
|
1563
|
+
}));
|
|
1564
|
+
|
|
1565
|
+
//#endregion
|
|
1566
|
+
//#region src/utils/composite-properties.ts
|
|
1567
|
+
var compositeProperties;
|
|
1568
|
+
var init_composite_properties = __esmMin((() => {
|
|
1569
|
+
compositeProperties = {
|
|
1570
|
+
animation: [
|
|
1571
|
+
"animationName",
|
|
1572
|
+
"animationDuration",
|
|
1573
|
+
"animationTimingFunction",
|
|
1574
|
+
"animationDelay",
|
|
1575
|
+
"animationIterationCount",
|
|
1576
|
+
"animationDirection",
|
|
1577
|
+
"animationFillMode",
|
|
1578
|
+
"animationPlayState"
|
|
1579
|
+
],
|
|
1580
|
+
background: [
|
|
1581
|
+
"backgroundImage",
|
|
1582
|
+
"backgroundPosition",
|
|
1583
|
+
"backgroundSize",
|
|
1584
|
+
"backgroundRepeat",
|
|
1585
|
+
"backgroundAttachment",
|
|
1586
|
+
"backgroundOrigin",
|
|
1587
|
+
"backgroundClip",
|
|
1588
|
+
"backgroundColor"
|
|
1589
|
+
],
|
|
1590
|
+
backgroundPosition: ["backgroundPositionX", "backgroundPositionY"],
|
|
1591
|
+
border: [
|
|
1592
|
+
"borderWidth",
|
|
1593
|
+
"borderStyle",
|
|
1594
|
+
"borderColor"
|
|
1595
|
+
],
|
|
1596
|
+
borderBlockEnd: [
|
|
1597
|
+
"borderBlockEndWidth",
|
|
1598
|
+
"borderBlockEndStyle",
|
|
1599
|
+
"borderBlockEndColor"
|
|
1600
|
+
],
|
|
1601
|
+
borderBlockStart: [
|
|
1602
|
+
"borderBlockStartWidth",
|
|
1603
|
+
"borderBlockStartStyle",
|
|
1604
|
+
"borderBlockStartColor"
|
|
1605
|
+
],
|
|
1606
|
+
borderBottom: [
|
|
1607
|
+
"borderBottomWidth",
|
|
1608
|
+
"borderBottomStyle",
|
|
1609
|
+
"borderBottomColor"
|
|
1610
|
+
],
|
|
1611
|
+
borderColor: [
|
|
1612
|
+
"borderTopColor",
|
|
1613
|
+
"borderRightColor",
|
|
1614
|
+
"borderBottomColor",
|
|
1615
|
+
"borderLeftColor"
|
|
1616
|
+
],
|
|
1617
|
+
borderImage: [
|
|
1618
|
+
"borderImageSource",
|
|
1619
|
+
"borderImageSlice",
|
|
1620
|
+
"borderImageWidth",
|
|
1621
|
+
"borderImageOutset",
|
|
1622
|
+
"borderImageRepeat"
|
|
1623
|
+
],
|
|
1624
|
+
borderInlineEnd: [
|
|
1625
|
+
"borderInlineEndWidth",
|
|
1626
|
+
"borderInlineEndStyle",
|
|
1627
|
+
"borderInlineEndColor"
|
|
1628
|
+
],
|
|
1629
|
+
borderInlineStart: [
|
|
1630
|
+
"borderInlineStartWidth",
|
|
1631
|
+
"borderInlineStartStyle",
|
|
1632
|
+
"borderInlineStartColor"
|
|
1633
|
+
],
|
|
1634
|
+
borderLeft: [
|
|
1635
|
+
"borderLeftWidth",
|
|
1636
|
+
"borderLeftStyle",
|
|
1637
|
+
"borderLeftColor"
|
|
1638
|
+
],
|
|
1639
|
+
borderRadius: [
|
|
1640
|
+
"borderTopLeftRadius",
|
|
1641
|
+
"borderTopRightRadius",
|
|
1642
|
+
"borderBottomRightRadius",
|
|
1643
|
+
"borderBottomLeftRadius"
|
|
1644
|
+
],
|
|
1645
|
+
borderRight: [
|
|
1646
|
+
"borderRightWidth",
|
|
1647
|
+
"borderRightStyle",
|
|
1648
|
+
"borderRightColor"
|
|
1649
|
+
],
|
|
1650
|
+
borderStyle: [
|
|
1651
|
+
"borderTopStyle",
|
|
1652
|
+
"borderRightStyle",
|
|
1653
|
+
"borderBottomStyle",
|
|
1654
|
+
"borderLeftStyle"
|
|
1655
|
+
],
|
|
1656
|
+
borderTop: [
|
|
1657
|
+
"borderTopWidth",
|
|
1658
|
+
"borderTopStyle",
|
|
1659
|
+
"borderTopColor"
|
|
1660
|
+
],
|
|
1661
|
+
borderWidth: [
|
|
1662
|
+
"borderTopWidth",
|
|
1663
|
+
"borderRightWidth",
|
|
1664
|
+
"borderBottomWidth",
|
|
1665
|
+
"borderLeftWidth"
|
|
1666
|
+
],
|
|
1667
|
+
columnRule: [
|
|
1668
|
+
"columnRuleWidth",
|
|
1669
|
+
"columnRuleStyle",
|
|
1670
|
+
"columnRuleColor"
|
|
1671
|
+
],
|
|
1672
|
+
columns: ["columnWidth", "columnCount"],
|
|
1673
|
+
container: ["contain", "content"],
|
|
1674
|
+
containIntrinsicSize: ["containIntrinsicSizeInline", "containIntrinsicSizeBlock"],
|
|
1675
|
+
cue: ["cueBefore", "cueAfter"],
|
|
1676
|
+
flex: [
|
|
1677
|
+
"flexGrow",
|
|
1678
|
+
"flexShrink",
|
|
1679
|
+
"flexBasis"
|
|
1680
|
+
],
|
|
1681
|
+
flexFlow: ["flexDirection", "flexWrap"],
|
|
1682
|
+
font: [
|
|
1683
|
+
"fontStyle",
|
|
1684
|
+
"fontVariantCaps",
|
|
1685
|
+
"fontVariantEastAsian",
|
|
1686
|
+
"fontVariantLigatures",
|
|
1687
|
+
"fontVariantNumeric",
|
|
1688
|
+
"fontVariantPosition",
|
|
1689
|
+
"fontWeight",
|
|
1690
|
+
"fontStretch",
|
|
1691
|
+
"fontSize",
|
|
1692
|
+
"lineHeight",
|
|
1693
|
+
"fontFamily"
|
|
1694
|
+
],
|
|
1695
|
+
fontSynthesis: [
|
|
1696
|
+
"fontSynthesisWeight",
|
|
1697
|
+
"fontSynthesisStyle",
|
|
1698
|
+
"fontSynthesisSmallCaps"
|
|
1699
|
+
],
|
|
1700
|
+
fontVariant: [
|
|
1701
|
+
"fontVariantCaps",
|
|
1702
|
+
"fontVariantEastAsian",
|
|
1703
|
+
"fontVariantLigatures",
|
|
1704
|
+
"fontVariantNumeric",
|
|
1705
|
+
"fontVariantPosition"
|
|
1706
|
+
],
|
|
1707
|
+
gap: ["columnGap", "rowGap"],
|
|
1708
|
+
grid: [
|
|
1709
|
+
"gridTemplateColumns",
|
|
1710
|
+
"gridTemplateRows",
|
|
1711
|
+
"gridTemplateAreas",
|
|
1712
|
+
"gridAutoColumns",
|
|
1713
|
+
"gridAutoRows",
|
|
1714
|
+
"gridAutoFlow"
|
|
1715
|
+
],
|
|
1716
|
+
gridArea: [
|
|
1717
|
+
"gridRowStart",
|
|
1718
|
+
"gridColumnStart",
|
|
1719
|
+
"gridRowEnd",
|
|
1720
|
+
"gridColumnEnd"
|
|
1721
|
+
],
|
|
1722
|
+
gridColumn: ["gridColumnStart", "gridColumnEnd"],
|
|
1723
|
+
gridGap: ["gridColumnGap", "gridRowGap"],
|
|
1724
|
+
gridRow: ["gridRowStart", "gridRowEnd"],
|
|
1725
|
+
gridTemplate: [
|
|
1726
|
+
"gridTemplateColumns",
|
|
1727
|
+
"gridTemplateRows",
|
|
1728
|
+
"gridTemplateAreas"
|
|
1729
|
+
],
|
|
1730
|
+
inset: [
|
|
1731
|
+
"top",
|
|
1732
|
+
"right",
|
|
1733
|
+
"bottom",
|
|
1734
|
+
"left"
|
|
1735
|
+
],
|
|
1736
|
+
listStyle: [
|
|
1737
|
+
"listStyleType",
|
|
1738
|
+
"listStylePosition",
|
|
1739
|
+
"listStyleImage"
|
|
1740
|
+
],
|
|
1741
|
+
margin: [
|
|
1742
|
+
"marginTop",
|
|
1743
|
+
"marginRight",
|
|
1744
|
+
"marginBottom",
|
|
1745
|
+
"marginLeft"
|
|
1746
|
+
],
|
|
1747
|
+
mask: [
|
|
1748
|
+
"maskImage",
|
|
1749
|
+
"maskMode",
|
|
1750
|
+
"maskRepeat",
|
|
1751
|
+
"maskPosition",
|
|
1752
|
+
"maskClip",
|
|
1753
|
+
"maskOrigin",
|
|
1754
|
+
"maskSize",
|
|
1755
|
+
"maskComposite"
|
|
1756
|
+
],
|
|
1757
|
+
maskBorder: [
|
|
1758
|
+
"maskBorderSource",
|
|
1759
|
+
"maskBorderMode",
|
|
1760
|
+
"maskBorderSlice",
|
|
1761
|
+
"maskBorderWidth",
|
|
1762
|
+
"maskBorderOutset",
|
|
1763
|
+
"maskBorderRepeat"
|
|
1764
|
+
],
|
|
1765
|
+
offset: [
|
|
1766
|
+
"offsetPosition",
|
|
1767
|
+
"offsetPath",
|
|
1768
|
+
"offsetDistance",
|
|
1769
|
+
"offsetRotate",
|
|
1770
|
+
"offsetAnchor"
|
|
1771
|
+
],
|
|
1772
|
+
outline: [
|
|
1773
|
+
"outlineWidth",
|
|
1774
|
+
"outlineStyle",
|
|
1775
|
+
"outlineColor"
|
|
1776
|
+
],
|
|
1777
|
+
overflow: ["overflowX", "overflowY"],
|
|
1778
|
+
padding: [
|
|
1779
|
+
"paddingTop",
|
|
1780
|
+
"paddingRight",
|
|
1781
|
+
"paddingBottom",
|
|
1782
|
+
"paddingLeft"
|
|
1783
|
+
],
|
|
1784
|
+
pause: ["pauseBefore", "pauseAfter"],
|
|
1785
|
+
placeContent: ["alignContent", "justifyContent"],
|
|
1786
|
+
placeItems: ["alignItems", "justifyItems"],
|
|
1787
|
+
placeSelf: ["alignSelf", "justifySelf"],
|
|
1788
|
+
rest: ["restBefore", "restAfter"],
|
|
1789
|
+
scrollMargin: [
|
|
1790
|
+
"scrollMarginTop",
|
|
1791
|
+
"scrollMarginRight",
|
|
1792
|
+
"scrollMarginBottom",
|
|
1793
|
+
"scrollMarginLeft"
|
|
1794
|
+
],
|
|
1795
|
+
scrollPadding: [
|
|
1796
|
+
"scrollPaddingTop",
|
|
1797
|
+
"scrollPaddingRight",
|
|
1798
|
+
"scrollPaddingBottom",
|
|
1799
|
+
"scrollPaddingLeft"
|
|
1800
|
+
],
|
|
1801
|
+
scrollPaddingBlock: ["scrollPaddingBlockStart", "scrollPaddingBlockEnd"],
|
|
1802
|
+
scrollPaddingInline: ["scrollPaddingInlineStart", "scrollPaddingInlineEnd"],
|
|
1803
|
+
scrollSnapMargin: [
|
|
1804
|
+
"scrollSnapMarginTop",
|
|
1805
|
+
"scrollSnapMarginRight",
|
|
1806
|
+
"scrollSnapMarginBottom",
|
|
1807
|
+
"scrollSnapMarginLeft"
|
|
1808
|
+
],
|
|
1809
|
+
scrollSnapMarginBlock: ["scrollSnapMarginBlockStart", "scrollSnapMarginBlockEnd"],
|
|
1810
|
+
scrollSnapMarginInline: ["scrollSnapMarginInlineStart", "scrollSnapMarginInlineEnd"],
|
|
1811
|
+
scrollTimeline: ["scrollTimelineSource", "scrollTimelineOrientation"],
|
|
1812
|
+
textDecoration: [
|
|
1813
|
+
"textDecorationLine",
|
|
1814
|
+
"textDecorationStyle",
|
|
1815
|
+
"textDecorationColor"
|
|
1816
|
+
],
|
|
1817
|
+
textEmphasis: ["textEmphasisStyle", "textEmphasisColor"],
|
|
1818
|
+
transition: [
|
|
1819
|
+
"transitionProperty",
|
|
1820
|
+
"transitionDuration",
|
|
1821
|
+
"transitionTimingFunction",
|
|
1822
|
+
"transitionDelay"
|
|
1823
|
+
]
|
|
1824
|
+
};
|
|
1825
|
+
}));
|
|
1826
|
+
|
|
1827
|
+
//#endregion
|
|
1828
|
+
//#region src/rules/prefer-atomic-properties.ts
|
|
1829
|
+
var RULE_NAME$4, rule$4;
|
|
1830
|
+
var init_prefer_atomic_properties = __esmMin((() => {
|
|
1831
|
+
init_utils();
|
|
1832
|
+
init_composite_properties();
|
|
1833
|
+
init_helpers();
|
|
1834
|
+
init_nodes();
|
|
1835
|
+
RULE_NAME$4 = "prefer-atomic-properties";
|
|
1836
|
+
rule$4 = createRule({
|
|
1837
|
+
create(context) {
|
|
1838
|
+
const whitelist = context.options[0]?.whitelist ?? [];
|
|
1839
|
+
const longhandCache = /* @__PURE__ */ new Map();
|
|
1840
|
+
const getLonghand = (name) => {
|
|
1841
|
+
if (longhandCache.has(name)) return longhandCache.get(name);
|
|
1842
|
+
const longhand = resolveLonghand(name, context) ?? name;
|
|
1843
|
+
longhandCache.set(name, longhand);
|
|
1844
|
+
return longhand;
|
|
1845
|
+
};
|
|
1846
|
+
const compositePropertyCache = /* @__PURE__ */ new Map();
|
|
1847
|
+
const resolveCompositeProperty = (name) => {
|
|
1848
|
+
if (compositePropertyCache.has(name)) return compositePropertyCache.get(name);
|
|
1849
|
+
if (Object.hasOwn(compositeProperties, name)) {
|
|
1850
|
+
compositePropertyCache.set(name, name);
|
|
1851
|
+
return name;
|
|
1852
|
+
}
|
|
1853
|
+
const longhand = getLonghand(name);
|
|
1854
|
+
if (isValidProperty(longhand, context) && Object.hasOwn(compositeProperties, longhand)) {
|
|
1855
|
+
compositePropertyCache.set(name, longhand);
|
|
1856
|
+
return longhand;
|
|
1857
|
+
}
|
|
1858
|
+
compositePropertyCache.set(name, void 0);
|
|
1859
|
+
};
|
|
1860
|
+
const bambooPropertyCache = /* @__PURE__ */ new WeakMap();
|
|
1861
|
+
const isCachedBambooProperty = (node) => {
|
|
1862
|
+
if (bambooPropertyCache.has(node)) return bambooPropertyCache.get(node);
|
|
1863
|
+
const result = isBambooProp(node, context);
|
|
1864
|
+
bambooPropertyCache.set(node, result);
|
|
1865
|
+
return Boolean(result);
|
|
1866
|
+
};
|
|
1867
|
+
const bambooAttributeCache = /* @__PURE__ */ new WeakMap();
|
|
1868
|
+
const isCachedBambooAttribute = (node) => {
|
|
1869
|
+
if (bambooAttributeCache.has(node)) return bambooAttributeCache.get(node);
|
|
1870
|
+
const result = isBambooAttribute(node, context);
|
|
1871
|
+
bambooAttributeCache.set(node, result);
|
|
1872
|
+
return Boolean(result);
|
|
1873
|
+
};
|
|
1874
|
+
const recipeVariantCache = /* @__PURE__ */ new WeakMap();
|
|
1875
|
+
const isCachedRecipeVariant = (node) => {
|
|
1876
|
+
if (recipeVariantCache.has(node)) return recipeVariantCache.get(node);
|
|
1877
|
+
const result = isRecipeVariant(node, context);
|
|
1878
|
+
recipeVariantCache.set(node, result);
|
|
1879
|
+
return Boolean(result);
|
|
1880
|
+
};
|
|
1881
|
+
const sendReport = (node, composite) => {
|
|
1882
|
+
if (whitelist.includes(node.name)) return;
|
|
1883
|
+
const atomics = compositeProperties[composite].map((name) => `\`${name}\``).join(",\n");
|
|
1884
|
+
context.report({
|
|
1885
|
+
data: {
|
|
1886
|
+
atomics,
|
|
1887
|
+
composite: node.name
|
|
1888
|
+
},
|
|
1889
|
+
messageId: "atomic",
|
|
1890
|
+
node
|
|
1891
|
+
});
|
|
1892
|
+
};
|
|
1893
|
+
return {
|
|
1894
|
+
JSXAttribute(node) {
|
|
1895
|
+
if (!isJSXIdentifier(node.name)) return;
|
|
1896
|
+
if (!isCachedBambooProperty(node)) return;
|
|
1897
|
+
const composite = resolveCompositeProperty(node.name.name);
|
|
1898
|
+
if (!composite) return;
|
|
1899
|
+
sendReport(node.name, composite);
|
|
1900
|
+
},
|
|
1901
|
+
Property(node) {
|
|
1902
|
+
if (!isIdentifier(node.key)) return;
|
|
1903
|
+
if (!isCachedBambooAttribute(node)) return;
|
|
1904
|
+
if (isCachedRecipeVariant(node)) return;
|
|
1905
|
+
const composite = resolveCompositeProperty(node.key.name);
|
|
1906
|
+
if (!composite) return;
|
|
1907
|
+
sendReport(node.key, composite);
|
|
1908
|
+
}
|
|
1909
|
+
};
|
|
1910
|
+
},
|
|
1911
|
+
defaultOptions: [{ whitelist: [] }],
|
|
1912
|
+
meta: {
|
|
1913
|
+
docs: { description: "Encourage the use of atomic properties instead of composite properties in the codebase." },
|
|
1914
|
+
messages: { atomic: "Use atomic properties instead of `{{composite}}`. Prefer: \n{{atomics}}" },
|
|
1915
|
+
schema: [{
|
|
1916
|
+
additionalProperties: false,
|
|
1917
|
+
properties: { whitelist: {
|
|
1918
|
+
items: {
|
|
1919
|
+
minLength: 0,
|
|
1920
|
+
type: "string"
|
|
1921
|
+
},
|
|
1922
|
+
type: "array",
|
|
1923
|
+
uniqueItems: true
|
|
1924
|
+
} },
|
|
1925
|
+
type: "object"
|
|
1926
|
+
}],
|
|
1927
|
+
type: "suggestion"
|
|
1928
|
+
},
|
|
1929
|
+
name: RULE_NAME$4
|
|
1930
|
+
});
|
|
1931
|
+
}));
|
|
1932
|
+
|
|
1933
|
+
//#endregion
|
|
1934
|
+
//#region src/rules/prefer-composite-properties.ts
|
|
1935
|
+
var RULE_NAME$3, rule$3;
|
|
1936
|
+
var init_prefer_composite_properties = __esmMin((() => {
|
|
1937
|
+
init_utils();
|
|
1938
|
+
init_composite_properties();
|
|
1939
|
+
init_helpers();
|
|
1940
|
+
init_nodes();
|
|
1941
|
+
RULE_NAME$3 = "prefer-composite-properties";
|
|
1942
|
+
rule$3 = createRule({
|
|
1943
|
+
create(context) {
|
|
1944
|
+
const whitelist = context.options[0]?.whitelist ?? [];
|
|
1945
|
+
const longhandCache = /* @__PURE__ */ new Map();
|
|
1946
|
+
const getLonghand = (name) => {
|
|
1947
|
+
if (longhandCache.has(name)) return longhandCache.get(name);
|
|
1948
|
+
const longhand = resolveLonghand(name, context) ?? name;
|
|
1949
|
+
longhandCache.set(name, longhand);
|
|
1950
|
+
return longhand;
|
|
1951
|
+
};
|
|
1952
|
+
const compositePropertyCache = /* @__PURE__ */ new Map();
|
|
1953
|
+
const resolveCompositeProperty = (name) => {
|
|
1954
|
+
if (compositePropertyCache.has(name)) return compositePropertyCache.get(name);
|
|
1955
|
+
const longhand = getLonghand(name);
|
|
1956
|
+
if (!isValidProperty(longhand, context)) {
|
|
1957
|
+
compositePropertyCache.set(name, void 0);
|
|
1958
|
+
return;
|
|
1959
|
+
}
|
|
1960
|
+
const composite = Object.keys(compositeProperties).find((cpd) => compositeProperties[cpd].includes(longhand));
|
|
1961
|
+
compositePropertyCache.set(name, composite);
|
|
1962
|
+
return composite;
|
|
1963
|
+
};
|
|
1964
|
+
const bambooPropertyCache = /* @__PURE__ */ new WeakMap();
|
|
1965
|
+
const isCachedBambooProperty = (node) => {
|
|
1966
|
+
if (bambooPropertyCache.has(node)) return bambooPropertyCache.get(node);
|
|
1967
|
+
const result = isBambooProp(node, context);
|
|
1968
|
+
bambooPropertyCache.set(node, result);
|
|
1969
|
+
return Boolean(result);
|
|
1970
|
+
};
|
|
1971
|
+
const bambooAttributeCache = /* @__PURE__ */ new WeakMap();
|
|
1972
|
+
const isCachedBambooAttribute = (node) => {
|
|
1973
|
+
if (bambooAttributeCache.has(node)) return bambooAttributeCache.get(node);
|
|
1974
|
+
const result = isBambooAttribute(node, context);
|
|
1975
|
+
bambooAttributeCache.set(node, result);
|
|
1976
|
+
return Boolean(result);
|
|
1977
|
+
};
|
|
1978
|
+
const recipeVariantCache = /* @__PURE__ */ new WeakMap();
|
|
1979
|
+
const isCachedRecipeVariant = (node) => {
|
|
1980
|
+
if (recipeVariantCache.has(node)) return recipeVariantCache.get(node);
|
|
1981
|
+
const result = isRecipeVariant(node, context);
|
|
1982
|
+
recipeVariantCache.set(node, result);
|
|
1983
|
+
return Boolean(result);
|
|
1984
|
+
};
|
|
1985
|
+
const sendReport = (node, composite) => {
|
|
1986
|
+
if (whitelist.includes(node.name)) return;
|
|
1987
|
+
context.report({
|
|
1988
|
+
data: {
|
|
1989
|
+
atomic: node.name,
|
|
1990
|
+
composite
|
|
1991
|
+
},
|
|
1992
|
+
messageId: "composite",
|
|
1993
|
+
node
|
|
1994
|
+
});
|
|
1995
|
+
};
|
|
1996
|
+
return {
|
|
1997
|
+
JSXAttribute(node) {
|
|
1998
|
+
if (!isJSXIdentifier(node.name)) return;
|
|
1999
|
+
if (!isCachedBambooProperty(node)) return;
|
|
2000
|
+
const composite = resolveCompositeProperty(node.name.name);
|
|
2001
|
+
if (!composite) return;
|
|
2002
|
+
sendReport(node.name, composite);
|
|
2003
|
+
},
|
|
2004
|
+
Property(node) {
|
|
2005
|
+
if (!isIdentifier(node.key)) return;
|
|
2006
|
+
if (!isCachedBambooAttribute(node)) return;
|
|
2007
|
+
if (isCachedRecipeVariant(node)) return;
|
|
2008
|
+
const composite = resolveCompositeProperty(node.key.name);
|
|
2009
|
+
if (!composite) return;
|
|
2010
|
+
sendReport(node.key, composite);
|
|
2011
|
+
}
|
|
2012
|
+
};
|
|
2013
|
+
},
|
|
2014
|
+
defaultOptions: [{ whitelist: [] }],
|
|
2015
|
+
meta: {
|
|
2016
|
+
docs: { description: "Encourage the use of composite properties instead of atomic properties in the codebase." },
|
|
2017
|
+
messages: { composite: "Use composite property instead of `{{atomic}}`. Prefer: `{{composite}}`." },
|
|
2018
|
+
schema: [{
|
|
2019
|
+
additionalProperties: false,
|
|
2020
|
+
properties: { whitelist: {
|
|
2021
|
+
items: {
|
|
2022
|
+
minLength: 0,
|
|
2023
|
+
type: "string"
|
|
2024
|
+
},
|
|
2025
|
+
type: "array",
|
|
2026
|
+
uniqueItems: true
|
|
2027
|
+
} },
|
|
2028
|
+
type: "object"
|
|
2029
|
+
}],
|
|
2030
|
+
type: "suggestion"
|
|
2031
|
+
},
|
|
2032
|
+
name: RULE_NAME$3
|
|
2033
|
+
});
|
|
2034
|
+
}));
|
|
2035
|
+
|
|
2036
|
+
//#endregion
|
|
2037
|
+
//#region src/rules/prefer-longhand-properties.ts
|
|
2038
|
+
var RULE_NAME$2, rule$2;
|
|
2039
|
+
var init_prefer_longhand_properties = __esmMin((() => {
|
|
2040
|
+
init_utils();
|
|
2041
|
+
init_helpers();
|
|
2042
|
+
init_nodes();
|
|
2043
|
+
RULE_NAME$2 = "prefer-longhand-properties";
|
|
2044
|
+
rule$2 = createRule({
|
|
2045
|
+
create(context) {
|
|
2046
|
+
const whitelist = context.options[0]?.whitelist ?? [];
|
|
2047
|
+
const longhandCache = /* @__PURE__ */ new Map();
|
|
2048
|
+
const getLonghand = (name) => {
|
|
2049
|
+
if (longhandCache.has(name)) return longhandCache.get(name);
|
|
2050
|
+
const longhand = resolveLonghand(name, context);
|
|
2051
|
+
longhandCache.set(name, longhand);
|
|
2052
|
+
return longhand;
|
|
2053
|
+
};
|
|
2054
|
+
const bambooPropertyCache = /* @__PURE__ */ new WeakMap();
|
|
2055
|
+
const isCachedBambooProperty = (node) => {
|
|
2056
|
+
if (bambooPropertyCache.has(node)) return bambooPropertyCache.get(node);
|
|
2057
|
+
const result = isBambooProp(node, context);
|
|
2058
|
+
bambooPropertyCache.set(node, result);
|
|
2059
|
+
return Boolean(result);
|
|
2060
|
+
};
|
|
2061
|
+
const bambooAttributeCache = /* @__PURE__ */ new WeakMap();
|
|
2062
|
+
const isCachedBambooAttribute = (node) => {
|
|
2063
|
+
if (bambooAttributeCache.has(node)) return bambooAttributeCache.get(node);
|
|
2064
|
+
const result = isBambooAttribute(node, context);
|
|
2065
|
+
bambooAttributeCache.set(node, result);
|
|
2066
|
+
return Boolean(result);
|
|
2067
|
+
};
|
|
2068
|
+
const recipeVariantCache = /* @__PURE__ */ new WeakMap();
|
|
2069
|
+
const isCachedRecipeVariant = (node) => {
|
|
2070
|
+
if (recipeVariantCache.has(node)) return recipeVariantCache.get(node);
|
|
2071
|
+
const result = isRecipeVariant(node, context);
|
|
2072
|
+
recipeVariantCache.set(node, result);
|
|
2073
|
+
return Boolean(result);
|
|
2074
|
+
};
|
|
2075
|
+
const sendReport = (node) => {
|
|
2076
|
+
if (whitelist.includes(node.name)) return;
|
|
2077
|
+
const longhand = getLonghand(node.name);
|
|
2078
|
+
if (!longhand || longhand === node.name) return;
|
|
2079
|
+
const data = {
|
|
2080
|
+
longhand,
|
|
2081
|
+
shorthand: node.name
|
|
2082
|
+
};
|
|
2083
|
+
context.report({
|
|
2084
|
+
data,
|
|
2085
|
+
messageId: "longhand",
|
|
2086
|
+
node,
|
|
2087
|
+
suggest: [{
|
|
2088
|
+
data,
|
|
2089
|
+
fix: (fixer) => fixer.replaceText(node, longhand),
|
|
2090
|
+
messageId: "replace"
|
|
2091
|
+
}]
|
|
2092
|
+
});
|
|
2093
|
+
};
|
|
2094
|
+
return {
|
|
2095
|
+
JSXAttribute(node) {
|
|
2096
|
+
if (!isJSXIdentifier(node.name)) return;
|
|
2097
|
+
if (!isCachedBambooProperty(node)) return;
|
|
2098
|
+
sendReport(node.name);
|
|
2099
|
+
},
|
|
2100
|
+
Property(node) {
|
|
2101
|
+
if (!isIdentifier(node.key)) return;
|
|
2102
|
+
if (!isCachedBambooAttribute(node)) return;
|
|
2103
|
+
if (isCachedRecipeVariant(node)) return;
|
|
2104
|
+
sendReport(node.key);
|
|
2105
|
+
}
|
|
2106
|
+
};
|
|
2107
|
+
},
|
|
2108
|
+
defaultOptions: [{ whitelist: [] }],
|
|
2109
|
+
meta: {
|
|
2110
|
+
docs: { description: "Discourage the use of shorthand properties and promote the preference for longhand properties in the codebase." },
|
|
2111
|
+
hasSuggestions: true,
|
|
2112
|
+
messages: {
|
|
2113
|
+
longhand: "Use longhand property instead of `{{shorthand}}`. Prefer `{{longhand}}`.",
|
|
2114
|
+
replace: "Replace `{{shorthand}}` with `{{longhand}}`."
|
|
2115
|
+
},
|
|
2116
|
+
schema: [{
|
|
2117
|
+
additionalProperties: false,
|
|
2118
|
+
properties: { whitelist: {
|
|
2119
|
+
items: {
|
|
2120
|
+
minLength: 0,
|
|
2121
|
+
type: "string"
|
|
2122
|
+
},
|
|
2123
|
+
type: "array",
|
|
2124
|
+
uniqueItems: true
|
|
2125
|
+
} },
|
|
2126
|
+
type: "object"
|
|
2127
|
+
}],
|
|
2128
|
+
type: "suggestion"
|
|
2129
|
+
},
|
|
2130
|
+
name: RULE_NAME$2
|
|
2131
|
+
});
|
|
2132
|
+
}));
|
|
2133
|
+
|
|
2134
|
+
//#endregion
|
|
2135
|
+
//#region src/rules/prefer-shorthand-properties.ts
|
|
2136
|
+
var RULE_NAME$1, rule$1;
|
|
2137
|
+
var init_prefer_shorthand_properties = __esmMin((() => {
|
|
2138
|
+
init_utils();
|
|
2139
|
+
init_helpers();
|
|
2140
|
+
init_nodes();
|
|
2141
|
+
RULE_NAME$1 = "prefer-shorthand-properties";
|
|
2142
|
+
rule$1 = createRule({
|
|
2143
|
+
create(context) {
|
|
2144
|
+
const whitelist = context.options[0]?.whitelist ?? [];
|
|
2145
|
+
const longhandCache = /* @__PURE__ */ new Map();
|
|
2146
|
+
const getLonghand = (name) => {
|
|
2147
|
+
if (longhandCache.has(name)) return longhandCache.get(name);
|
|
2148
|
+
const longhand = resolveLonghand(name, context);
|
|
2149
|
+
longhandCache.set(name, longhand);
|
|
2150
|
+
return longhand;
|
|
2151
|
+
};
|
|
2152
|
+
const shorthandsCache = /* @__PURE__ */ new Map();
|
|
2153
|
+
const getShorthands = (name) => {
|
|
2154
|
+
if (shorthandsCache.has(name)) return shorthandsCache.get(name);
|
|
2155
|
+
const shorthands = resolveShorthands(name, context);
|
|
2156
|
+
shorthandsCache.set(name, shorthands);
|
|
2157
|
+
return shorthands;
|
|
2158
|
+
};
|
|
2159
|
+
const bambooPropertyCache = /* @__PURE__ */ new WeakMap();
|
|
2160
|
+
const isCachedBambooProperty = (node) => {
|
|
2161
|
+
if (bambooPropertyCache.has(node)) return bambooPropertyCache.get(node);
|
|
2162
|
+
const result = isBambooProp(node, context);
|
|
2163
|
+
bambooPropertyCache.set(node, result);
|
|
2164
|
+
return Boolean(result);
|
|
2165
|
+
};
|
|
2166
|
+
const bambooAttributeCache = /* @__PURE__ */ new WeakMap();
|
|
2167
|
+
const isCachedBambooAttribute = (node) => {
|
|
2168
|
+
if (bambooAttributeCache.has(node)) return bambooAttributeCache.get(node);
|
|
2169
|
+
const result = isBambooAttribute(node, context);
|
|
2170
|
+
bambooAttributeCache.set(node, result);
|
|
2171
|
+
return Boolean(result);
|
|
2172
|
+
};
|
|
2173
|
+
const recipeVariantCache = /* @__PURE__ */ new WeakMap();
|
|
2174
|
+
const isCachedRecipeVariant = (node) => {
|
|
2175
|
+
if (recipeVariantCache.has(node)) return recipeVariantCache.get(node);
|
|
2176
|
+
const result = isRecipeVariant(node, context);
|
|
2177
|
+
recipeVariantCache.set(node, result);
|
|
2178
|
+
return Boolean(result);
|
|
2179
|
+
};
|
|
2180
|
+
const sendReport = (node) => {
|
|
2181
|
+
if (whitelist.includes(node.name)) return;
|
|
2182
|
+
if (getLonghand(node.name)) return;
|
|
2183
|
+
const shorthands = getShorthands(node.name);
|
|
2184
|
+
if (!shorthands || shorthands.length === 0) return;
|
|
2185
|
+
const shorthandList = shorthands.map((s) => `\`${s}\``).join(", ");
|
|
2186
|
+
const data = {
|
|
2187
|
+
longhand: node.name,
|
|
2188
|
+
shorthand: shorthandList
|
|
2189
|
+
};
|
|
2190
|
+
context.report({
|
|
2191
|
+
data,
|
|
2192
|
+
messageId: "shorthand",
|
|
2193
|
+
node,
|
|
2194
|
+
suggest: [{
|
|
2195
|
+
data,
|
|
2196
|
+
fix: (fixer) => fixer.replaceText(node, shorthands[0]),
|
|
2197
|
+
messageId: "replace"
|
|
2198
|
+
}]
|
|
2199
|
+
});
|
|
2200
|
+
};
|
|
2201
|
+
return {
|
|
2202
|
+
JSXAttribute(node) {
|
|
2203
|
+
if (!isJSXIdentifier(node.name)) return;
|
|
2204
|
+
if (!isCachedBambooProperty(node)) return;
|
|
2205
|
+
sendReport(node.name);
|
|
2206
|
+
},
|
|
2207
|
+
Property(node) {
|
|
2208
|
+
if (!isIdentifier(node.key)) return;
|
|
2209
|
+
if (!isCachedBambooAttribute(node)) return;
|
|
2210
|
+
if (isCachedRecipeVariant(node)) return;
|
|
2211
|
+
sendReport(node.key);
|
|
2212
|
+
}
|
|
2213
|
+
};
|
|
2214
|
+
},
|
|
2215
|
+
defaultOptions: [{ whitelist: [] }],
|
|
2216
|
+
meta: {
|
|
2217
|
+
docs: { description: "Discourage the use of longhand properties and promote the preference for shorthand properties in the codebase." },
|
|
2218
|
+
hasSuggestions: true,
|
|
2219
|
+
messages: {
|
|
2220
|
+
replace: "Replace `{{longhand}}` with `{{shorthand}}`.",
|
|
2221
|
+
shorthand: "Use shorthand property instead of `{{longhand}}`. Prefer `{{shorthand}}`."
|
|
2222
|
+
},
|
|
2223
|
+
schema: [{
|
|
2224
|
+
additionalProperties: false,
|
|
2225
|
+
properties: { whitelist: {
|
|
2226
|
+
items: {
|
|
2227
|
+
minLength: 0,
|
|
2228
|
+
type: "string"
|
|
2229
|
+
},
|
|
2230
|
+
type: "array",
|
|
2231
|
+
uniqueItems: true
|
|
2232
|
+
} },
|
|
2233
|
+
type: "object"
|
|
2234
|
+
}],
|
|
2235
|
+
type: "suggestion"
|
|
2236
|
+
},
|
|
2237
|
+
name: RULE_NAME$1
|
|
2238
|
+
});
|
|
2239
|
+
}));
|
|
2240
|
+
|
|
2241
|
+
//#endregion
|
|
2242
|
+
//#region src/rules/prefer-unified-property-style.ts
|
|
2243
|
+
var RULE_NAME, rule;
|
|
2244
|
+
var init_prefer_unified_property_style = __esmMin((() => {
|
|
2245
|
+
init_utils();
|
|
2246
|
+
init_composite_properties();
|
|
2247
|
+
init_helpers();
|
|
2248
|
+
init_nodes();
|
|
2249
|
+
RULE_NAME = "prefer-unified-property-style";
|
|
2250
|
+
rule = createRule({
|
|
2251
|
+
create(context) {
|
|
2252
|
+
const longhandCache = /* @__PURE__ */ new Map();
|
|
2253
|
+
const getLonghand = (name) => {
|
|
2254
|
+
if (longhandCache.has(name)) return longhandCache.get(name);
|
|
2255
|
+
const longhand = resolveLonghand(name, context) ?? name;
|
|
2256
|
+
longhandCache.set(name, longhand);
|
|
2257
|
+
return longhand;
|
|
2258
|
+
};
|
|
2259
|
+
const compositePropertyCache = /* @__PURE__ */ new Map();
|
|
2260
|
+
const resolveCompositeProperty = (name) => {
|
|
2261
|
+
if (compositePropertyCache.has(name)) return compositePropertyCache.get(name);
|
|
2262
|
+
if (name in compositeProperties) {
|
|
2263
|
+
compositePropertyCache.set(name, name);
|
|
2264
|
+
return name;
|
|
2265
|
+
}
|
|
2266
|
+
const longhand = getLonghand(name);
|
|
2267
|
+
if (isValidProperty(longhand, context) && longhand in compositeProperties) {
|
|
2268
|
+
compositePropertyCache.set(name, longhand);
|
|
2269
|
+
return longhand;
|
|
2270
|
+
}
|
|
2271
|
+
compositePropertyCache.set(name, void 0);
|
|
2272
|
+
};
|
|
2273
|
+
const bambooPropertyCache = /* @__PURE__ */ new WeakMap();
|
|
2274
|
+
const isCachedBambooProperty = (node) => {
|
|
2275
|
+
if (bambooPropertyCache.has(node)) return bambooPropertyCache.get(node);
|
|
2276
|
+
const result = isBambooProp(node, context);
|
|
2277
|
+
bambooPropertyCache.set(node, result);
|
|
2278
|
+
return Boolean(result);
|
|
2279
|
+
};
|
|
2280
|
+
const bambooAttributeCache = /* @__PURE__ */ new WeakMap();
|
|
2281
|
+
const isCachedBambooAttribute = (node) => {
|
|
2282
|
+
if (bambooAttributeCache.has(node)) return bambooAttributeCache.get(node);
|
|
2283
|
+
const result = isBambooAttribute(node, context);
|
|
2284
|
+
bambooAttributeCache.set(node, result);
|
|
2285
|
+
return Boolean(result);
|
|
2286
|
+
};
|
|
2287
|
+
const recipeVariantCache = /* @__PURE__ */ new WeakMap();
|
|
2288
|
+
const isCachedRecipeVariant = (node) => {
|
|
2289
|
+
if (recipeVariantCache.has(node)) return recipeVariantCache.get(node);
|
|
2290
|
+
const result = isRecipeVariant(node, context);
|
|
2291
|
+
recipeVariantCache.set(node, result);
|
|
2292
|
+
return Boolean(result);
|
|
2293
|
+
};
|
|
2294
|
+
const sendReport = (node, composite, siblings) => {
|
|
2295
|
+
const atomicPropertiesSet = new Set(siblings.filter((property) => compositeProperties[composite].includes(getLonghand(property))));
|
|
2296
|
+
if (atomicPropertiesSet.size === 0) return;
|
|
2297
|
+
const atomicProperties = Array.from(atomicPropertiesSet).map((property) => `\`${property}\``).join(", ");
|
|
2298
|
+
const atomics = compositeProperties[composite].map((name) => `\`${name}\``).join(", ");
|
|
2299
|
+
context.report({
|
|
2300
|
+
data: {
|
|
2301
|
+
atomicProperties,
|
|
2302
|
+
atomics,
|
|
2303
|
+
composite
|
|
2304
|
+
},
|
|
2305
|
+
messageId: "unify",
|
|
2306
|
+
node
|
|
2307
|
+
});
|
|
2308
|
+
};
|
|
2309
|
+
return {
|
|
2310
|
+
JSXAttribute(node) {
|
|
2311
|
+
if (!isJSXIdentifier(node.name)) return;
|
|
2312
|
+
if (!isCachedBambooProperty(node)) return;
|
|
2313
|
+
const composite = resolveCompositeProperty(node.name.name);
|
|
2314
|
+
if (!composite) return;
|
|
2315
|
+
if (!isJSXOpeningElement(node.parent)) return;
|
|
2316
|
+
sendReport(node, composite, node.parent.attributes.map((attribute) => attribute.name.name));
|
|
2317
|
+
},
|
|
2318
|
+
Property(node) {
|
|
2319
|
+
if (!isIdentifier(node.key)) return;
|
|
2320
|
+
if (!isCachedBambooAttribute(node)) return;
|
|
2321
|
+
if (isCachedRecipeVariant(node)) return;
|
|
2322
|
+
const composite = resolveCompositeProperty(node.key.name);
|
|
2323
|
+
if (!composite) return;
|
|
2324
|
+
if (!isObjectExpression(node.parent)) return;
|
|
2325
|
+
const siblings = node.parent.properties.filter((property) => property.type === "Property").map((property) => isIdentifier(property.key) ? property.key.name : "");
|
|
2326
|
+
sendReport(node.key, composite, siblings);
|
|
2327
|
+
}
|
|
2328
|
+
};
|
|
2329
|
+
},
|
|
2330
|
+
defaultOptions: [],
|
|
2331
|
+
meta: {
|
|
2332
|
+
docs: { description: "Discourage mixing atomic and composite forms of the same property in a style declaration. Atomic styles give more consistent results." },
|
|
2333
|
+
messages: { unify: "You're mixing atomic {{atomicProperties}} with composite property `{{composite}}`. Prefer atomic styling to mixing atomic and composite properties. Remove `{{composite}}` and use one or more of {{atomics}} instead." },
|
|
2334
|
+
schema: [],
|
|
2335
|
+
type: "suggestion"
|
|
2336
|
+
},
|
|
2337
|
+
name: RULE_NAME
|
|
2338
|
+
});
|
|
2339
|
+
}));
|
|
2340
|
+
|
|
2341
|
+
//#endregion
|
|
2342
|
+
//#region src/rules/index.ts
|
|
2343
|
+
var rules;
|
|
2344
|
+
var init_rules = __esmMin((() => {
|
|
2345
|
+
init_file_not_included();
|
|
2346
|
+
init_no_config_function_in_source();
|
|
2347
|
+
init_no_debug();
|
|
2348
|
+
init_no_deprecated_tokens();
|
|
2349
|
+
init_no_dynamic_styling();
|
|
2350
|
+
init_no_escape_hatch();
|
|
2351
|
+
init_no_hardcoded_color();
|
|
2352
|
+
init_no_important();
|
|
2353
|
+
init_no_invalid_nesting();
|
|
2354
|
+
init_no_invalid_token_paths();
|
|
2355
|
+
init_no_margin_properties();
|
|
2356
|
+
init_no_physical_properties();
|
|
2357
|
+
init_no_property_renaming();
|
|
2358
|
+
init_no_unsafe_token_fn_usage();
|
|
2359
|
+
init_prefer_atomic_properties();
|
|
2360
|
+
init_prefer_composite_properties();
|
|
2361
|
+
init_prefer_longhand_properties();
|
|
2362
|
+
init_prefer_shorthand_properties();
|
|
2363
|
+
init_prefer_unified_property_style();
|
|
2364
|
+
rules = {
|
|
2365
|
+
[RULE_NAME$18]: rule$18,
|
|
2366
|
+
[RULE_NAME$17]: rule$17,
|
|
2367
|
+
[RULE_NAME$16]: rule$16,
|
|
2368
|
+
[RULE_NAME$15]: rule$15,
|
|
2369
|
+
[RULE_NAME$14]: rule$14,
|
|
2370
|
+
[RULE_NAME$13]: rule$13,
|
|
2371
|
+
[RULE_NAME$12]: rule$12,
|
|
2372
|
+
[RULE_NAME$11]: rule$11,
|
|
2373
|
+
[RULE_NAME$10]: rule$10,
|
|
2374
|
+
[RULE_NAME$9]: rule$9,
|
|
2375
|
+
[RULE_NAME$8]: rule$8,
|
|
2376
|
+
[RULE_NAME$7]: rule$7,
|
|
2377
|
+
[RULE_NAME$6]: rule$6,
|
|
2378
|
+
[RULE_NAME$5]: rule$5,
|
|
2379
|
+
[RULE_NAME$4]: rule$4,
|
|
2380
|
+
[RULE_NAME$3]: rule$3,
|
|
2381
|
+
[RULE_NAME$2]: rule$2,
|
|
2382
|
+
[RULE_NAME$1]: rule$1,
|
|
2383
|
+
[RULE_NAME]: rule
|
|
2384
|
+
};
|
|
2385
|
+
}));
|
|
2386
|
+
|
|
2387
|
+
//#endregion
|
|
2388
|
+
//#region src/configs/all.ts
|
|
2389
|
+
var errorRules, allRules, all_default;
|
|
2390
|
+
var init_all = __esmMin((() => {
|
|
2391
|
+
init_rules();
|
|
2392
|
+
init_file_not_included();
|
|
2393
|
+
init_no_config_function_in_source();
|
|
2394
|
+
init_no_invalid_token_paths();
|
|
2395
|
+
errorRules = [
|
|
2396
|
+
RULE_NAME$18,
|
|
2397
|
+
RULE_NAME$17,
|
|
2398
|
+
RULE_NAME$9
|
|
2399
|
+
];
|
|
2400
|
+
allRules = Object.fromEntries(Object.entries(rules).map(([name]) => {
|
|
2401
|
+
return [`@bamboocss/${name}`, errorRules.includes(name) ? "error" : "warn"];
|
|
2402
|
+
}));
|
|
2403
|
+
all_default = {
|
|
2404
|
+
parser: "@typescript-eslint/parser",
|
|
2405
|
+
parserOptions: { sourceType: "module" },
|
|
2406
|
+
plugins: ["@bamboocss"],
|
|
2407
|
+
rules: allRules
|
|
2408
|
+
};
|
|
2409
|
+
}));
|
|
2410
|
+
|
|
2411
|
+
//#endregion
|
|
2412
|
+
//#region src/configs/recommended.ts
|
|
2413
|
+
var recommended_default;
|
|
2414
|
+
var init_recommended = __esmMin((() => {
|
|
2415
|
+
recommended_default = {
|
|
2416
|
+
parser: "@typescript-eslint/parser",
|
|
2417
|
+
parserOptions: { sourceType: "module" },
|
|
2418
|
+
plugins: ["@bamboocss"],
|
|
2419
|
+
rules: {
|
|
2420
|
+
"@bamboocss/file-not-included": "error",
|
|
2421
|
+
"@bamboocss/no-config-function-in-source": "error",
|
|
2422
|
+
"@bamboocss/no-debug": "warn",
|
|
2423
|
+
"@bamboocss/no-deprecated-tokens": "warn",
|
|
2424
|
+
"@bamboocss/no-dynamic-styling": "warn",
|
|
2425
|
+
"@bamboocss/no-hardcoded-color": "warn",
|
|
2426
|
+
"@bamboocss/no-invalid-nesting": "error",
|
|
2427
|
+
"@bamboocss/no-invalid-token-paths": "error",
|
|
2428
|
+
"@bamboocss/no-property-renaming": "warn",
|
|
2429
|
+
"@bamboocss/no-unsafe-token-fn-usage": "warn"
|
|
2430
|
+
}
|
|
2431
|
+
};
|
|
2432
|
+
}));
|
|
2433
|
+
|
|
2434
|
+
//#endregion
|
|
2435
|
+
//#region src/index.ts
|
|
2436
|
+
var require_src = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2437
|
+
init_all();
|
|
2438
|
+
init_recommended();
|
|
2439
|
+
init_rules();
|
|
2440
|
+
const plugin = {
|
|
2441
|
+
configs: {
|
|
2442
|
+
all: all_default,
|
|
2443
|
+
recommended: recommended_default
|
|
2444
|
+
},
|
|
2445
|
+
meta: {
|
|
2446
|
+
name,
|
|
2447
|
+
version
|
|
2448
|
+
},
|
|
2449
|
+
rules
|
|
2450
|
+
};
|
|
2451
|
+
module.exports = plugin;
|
|
2452
|
+
}));
|
|
2453
|
+
|
|
2454
|
+
//#endregion
|
|
2455
|
+
export default require_src();
|
|
2456
|
+
|
|
2457
|
+
export { };
|
|
2458
|
+
//# sourceMappingURL=index.mjs.map
|