@bamboocss/eslint-plugin 1.28.1 → 1.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +200 -44
- package/dist/index.mjs +200 -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.30.0";
|
|
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$21 = "file-not-included";
|
|
311
|
+
const rule$21 = createRule({
|
|
312
312
|
create(context) {
|
|
313
313
|
if (isValidFile(context)) return {};
|
|
314
314
|
let hasReported = false;
|
|
@@ -329,11 +329,11 @@ const rule$20 = createRule({
|
|
|
329
329
|
schema: [],
|
|
330
330
|
type: "problem"
|
|
331
331
|
},
|
|
332
|
-
name: RULE_NAME$
|
|
332
|
+
name: RULE_NAME$21
|
|
333
333
|
});
|
|
334
334
|
//#endregion
|
|
335
335
|
//#region src/rules/no-config-function-in-source.ts
|
|
336
|
-
const RULE_NAME$
|
|
336
|
+
const RULE_NAME$20 = "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$20 = createRule({
|
|
354
354
|
create(context) {
|
|
355
355
|
if (!hasPkgImport(context)) return {};
|
|
356
356
|
if (!isValidFile(context)) return {};
|
|
@@ -390,12 +390,12 @@ const rule$19 = createRule({
|
|
|
390
390
|
schema: [],
|
|
391
391
|
type: "problem"
|
|
392
392
|
},
|
|
393
|
-
name: RULE_NAME$
|
|
393
|
+
name: RULE_NAME$20
|
|
394
394
|
});
|
|
395
395
|
//#endregion
|
|
396
396
|
//#region src/rules/no-debug.ts
|
|
397
|
-
const RULE_NAME$
|
|
398
|
-
const rule$
|
|
397
|
+
const RULE_NAME$19 = "no-debug";
|
|
398
|
+
const rule$19 = createRule({
|
|
399
399
|
create(context) {
|
|
400
400
|
const processedNodes = /* @__PURE__ */ new WeakSet();
|
|
401
401
|
const checkObjectForDebug = (object) => {
|
|
@@ -464,12 +464,12 @@ const rule$18 = createRule({
|
|
|
464
464
|
schema: [],
|
|
465
465
|
type: "problem"
|
|
466
466
|
},
|
|
467
|
-
name: RULE_NAME$
|
|
467
|
+
name: RULE_NAME$19
|
|
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$18 = "no-deprecated-tokens";
|
|
472
|
+
const rule$18 = 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$17 = createRule({
|
|
|
523
523
|
schema: [],
|
|
524
524
|
type: "problem"
|
|
525
525
|
},
|
|
526
|
-
name: RULE_NAME$
|
|
526
|
+
name: RULE_NAME$18
|
|
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$17 = "no-dynamic-styling";
|
|
531
|
+
const rule$17 = createRule({
|
|
532
532
|
create(context) {
|
|
533
533
|
function isStaticValue(node) {
|
|
534
534
|
if (!node) return false;
|
|
@@ -599,12 +599,12 @@ const rule$16 = createRule({
|
|
|
599
599
|
schema: [],
|
|
600
600
|
type: "problem"
|
|
601
601
|
},
|
|
602
|
-
name: RULE_NAME$
|
|
602
|
+
name: RULE_NAME$17
|
|
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$16 = "no-escape-hatch";
|
|
607
|
+
const rule$16 = createRule({
|
|
608
608
|
create(context) {
|
|
609
609
|
const removeBrackets = (range) => {
|
|
610
610
|
const [start, end] = range;
|
|
@@ -677,12 +677,12 @@ const rule$15 = createRule({
|
|
|
677
677
|
schema: [],
|
|
678
678
|
type: "problem"
|
|
679
679
|
},
|
|
680
|
-
name: RULE_NAME$
|
|
680
|
+
name: RULE_NAME$16
|
|
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$15 = "no-hardcoded-color";
|
|
685
|
+
const rule$15 = 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$14 = createRule({
|
|
|
778
778
|
}],
|
|
779
779
|
type: "problem"
|
|
780
780
|
},
|
|
781
|
-
name: RULE_NAME$
|
|
781
|
+
name: RULE_NAME$15
|
|
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$14 = "no-important";
|
|
788
|
+
const rule$14 = createRule({
|
|
789
789
|
create(context) {
|
|
790
790
|
const removeQuotes = (range) => {
|
|
791
791
|
const [start, end] = range;
|
|
@@ -889,12 +889,12 @@ const rule$13 = createRule({
|
|
|
889
889
|
schema: [],
|
|
890
890
|
type: "problem"
|
|
891
891
|
},
|
|
892
|
-
name: RULE_NAME$
|
|
892
|
+
name: RULE_NAME$14
|
|
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$13 = "no-invalid-nesting";
|
|
897
|
+
const rule$13 = 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$12 = createRule({
|
|
|
949
949
|
schema: [],
|
|
950
950
|
type: "problem"
|
|
951
951
|
},
|
|
952
|
-
name: RULE_NAME$
|
|
952
|
+
name: RULE_NAME$13
|
|
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$12 = "no-invalid-token-paths";
|
|
957
|
+
const rule$12 = createRule({
|
|
958
958
|
create(context) {
|
|
959
959
|
const invalidTokensCache = /* @__PURE__ */ new Map();
|
|
960
960
|
const sendReport = (node, value) => {
|
|
@@ -1031,12 +1031,12 @@ const rule$11 = createRule({
|
|
|
1031
1031
|
schema: [],
|
|
1032
1032
|
type: "problem"
|
|
1033
1033
|
},
|
|
1034
|
-
name: RULE_NAME$
|
|
1034
|
+
name: RULE_NAME$12
|
|
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$11 = "no-margin-properties";
|
|
1039
|
+
const rule$11 = 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$10 = createRule({
|
|
|
1112
1112
|
}],
|
|
1113
1113
|
type: "suggestion"
|
|
1114
1114
|
},
|
|
1115
|
-
name: RULE_NAME$
|
|
1115
|
+
name: RULE_NAME$11
|
|
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$10 = "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$10 = 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$9 = createRule({
|
|
|
1294
1294
|
}],
|
|
1295
1295
|
type: "suggestion"
|
|
1296
1296
|
},
|
|
1297
|
-
name: RULE_NAME$
|
|
1297
|
+
name: RULE_NAME$10
|
|
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$9 = "no-property-renaming";
|
|
1302
|
+
const rule$9 = 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$8 = createRule({
|
|
|
1363
1363
|
schema: [],
|
|
1364
1364
|
type: "problem"
|
|
1365
1365
|
},
|
|
1366
|
-
name: RULE_NAME$
|
|
1366
|
+
name: RULE_NAME$9
|
|
1367
1367
|
});
|
|
1368
1368
|
//#endregion
|
|
1369
1369
|
//#region src/rules/no-unlayered-override.ts
|
|
1370
|
-
const RULE_NAME$
|
|
1370
|
+
const RULE_NAME$8 = "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$8 = createRule({
|
|
1396
1396
|
create(context) {
|
|
1397
1397
|
if (!isValidFile(context)) return {};
|
|
1398
1398
|
const isOwnStyles = (node) => {
|
|
@@ -1422,6 +1422,161 @@ const rule$7 = createRule({
|
|
|
1422
1422
|
schema: [],
|
|
1423
1423
|
type: "problem"
|
|
1424
1424
|
},
|
|
1425
|
+
name: RULE_NAME$8
|
|
1426
|
+
});
|
|
1427
|
+
//#endregion
|
|
1428
|
+
//#region src/rules/require-literal-token-path.ts
|
|
1429
|
+
const RULE_NAME$7 = "require-literal-token-path";
|
|
1430
|
+
/**
|
|
1431
|
+
* The wrappers a typed caller writes around a path, which carry no runtime meaning.
|
|
1432
|
+
*
|
|
1433
|
+
* The generated `Token` type is a union of template literals, so a `string`-typed substitution
|
|
1434
|
+
* does not typecheck without an assertion — `` token(`colors.${shade}` as Token) `` is the
|
|
1435
|
+
* idiomatic spelling, and reading only the outermost node would report it as dynamic when the
|
|
1436
|
+
* build bounds it perfectly well.
|
|
1437
|
+
*/
|
|
1438
|
+
const unwrap = (node) => {
|
|
1439
|
+
switch (node.type) {
|
|
1440
|
+
case "TSAsExpression":
|
|
1441
|
+
case "TSSatisfiesExpression":
|
|
1442
|
+
case "TSNonNullExpression":
|
|
1443
|
+
case "TSTypeAssertion": return unwrap(node.expression);
|
|
1444
|
+
default: return node;
|
|
1445
|
+
}
|
|
1446
|
+
};
|
|
1447
|
+
/**
|
|
1448
|
+
* How much of a token path the build can see.
|
|
1449
|
+
*
|
|
1450
|
+
* `literal` is a path spelled at the call. `bounded` is a template whose static head names a
|
|
1451
|
+
* category — the build cannot say which token it wants but knows which it cannot, so it keeps
|
|
1452
|
+
* that category and prunes the rest. `opaque` is everything else.
|
|
1453
|
+
*
|
|
1454
|
+
* Mirrors `literalPath` in `@bamboocss/node`, down to reading the *cooked* head and treating an
|
|
1455
|
+
* empty one as no bound at all. The rule's whole value is predicting what the build will do,
|
|
1456
|
+
* so a disagreement here is worse than no rule.
|
|
1457
|
+
*/
|
|
1458
|
+
const reach = (argument) => {
|
|
1459
|
+
if (!argument) return "opaque";
|
|
1460
|
+
const node = unwrap(argument);
|
|
1461
|
+
if (isLiteral(node) && typeof node.value === "string") return "literal";
|
|
1462
|
+
if (isTemplateLiteral(node)) {
|
|
1463
|
+
if (node.expressions.length === 0) return "literal";
|
|
1464
|
+
return node.quasis[0]?.value.cooked ? "bounded" : "opaque";
|
|
1465
|
+
}
|
|
1466
|
+
return "opaque";
|
|
1467
|
+
};
|
|
1468
|
+
/** A member name, whether written `a.b` or `a['b']`. */
|
|
1469
|
+
const memberName = (node) => {
|
|
1470
|
+
if (!node.computed) return isIdentifier(node.property) ? node.property.name : void 0;
|
|
1471
|
+
return isLiteral(node.property) && typeof node.property.value === "string" ? node.property.value : void 0;
|
|
1472
|
+
};
|
|
1473
|
+
const rule$7 = createRule({
|
|
1474
|
+
create(context) {
|
|
1475
|
+
/**
|
|
1476
|
+
* Names bound to the generated token artifact in this file.
|
|
1477
|
+
*
|
|
1478
|
+
* Collected here rather than through the shared `getTokenImport`, which searches *every*
|
|
1479
|
+
* module for a specifier named `token` and takes the first. That is wrong in both
|
|
1480
|
+
* directions: an unrelated `import { token as authToken } from './auth'` made this rule
|
|
1481
|
+
* report on a file with no Bamboo in it, and — worse — an unrelated `token` import
|
|
1482
|
+
* declared above the real one *masked* it, so whether a genuinely dynamic path was
|
|
1483
|
+
* reported depended on import order.
|
|
1484
|
+
*
|
|
1485
|
+
* The specifier test is a substring, like the build's cheap pass. It over-matches
|
|
1486
|
+
* `./tokenserver`, which is harmless: the build declines a `token` call through any
|
|
1487
|
+
* namespace it cannot classify, so over-matching agrees with it. It under-matches a
|
|
1488
|
+
* tsconfig path alias, which the build resolves and this cannot — that gap is documented
|
|
1489
|
+
* rather than papered over.
|
|
1490
|
+
*/
|
|
1491
|
+
let bindings;
|
|
1492
|
+
const bound = () => {
|
|
1493
|
+
if (bindings) return bindings;
|
|
1494
|
+
bindings = {
|
|
1495
|
+
direct: /* @__PURE__ */ new Set(),
|
|
1496
|
+
namespaces: /* @__PURE__ */ new Set()
|
|
1497
|
+
};
|
|
1498
|
+
for (const node of context.sourceCode.ast.body) {
|
|
1499
|
+
if (node.type !== "ImportDeclaration") continue;
|
|
1500
|
+
if (!String(node.source.value).includes("tokens")) continue;
|
|
1501
|
+
for (const specifier of node.specifiers) {
|
|
1502
|
+
if (specifier.type === "ImportNamespaceSpecifier") bindings.namespaces.add(specifier.local.name);
|
|
1503
|
+
if (specifier.type === "ImportSpecifier" && isIdentifier(specifier.imported)) {
|
|
1504
|
+
if (specifier.imported.name === "token") bindings.direct.add(specifier.local.name);
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
return bindings;
|
|
1509
|
+
};
|
|
1510
|
+
/**
|
|
1511
|
+
* Whether this call reaches the generated `token`.
|
|
1512
|
+
*
|
|
1513
|
+
* A bare `token(…)` counts even with no import to bind it, because the build counts it: its
|
|
1514
|
+
* accounting keys on the name, so a local helper of that name declines there too. Staying
|
|
1515
|
+
* quiet about it would mean `strict` failing a build the editor called clean.
|
|
1516
|
+
*/
|
|
1517
|
+
const isTokenCall = (node) => {
|
|
1518
|
+
const callee = node.type === "CallExpression" ? node.callee : node.tag;
|
|
1519
|
+
const { direct, namespaces } = bound();
|
|
1520
|
+
if (isIdentifier(callee)) return direct.has(callee.name) || callee.name === "token";
|
|
1521
|
+
if (callee.type !== "MemberExpression") return false;
|
|
1522
|
+
if (callee.computed) return isComputedTokenCallee(callee, direct, namespaces) ? "computed" : false;
|
|
1523
|
+
const property = memberName(callee);
|
|
1524
|
+
if (property === void 0) return false;
|
|
1525
|
+
if (isIdentifier(callee.object) && (direct.has(callee.object.name) || callee.object.name === "token")) return property === "value";
|
|
1526
|
+
if (property === "token") return isIdentifier(callee.object) && namespaces.has(callee.object.name);
|
|
1527
|
+
return property === "value" && callee.object.type === "MemberExpression" && memberName(callee.object) === "token" && isIdentifier(callee.object.object) && namespaces.has(callee.object.object.name);
|
|
1528
|
+
};
|
|
1529
|
+
/** The same shapes as below, but reached through a computed member. */
|
|
1530
|
+
const isComputedTokenCallee = (callee, direct, namespaces) => {
|
|
1531
|
+
const property = memberName(callee);
|
|
1532
|
+
if (property === void 0) return false;
|
|
1533
|
+
if (isIdentifier(callee.object) && (direct.has(callee.object.name) || callee.object.name === "token")) return property === "value";
|
|
1534
|
+
if (property === "token") return isIdentifier(callee.object) && namespaces.has(callee.object.name);
|
|
1535
|
+
return false;
|
|
1536
|
+
};
|
|
1537
|
+
const report = (node, found, at) => {
|
|
1538
|
+
context.report({
|
|
1539
|
+
messageId: found === "bounded" ? "boundedTokenPath" : "opaqueTokenPath",
|
|
1540
|
+
node: at
|
|
1541
|
+
});
|
|
1542
|
+
};
|
|
1543
|
+
return {
|
|
1544
|
+
CallExpression(node) {
|
|
1545
|
+
const kind = isTokenCall(node);
|
|
1546
|
+
if (!kind) return;
|
|
1547
|
+
const found = kind === "computed" ? "opaque" : reach(node.arguments[0]);
|
|
1548
|
+
if (found === "literal") return;
|
|
1549
|
+
report(node, found, node.arguments[0] ?? node);
|
|
1550
|
+
},
|
|
1551
|
+
/**
|
|
1552
|
+
* `` token`colors.${s}` `` — a different node, and one the build declines outright since
|
|
1553
|
+
* the artifact exports a function rather than a tag. Reported as opaque whatever its
|
|
1554
|
+
* head, because the call never resolves at all.
|
|
1555
|
+
*/
|
|
1556
|
+
TaggedTemplateExpression(node) {
|
|
1557
|
+
if (!isTokenCall(node)) return;
|
|
1558
|
+
report(node, "opaque", node.quasi);
|
|
1559
|
+
}
|
|
1560
|
+
};
|
|
1561
|
+
},
|
|
1562
|
+
defaultOptions: [],
|
|
1563
|
+
meta: {
|
|
1564
|
+
docs: { description: "Require a token path the build can resolve, so `pruneUnusedTokens` can drop the declarations nothing asks for." },
|
|
1565
|
+
messages: {
|
|
1566
|
+
/**
|
|
1567
|
+
* The build keeps every token declaration for this, because the path could name any of
|
|
1568
|
+
* them. Under `pruneUnusedTokens: 'strict'` it is an error rather than a size cost.
|
|
1569
|
+
*/
|
|
1570
|
+
opaqueTokenPath: "Token path cannot be resolved at build time, so every token declaration is kept. Spell the path at the call, or give a template a static prefix.",
|
|
1571
|
+
/**
|
|
1572
|
+
* Not wrong — the build keeps the category and prunes the rest — but a spelled-out path
|
|
1573
|
+
* keeps one declaration where this keeps hundreds, so it is worth knowing about.
|
|
1574
|
+
*/
|
|
1575
|
+
boundedTokenPath: "Token path is bounded by its prefix rather than resolved, so the whole category is kept. Spell the path at the call to keep only what you use."
|
|
1576
|
+
},
|
|
1577
|
+
schema: [],
|
|
1578
|
+
type: "problem"
|
|
1579
|
+
},
|
|
1425
1580
|
name: RULE_NAME$7
|
|
1426
1581
|
});
|
|
1427
1582
|
//#endregion
|
|
@@ -2339,6 +2494,7 @@ const rule = createRule({
|
|
|
2339
2494
|
//#endregion
|
|
2340
2495
|
//#region src/rules/index.ts
|
|
2341
2496
|
const rules = {
|
|
2497
|
+
[RULE_NAME$21]: rule$21,
|
|
2342
2498
|
[RULE_NAME$20]: rule$20,
|
|
2343
2499
|
[RULE_NAME$19]: rule$19,
|
|
2344
2500
|
[RULE_NAME$18]: rule$18,
|
|
@@ -2364,9 +2520,9 @@ const rules = {
|
|
|
2364
2520
|
//#endregion
|
|
2365
2521
|
//#region src/configs/all.ts
|
|
2366
2522
|
const errorRules = [
|
|
2523
|
+
RULE_NAME$21,
|
|
2367
2524
|
RULE_NAME$20,
|
|
2368
|
-
RULE_NAME$
|
|
2369
|
-
RULE_NAME$11
|
|
2525
|
+
RULE_NAME$12
|
|
2370
2526
|
];
|
|
2371
2527
|
//#endregion
|
|
2372
2528
|
//#region src/index.ts
|
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.30.0";
|
|
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$21 = "file-not-included";
|
|
311
|
+
const rule$21 = createRule({
|
|
312
312
|
create(context) {
|
|
313
313
|
if (isValidFile(context)) return {};
|
|
314
314
|
let hasReported = false;
|
|
@@ -329,11 +329,11 @@ const rule$20 = createRule({
|
|
|
329
329
|
schema: [],
|
|
330
330
|
type: "problem"
|
|
331
331
|
},
|
|
332
|
-
name: RULE_NAME$
|
|
332
|
+
name: RULE_NAME$21
|
|
333
333
|
});
|
|
334
334
|
//#endregion
|
|
335
335
|
//#region src/rules/no-config-function-in-source.ts
|
|
336
|
-
const RULE_NAME$
|
|
336
|
+
const RULE_NAME$20 = "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$20 = createRule({
|
|
354
354
|
create(context) {
|
|
355
355
|
if (!hasPkgImport(context)) return {};
|
|
356
356
|
if (!isValidFile(context)) return {};
|
|
@@ -390,12 +390,12 @@ const rule$19 = createRule({
|
|
|
390
390
|
schema: [],
|
|
391
391
|
type: "problem"
|
|
392
392
|
},
|
|
393
|
-
name: RULE_NAME$
|
|
393
|
+
name: RULE_NAME$20
|
|
394
394
|
});
|
|
395
395
|
//#endregion
|
|
396
396
|
//#region src/rules/no-debug.ts
|
|
397
|
-
const RULE_NAME$
|
|
398
|
-
const rule$
|
|
397
|
+
const RULE_NAME$19 = "no-debug";
|
|
398
|
+
const rule$19 = createRule({
|
|
399
399
|
create(context) {
|
|
400
400
|
const processedNodes = /* @__PURE__ */ new WeakSet();
|
|
401
401
|
const checkObjectForDebug = (object) => {
|
|
@@ -464,12 +464,12 @@ const rule$18 = createRule({
|
|
|
464
464
|
schema: [],
|
|
465
465
|
type: "problem"
|
|
466
466
|
},
|
|
467
|
-
name: RULE_NAME$
|
|
467
|
+
name: RULE_NAME$19
|
|
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$18 = "no-deprecated-tokens";
|
|
472
|
+
const rule$18 = 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$17 = createRule({
|
|
|
523
523
|
schema: [],
|
|
524
524
|
type: "problem"
|
|
525
525
|
},
|
|
526
|
-
name: RULE_NAME$
|
|
526
|
+
name: RULE_NAME$18
|
|
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$17 = "no-dynamic-styling";
|
|
531
|
+
const rule$17 = createRule({
|
|
532
532
|
create(context) {
|
|
533
533
|
function isStaticValue(node) {
|
|
534
534
|
if (!node) return false;
|
|
@@ -599,12 +599,12 @@ const rule$16 = createRule({
|
|
|
599
599
|
schema: [],
|
|
600
600
|
type: "problem"
|
|
601
601
|
},
|
|
602
|
-
name: RULE_NAME$
|
|
602
|
+
name: RULE_NAME$17
|
|
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$16 = "no-escape-hatch";
|
|
607
|
+
const rule$16 = createRule({
|
|
608
608
|
create(context) {
|
|
609
609
|
const removeBrackets = (range) => {
|
|
610
610
|
const [start, end] = range;
|
|
@@ -677,12 +677,12 @@ const rule$15 = createRule({
|
|
|
677
677
|
schema: [],
|
|
678
678
|
type: "problem"
|
|
679
679
|
},
|
|
680
|
-
name: RULE_NAME$
|
|
680
|
+
name: RULE_NAME$16
|
|
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$15 = "no-hardcoded-color";
|
|
685
|
+
const rule$15 = 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$14 = createRule({
|
|
|
778
778
|
}],
|
|
779
779
|
type: "problem"
|
|
780
780
|
},
|
|
781
|
-
name: RULE_NAME$
|
|
781
|
+
name: RULE_NAME$15
|
|
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$14 = "no-important";
|
|
788
|
+
const rule$14 = createRule({
|
|
789
789
|
create(context) {
|
|
790
790
|
const removeQuotes = (range) => {
|
|
791
791
|
const [start, end] = range;
|
|
@@ -889,12 +889,12 @@ const rule$13 = createRule({
|
|
|
889
889
|
schema: [],
|
|
890
890
|
type: "problem"
|
|
891
891
|
},
|
|
892
|
-
name: RULE_NAME$
|
|
892
|
+
name: RULE_NAME$14
|
|
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$13 = "no-invalid-nesting";
|
|
897
|
+
const rule$13 = 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$12 = createRule({
|
|
|
949
949
|
schema: [],
|
|
950
950
|
type: "problem"
|
|
951
951
|
},
|
|
952
|
-
name: RULE_NAME$
|
|
952
|
+
name: RULE_NAME$13
|
|
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$12 = "no-invalid-token-paths";
|
|
957
|
+
const rule$12 = createRule({
|
|
958
958
|
create(context) {
|
|
959
959
|
const invalidTokensCache = /* @__PURE__ */ new Map();
|
|
960
960
|
const sendReport = (node, value) => {
|
|
@@ -1031,12 +1031,12 @@ const rule$11 = createRule({
|
|
|
1031
1031
|
schema: [],
|
|
1032
1032
|
type: "problem"
|
|
1033
1033
|
},
|
|
1034
|
-
name: RULE_NAME$
|
|
1034
|
+
name: RULE_NAME$12
|
|
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$11 = "no-margin-properties";
|
|
1039
|
+
const rule$11 = 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$10 = createRule({
|
|
|
1112
1112
|
}],
|
|
1113
1113
|
type: "suggestion"
|
|
1114
1114
|
},
|
|
1115
|
-
name: RULE_NAME$
|
|
1115
|
+
name: RULE_NAME$11
|
|
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$10 = "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$10 = 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$9 = createRule({
|
|
|
1294
1294
|
}],
|
|
1295
1295
|
type: "suggestion"
|
|
1296
1296
|
},
|
|
1297
|
-
name: RULE_NAME$
|
|
1297
|
+
name: RULE_NAME$10
|
|
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$9 = "no-property-renaming";
|
|
1302
|
+
const rule$9 = 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$8 = createRule({
|
|
|
1363
1363
|
schema: [],
|
|
1364
1364
|
type: "problem"
|
|
1365
1365
|
},
|
|
1366
|
-
name: RULE_NAME$
|
|
1366
|
+
name: RULE_NAME$9
|
|
1367
1367
|
});
|
|
1368
1368
|
//#endregion
|
|
1369
1369
|
//#region src/rules/no-unlayered-override.ts
|
|
1370
|
-
const RULE_NAME$
|
|
1370
|
+
const RULE_NAME$8 = "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$8 = createRule({
|
|
1396
1396
|
create(context) {
|
|
1397
1397
|
if (!isValidFile(context)) return {};
|
|
1398
1398
|
const isOwnStyles = (node) => {
|
|
@@ -1422,6 +1422,161 @@ const rule$7 = createRule({
|
|
|
1422
1422
|
schema: [],
|
|
1423
1423
|
type: "problem"
|
|
1424
1424
|
},
|
|
1425
|
+
name: RULE_NAME$8
|
|
1426
|
+
});
|
|
1427
|
+
//#endregion
|
|
1428
|
+
//#region src/rules/require-literal-token-path.ts
|
|
1429
|
+
const RULE_NAME$7 = "require-literal-token-path";
|
|
1430
|
+
/**
|
|
1431
|
+
* The wrappers a typed caller writes around a path, which carry no runtime meaning.
|
|
1432
|
+
*
|
|
1433
|
+
* The generated `Token` type is a union of template literals, so a `string`-typed substitution
|
|
1434
|
+
* does not typecheck without an assertion — `` token(`colors.${shade}` as Token) `` is the
|
|
1435
|
+
* idiomatic spelling, and reading only the outermost node would report it as dynamic when the
|
|
1436
|
+
* build bounds it perfectly well.
|
|
1437
|
+
*/
|
|
1438
|
+
const unwrap = (node) => {
|
|
1439
|
+
switch (node.type) {
|
|
1440
|
+
case "TSAsExpression":
|
|
1441
|
+
case "TSSatisfiesExpression":
|
|
1442
|
+
case "TSNonNullExpression":
|
|
1443
|
+
case "TSTypeAssertion": return unwrap(node.expression);
|
|
1444
|
+
default: return node;
|
|
1445
|
+
}
|
|
1446
|
+
};
|
|
1447
|
+
/**
|
|
1448
|
+
* How much of a token path the build can see.
|
|
1449
|
+
*
|
|
1450
|
+
* `literal` is a path spelled at the call. `bounded` is a template whose static head names a
|
|
1451
|
+
* category — the build cannot say which token it wants but knows which it cannot, so it keeps
|
|
1452
|
+
* that category and prunes the rest. `opaque` is everything else.
|
|
1453
|
+
*
|
|
1454
|
+
* Mirrors `literalPath` in `@bamboocss/node`, down to reading the *cooked* head and treating an
|
|
1455
|
+
* empty one as no bound at all. The rule's whole value is predicting what the build will do,
|
|
1456
|
+
* so a disagreement here is worse than no rule.
|
|
1457
|
+
*/
|
|
1458
|
+
const reach = (argument) => {
|
|
1459
|
+
if (!argument) return "opaque";
|
|
1460
|
+
const node = unwrap(argument);
|
|
1461
|
+
if (isLiteral(node) && typeof node.value === "string") return "literal";
|
|
1462
|
+
if (isTemplateLiteral(node)) {
|
|
1463
|
+
if (node.expressions.length === 0) return "literal";
|
|
1464
|
+
return node.quasis[0]?.value.cooked ? "bounded" : "opaque";
|
|
1465
|
+
}
|
|
1466
|
+
return "opaque";
|
|
1467
|
+
};
|
|
1468
|
+
/** A member name, whether written `a.b` or `a['b']`. */
|
|
1469
|
+
const memberName = (node) => {
|
|
1470
|
+
if (!node.computed) return isIdentifier(node.property) ? node.property.name : void 0;
|
|
1471
|
+
return isLiteral(node.property) && typeof node.property.value === "string" ? node.property.value : void 0;
|
|
1472
|
+
};
|
|
1473
|
+
const rule$7 = createRule({
|
|
1474
|
+
create(context) {
|
|
1475
|
+
/**
|
|
1476
|
+
* Names bound to the generated token artifact in this file.
|
|
1477
|
+
*
|
|
1478
|
+
* Collected here rather than through the shared `getTokenImport`, which searches *every*
|
|
1479
|
+
* module for a specifier named `token` and takes the first. That is wrong in both
|
|
1480
|
+
* directions: an unrelated `import { token as authToken } from './auth'` made this rule
|
|
1481
|
+
* report on a file with no Bamboo in it, and — worse — an unrelated `token` import
|
|
1482
|
+
* declared above the real one *masked* it, so whether a genuinely dynamic path was
|
|
1483
|
+
* reported depended on import order.
|
|
1484
|
+
*
|
|
1485
|
+
* The specifier test is a substring, like the build's cheap pass. It over-matches
|
|
1486
|
+
* `./tokenserver`, which is harmless: the build declines a `token` call through any
|
|
1487
|
+
* namespace it cannot classify, so over-matching agrees with it. It under-matches a
|
|
1488
|
+
* tsconfig path alias, which the build resolves and this cannot — that gap is documented
|
|
1489
|
+
* rather than papered over.
|
|
1490
|
+
*/
|
|
1491
|
+
let bindings;
|
|
1492
|
+
const bound = () => {
|
|
1493
|
+
if (bindings) return bindings;
|
|
1494
|
+
bindings = {
|
|
1495
|
+
direct: /* @__PURE__ */ new Set(),
|
|
1496
|
+
namespaces: /* @__PURE__ */ new Set()
|
|
1497
|
+
};
|
|
1498
|
+
for (const node of context.sourceCode.ast.body) {
|
|
1499
|
+
if (node.type !== "ImportDeclaration") continue;
|
|
1500
|
+
if (!String(node.source.value).includes("tokens")) continue;
|
|
1501
|
+
for (const specifier of node.specifiers) {
|
|
1502
|
+
if (specifier.type === "ImportNamespaceSpecifier") bindings.namespaces.add(specifier.local.name);
|
|
1503
|
+
if (specifier.type === "ImportSpecifier" && isIdentifier(specifier.imported)) {
|
|
1504
|
+
if (specifier.imported.name === "token") bindings.direct.add(specifier.local.name);
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
return bindings;
|
|
1509
|
+
};
|
|
1510
|
+
/**
|
|
1511
|
+
* Whether this call reaches the generated `token`.
|
|
1512
|
+
*
|
|
1513
|
+
* A bare `token(…)` counts even with no import to bind it, because the build counts it: its
|
|
1514
|
+
* accounting keys on the name, so a local helper of that name declines there too. Staying
|
|
1515
|
+
* quiet about it would mean `strict` failing a build the editor called clean.
|
|
1516
|
+
*/
|
|
1517
|
+
const isTokenCall = (node) => {
|
|
1518
|
+
const callee = node.type === "CallExpression" ? node.callee : node.tag;
|
|
1519
|
+
const { direct, namespaces } = bound();
|
|
1520
|
+
if (isIdentifier(callee)) return direct.has(callee.name) || callee.name === "token";
|
|
1521
|
+
if (callee.type !== "MemberExpression") return false;
|
|
1522
|
+
if (callee.computed) return isComputedTokenCallee(callee, direct, namespaces) ? "computed" : false;
|
|
1523
|
+
const property = memberName(callee);
|
|
1524
|
+
if (property === void 0) return false;
|
|
1525
|
+
if (isIdentifier(callee.object) && (direct.has(callee.object.name) || callee.object.name === "token")) return property === "value";
|
|
1526
|
+
if (property === "token") return isIdentifier(callee.object) && namespaces.has(callee.object.name);
|
|
1527
|
+
return property === "value" && callee.object.type === "MemberExpression" && memberName(callee.object) === "token" && isIdentifier(callee.object.object) && namespaces.has(callee.object.object.name);
|
|
1528
|
+
};
|
|
1529
|
+
/** The same shapes as below, but reached through a computed member. */
|
|
1530
|
+
const isComputedTokenCallee = (callee, direct, namespaces) => {
|
|
1531
|
+
const property = memberName(callee);
|
|
1532
|
+
if (property === void 0) return false;
|
|
1533
|
+
if (isIdentifier(callee.object) && (direct.has(callee.object.name) || callee.object.name === "token")) return property === "value";
|
|
1534
|
+
if (property === "token") return isIdentifier(callee.object) && namespaces.has(callee.object.name);
|
|
1535
|
+
return false;
|
|
1536
|
+
};
|
|
1537
|
+
const report = (node, found, at) => {
|
|
1538
|
+
context.report({
|
|
1539
|
+
messageId: found === "bounded" ? "boundedTokenPath" : "opaqueTokenPath",
|
|
1540
|
+
node: at
|
|
1541
|
+
});
|
|
1542
|
+
};
|
|
1543
|
+
return {
|
|
1544
|
+
CallExpression(node) {
|
|
1545
|
+
const kind = isTokenCall(node);
|
|
1546
|
+
if (!kind) return;
|
|
1547
|
+
const found = kind === "computed" ? "opaque" : reach(node.arguments[0]);
|
|
1548
|
+
if (found === "literal") return;
|
|
1549
|
+
report(node, found, node.arguments[0] ?? node);
|
|
1550
|
+
},
|
|
1551
|
+
/**
|
|
1552
|
+
* `` token`colors.${s}` `` — a different node, and one the build declines outright since
|
|
1553
|
+
* the artifact exports a function rather than a tag. Reported as opaque whatever its
|
|
1554
|
+
* head, because the call never resolves at all.
|
|
1555
|
+
*/
|
|
1556
|
+
TaggedTemplateExpression(node) {
|
|
1557
|
+
if (!isTokenCall(node)) return;
|
|
1558
|
+
report(node, "opaque", node.quasi);
|
|
1559
|
+
}
|
|
1560
|
+
};
|
|
1561
|
+
},
|
|
1562
|
+
defaultOptions: [],
|
|
1563
|
+
meta: {
|
|
1564
|
+
docs: { description: "Require a token path the build can resolve, so `pruneUnusedTokens` can drop the declarations nothing asks for." },
|
|
1565
|
+
messages: {
|
|
1566
|
+
/**
|
|
1567
|
+
* The build keeps every token declaration for this, because the path could name any of
|
|
1568
|
+
* them. Under `pruneUnusedTokens: 'strict'` it is an error rather than a size cost.
|
|
1569
|
+
*/
|
|
1570
|
+
opaqueTokenPath: "Token path cannot be resolved at build time, so every token declaration is kept. Spell the path at the call, or give a template a static prefix.",
|
|
1571
|
+
/**
|
|
1572
|
+
* Not wrong — the build keeps the category and prunes the rest — but a spelled-out path
|
|
1573
|
+
* keeps one declaration where this keeps hundreds, so it is worth knowing about.
|
|
1574
|
+
*/
|
|
1575
|
+
boundedTokenPath: "Token path is bounded by its prefix rather than resolved, so the whole category is kept. Spell the path at the call to keep only what you use."
|
|
1576
|
+
},
|
|
1577
|
+
schema: [],
|
|
1578
|
+
type: "problem"
|
|
1579
|
+
},
|
|
1425
1580
|
name: RULE_NAME$7
|
|
1426
1581
|
});
|
|
1427
1582
|
//#endregion
|
|
@@ -2339,6 +2494,7 @@ const rule = createRule({
|
|
|
2339
2494
|
//#endregion
|
|
2340
2495
|
//#region src/rules/index.ts
|
|
2341
2496
|
const rules = {
|
|
2497
|
+
[RULE_NAME$21]: rule$21,
|
|
2342
2498
|
[RULE_NAME$20]: rule$20,
|
|
2343
2499
|
[RULE_NAME$19]: rule$19,
|
|
2344
2500
|
[RULE_NAME$18]: rule$18,
|
|
@@ -2364,9 +2520,9 @@ const rules = {
|
|
|
2364
2520
|
//#endregion
|
|
2365
2521
|
//#region src/configs/all.ts
|
|
2366
2522
|
const errorRules = [
|
|
2523
|
+
RULE_NAME$21,
|
|
2367
2524
|
RULE_NAME$20,
|
|
2368
|
-
RULE_NAME$
|
|
2369
|
-
RULE_NAME$11
|
|
2525
|
+
RULE_NAME$12
|
|
2370
2526
|
];
|
|
2371
2527
|
//#endregion
|
|
2372
2528
|
//#region src/index.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bamboocss/eslint-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.30.0",
|
|
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.30.0",
|
|
40
|
+
"@bamboocss/generator": "1.30.0",
|
|
41
|
+
"@bamboocss/shared": "1.30.0"
|
|
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.30.0",
|
|
50
|
+
"@bamboocss/preset-bamboo": "1.30.0",
|
|
51
|
+
"@bamboocss/preset-base": "1.30.0",
|
|
52
|
+
"@bamboocss/types": "1.30.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"eslint": "*"
|