@bridge-ds/stylelint-plugin 0.2.0 → 0.2.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.
Files changed (2) hide show
  1. package/dist/index.js +74 -4
  2. package/package.json +2 -2
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
- const o = gov.owners;
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.0",
3
+ "version": "0.2.1",
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.2.0"
59
+ "@bridge-ds/core": "^0.3.0"
60
60
  }
61
61
  }