@bamboocss/eslint-plugin 1.16.1 → 1.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +113 -44
- package/dist/index.d.cts +3 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +113 -44
- package/package.json +8 -8
package/dist/index.cjs
CHANGED
|
@@ -8,7 +8,7 @@ require("@typescript-eslint/utils/ts-eslint");
|
|
|
8
8
|
let _bamboocss_shared = require("@bamboocss/shared");
|
|
9
9
|
//#region package.json
|
|
10
10
|
var name = "@bamboocss/eslint-plugin";
|
|
11
|
-
var version = "1.
|
|
11
|
+
var version = "1.17.1";
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region src/utils/index.ts
|
|
14
14
|
const createRule = _typescript_eslint_utils.ESLintUtils.RuleCreator((name) => `https://github.com/bamboocss/bamboo/blob/main/packages/eslint-plugin/docs/rules/${name}.md`);
|
|
@@ -307,8 +307,8 @@ function isRecipeVariant(node, context) {
|
|
|
307
307
|
}
|
|
308
308
|
//#endregion
|
|
309
309
|
//#region src/rules/file-not-included.ts
|
|
310
|
-
const RULE_NAME$
|
|
311
|
-
const rule$
|
|
310
|
+
const RULE_NAME$20 = "file-not-included";
|
|
311
|
+
const rule$20 = createRule({
|
|
312
312
|
create(context) {
|
|
313
313
|
if (isValidFile(context)) return {};
|
|
314
314
|
let hasReported = false;
|
|
@@ -329,11 +329,11 @@ const rule$19 = createRule({
|
|
|
329
329
|
schema: [],
|
|
330
330
|
type: "problem"
|
|
331
331
|
},
|
|
332
|
-
name: RULE_NAME$
|
|
332
|
+
name: RULE_NAME$20
|
|
333
333
|
});
|
|
334
334
|
//#endregion
|
|
335
335
|
//#region src/rules/no-config-function-in-source.ts
|
|
336
|
-
const RULE_NAME$
|
|
336
|
+
const RULE_NAME$19 = "no-config-function-in-source";
|
|
337
337
|
const CONFIG_FUNCTIONS = new Set([
|
|
338
338
|
"defineConfig",
|
|
339
339
|
"defineGlobalStyles",
|
|
@@ -350,7 +350,7 @@ const CONFIG_FUNCTIONS = new Set([
|
|
|
350
350
|
"defineTokens",
|
|
351
351
|
"defineUtility"
|
|
352
352
|
]);
|
|
353
|
-
const rule$
|
|
353
|
+
const rule$19 = createRule({
|
|
354
354
|
create(context) {
|
|
355
355
|
if (!hasPkgImport(context)) return {};
|
|
356
356
|
if (!isValidFile(context)) return {};
|
|
@@ -390,12 +390,12 @@ const rule$18 = createRule({
|
|
|
390
390
|
schema: [],
|
|
391
391
|
type: "problem"
|
|
392
392
|
},
|
|
393
|
-
name: RULE_NAME$
|
|
393
|
+
name: RULE_NAME$19
|
|
394
394
|
});
|
|
395
395
|
//#endregion
|
|
396
396
|
//#region src/rules/no-debug.ts
|
|
397
|
-
const RULE_NAME$
|
|
398
|
-
const rule$
|
|
397
|
+
const RULE_NAME$18 = "no-debug";
|
|
398
|
+
const rule$18 = createRule({
|
|
399
399
|
create(context) {
|
|
400
400
|
const processedNodes = /* @__PURE__ */ new WeakSet();
|
|
401
401
|
const checkObjectForDebug = (object) => {
|
|
@@ -464,12 +464,12 @@ const rule$17 = createRule({
|
|
|
464
464
|
schema: [],
|
|
465
465
|
type: "problem"
|
|
466
466
|
},
|
|
467
|
-
name: RULE_NAME$
|
|
467
|
+
name: RULE_NAME$18
|
|
468
468
|
});
|
|
469
469
|
//#endregion
|
|
470
470
|
//#region src/rules/no-deprecated-tokens.ts
|
|
471
|
-
const RULE_NAME$
|
|
472
|
-
const rule$
|
|
471
|
+
const RULE_NAME$17 = "no-deprecated-tokens";
|
|
472
|
+
const rule$17 = createRule({
|
|
473
473
|
create(context) {
|
|
474
474
|
const deprecatedTokensCache = /* @__PURE__ */ new Map();
|
|
475
475
|
const sendReport = (property, node, value) => {
|
|
@@ -523,12 +523,12 @@ const rule$16 = createRule({
|
|
|
523
523
|
schema: [],
|
|
524
524
|
type: "problem"
|
|
525
525
|
},
|
|
526
|
-
name: RULE_NAME$
|
|
526
|
+
name: RULE_NAME$17
|
|
527
527
|
});
|
|
528
528
|
//#endregion
|
|
529
529
|
//#region src/rules/no-dynamic-styling.ts
|
|
530
|
-
const RULE_NAME$
|
|
531
|
-
const rule$
|
|
530
|
+
const RULE_NAME$16 = "no-dynamic-styling";
|
|
531
|
+
const rule$16 = createRule({
|
|
532
532
|
create(context) {
|
|
533
533
|
function isStaticValue(node) {
|
|
534
534
|
if (!node) return false;
|
|
@@ -599,12 +599,12 @@ const rule$15 = createRule({
|
|
|
599
599
|
schema: [],
|
|
600
600
|
type: "problem"
|
|
601
601
|
},
|
|
602
|
-
name: RULE_NAME$
|
|
602
|
+
name: RULE_NAME$16
|
|
603
603
|
});
|
|
604
604
|
//#endregion
|
|
605
605
|
//#region src/rules/no-escape-hatch.ts
|
|
606
|
-
const RULE_NAME$
|
|
607
|
-
const rule$
|
|
606
|
+
const RULE_NAME$15 = "no-escape-hatch";
|
|
607
|
+
const rule$15 = createRule({
|
|
608
608
|
create(context) {
|
|
609
609
|
const removeBrackets = (range) => {
|
|
610
610
|
const [start, end] = range;
|
|
@@ -677,12 +677,12 @@ const rule$14 = createRule({
|
|
|
677
677
|
schema: [],
|
|
678
678
|
type: "problem"
|
|
679
679
|
},
|
|
680
|
-
name: RULE_NAME$
|
|
680
|
+
name: RULE_NAME$15
|
|
681
681
|
});
|
|
682
682
|
//#endregion
|
|
683
683
|
//#region src/rules/no-hardcoded-color.ts
|
|
684
|
-
const RULE_NAME$
|
|
685
|
-
const rule$
|
|
684
|
+
const RULE_NAME$14 = "no-hardcoded-color";
|
|
685
|
+
const rule$14 = createRule({
|
|
686
686
|
create(context) {
|
|
687
687
|
const noOpacity = context.options[0]?.noOpacity;
|
|
688
688
|
const whitelist = context.options[0]?.whitelist ?? [];
|
|
@@ -778,14 +778,14 @@ const rule$13 = createRule({
|
|
|
778
778
|
}],
|
|
779
779
|
type: "problem"
|
|
780
780
|
},
|
|
781
|
-
name: RULE_NAME$
|
|
781
|
+
name: RULE_NAME$14
|
|
782
782
|
});
|
|
783
783
|
//#endregion
|
|
784
784
|
//#region src/rules/no-important.ts
|
|
785
785
|
const exclamationRegex = /\s*!$/;
|
|
786
786
|
const importantRegex = /\s*!important\s*$/;
|
|
787
|
-
const RULE_NAME$
|
|
788
|
-
const rule$
|
|
787
|
+
const RULE_NAME$13 = "no-important";
|
|
788
|
+
const rule$13 = createRule({
|
|
789
789
|
create(context) {
|
|
790
790
|
const removeQuotes = (range) => {
|
|
791
791
|
const [start, end] = range;
|
|
@@ -889,12 +889,12 @@ const rule$12 = createRule({
|
|
|
889
889
|
schema: [],
|
|
890
890
|
type: "problem"
|
|
891
891
|
},
|
|
892
|
-
name: RULE_NAME$
|
|
892
|
+
name: RULE_NAME$13
|
|
893
893
|
});
|
|
894
894
|
//#endregion
|
|
895
895
|
//#region src/rules/no-invalid-nesting.ts
|
|
896
|
-
const RULE_NAME$
|
|
897
|
-
const rule$
|
|
896
|
+
const RULE_NAME$12 = "no-invalid-nesting";
|
|
897
|
+
const rule$12 = createRule({
|
|
898
898
|
create(context) {
|
|
899
899
|
const bambooFunctionCache = /* @__PURE__ */ new WeakMap();
|
|
900
900
|
const jsxPropertyCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -949,12 +949,12 @@ const rule$11 = createRule({
|
|
|
949
949
|
schema: [],
|
|
950
950
|
type: "problem"
|
|
951
951
|
},
|
|
952
|
-
name: RULE_NAME$
|
|
952
|
+
name: RULE_NAME$12
|
|
953
953
|
});
|
|
954
954
|
//#endregion
|
|
955
955
|
//#region src/rules/no-invalid-token-paths.ts
|
|
956
|
-
const RULE_NAME$
|
|
957
|
-
const rule$
|
|
956
|
+
const RULE_NAME$11 = "no-invalid-token-paths";
|
|
957
|
+
const rule$11 = createRule({
|
|
958
958
|
create(context) {
|
|
959
959
|
const invalidTokensCache = /* @__PURE__ */ new Map();
|
|
960
960
|
const sendReport = (node, value) => {
|
|
@@ -1031,12 +1031,12 @@ const rule$10 = createRule({
|
|
|
1031
1031
|
schema: [],
|
|
1032
1032
|
type: "problem"
|
|
1033
1033
|
},
|
|
1034
|
-
name: RULE_NAME$
|
|
1034
|
+
name: RULE_NAME$11
|
|
1035
1035
|
});
|
|
1036
1036
|
//#endregion
|
|
1037
1037
|
//#region src/rules/no-margin-properties.ts
|
|
1038
|
-
const RULE_NAME$
|
|
1039
|
-
const rule$
|
|
1038
|
+
const RULE_NAME$10 = "no-margin-properties";
|
|
1039
|
+
const rule$10 = createRule({
|
|
1040
1040
|
create(context) {
|
|
1041
1041
|
const whitelist = context.options[0]?.whitelist ?? [];
|
|
1042
1042
|
const longhandCache = /* @__PURE__ */ new Map();
|
|
@@ -1112,7 +1112,7 @@ const rule$9 = createRule({
|
|
|
1112
1112
|
}],
|
|
1113
1113
|
type: "suggestion"
|
|
1114
1114
|
},
|
|
1115
|
-
name: RULE_NAME$
|
|
1115
|
+
name: RULE_NAME$10
|
|
1116
1116
|
});
|
|
1117
1117
|
//#endregion
|
|
1118
1118
|
//#region src/utils/physical-properties.ts
|
|
@@ -1156,7 +1156,7 @@ const physicalPropertyValues = { textAlign: {
|
|
|
1156
1156
|
} };
|
|
1157
1157
|
//#endregion
|
|
1158
1158
|
//#region src/rules/no-physical-properties.ts
|
|
1159
|
-
const RULE_NAME$
|
|
1159
|
+
const RULE_NAME$9 = "no-physical-properties";
|
|
1160
1160
|
const MESSAGES = {
|
|
1161
1161
|
physical: "Use logical property instead of {{physical}}. Prefer `{{logical}}`.",
|
|
1162
1162
|
physicalValue: "Use logical value instead of {{physical}}. Prefer `{{logical}}`.",
|
|
@@ -1238,7 +1238,7 @@ const createValueReport = (valueNode, valueText, logical, context) => {
|
|
|
1238
1238
|
}]
|
|
1239
1239
|
});
|
|
1240
1240
|
};
|
|
1241
|
-
const rule$
|
|
1241
|
+
const rule$9 = createRule({
|
|
1242
1242
|
create(context) {
|
|
1243
1243
|
const whitelist = context.options[0]?.whitelist ?? [];
|
|
1244
1244
|
const cache = new PropertyCache();
|
|
@@ -1294,12 +1294,12 @@ const rule$8 = createRule({
|
|
|
1294
1294
|
}],
|
|
1295
1295
|
type: "suggestion"
|
|
1296
1296
|
},
|
|
1297
|
-
name: RULE_NAME$
|
|
1297
|
+
name: RULE_NAME$9
|
|
1298
1298
|
});
|
|
1299
1299
|
//#endregion
|
|
1300
1300
|
//#region src/rules/no-property-renaming.ts
|
|
1301
|
-
const RULE_NAME$
|
|
1302
|
-
const rule$
|
|
1301
|
+
const RULE_NAME$8 = "no-property-renaming";
|
|
1302
|
+
const rule$8 = createRule({
|
|
1303
1303
|
create(context) {
|
|
1304
1304
|
const bambooPropertyCache = /* @__PURE__ */ new WeakMap();
|
|
1305
1305
|
const bambooAttributeCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -1363,11 +1363,11 @@ const rule$7 = createRule({
|
|
|
1363
1363
|
schema: [],
|
|
1364
1364
|
type: "problem"
|
|
1365
1365
|
},
|
|
1366
|
-
name: RULE_NAME$
|
|
1366
|
+
name: RULE_NAME$8
|
|
1367
1367
|
});
|
|
1368
1368
|
//#endregion
|
|
1369
1369
|
//#region src/rules/no-unlayered-override.ts
|
|
1370
|
-
const RULE_NAME$
|
|
1370
|
+
const RULE_NAME$7 = "no-unlayered-override";
|
|
1371
1371
|
/**
|
|
1372
1372
|
* The call whose result is a class string in the `utilities` layer — the same layer a
|
|
1373
1373
|
* consumer's `css()` is in, so neither can win over the other by cascade.
|
|
@@ -1392,7 +1392,7 @@ const isOpaque = (node) => {
|
|
|
1392
1392
|
if (isIdentifier(node) && node.name !== "undefined") return true;
|
|
1393
1393
|
return false;
|
|
1394
1394
|
};
|
|
1395
|
-
const rule$
|
|
1395
|
+
const rule$7 = createRule({
|
|
1396
1396
|
create(context) {
|
|
1397
1397
|
if (!isValidFile(context)) return {};
|
|
1398
1398
|
const isOwnStyles = (node) => {
|
|
@@ -1422,6 +1422,73 @@ const rule$6 = createRule({
|
|
|
1422
1422
|
schema: [],
|
|
1423
1423
|
type: "problem"
|
|
1424
1424
|
},
|
|
1425
|
+
name: RULE_NAME$7
|
|
1426
|
+
});
|
|
1427
|
+
//#endregion
|
|
1428
|
+
//#region src/rules/require-recipe-class-name.ts
|
|
1429
|
+
const RULE_NAME$6 = "require-recipe-class-name";
|
|
1430
|
+
const RECIPE_CALLS = new Set(["cva", "sva"]);
|
|
1431
|
+
/**
|
|
1432
|
+
* A property whose value the build reads as written, so the config it hashes is the config
|
|
1433
|
+
* the browser holds.
|
|
1434
|
+
*
|
|
1435
|
+
* Deliberately narrow. A spread, a computed key, a call — anything the extractor might not
|
|
1436
|
+
* resolve — makes the config's *content* uncertain, and the content is what the name is
|
|
1437
|
+
* derived from.
|
|
1438
|
+
*/
|
|
1439
|
+
const isStatic = (node) => {
|
|
1440
|
+
switch (node.type) {
|
|
1441
|
+
case "Literal": return true;
|
|
1442
|
+
case "TemplateLiteral": return node.expressions.length === 0;
|
|
1443
|
+
case "TSAsExpression":
|
|
1444
|
+
case "TSSatisfiesExpression":
|
|
1445
|
+
case "TSNonNullExpression": return isStatic(node.expression);
|
|
1446
|
+
case "ArrayExpression": return node.elements.every((element) => element !== null && isStatic(element));
|
|
1447
|
+
case "ObjectExpression": return node.properties.every((property) => {
|
|
1448
|
+
if (property.type !== "Property" || property.computed) return false;
|
|
1449
|
+
return isStatic(property.value);
|
|
1450
|
+
});
|
|
1451
|
+
default: return false;
|
|
1452
|
+
}
|
|
1453
|
+
};
|
|
1454
|
+
const rule$6 = createRule({
|
|
1455
|
+
create(context) {
|
|
1456
|
+
if (!isValidFile(context)) return {};
|
|
1457
|
+
const mode = context.options[0]?.mode ?? "always";
|
|
1458
|
+
return { CallExpression(node) {
|
|
1459
|
+
if (!isIdentifier(node.callee) || !RECIPE_CALLS.has(node.callee.name)) return;
|
|
1460
|
+
const config = node.arguments[0];
|
|
1461
|
+
if (!config) return;
|
|
1462
|
+
const unwrapped = config.type === "TSAsExpression" || config.type === "TSSatisfiesExpression" ? config.expression : config;
|
|
1463
|
+
if (unwrapped.type === "ObjectExpression") {
|
|
1464
|
+
if (unwrapped.properties.some((property) => property.type === "Property" && !property.computed && (property.key.type === "Identifier" && property.key.name === "className" || property.key.type === "Literal" && property.key.value === "className") && property.value.type === "Literal" && typeof property.value.value === "string" && property.value.value !== "")) return;
|
|
1465
|
+
if (mode === "dynamic-only" && isStatic(unwrapped)) return;
|
|
1466
|
+
}
|
|
1467
|
+
context.report({
|
|
1468
|
+
messageId: "requireRecipeClassName",
|
|
1469
|
+
node: node.callee
|
|
1470
|
+
});
|
|
1471
|
+
} };
|
|
1472
|
+
},
|
|
1473
|
+
defaultOptions: [{ mode: "always" }],
|
|
1474
|
+
meta: {
|
|
1475
|
+
docs: { description: "Require a `className` on a recipe, so its class names do not depend on what the build could read." },
|
|
1476
|
+
messages: { requireRecipeClassName: [
|
|
1477
|
+
"This recipe has no `className`, so its classes are named by hashing its config.",
|
|
1478
|
+
"The build hashes the config it could read and the browser hashes the one it holds, so anything the build cannot resolve — a spread of a call, a value it cannot evaluate — gives the two different names and the element renders with no styles at all.",
|
|
1479
|
+
"Add `className: 'name'` to fix the name, and get readable classes with it."
|
|
1480
|
+
].join(" ") },
|
|
1481
|
+
schema: [{
|
|
1482
|
+
additionalProperties: false,
|
|
1483
|
+
properties: { mode: {
|
|
1484
|
+
description: "`always` requires a name on every recipe. `dynamic-only` requires one only where the config is not a plain static literal, which is where the failure is possible.",
|
|
1485
|
+
enum: ["always", "dynamic-only"],
|
|
1486
|
+
type: "string"
|
|
1487
|
+
} },
|
|
1488
|
+
type: "object"
|
|
1489
|
+
}],
|
|
1490
|
+
type: "problem"
|
|
1491
|
+
},
|
|
1425
1492
|
name: RULE_NAME$6
|
|
1426
1493
|
});
|
|
1427
1494
|
//#endregion
|
|
@@ -2272,6 +2339,7 @@ const rule = createRule({
|
|
|
2272
2339
|
//#endregion
|
|
2273
2340
|
//#region src/rules/index.ts
|
|
2274
2341
|
const rules = {
|
|
2342
|
+
[RULE_NAME$20]: rule$20,
|
|
2275
2343
|
[RULE_NAME$19]: rule$19,
|
|
2276
2344
|
[RULE_NAME$18]: rule$18,
|
|
2277
2345
|
[RULE_NAME$17]: rule$17,
|
|
@@ -2296,9 +2364,9 @@ const rules = {
|
|
|
2296
2364
|
//#endregion
|
|
2297
2365
|
//#region src/configs/all.ts
|
|
2298
2366
|
const errorRules = [
|
|
2367
|
+
RULE_NAME$20,
|
|
2299
2368
|
RULE_NAME$19,
|
|
2300
|
-
RULE_NAME$
|
|
2301
|
-
RULE_NAME$10
|
|
2369
|
+
RULE_NAME$11
|
|
2302
2370
|
];
|
|
2303
2371
|
//#endregion
|
|
2304
2372
|
//#region src/index.ts
|
|
@@ -2327,6 +2395,7 @@ const plugin = {
|
|
|
2327
2395
|
"bamboo/no-invalid-token-paths": "error",
|
|
2328
2396
|
"bamboo/no-property-renaming": "warn",
|
|
2329
2397
|
"bamboo/no-unlayered-override": "warn",
|
|
2398
|
+
"bamboo/require-recipe-class-name": ["warn", { mode: "dynamic-only" }],
|
|
2330
2399
|
"bamboo/no-unsafe-token-fn-usage": "warn"
|
|
2331
2400
|
}
|
|
2332
2401
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -28,6 +28,9 @@ declare const plugin: {
|
|
|
28
28
|
'bamboo/no-invalid-token-paths': string;
|
|
29
29
|
'bamboo/no-property-renaming': string;
|
|
30
30
|
'bamboo/no-unlayered-override': string;
|
|
31
|
+
'bamboo/require-recipe-class-name': (string | {
|
|
32
|
+
mode: string;
|
|
33
|
+
})[];
|
|
31
34
|
'bamboo/no-unsafe-token-fn-usage': string;
|
|
32
35
|
};
|
|
33
36
|
};
|
package/dist/index.d.mts
CHANGED
|
@@ -28,6 +28,9 @@ declare const plugin: {
|
|
|
28
28
|
'bamboo/no-invalid-token-paths': string;
|
|
29
29
|
'bamboo/no-property-renaming': string;
|
|
30
30
|
'bamboo/no-unlayered-override': string;
|
|
31
|
+
'bamboo/require-recipe-class-name': (string | {
|
|
32
|
+
mode: string;
|
|
33
|
+
})[];
|
|
31
34
|
'bamboo/no-unsafe-token-fn-usage': string;
|
|
32
35
|
};
|
|
33
36
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import "@typescript-eslint/utils/ts-eslint";
|
|
|
8
8
|
import { getArbitraryValue, parseFallbackValue } from "@bamboocss/shared";
|
|
9
9
|
//#region package.json
|
|
10
10
|
var name = "@bamboocss/eslint-plugin";
|
|
11
|
-
var version = "1.
|
|
11
|
+
var version = "1.17.1";
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region src/utils/index.ts
|
|
14
14
|
const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/bamboocss/bamboo/blob/main/packages/eslint-plugin/docs/rules/${name}.md`);
|
|
@@ -307,8 +307,8 @@ function isRecipeVariant(node, context) {
|
|
|
307
307
|
}
|
|
308
308
|
//#endregion
|
|
309
309
|
//#region src/rules/file-not-included.ts
|
|
310
|
-
const RULE_NAME$
|
|
311
|
-
const rule$
|
|
310
|
+
const RULE_NAME$20 = "file-not-included";
|
|
311
|
+
const rule$20 = createRule({
|
|
312
312
|
create(context) {
|
|
313
313
|
if (isValidFile(context)) return {};
|
|
314
314
|
let hasReported = false;
|
|
@@ -329,11 +329,11 @@ const rule$19 = createRule({
|
|
|
329
329
|
schema: [],
|
|
330
330
|
type: "problem"
|
|
331
331
|
},
|
|
332
|
-
name: RULE_NAME$
|
|
332
|
+
name: RULE_NAME$20
|
|
333
333
|
});
|
|
334
334
|
//#endregion
|
|
335
335
|
//#region src/rules/no-config-function-in-source.ts
|
|
336
|
-
const RULE_NAME$
|
|
336
|
+
const RULE_NAME$19 = "no-config-function-in-source";
|
|
337
337
|
const CONFIG_FUNCTIONS = new Set([
|
|
338
338
|
"defineConfig",
|
|
339
339
|
"defineGlobalStyles",
|
|
@@ -350,7 +350,7 @@ const CONFIG_FUNCTIONS = new Set([
|
|
|
350
350
|
"defineTokens",
|
|
351
351
|
"defineUtility"
|
|
352
352
|
]);
|
|
353
|
-
const rule$
|
|
353
|
+
const rule$19 = createRule({
|
|
354
354
|
create(context) {
|
|
355
355
|
if (!hasPkgImport(context)) return {};
|
|
356
356
|
if (!isValidFile(context)) return {};
|
|
@@ -390,12 +390,12 @@ const rule$18 = createRule({
|
|
|
390
390
|
schema: [],
|
|
391
391
|
type: "problem"
|
|
392
392
|
},
|
|
393
|
-
name: RULE_NAME$
|
|
393
|
+
name: RULE_NAME$19
|
|
394
394
|
});
|
|
395
395
|
//#endregion
|
|
396
396
|
//#region src/rules/no-debug.ts
|
|
397
|
-
const RULE_NAME$
|
|
398
|
-
const rule$
|
|
397
|
+
const RULE_NAME$18 = "no-debug";
|
|
398
|
+
const rule$18 = createRule({
|
|
399
399
|
create(context) {
|
|
400
400
|
const processedNodes = /* @__PURE__ */ new WeakSet();
|
|
401
401
|
const checkObjectForDebug = (object) => {
|
|
@@ -464,12 +464,12 @@ const rule$17 = createRule({
|
|
|
464
464
|
schema: [],
|
|
465
465
|
type: "problem"
|
|
466
466
|
},
|
|
467
|
-
name: RULE_NAME$
|
|
467
|
+
name: RULE_NAME$18
|
|
468
468
|
});
|
|
469
469
|
//#endregion
|
|
470
470
|
//#region src/rules/no-deprecated-tokens.ts
|
|
471
|
-
const RULE_NAME$
|
|
472
|
-
const rule$
|
|
471
|
+
const RULE_NAME$17 = "no-deprecated-tokens";
|
|
472
|
+
const rule$17 = createRule({
|
|
473
473
|
create(context) {
|
|
474
474
|
const deprecatedTokensCache = /* @__PURE__ */ new Map();
|
|
475
475
|
const sendReport = (property, node, value) => {
|
|
@@ -523,12 +523,12 @@ const rule$16 = createRule({
|
|
|
523
523
|
schema: [],
|
|
524
524
|
type: "problem"
|
|
525
525
|
},
|
|
526
|
-
name: RULE_NAME$
|
|
526
|
+
name: RULE_NAME$17
|
|
527
527
|
});
|
|
528
528
|
//#endregion
|
|
529
529
|
//#region src/rules/no-dynamic-styling.ts
|
|
530
|
-
const RULE_NAME$
|
|
531
|
-
const rule$
|
|
530
|
+
const RULE_NAME$16 = "no-dynamic-styling";
|
|
531
|
+
const rule$16 = createRule({
|
|
532
532
|
create(context) {
|
|
533
533
|
function isStaticValue(node) {
|
|
534
534
|
if (!node) return false;
|
|
@@ -599,12 +599,12 @@ const rule$15 = createRule({
|
|
|
599
599
|
schema: [],
|
|
600
600
|
type: "problem"
|
|
601
601
|
},
|
|
602
|
-
name: RULE_NAME$
|
|
602
|
+
name: RULE_NAME$16
|
|
603
603
|
});
|
|
604
604
|
//#endregion
|
|
605
605
|
//#region src/rules/no-escape-hatch.ts
|
|
606
|
-
const RULE_NAME$
|
|
607
|
-
const rule$
|
|
606
|
+
const RULE_NAME$15 = "no-escape-hatch";
|
|
607
|
+
const rule$15 = createRule({
|
|
608
608
|
create(context) {
|
|
609
609
|
const removeBrackets = (range) => {
|
|
610
610
|
const [start, end] = range;
|
|
@@ -677,12 +677,12 @@ const rule$14 = createRule({
|
|
|
677
677
|
schema: [],
|
|
678
678
|
type: "problem"
|
|
679
679
|
},
|
|
680
|
-
name: RULE_NAME$
|
|
680
|
+
name: RULE_NAME$15
|
|
681
681
|
});
|
|
682
682
|
//#endregion
|
|
683
683
|
//#region src/rules/no-hardcoded-color.ts
|
|
684
|
-
const RULE_NAME$
|
|
685
|
-
const rule$
|
|
684
|
+
const RULE_NAME$14 = "no-hardcoded-color";
|
|
685
|
+
const rule$14 = createRule({
|
|
686
686
|
create(context) {
|
|
687
687
|
const noOpacity = context.options[0]?.noOpacity;
|
|
688
688
|
const whitelist = context.options[0]?.whitelist ?? [];
|
|
@@ -778,14 +778,14 @@ const rule$13 = createRule({
|
|
|
778
778
|
}],
|
|
779
779
|
type: "problem"
|
|
780
780
|
},
|
|
781
|
-
name: RULE_NAME$
|
|
781
|
+
name: RULE_NAME$14
|
|
782
782
|
});
|
|
783
783
|
//#endregion
|
|
784
784
|
//#region src/rules/no-important.ts
|
|
785
785
|
const exclamationRegex = /\s*!$/;
|
|
786
786
|
const importantRegex = /\s*!important\s*$/;
|
|
787
|
-
const RULE_NAME$
|
|
788
|
-
const rule$
|
|
787
|
+
const RULE_NAME$13 = "no-important";
|
|
788
|
+
const rule$13 = createRule({
|
|
789
789
|
create(context) {
|
|
790
790
|
const removeQuotes = (range) => {
|
|
791
791
|
const [start, end] = range;
|
|
@@ -889,12 +889,12 @@ const rule$12 = createRule({
|
|
|
889
889
|
schema: [],
|
|
890
890
|
type: "problem"
|
|
891
891
|
},
|
|
892
|
-
name: RULE_NAME$
|
|
892
|
+
name: RULE_NAME$13
|
|
893
893
|
});
|
|
894
894
|
//#endregion
|
|
895
895
|
//#region src/rules/no-invalid-nesting.ts
|
|
896
|
-
const RULE_NAME$
|
|
897
|
-
const rule$
|
|
896
|
+
const RULE_NAME$12 = "no-invalid-nesting";
|
|
897
|
+
const rule$12 = createRule({
|
|
898
898
|
create(context) {
|
|
899
899
|
const bambooFunctionCache = /* @__PURE__ */ new WeakMap();
|
|
900
900
|
const jsxPropertyCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -949,12 +949,12 @@ const rule$11 = createRule({
|
|
|
949
949
|
schema: [],
|
|
950
950
|
type: "problem"
|
|
951
951
|
},
|
|
952
|
-
name: RULE_NAME$
|
|
952
|
+
name: RULE_NAME$12
|
|
953
953
|
});
|
|
954
954
|
//#endregion
|
|
955
955
|
//#region src/rules/no-invalid-token-paths.ts
|
|
956
|
-
const RULE_NAME$
|
|
957
|
-
const rule$
|
|
956
|
+
const RULE_NAME$11 = "no-invalid-token-paths";
|
|
957
|
+
const rule$11 = createRule({
|
|
958
958
|
create(context) {
|
|
959
959
|
const invalidTokensCache = /* @__PURE__ */ new Map();
|
|
960
960
|
const sendReport = (node, value) => {
|
|
@@ -1031,12 +1031,12 @@ const rule$10 = createRule({
|
|
|
1031
1031
|
schema: [],
|
|
1032
1032
|
type: "problem"
|
|
1033
1033
|
},
|
|
1034
|
-
name: RULE_NAME$
|
|
1034
|
+
name: RULE_NAME$11
|
|
1035
1035
|
});
|
|
1036
1036
|
//#endregion
|
|
1037
1037
|
//#region src/rules/no-margin-properties.ts
|
|
1038
|
-
const RULE_NAME$
|
|
1039
|
-
const rule$
|
|
1038
|
+
const RULE_NAME$10 = "no-margin-properties";
|
|
1039
|
+
const rule$10 = createRule({
|
|
1040
1040
|
create(context) {
|
|
1041
1041
|
const whitelist = context.options[0]?.whitelist ?? [];
|
|
1042
1042
|
const longhandCache = /* @__PURE__ */ new Map();
|
|
@@ -1112,7 +1112,7 @@ const rule$9 = createRule({
|
|
|
1112
1112
|
}],
|
|
1113
1113
|
type: "suggestion"
|
|
1114
1114
|
},
|
|
1115
|
-
name: RULE_NAME$
|
|
1115
|
+
name: RULE_NAME$10
|
|
1116
1116
|
});
|
|
1117
1117
|
//#endregion
|
|
1118
1118
|
//#region src/utils/physical-properties.ts
|
|
@@ -1156,7 +1156,7 @@ const physicalPropertyValues = { textAlign: {
|
|
|
1156
1156
|
} };
|
|
1157
1157
|
//#endregion
|
|
1158
1158
|
//#region src/rules/no-physical-properties.ts
|
|
1159
|
-
const RULE_NAME$
|
|
1159
|
+
const RULE_NAME$9 = "no-physical-properties";
|
|
1160
1160
|
const MESSAGES = {
|
|
1161
1161
|
physical: "Use logical property instead of {{physical}}. Prefer `{{logical}}`.",
|
|
1162
1162
|
physicalValue: "Use logical value instead of {{physical}}. Prefer `{{logical}}`.",
|
|
@@ -1238,7 +1238,7 @@ const createValueReport = (valueNode, valueText, logical, context) => {
|
|
|
1238
1238
|
}]
|
|
1239
1239
|
});
|
|
1240
1240
|
};
|
|
1241
|
-
const rule$
|
|
1241
|
+
const rule$9 = createRule({
|
|
1242
1242
|
create(context) {
|
|
1243
1243
|
const whitelist = context.options[0]?.whitelist ?? [];
|
|
1244
1244
|
const cache = new PropertyCache();
|
|
@@ -1294,12 +1294,12 @@ const rule$8 = createRule({
|
|
|
1294
1294
|
}],
|
|
1295
1295
|
type: "suggestion"
|
|
1296
1296
|
},
|
|
1297
|
-
name: RULE_NAME$
|
|
1297
|
+
name: RULE_NAME$9
|
|
1298
1298
|
});
|
|
1299
1299
|
//#endregion
|
|
1300
1300
|
//#region src/rules/no-property-renaming.ts
|
|
1301
|
-
const RULE_NAME$
|
|
1302
|
-
const rule$
|
|
1301
|
+
const RULE_NAME$8 = "no-property-renaming";
|
|
1302
|
+
const rule$8 = createRule({
|
|
1303
1303
|
create(context) {
|
|
1304
1304
|
const bambooPropertyCache = /* @__PURE__ */ new WeakMap();
|
|
1305
1305
|
const bambooAttributeCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -1363,11 +1363,11 @@ const rule$7 = createRule({
|
|
|
1363
1363
|
schema: [],
|
|
1364
1364
|
type: "problem"
|
|
1365
1365
|
},
|
|
1366
|
-
name: RULE_NAME$
|
|
1366
|
+
name: RULE_NAME$8
|
|
1367
1367
|
});
|
|
1368
1368
|
//#endregion
|
|
1369
1369
|
//#region src/rules/no-unlayered-override.ts
|
|
1370
|
-
const RULE_NAME$
|
|
1370
|
+
const RULE_NAME$7 = "no-unlayered-override";
|
|
1371
1371
|
/**
|
|
1372
1372
|
* The call whose result is a class string in the `utilities` layer — the same layer a
|
|
1373
1373
|
* consumer's `css()` is in, so neither can win over the other by cascade.
|
|
@@ -1392,7 +1392,7 @@ const isOpaque = (node) => {
|
|
|
1392
1392
|
if (isIdentifier(node) && node.name !== "undefined") return true;
|
|
1393
1393
|
return false;
|
|
1394
1394
|
};
|
|
1395
|
-
const rule$
|
|
1395
|
+
const rule$7 = createRule({
|
|
1396
1396
|
create(context) {
|
|
1397
1397
|
if (!isValidFile(context)) return {};
|
|
1398
1398
|
const isOwnStyles = (node) => {
|
|
@@ -1422,6 +1422,73 @@ const rule$6 = createRule({
|
|
|
1422
1422
|
schema: [],
|
|
1423
1423
|
type: "problem"
|
|
1424
1424
|
},
|
|
1425
|
+
name: RULE_NAME$7
|
|
1426
|
+
});
|
|
1427
|
+
//#endregion
|
|
1428
|
+
//#region src/rules/require-recipe-class-name.ts
|
|
1429
|
+
const RULE_NAME$6 = "require-recipe-class-name";
|
|
1430
|
+
const RECIPE_CALLS = new Set(["cva", "sva"]);
|
|
1431
|
+
/**
|
|
1432
|
+
* A property whose value the build reads as written, so the config it hashes is the config
|
|
1433
|
+
* the browser holds.
|
|
1434
|
+
*
|
|
1435
|
+
* Deliberately narrow. A spread, a computed key, a call — anything the extractor might not
|
|
1436
|
+
* resolve — makes the config's *content* uncertain, and the content is what the name is
|
|
1437
|
+
* derived from.
|
|
1438
|
+
*/
|
|
1439
|
+
const isStatic = (node) => {
|
|
1440
|
+
switch (node.type) {
|
|
1441
|
+
case "Literal": return true;
|
|
1442
|
+
case "TemplateLiteral": return node.expressions.length === 0;
|
|
1443
|
+
case "TSAsExpression":
|
|
1444
|
+
case "TSSatisfiesExpression":
|
|
1445
|
+
case "TSNonNullExpression": return isStatic(node.expression);
|
|
1446
|
+
case "ArrayExpression": return node.elements.every((element) => element !== null && isStatic(element));
|
|
1447
|
+
case "ObjectExpression": return node.properties.every((property) => {
|
|
1448
|
+
if (property.type !== "Property" || property.computed) return false;
|
|
1449
|
+
return isStatic(property.value);
|
|
1450
|
+
});
|
|
1451
|
+
default: return false;
|
|
1452
|
+
}
|
|
1453
|
+
};
|
|
1454
|
+
const rule$6 = createRule({
|
|
1455
|
+
create(context) {
|
|
1456
|
+
if (!isValidFile(context)) return {};
|
|
1457
|
+
const mode = context.options[0]?.mode ?? "always";
|
|
1458
|
+
return { CallExpression(node) {
|
|
1459
|
+
if (!isIdentifier(node.callee) || !RECIPE_CALLS.has(node.callee.name)) return;
|
|
1460
|
+
const config = node.arguments[0];
|
|
1461
|
+
if (!config) return;
|
|
1462
|
+
const unwrapped = config.type === "TSAsExpression" || config.type === "TSSatisfiesExpression" ? config.expression : config;
|
|
1463
|
+
if (unwrapped.type === "ObjectExpression") {
|
|
1464
|
+
if (unwrapped.properties.some((property) => property.type === "Property" && !property.computed && (property.key.type === "Identifier" && property.key.name === "className" || property.key.type === "Literal" && property.key.value === "className") && property.value.type === "Literal" && typeof property.value.value === "string" && property.value.value !== "")) return;
|
|
1465
|
+
if (mode === "dynamic-only" && isStatic(unwrapped)) return;
|
|
1466
|
+
}
|
|
1467
|
+
context.report({
|
|
1468
|
+
messageId: "requireRecipeClassName",
|
|
1469
|
+
node: node.callee
|
|
1470
|
+
});
|
|
1471
|
+
} };
|
|
1472
|
+
},
|
|
1473
|
+
defaultOptions: [{ mode: "always" }],
|
|
1474
|
+
meta: {
|
|
1475
|
+
docs: { description: "Require a `className` on a recipe, so its class names do not depend on what the build could read." },
|
|
1476
|
+
messages: { requireRecipeClassName: [
|
|
1477
|
+
"This recipe has no `className`, so its classes are named by hashing its config.",
|
|
1478
|
+
"The build hashes the config it could read and the browser hashes the one it holds, so anything the build cannot resolve — a spread of a call, a value it cannot evaluate — gives the two different names and the element renders with no styles at all.",
|
|
1479
|
+
"Add `className: 'name'` to fix the name, and get readable classes with it."
|
|
1480
|
+
].join(" ") },
|
|
1481
|
+
schema: [{
|
|
1482
|
+
additionalProperties: false,
|
|
1483
|
+
properties: { mode: {
|
|
1484
|
+
description: "`always` requires a name on every recipe. `dynamic-only` requires one only where the config is not a plain static literal, which is where the failure is possible.",
|
|
1485
|
+
enum: ["always", "dynamic-only"],
|
|
1486
|
+
type: "string"
|
|
1487
|
+
} },
|
|
1488
|
+
type: "object"
|
|
1489
|
+
}],
|
|
1490
|
+
type: "problem"
|
|
1491
|
+
},
|
|
1425
1492
|
name: RULE_NAME$6
|
|
1426
1493
|
});
|
|
1427
1494
|
//#endregion
|
|
@@ -2272,6 +2339,7 @@ const rule = createRule({
|
|
|
2272
2339
|
//#endregion
|
|
2273
2340
|
//#region src/rules/index.ts
|
|
2274
2341
|
const rules = {
|
|
2342
|
+
[RULE_NAME$20]: rule$20,
|
|
2275
2343
|
[RULE_NAME$19]: rule$19,
|
|
2276
2344
|
[RULE_NAME$18]: rule$18,
|
|
2277
2345
|
[RULE_NAME$17]: rule$17,
|
|
@@ -2296,9 +2364,9 @@ const rules = {
|
|
|
2296
2364
|
//#endregion
|
|
2297
2365
|
//#region src/configs/all.ts
|
|
2298
2366
|
const errorRules = [
|
|
2367
|
+
RULE_NAME$20,
|
|
2299
2368
|
RULE_NAME$19,
|
|
2300
|
-
RULE_NAME$
|
|
2301
|
-
RULE_NAME$10
|
|
2369
|
+
RULE_NAME$11
|
|
2302
2370
|
];
|
|
2303
2371
|
//#endregion
|
|
2304
2372
|
//#region src/index.ts
|
|
@@ -2327,6 +2395,7 @@ const plugin = {
|
|
|
2327
2395
|
"bamboo/no-invalid-token-paths": "error",
|
|
2328
2396
|
"bamboo/no-property-renaming": "warn",
|
|
2329
2397
|
"bamboo/no-unlayered-override": "warn",
|
|
2398
|
+
"bamboo/require-recipe-class-name": ["warn", { mode: "dynamic-only" }],
|
|
2330
2399
|
"bamboo/no-unsafe-token-fn-usage": "warn"
|
|
2331
2400
|
}
|
|
2332
2401
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bamboocss/eslint-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.1",
|
|
4
4
|
"description": "ESLint plugin for Bamboo CSS",
|
|
5
5
|
"homepage": "https://bamboocss.com",
|
|
6
6
|
"license": "MIT",
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
"@typescript-eslint/utils": "^8.21.0",
|
|
37
37
|
"micromatch": "^4.0.8",
|
|
38
38
|
"synckit": "^0.9.0",
|
|
39
|
-
"@bamboocss/config": "1.
|
|
40
|
-
"@bamboocss/generator": "1.
|
|
41
|
-
"@bamboocss/shared": "1.
|
|
39
|
+
"@bamboocss/config": "1.17.1",
|
|
40
|
+
"@bamboocss/generator": "1.17.1",
|
|
41
|
+
"@bamboocss/shared": "1.17.1"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/micromatch": "^4.0.10",
|
|
@@ -46,10 +46,10 @@
|
|
|
46
46
|
"eslint": "^9.35.0",
|
|
47
47
|
"multiline-ts": "^4.0.1",
|
|
48
48
|
"typescript": "^5.7.2",
|
|
49
|
-
"@bamboocss/dev": "1.
|
|
50
|
-
"@bamboocss/preset-bamboo": "1.
|
|
51
|
-
"@bamboocss/preset-base": "1.
|
|
52
|
-
"@bamboocss/types": "1.
|
|
49
|
+
"@bamboocss/dev": "1.17.1",
|
|
50
|
+
"@bamboocss/preset-bamboo": "1.17.1",
|
|
51
|
+
"@bamboocss/preset-base": "1.17.1",
|
|
52
|
+
"@bamboocss/types": "1.17.1"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"eslint": "*"
|