@bridge-ds/stylelint-plugin 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -3
- package/dist/index.js +74 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -7,9 +7,6 @@ durations, easings, z-index and fonts are reported where a design token exists,
|
|
|
7
7
|
It reads the tokens (every brand, theme and density) through `@bridge-ds/core` and the design system's
|
|
8
8
|
`bridge.config.json`, so the suggestions are the same as `bridge audit` and the `bridge_audit` MCP tool.
|
|
9
9
|
|
|
10
|
-
> Not published to npm yet: build it from this repo (`npm run plugins:build`) and install the folder, or use
|
|
11
|
-
> the path to `packages/stylelint-plugin/dist/index.js` in `plugins`.
|
|
12
|
-
|
|
13
10
|
## Install
|
|
14
11
|
|
|
15
12
|
```sh
|
package/dist/index.js
CHANGED
|
@@ -843,6 +843,74 @@ function isSafeFix(h, s) {
|
|
|
843
843
|
// ../core/src/previews.ts
|
|
844
844
|
var PREVIEW_APP_LABELS = { docs: "Docs", storybook: "Storybook", admin: "Admin demo" };
|
|
845
845
|
|
|
846
|
+
// ../core/src/teams.ts
|
|
847
|
+
var LOGIN = /^[A-Za-z0-9](?:[A-Za-z0-9]|-(?=[A-Za-z0-9])){0,38}$/;
|
|
848
|
+
var SLUG = /^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/;
|
|
849
|
+
function parseOwnerEntry(raw) {
|
|
850
|
+
if (typeof raw !== "string") return null;
|
|
851
|
+
const s = raw.trim().replace(/^@/, "");
|
|
852
|
+
const slash = s.indexOf("/");
|
|
853
|
+
if (slash < 0) return LOGIN.test(s) ? { kind: "person", login: s } : null;
|
|
854
|
+
const org = s.slice(0, slash);
|
|
855
|
+
const slug = s.slice(slash + 1);
|
|
856
|
+
return LOGIN.test(org) && SLUG.test(slug) ? { kind: "team", org, slug } : null;
|
|
857
|
+
}
|
|
858
|
+
function ownerEntryProblems(raw) {
|
|
859
|
+
if (raw === void 0) return [];
|
|
860
|
+
const isObj2 = (x) => Boolean(x) && typeof x === "object" && !Array.isArray(x);
|
|
861
|
+
if (!isObj2(raw)) return ['"governance.owners" must be { "design": [people or teams], "tech": [people or teams] }'];
|
|
862
|
+
const out = [];
|
|
863
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
864
|
+
if (k !== "design" && k !== "tech") {
|
|
865
|
+
out.push(`"governance.owners.${k}" is not an owner group (design, tech)`);
|
|
866
|
+
continue;
|
|
867
|
+
}
|
|
868
|
+
if (!Array.isArray(v)) {
|
|
869
|
+
out.push(`"governance.owners.${k}" must be a list of people or teams`);
|
|
870
|
+
continue;
|
|
871
|
+
}
|
|
872
|
+
v.forEach((x, i) => {
|
|
873
|
+
if (typeof x !== "string" || !parseOwnerEntry(x))
|
|
874
|
+
out.push(`"governance.owners.${k}[${i}]" (${JSON.stringify(x)}) is not a GitHub login or team. Write a person as "peterbono" or "@peterbono", a team as "@org/team-slug".`);
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
return out;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
// ../core/src/rights.ts
|
|
881
|
+
var OWNER_GROUPS = ["design", "tech"];
|
|
882
|
+
var RIGHTS = ["approveDesign", "approveTech", "ship"];
|
|
883
|
+
var DEFAULT_RIGHTS = { approveDesign: ["design"], approveTech: ["tech"], ship: ["tech"] };
|
|
884
|
+
function normalizeRights(input) {
|
|
885
|
+
const pick = (r) => {
|
|
886
|
+
const v = input?.[r];
|
|
887
|
+
if (!Array.isArray(v)) return [...DEFAULT_RIGHTS[r]];
|
|
888
|
+
return OWNER_GROUPS.filter((g) => v.includes(g));
|
|
889
|
+
};
|
|
890
|
+
return { approveDesign: pick("approveDesign"), approveTech: pick("approveTech"), ship: pick("ship") };
|
|
891
|
+
}
|
|
892
|
+
function rightsProblems(raw) {
|
|
893
|
+
if (raw === void 0) return [];
|
|
894
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return ['"governance.rights" must be { "approveDesign": [groups], "approveTech": [groups], "ship": [groups] }'];
|
|
895
|
+
const out = [];
|
|
896
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
897
|
+
if (!RIGHTS.includes(k)) out.push(`"governance.rights.${k}" is not a right (${RIGHTS.join(", ")})`);
|
|
898
|
+
else if (!Array.isArray(v) || v.length === 0 || !v.every((g) => OWNER_GROUPS.includes(g)))
|
|
899
|
+
out.push(`"governance.rights.${k}" must list one or more of "design", "tech"`);
|
|
900
|
+
}
|
|
901
|
+
return out;
|
|
902
|
+
}
|
|
903
|
+
function visualImpactProblems(raw) {
|
|
904
|
+
if (raw === void 0) return [];
|
|
905
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return ['"visualImpact" must be { "mode": "auto" | "on-demand" }'];
|
|
906
|
+
const out = [];
|
|
907
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
908
|
+
if (k !== "mode") out.push(`"visualImpact.${k}" is not a setting (mode)`);
|
|
909
|
+
else if (v !== "auto" && v !== "on-demand") out.push('"visualImpact.mode" must be "auto" or "on-demand"');
|
|
910
|
+
}
|
|
911
|
+
return out;
|
|
912
|
+
}
|
|
913
|
+
|
|
846
914
|
// ../core/src/config.ts
|
|
847
915
|
var CONFIG_FILE = "bridge.config.json";
|
|
848
916
|
var DEFAULT_OVERRIDE = { allowed: [], requireReason: true, minReasonLength: 20 };
|
|
@@ -980,9 +1048,11 @@ function defineConfig(input) {
|
|
|
980
1048
|
requireReason: g.override.requireReason ?? DEFAULT_OVERRIDE.requireReason,
|
|
981
1049
|
minReasonLength: g.override.minReasonLength ?? DEFAULT_OVERRIDE.minReasonLength
|
|
982
1050
|
}
|
|
983
|
-
} : {}
|
|
1051
|
+
} : {},
|
|
1052
|
+
...g.rights ? { rights: normalizeRights(g.rights) } : {}
|
|
984
1053
|
},
|
|
985
1054
|
...input.audit ? { audit: { ...input.audit } } : {},
|
|
1055
|
+
...input.visualImpact ? { visualImpact: { mode: input.visualImpact.mode === "on-demand" ? "on-demand" : "auto" } } : {},
|
|
986
1056
|
...input.integrations ? { integrations: { ...input.integrations } } : {},
|
|
987
1057
|
...input.previews ? {
|
|
988
1058
|
previews: {
|
|
@@ -1089,9 +1159,7 @@ function loadConfig(source) {
|
|
|
1089
1159
|
else {
|
|
1090
1160
|
for (const k of ["protectedBranches", "labels", "guardrails"]) if (gov[k] !== void 0 && !(Array.isArray(gov[k]) && gov[k].every((x) => typeof x === "string"))) problems.push(`"governance.${k}" must be a list of strings`);
|
|
1091
1161
|
if (gov.branchPrefix !== void 0 && !isStr(gov.branchPrefix)) problems.push('"governance.branchPrefix" must be a non-empty string');
|
|
1092
|
-
|
|
1093
|
-
if (o !== void 0 && (!isObj(o) || ["design", "tech"].some((k) => o[k] !== void 0 && !(Array.isArray(o[k]) && o[k].every((x) => typeof x === "string")))))
|
|
1094
|
-
problems.push('"governance.owners" must be { "design": [logins], "tech": [logins] }');
|
|
1162
|
+
problems.push(...ownerEntryProblems(gov.owners));
|
|
1095
1163
|
const ov = gov.override;
|
|
1096
1164
|
if (ov !== void 0) {
|
|
1097
1165
|
if (!isObj(ov)) problems.push('"governance.override" must be an object');
|
|
@@ -1101,8 +1169,10 @@ function loadConfig(source) {
|
|
|
1101
1169
|
if (ov.minReasonLength !== void 0 && !(Number.isInteger(ov.minReasonLength) && ov.minReasonLength >= 0)) problems.push('"governance.override.minReasonLength" must be a whole number, 0 or more');
|
|
1102
1170
|
}
|
|
1103
1171
|
}
|
|
1172
|
+
problems.push(...rightsProblems(gov.rights));
|
|
1104
1173
|
}
|
|
1105
1174
|
}
|
|
1175
|
+
problems.push(...visualImpactProblems(d.visualImpact));
|
|
1106
1176
|
const audit = d.audit;
|
|
1107
1177
|
if (audit !== void 0) {
|
|
1108
1178
|
if (!isObj(audit)) problems.push('"audit" must be an object');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bridge-ds/stylelint-plugin",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Stylelint rule bridge/use-tokens: no raw colors, lengths, radii, shadows, durations or z-index in product CSS where a design token exists. Autofixes exact matches. Reads the tokens through @bridge-ds/core and bridge.config.json.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -56,6 +56,6 @@
|
|
|
56
56
|
"stylelint": "16.26.1"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@bridge-ds/core": "^0.
|
|
59
|
+
"@bridge-ds/core": "^0.4.0"
|
|
60
60
|
}
|
|
61
61
|
}
|