@bridge-ds/stylelint-plugin 0.2.3 → 0.2.5

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 +43 -0
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -911,6 +911,47 @@ function visualImpactProblems(raw) {
911
911
  return out;
912
912
  }
913
913
 
914
+ // ../core/src/products.ts
915
+ var DEFAULT_PRODUCTS = [
916
+ { key: "admin", name: "Admin demo", path: "apps/admin", framework: "react" },
917
+ { key: "library", name: "Library", default: true }
918
+ ];
919
+ var KEY = /^[a-z0-9][a-z0-9-]*$/;
920
+ var REPO = /^[\w.-]+\/[\w.-]+$/;
921
+ var FIELDS = ["key", "name", "repo", "path", "preview", "framework", "default"];
922
+ function productProblems(raw) {
923
+ if (raw === void 0) return [];
924
+ if (!Array.isArray(raw)) return ['"products" must be a list of { "key", "name" } objects'];
925
+ if (!raw.length) return ['"products" must list at least one product, or be left out to use the defaults'];
926
+ const problems = [];
927
+ const seen = /* @__PURE__ */ new Set();
928
+ let defaults = 0;
929
+ raw.forEach((p, i) => {
930
+ const at = `"products[${i}]`;
931
+ if (!p || typeof p !== "object" || Array.isArray(p)) {
932
+ problems.push(`${at}" must be an object with a "key" and a "name"`);
933
+ return;
934
+ }
935
+ const o = p;
936
+ for (const k of Object.keys(o)) if (!FIELDS.includes(k)) problems.push(`${at}.${k}" is not a known field (${FIELDS.join(", ")})`);
937
+ if (typeof o.key !== "string" || !KEY.test(o.key)) problems.push(`${at}.key" must be lowercase letters, digits and dashes, such as "admin"`);
938
+ else if (seen.has(o.key)) problems.push(`${at}.key" ("${o.key}") is used twice: give each product its own key`);
939
+ else seen.add(o.key);
940
+ if (typeof o.name !== "string" || !o.name.trim()) problems.push(`${at}.name" must be the name people read, such as "Admin demo"`);
941
+ if (o.repo !== void 0 && (typeof o.repo !== "string" || !REPO.test(o.repo))) problems.push(`${at}.repo" must be "owner/name"`);
942
+ if (o.path !== void 0) {
943
+ const bad = typeof o.path !== "string" || !o.path.trim() || o.path.startsWith("/") || o.path.split("/").includes("..");
944
+ if (bad) problems.push(`${at}.path" must be a folder relative to the repository root, without a leading "/" or "..", such as "apps/admin"`);
945
+ }
946
+ if (o.preview !== void 0 && (typeof o.preview !== "string" || !/^https?:\/\//.test(o.preview))) problems.push(`${at}.preview" must be an http(s) URL template, such as "https://app-git-{branch}.vercel.app"`);
947
+ if (o.framework !== void 0 && (typeof o.framework !== "string" || !o.framework.trim())) problems.push(`${at}.framework" must be a name such as "react", "vue" or "other"`);
948
+ if (o.default !== void 0 && typeof o.default !== "boolean") problems.push(`${at}.default" must be true or false`);
949
+ if (o.default === true) defaults++;
950
+ });
951
+ if (defaults > 1) problems.push('"products" marks more than one product as default: keep "default": true on the library only');
952
+ return problems;
953
+ }
954
+
914
955
  // ../core/src/config.ts
915
956
  var CONFIG_FILE = "bridge.config.json";
916
957
  var DEFAULT_OVERRIDE = { allowed: [], requireReason: true, minReasonLength: 20 };
@@ -1051,6 +1092,7 @@ function defineConfig(input) {
1051
1092
  } : {},
1052
1093
  ...g.rights ? { rights: normalizeRights(g.rights) } : {}
1053
1094
  },
1095
+ products: input.products?.length ? input.products.map((p) => ({ ...p })) : DEFAULT_PRODUCTS.map((p) => ({ ...p })),
1054
1096
  ...input.audit ? { audit: { ...input.audit } } : {},
1055
1097
  ...input.visualImpact ? { visualImpact: { mode: input.visualImpact.mode === "on-demand" ? "on-demand" : "auto" } } : {},
1056
1098
  ...input.integrations ? { integrations: { ...input.integrations } } : {},
@@ -1173,6 +1215,7 @@ function loadConfig(source) {
1173
1215
  }
1174
1216
  }
1175
1217
  problems.push(...visualImpactProblems(d.visualImpact));
1218
+ problems.push(...productProblems(d.products));
1176
1219
  const audit = d.audit;
1177
1220
  if (audit !== void 0) {
1178
1221
  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",
3
+ "version": "0.2.5",
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.5.0"
59
+ "@bridge-ds/core": "^0.7.0"
60
60
  }
61
61
  }