@bridge-ds/core 0.11.0 → 0.13.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/README.md +17 -1
- package/bridge.config.schema.json +5 -0
- package/dist/audit/index.js +3 -3
- package/dist/config.d.ts +5 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +212 -58
- package/dist/index.js.map +1 -1
- package/dist/node/index.js +3 -3
- package/dist/{prod-branch-BdMPKffE.js → prod-branch-6ftQWwdu.js} +41 -23
- package/dist/prod-branch-6ftQWwdu.js.map +1 -0
- package/dist/{report-DOnKUw8G.js → report-BeWNSjPk.js} +2 -2
- package/dist/{report-DOnKUw8G.js.map → report-BeWNSjPk.js.map} +1 -1
- package/dist/review-gate.d.ts +8 -1
- package/dist/rights.d.ts +20 -0
- package/dist/storybook.d.ts +94 -0
- package/dist/{suggestion-apply-DxXRGQrO.js → suggestion-apply-bH6-gZrE.js} +7 -6
- package/dist/suggestion-apply-bH6-gZrE.js.map +1 -0
- package/dist/suggestion-review.d.ts +4 -1
- package/package.json +1 -1
- package/dist/prod-branch-BdMPKffE.js.map +0 -1
- package/dist/suggestion-apply-DxXRGQrO.js.map +0 -1
package/README.md
CHANGED
|
@@ -275,7 +275,7 @@ parseSuggestionIssue(body, { comments?, author? }): { ok: true; payload; sha; ma
|
|
|
275
275
|
suggestionPayloadSha(payload); canonicalJson(value); sha256Hex(text); gitBlobSha(text);
|
|
276
276
|
suggestionLabels(payload, { state?, labels? }); suggestionIssueTitle(payload); suggestionStatus({ state, stateReason?, linkedPrs?, review?, applied?, outdated? });
|
|
277
277
|
suggestionPathProblems(payload, config): string[]; unsafePathProblem(path): string | null;
|
|
278
|
-
summarizeSuggestionApprovals(comments, { owners, rights?, teams? }, { payloadSha, author? }); suggestionReviewState(tier, approvals);
|
|
278
|
+
summarizeSuggestionApprovals(comments, { owners, rights?, teams?, soloOwnerCanApproveBoth? }, { payloadSha, author? }); suggestionReviewState(tier, approvals);
|
|
279
279
|
composeSuggestionReviewComment(record); parseSuggestionReviewComment(body); composeSuggestionAppliedComment(record); parseSuggestionAppliedComment(body);
|
|
280
280
|
// GitHub (Issues read and write only)
|
|
281
281
|
createSuggestionOnGitHub(gh, payload, opts); listSuggestionsOnGitHub(gh, { state? }); getSuggestionOnGitHub(gh, n, gov, { outdated? });
|
|
@@ -283,6 +283,22 @@ reviewSuggestionOnGitHub(gh, n, { event, role?, message?, payloadSha? }, gov); l
|
|
|
283
283
|
declineSuggestionOnGitHub(gh, n, reason, by?); syncSuggestionStateLabel(gh, n, labels, status);
|
|
284
284
|
```
|
|
285
285
|
|
|
286
|
+
## storybook (storybook.ts)
|
|
287
|
+
|
|
288
|
+
Reads a deployed or built Storybook without the repo: `index.json` (v4 for Storybook 7, v5 for 8 and later), else
|
|
289
|
+
`stories.json` (v3). Entries are grouped by title into components (name = last title segment); test entries stay out
|
|
290
|
+
of `stories`. A 404, an HTML answer from a host that falls back to `index.html`, or a body with no entries moves on to
|
|
291
|
+
the next file. Errors carry a code: `invalid-url`, `not-found`, `not-json`, `private` (sign-in wall, Chromatic login
|
|
292
|
+
answer, 401/403), `empty`, `http`, `network`. Pure, with an injected `fetch`; `@bridge-ds/visual` uses the parser for
|
|
293
|
+
`storybook-static/index.json` and the iframe URL builder for its captures.
|
|
294
|
+
|
|
295
|
+
```ts
|
|
296
|
+
fetchStorybookIndex(base, { fetch?, signal? }): Promise<{ version; source: 'index.json' | 'stories.json'; entries; components }>;
|
|
297
|
+
parseStorybookIndex(json, source?); groupStorybookComponents(entries): { title; name; group; stories; docs; tags }[];
|
|
298
|
+
normalizeStorybookUrl(pasted): string; // https only (http on localhost), drops ?path=, /index.html, /iframe.html
|
|
299
|
+
storybookIframeUrl(base, id, { viewMode?, globals?, args? }); storybookManagerUrl(base, id, viewMode?); storybookIndexUrls(base);
|
|
300
|
+
```
|
|
301
|
+
|
|
286
302
|
## history (history.ts, history-github.ts, history-demo.ts)
|
|
287
303
|
|
|
288
304
|
What changed in the tokens, when, who changed it and why, and how to undo it safely.
|
|
@@ -437,6 +437,11 @@
|
|
|
437
437
|
}
|
|
438
438
|
}
|
|
439
439
|
},
|
|
440
|
+
"soloOwnerCanApproveBoth": {
|
|
441
|
+
"type": "boolean",
|
|
442
|
+
"description": "For a design system run by one person. When true and the owners resolve to exactly one person who holds both roles, that person's approval counts as the design and the tech approval, so Tier 2 and Tier 3 changes can be approved. The author of a change still never approves it. Default false: one person never covers both approvals alone.",
|
|
443
|
+
"default": false
|
|
444
|
+
},
|
|
440
445
|
"rights": {
|
|
441
446
|
"type": "object",
|
|
442
447
|
"additionalProperties": false,
|
package/dist/audit/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { i as isAuditable, a as auditFile } from "../report-
|
|
2
|
-
import { A, b, c, C, D, d, F, I, L, e, M, N, f, g, h, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, B, E, G, H, J, K, O, P, Q, R, S, T, U, V, W, X, Y, Z } from "../report-
|
|
3
|
-
import { p as pieceId, a as proposedTokenPath, t as tokenLabel } from "../prod-branch-
|
|
1
|
+
import { i as isAuditable, a as auditFile } from "../report-BeWNSjPk.js";
|
|
2
|
+
import { A, b, c, C, D, d, F, I, L, e, M, N, f, g, h, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, B, E, G, H, J, K, O, P, Q, R, S, T, U, V, W, X, Y, Z } from "../report-BeWNSjPk.js";
|
|
3
|
+
import { p as pieceId, a as proposedTokenPath, t as tokenLabel } from "../prod-branch-6ftQWwdu.js";
|
|
4
4
|
const lines = (text) => text.split(/\r?\n/);
|
|
5
5
|
function lineBag(text) {
|
|
6
6
|
const bag = /* @__PURE__ */ new Map();
|
package/dist/config.d.ts
CHANGED
|
@@ -114,6 +114,11 @@ export interface GovernanceConfig {
|
|
|
114
114
|
* and anyone with write access may ship, as before the field existed.
|
|
115
115
|
*/
|
|
116
116
|
rights?: Rights | undefined;
|
|
117
|
+
/**
|
|
118
|
+
* A design system run by one person: when the owners resolve to exactly one person holding both roles, that
|
|
119
|
+
* person's approval counts for design and tech. Default false: one person never covers both approvals alone.
|
|
120
|
+
*/
|
|
121
|
+
soloOwnerCanApproveBoth?: boolean | undefined;
|
|
117
122
|
}
|
|
118
123
|
/** `bridge audit` settings: how product code that consumes the design system is measured. */
|
|
119
124
|
export interface AuditConfig {
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { m as modeDisplayName, b as modesOf$1, i as isMultiMode, T as TIER_NAMES, c as TIER_AXIS, d as collectRefs, f as findReferenceProblems, e as evaluatePairs, g as contrastScope, h as contextLabel, S as SINGLE_MODE, j as isAlias, k as aliasTarget, l as pathId, v as valuesEqual, n as flattenTokens, s as serializeTokenFile, r as removeToken, u as upsertToken, o as threeWayDiff, q as emptyTokenFile, w as parseTokenFile, E as EXT_ID, x as EXT_SCOPES, y as parseColor, z as rgbaToHex, A as formatValue, B as resolve, C as moveToken, D as effectiveScopes, F as sameScopes, G as defaultScopes, H as readTokenAt, I as modeFile, J as defaultFile, K as selectTokenFiles, L as LayeredTokenSet, M as resolveBranchPreviews, N as loadConfig, O as tokensPath, P as toConfigJson, Q as validateLayered, R as parseContrastChecks, U as classifyRisk, V as CONFIG_FILE, W as RISK_LABELS, X as previewLinks, Y as findPreviewComment, Z as previewsSettled, _ as DEFAULT_TOKEN_PATHS, $ as layoutOptions, a0 as buildTokenSet, a1 as readPreviewComment, a2 as linkStatus, a3 as libraryPreviewState, a4 as parsePiecesRecord, a5 as libraryBranchPlan, a6 as NEEDED_BY_LABEL, a7 as withNeededBy, a8 as withLink, a9 as withPiecesRecord, aa as productBranchSentence, ab as mergePiecesRecord, ac as productOfBranch, ad as defaultProduct, ae as slugify } from "./prod-branch-
|
|
2
|
-
import { af, ag, ah, ai, aj, ak, al, am, an, ao, ap, aq, ar, as, at, au, av, aw, ax, ay, az, aA, aB, aC, aD, aE, aF, aG, aH, aI, aJ, aK, aL, aM, aN, aO, aP, aQ, aR, aS, aT, aU, aV, aW, aX, aY, aZ, a_, a$, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, bn, bo, bp, bq, br, bs, bt, bu, bv, bw, bx, by, bz, bA, bB, bC, bD, bE, bF, bG, bH, bI, bJ, bK, bL, p, bM, bN, bO, bP, bQ, bR, bS, bT, bU, bV, bW, a, bX, bY, bZ, b_, b$, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf, cg,
|
|
3
|
-
import { G as GitHubError, c as collectHistory, p as packageDirCandidates, a as parseChangelog, r as releasesFromTags, m as mergeReleases, b as buildReport, d as applyTokenEdits, e as buildHistoryEntry, f as coerceValue, g as checkLayeredPair, h as formatChangeset, P as PROSE_KEYS, i as markClaudeDraft, j as cleanDraftText, k as docsPrompt, D as DRAFT_LINE_MAX, R as REQUESTS_BRANCH, l as REQUEST_KINDS, s as sanitizeDraftLine, n as parseExplorationBody, E as EXPLORATION_PREFIX, o as explorationSlug, q as explorationStatus, t as explorationTryIt, u as isExplorationPull, v as promotionPlan, w as EXPLORATION_LABEL, x as explorationProblems, y as explorationNote, z as explorationNotePath, A as explorationPrTitle, B as explorationPrBody, C as variantKeyOf, F as overrideComment, O as OVERRIDE_HEADING, H as overrideRefusedComment, I as suggestionStateFromLabels, J as suggestionStatus, K as composeRequestIssue, L as EXPLORATION_NOTES_DIR, M as isExplorationBranch, N as diffLayered, Q as contrastDelta, S as runLayeredContrast, T as layeredImpact, U as classifyLayered, V as composeProposalBody, W as createSuggestionOnGitHub, X as gitBlobSha, Y as SUGGESTION_SCHEMA, Z as branchWithJiraKey, _ as titleWithJiraKey, $ as figmaSpecPath, a0 as formatFigmaSpec, a1 as figmaDraftBrief, a2 as parseFigmaOrigin, a3 as figmaPushStatus, a4 as parseFigmaSpec, a5 as FIGMA_SPEC_DIR, a6 as FROM_FIGMA_LABEL, a7 as withFigmaOrigin, a8 as WAITING_FOR_CLAUDE_LABEL, a9 as DRAFTED_BY_CLAUDE_LABEL, aa as planComponentPush, ab as figmaOriginSection, ac as figmaBranchTitle, ad as figmaSpecSlug, ae as figmaDraftBody, af as REQUEST_LABEL, ag as figmaNodeUrl } from "./suggestion-apply-
|
|
4
|
-
import { ah as ah2, ai as ai2, aj as aj2, ak as ak2, al as al2, am as am2, an as an2, ao as ao2, ap as ap2, aq as aq2, ar as ar2, as as as2, at as at2, au as au2, av as av2, aw as aw2, ax as ax2, ay as ay2, az as az2, aA as aA2, aB as aB2, aC as aC2, aD as aD2, aE as aE2, aF as aF2, aG as aG2, aH as aH2, aI as aI2, aJ as aJ2, aK as aK2, aL as aL2, aM as aM2, aN as aN2, aO as aO2, aP as aP2, aQ as aQ2, aR as aR2, aS as aS2, aT as aT2, aU as aU2, aV as aV2, aW as aW2, aX as aX2, aY as aY2, aZ as aZ2, a_ as a_2, a$ as a$2, b0 as b02, b1 as b12, b2 as b22, b3 as b32, b4 as b42, b5 as b52, b6 as b62, b7 as b72, b8 as b82, b9 as b92, ba as ba2, bb as bb2, bc as bc2, bd as bd2, be as be2, bf as bf2, bg as bg2, bh as bh2, bi as bi2, bj as bj2, bk as bk2, bl as bl2, bm as bm2, bn as bn2, bo as bo2, bp as bp2, bq as bq2, br as br2, bs as bs2, bt as bt2, bu as bu2, bv as bv2, bw as bw2, bx as bx2, by as by2, bz as bz2, bA as bA2, bB as bB2, bC as bC2, bD as bD2, bE as bE2, bF as bF2, bG as bG2, bH as bH2, bI as bI2, bJ as bJ2, bK as bK2, bL as bL2, bM as bM2, bN as bN2, bO as bO2, bP as bP2, bQ as bQ2, bR as bR2, bS as bS2, bT as bT2, bU as bU2, bV as bV2, bW as bW2, bX as bX2, bY as bY2, bZ as bZ2, b_ as b_2, b$ as b$2, c0 as c02, c1 as c12, c2 as c22, c3 as c32, c4 as c42, c5 as c52, c6 as c62, c7 as c72, c8 as c82, c9 as c92, ca as ca2, cb as cb2, cc as cc2, cd as cd2, ce as ce2, cf as cf2, cg as cg2, ch as ch2, ci as ci2, cj as cj2, ck as ck2, cl as cl2, cm as cm2, cn as cn2, co as co2, cp, cq, cr, cs, ct, cu, cv, cw, cx, cy, cz, cA, cB, cC, cD, cE, cF, cG, cH, cI, cJ, cK, cL, cM, cN, cO, cP, cQ, cR, cS, cT, cU, cV, cW, cX, cY, cZ, c_, c$, d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, da, db, dc, dd, de, df, dg, dh } from "./suggestion-apply-
|
|
1
|
+
import { m as modeDisplayName, b as modesOf$1, i as isMultiMode, T as TIER_NAMES, c as TIER_AXIS, d as collectRefs, f as findReferenceProblems, e as evaluatePairs, g as contrastScope, h as contextLabel, S as SINGLE_MODE, j as isAlias, k as aliasTarget, l as pathId, v as valuesEqual, n as flattenTokens, s as serializeTokenFile, r as removeToken, u as upsertToken, o as threeWayDiff, q as emptyTokenFile, w as parseTokenFile, E as EXT_ID, x as EXT_SCOPES, y as parseColor, z as rgbaToHex, A as formatValue, B as resolve, C as moveToken, D as effectiveScopes, F as sameScopes, G as defaultScopes, H as readTokenAt, I as modeFile, J as defaultFile, K as selectTokenFiles, L as LayeredTokenSet, M as resolveBranchPreviews, N as loadConfig, O as tokensPath, P as toConfigJson, Q as validateLayered, R as parseContrastChecks, U as classifyRisk, V as CONFIG_FILE, W as RISK_LABELS, X as previewLinks, Y as findPreviewComment, Z as previewsSettled, _ as DEFAULT_TOKEN_PATHS, $ as layoutOptions, a0 as buildTokenSet, a1 as readPreviewComment, a2 as linkStatus, a3 as libraryPreviewState, a4 as parsePiecesRecord, a5 as libraryBranchPlan, a6 as NEEDED_BY_LABEL, a7 as withNeededBy, a8 as withLink, a9 as withPiecesRecord, aa as productBranchSentence, ab as mergePiecesRecord, ac as productOfBranch, ad as defaultProduct, ae as slugify } from "./prod-branch-6ftQWwdu.js";
|
|
2
|
+
import { af, ag, ah, ai, aj, ak, al, am, an, ao, ap, aq, ar, as, at, au, av, aw, ax, ay, az, aA, aB, aC, aD, aE, aF, aG, aH, aI, aJ, aK, aL, aM, aN, aO, aP, aQ, aR, aS, aT, aU, aV, aW, aX, aY, aZ, a_, a$, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, bn, bo, bp, bq, br, bs, bt, bu, bv, bw, bx, by, bz, bA, bB, bC, bD, bE, bF, bG, bH, bI, bJ, bK, bL, p, bM, bN, bO, bP, bQ, bR, bS, bT, bU, bV, bW, a, bX, bY, bZ, b_, b$, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, t, ck, cl, cm, cn, co, cp, cq, cr } from "./prod-branch-6ftQWwdu.js";
|
|
3
|
+
import { G as GitHubError, c as collectHistory, p as packageDirCandidates, a as parseChangelog, r as releasesFromTags, m as mergeReleases, b as buildReport, d as applyTokenEdits, e as buildHistoryEntry, f as coerceValue, g as checkLayeredPair, h as formatChangeset, P as PROSE_KEYS, i as markClaudeDraft, j as cleanDraftText, k as docsPrompt, D as DRAFT_LINE_MAX, R as REQUESTS_BRANCH, l as REQUEST_KINDS, s as sanitizeDraftLine, n as parseExplorationBody, E as EXPLORATION_PREFIX, o as explorationSlug, q as explorationStatus, t as explorationTryIt, u as isExplorationPull, v as promotionPlan, w as EXPLORATION_LABEL, x as explorationProblems, y as explorationNote, z as explorationNotePath, A as explorationPrTitle, B as explorationPrBody, C as variantKeyOf, F as overrideComment, O as OVERRIDE_HEADING, H as overrideRefusedComment, I as suggestionStateFromLabels, J as suggestionStatus, K as composeRequestIssue, L as EXPLORATION_NOTES_DIR, M as isExplorationBranch, N as diffLayered, Q as contrastDelta, S as runLayeredContrast, T as layeredImpact, U as classifyLayered, V as composeProposalBody, W as createSuggestionOnGitHub, X as gitBlobSha, Y as SUGGESTION_SCHEMA, Z as branchWithJiraKey, _ as titleWithJiraKey, $ as figmaSpecPath, a0 as formatFigmaSpec, a1 as figmaDraftBrief, a2 as parseFigmaOrigin, a3 as figmaPushStatus, a4 as parseFigmaSpec, a5 as FIGMA_SPEC_DIR, a6 as FROM_FIGMA_LABEL, a7 as withFigmaOrigin, a8 as WAITING_FOR_CLAUDE_LABEL, a9 as DRAFTED_BY_CLAUDE_LABEL, aa as planComponentPush, ab as figmaOriginSection, ac as figmaBranchTitle, ad as figmaSpecSlug, ae as figmaDraftBody, af as REQUEST_LABEL, ag as figmaNodeUrl } from "./suggestion-apply-bH6-gZrE.js";
|
|
4
|
+
import { ah as ah2, ai as ai2, aj as aj2, ak as ak2, al as al2, am as am2, an as an2, ao as ao2, ap as ap2, aq as aq2, ar as ar2, as as as2, at as at2, au as au2, av as av2, aw as aw2, ax as ax2, ay as ay2, az as az2, aA as aA2, aB as aB2, aC as aC2, aD as aD2, aE as aE2, aF as aF2, aG as aG2, aH as aH2, aI as aI2, aJ as aJ2, aK as aK2, aL as aL2, aM as aM2, aN as aN2, aO as aO2, aP as aP2, aQ as aQ2, aR as aR2, aS as aS2, aT as aT2, aU as aU2, aV as aV2, aW as aW2, aX as aX2, aY as aY2, aZ as aZ2, a_ as a_2, a$ as a$2, b0 as b02, b1 as b12, b2 as b22, b3 as b32, b4 as b42, b5 as b52, b6 as b62, b7 as b72, b8 as b82, b9 as b92, ba as ba2, bb as bb2, bc as bc2, bd as bd2, be as be2, bf as bf2, bg as bg2, bh as bh2, bi as bi2, bj as bj2, bk as bk2, bl as bl2, bm as bm2, bn as bn2, bo as bo2, bp as bp2, bq as bq2, br as br2, bs as bs2, bt as bt2, bu as bu2, bv as bv2, bw as bw2, bx as bx2, by as by2, bz as bz2, bA as bA2, bB as bB2, bC as bC2, bD as bD2, bE as bE2, bF as bF2, bG as bG2, bH as bH2, bI as bI2, bJ as bJ2, bK as bK2, bL as bL2, bM as bM2, bN as bN2, bO as bO2, bP as bP2, bQ as bQ2, bR as bR2, bS as bS2, bT as bT2, bU as bU2, bV as bV2, bW as bW2, bX as bX2, bY as bY2, bZ as bZ2, b_ as b_2, b$ as b$2, c0 as c02, c1 as c12, c2 as c22, c3 as c32, c4 as c42, c5 as c52, c6 as c62, c7 as c72, c8 as c82, c9 as c92, ca as ca2, cb as cb2, cc as cc2, cd as cd2, ce as ce2, cf as cf2, cg as cg2, ch as ch2, ci as ci2, cj as cj2, ck as ck2, cl as cl2, cm as cm2, cn as cn2, co as co2, cp as cp2, cq as cq2, cr as cr2, cs, ct, cu, cv, cw, cx, cy, cz, cA, cB, cC, cD, cE, cF, cG, cH, cI, cJ, cK, cL, cM, cN, cO, cP, cQ, cR, cS, cT, cU, cV, cW, cX, cY, cZ, c_, c$, d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, da, db, dc, dd, de, df, dg, dh } from "./suggestion-apply-bH6-gZrE.js";
|
|
5
5
|
const issueKey$1 = (i) => `${i.code}|${i.path ?? ""}|${i.mode ?? ""}|${i.code === "file-problem" ? i.message : ""}`;
|
|
6
6
|
const modeName = (mode) => mode === SINGLE_MODE ? "all modes" : modeDisplayName(mode);
|
|
7
7
|
const isPalette = (t2) => t2.tier === "brand" && t2.path.startsWith("palette.");
|
|
@@ -52,7 +52,7 @@ function checkValue(set, owner, value, mode, where, issues) {
|
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
-
function validateSet(set,
|
|
55
|
+
function validateSet(set, pairs2) {
|
|
56
56
|
const issues = [];
|
|
57
57
|
for (const p2 of set.problems) issues.push({ code: "file-problem", severity: "error", message: p2 });
|
|
58
58
|
for (const t2 of set.tokens.values()) {
|
|
@@ -119,7 +119,7 @@ function validateSet(set, pairs) {
|
|
|
119
119
|
}
|
|
120
120
|
);
|
|
121
121
|
}
|
|
122
|
-
const contrast = evaluatePairs(set.byPath,
|
|
122
|
+
const contrast = evaluatePairs(set.byPath, pairs2, contrastScope(set));
|
|
123
123
|
for (const r of contrast) {
|
|
124
124
|
const path = `${r.pair.foreground} on ${r.pair.background}`;
|
|
125
125
|
const mode = `${r.brand ?? ""}.${r.theme}`;
|
|
@@ -154,9 +154,9 @@ function shadowedEdits(set, edits) {
|
|
|
154
154
|
}
|
|
155
155
|
return out;
|
|
156
156
|
}
|
|
157
|
-
function validateProposal(proposed, head,
|
|
158
|
-
const after = validateSet(proposed,
|
|
159
|
-
const before = validateSet(head,
|
|
157
|
+
function validateProposal(proposed, head, pairs2, typeChanges = []) {
|
|
158
|
+
const after = validateSet(proposed, pairs2);
|
|
159
|
+
const before = validateSet(head, pairs2);
|
|
160
160
|
const existing = new Set(before.issues.map(issueKey$1));
|
|
161
161
|
const blocking = [];
|
|
162
162
|
const warnings = [];
|
|
@@ -1112,7 +1112,7 @@ const RADIUS_ROLES = ["inset", "control", "container", "overlay"];
|
|
|
1112
1112
|
const RESERVED = /* @__PURE__ */ new Set(["default", "base", "all", "none", "new", "blank", "primitives", "semantic", "components", "density"]);
|
|
1113
1113
|
const BRAND_SLUG_RE = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
1114
1114
|
const DEFAULT_PRIMARY_CHROMA = 0.14;
|
|
1115
|
-
const isObj = (x) => !!x && typeof x === "object" && !Array.isArray(x);
|
|
1115
|
+
const isObj$1 = (x) => !!x && typeof x === "object" && !Array.isArray(x);
|
|
1116
1116
|
const fileMap = (f) => f instanceof Map ? new Map(f) : new Map(Object.entries(f));
|
|
1117
1117
|
const brandDisplayName = (slug) => slug.split("-").filter(Boolean).map((w) => w[0].toUpperCase() + w.slice(1)).join(" ");
|
|
1118
1118
|
function brandLayers(config) {
|
|
@@ -1133,27 +1133,27 @@ function setAt(doc, path, node) {
|
|
|
1133
1133
|
const keys = path.split(".");
|
|
1134
1134
|
let cur = doc;
|
|
1135
1135
|
for (const k of keys.slice(0, -1)) {
|
|
1136
|
-
if (!isObj(cur[k])) cur[k] = {};
|
|
1136
|
+
if (!isObj$1(cur[k])) cur[k] = {};
|
|
1137
1137
|
cur = cur[k];
|
|
1138
1138
|
}
|
|
1139
1139
|
const last = keys[keys.length - 1];
|
|
1140
|
-
const prev = isObj(cur[last]) ? cur[last] : {};
|
|
1140
|
+
const prev = isObj$1(cur[last]) ? cur[last] : {};
|
|
1141
1141
|
cur[last] = { ...prev, ...node };
|
|
1142
1142
|
}
|
|
1143
1143
|
function getAt(doc, path) {
|
|
1144
1144
|
let cur = doc;
|
|
1145
|
-
for (const k of path.split(".")) cur = isObj(cur) ? cur[k] : void 0;
|
|
1146
|
-
return isObj(cur) ? cur : void 0;
|
|
1145
|
+
for (const k of path.split(".")) cur = isObj$1(cur) ? cur[k] : void 0;
|
|
1146
|
+
return isObj$1(cur) ? cur : void 0;
|
|
1147
1147
|
}
|
|
1148
1148
|
function typeAt(doc, path) {
|
|
1149
1149
|
let cur = doc;
|
|
1150
1150
|
let type;
|
|
1151
1151
|
for (const k of path.split(".")) {
|
|
1152
|
-
if (!isObj(cur)) return type;
|
|
1152
|
+
if (!isObj$1(cur)) return type;
|
|
1153
1153
|
if (typeof cur.$type === "string") type = cur.$type;
|
|
1154
1154
|
cur = cur[k];
|
|
1155
1155
|
}
|
|
1156
|
-
return isObj(cur) && typeof cur.$type === "string" ? cur.$type : type;
|
|
1156
|
+
return isObj$1(cur) && typeof cur.$type === "string" ? cur.$type : type;
|
|
1157
1157
|
}
|
|
1158
1158
|
function rampFor(input, pinStep, kind) {
|
|
1159
1159
|
if (typeof input === "number" || typeof input === "string" && /^\d+(\.\d+)?$/.test(input.trim())) {
|
|
@@ -1210,7 +1210,7 @@ function listBrands(source) {
|
|
|
1210
1210
|
doc = JSON.parse(files.get(file) ?? "{}");
|
|
1211
1211
|
} catch {
|
|
1212
1212
|
}
|
|
1213
|
-
const meta = isObj(doc.$extensions) && isObj(doc.$extensions["dev.bridge.brand"]) ? doc.$extensions["dev.bridge.brand"] : {};
|
|
1213
|
+
const meta = isObj$1(doc.$extensions) && isObj$1(doc.$extensions["dev.bridge.brand"]) ? doc.$extensions["dev.bridge.brand"] : {};
|
|
1214
1214
|
const combo = set.normalizeCombo({ brand: slug });
|
|
1215
1215
|
const primary = set.resolve("color.action.primary.bg", combo);
|
|
1216
1216
|
const overrides = layers.override ? (config.axes[layers.overrideAxis]?.values ?? []).map((v) => fill(layers.override, { brand: slug, [layers.overrideAxis]: v })).filter((f) => files.has(f)) : [];
|
|
@@ -1300,7 +1300,7 @@ function planNewBrand(source, input) {
|
|
|
1300
1300
|
for (const [path, defs] of before.view(before.defaultCombo)) {
|
|
1301
1301
|
const m = /^radius\.([\w-]+)$/.exec(path);
|
|
1302
1302
|
const v = defs[defs.length - 1].value;
|
|
1303
|
-
if (m && isObj(v) && typeof v.value === "number" && v.unit === "px" && !getAt(doc, path)) scale.set(v.value, m[1]);
|
|
1303
|
+
if (m && isObj$1(v) && typeof v.value === "number" && v.unit === "px" && !getAt(doc, path)) scale.set(v.value, m[1]);
|
|
1304
1304
|
}
|
|
1305
1305
|
const radius = input.radius ?? (blank ? RADIUS_PRESETS[0].radius : void 0);
|
|
1306
1306
|
if (radius) {
|
|
@@ -1339,9 +1339,9 @@ function planNewBrand(source, input) {
|
|
|
1339
1339
|
}
|
|
1340
1340
|
const palette = getAt(doc, "palette");
|
|
1341
1341
|
for (const [role, group] of Object.entries(palette ?? {})) {
|
|
1342
|
-
if (role.startsWith("$") || !isObj(group)) continue;
|
|
1342
|
+
if (role.startsWith("$") || !isObj$1(group)) continue;
|
|
1343
1343
|
for (const [step, node] of Object.entries(group)) {
|
|
1344
|
-
if (step.startsWith("$") || !isObj(node) || !("$value" in node) || typeof node.$value === "string") continue;
|
|
1344
|
+
if (step.startsWith("$") || !isObj$1(node) || !("$value" in node) || typeof node.$value === "string") continue;
|
|
1345
1345
|
const ramp = `${slug}-${role}`;
|
|
1346
1346
|
const entry = prims.get(ramp) ?? { description: `${name} ${role}. Exact values set when the brand was created.`, steps: /* @__PURE__ */ new Map() };
|
|
1347
1347
|
entry.steps.set(Number(step), node.$value);
|
|
@@ -1354,7 +1354,7 @@ function planNewBrand(source, input) {
|
|
|
1354
1354
|
if (prims.size && files.has(primFile)) issues.push({ level: "error", code: "slug-file-exists", message: `${tokensPath(config, primFile)} already exists. Pick another name.` });
|
|
1355
1355
|
for (const r of prims.keys()) if (before.allPaths().some((p2) => p2.startsWith(`color.${r}.`))) issues.push({ level: "error", code: "ramp-exists", message: `A primitive ramp color.${r} already exists. Pick another name.` });
|
|
1356
1356
|
doc.$description = `${name}: created with Bridge, started from ${blank ? "a blank brand" : brandDisplayName(from)}.`;
|
|
1357
|
-
doc.$extensions = { ...isObj(doc.$extensions) ? doc.$extensions : {}, "dev.bridge.brand": { name, from, ...Object.keys(anchors).length ? { anchors } : {} } };
|
|
1357
|
+
doc.$extensions = { ...isObj$1(doc.$extensions) ? doc.$extensions : {}, "dev.bridge.brand": { name, from, ...Object.keys(anchors).length ? { anchors } : {} } };
|
|
1358
1358
|
const { $description, $extensions, ...rest } = doc;
|
|
1359
1359
|
const brandFile = fill(layers.brand, { brand: slug });
|
|
1360
1360
|
const nextFiles = new Map(files);
|
|
@@ -1406,10 +1406,10 @@ function planNewBrand(source, input) {
|
|
|
1406
1406
|
if (i.modes && !i.modes.some((m) => m.split(",").includes(brandKey)) && !created.includes(i.file ?? "")) continue;
|
|
1407
1407
|
issues.push({ level: i.level, code: i.code, message: i.message, ...i.path ? { path: i.path } : {}, ...i.file ? { file: tokensPath(config, i.file) } : {} });
|
|
1408
1408
|
}
|
|
1409
|
-
const
|
|
1409
|
+
const pairs2 = parseContrastChecks(source.contrastText);
|
|
1410
1410
|
const inGate = nextConfig.axes.brand?.values.includes(slug);
|
|
1411
1411
|
const combos = inGate ? after.combos(nextConfig.contrast?.modes).filter((c) => c.brand === slug) : [];
|
|
1412
|
-
const results = combos.flatMap((c) =>
|
|
1412
|
+
const results = combos.flatMap((c) => pairs2.map((p2) => checkLayeredPair(after, p2, c)));
|
|
1413
1413
|
const failing = results.filter((r) => !r.pass);
|
|
1414
1414
|
const themes = [...new Set(combos.map((c) => c.theme).filter((t2) => !!t2))];
|
|
1415
1415
|
const ramps = {};
|
|
@@ -1780,7 +1780,7 @@ function composePendingDrafts(input) {
|
|
|
1780
1780
|
return p2;
|
|
1781
1781
|
}
|
|
1782
1782
|
const KINDS = new Set(REQUEST_KINDS.map((k) => k.value));
|
|
1783
|
-
const str = (x) => typeof x === "string";
|
|
1783
|
+
const str$1 = (x) => typeof x === "string";
|
|
1784
1784
|
const optStr = (x) => x === void 0 || typeof x === "string";
|
|
1785
1785
|
function validatePendingDrafts(x) {
|
|
1786
1786
|
const out = [];
|
|
@@ -1788,7 +1788,7 @@ function validatePendingDrafts(x) {
|
|
|
1788
1788
|
const p2 = x;
|
|
1789
1789
|
if (p2.version !== DRAFT_EXCHANGE_VERSION) out.push(`Unsupported draft session version ${String(p2.version)}: update Bridge.`);
|
|
1790
1790
|
if (!isDraftSessionId(p2.sessionId)) out.push("The session id is missing or invalid.");
|
|
1791
|
-
if (!str(p2.createdAt) || Number.isNaN(Date.parse(p2.createdAt))) out.push("createdAt must be an ISO date.");
|
|
1791
|
+
if (!str$1(p2.createdAt) || Number.isNaN(Date.parse(p2.createdAt))) out.push("createdAt must be an ISO date.");
|
|
1792
1792
|
if (p2.status !== "pending" && p2.status !== "drafted") out.push('status must be "pending" or "drafted".');
|
|
1793
1793
|
if (p2.source !== "figma" && p2.source !== "studio") out.push('source must be "figma" or "studio".');
|
|
1794
1794
|
if (!Array.isArray(p2.items) || !p2.items.length) out.push("A draft session needs at least one item.");
|
|
@@ -1799,32 +1799,32 @@ function validatePendingDrafts(x) {
|
|
|
1799
1799
|
out.push(`${at3} is not an object.`);
|
|
1800
1800
|
continue;
|
|
1801
1801
|
}
|
|
1802
|
-
if (!str(i.id) || !i.id) out.push(`${at3} has no id.`);
|
|
1802
|
+
if (!str$1(i.id) || !i.id) out.push(`${at3} has no id.`);
|
|
1803
1803
|
else if (ids.has(i.id)) out.push(`${at3} repeats the id "${i.id}".`);
|
|
1804
1804
|
else ids.add(i.id);
|
|
1805
1805
|
if (i.scope !== "request" && i.scope !== "push" && i.scope !== "docs") out.push(`${at3}: scope must be "request", "push" or "docs".`);
|
|
1806
1806
|
if (i.scope === "docs") {
|
|
1807
1807
|
const d = i.docs;
|
|
1808
|
-
if (!d || typeof d !== "object" || !str(d.slug) || !d.slug || !str(d.prompt) || !d.prompt || !optStr(d.path)) out.push(`${at3}: a docs item needs docs {slug, task, prompt}.`);
|
|
1808
|
+
if (!d || typeof d !== "object" || !str$1(d.slug) || !d.slug || !str$1(d.prompt) || !d.prompt || !optStr(d.path)) out.push(`${at3}: a docs item needs docs {slug, task, prompt}.`);
|
|
1809
1809
|
else out.push(...validateDocsTask(d.task).map((m) => `${at3}: ${m}`));
|
|
1810
1810
|
} else if (i.docs !== void 0) out.push(`${at3}: only a docs item has docs.`);
|
|
1811
1811
|
if (!optStr(i.component)) out.push(`${at3}: component must be text.`);
|
|
1812
1812
|
if (i.kind !== void 0 && !KINDS.has(i.kind)) out.push(`${at3}: unknown kind "${String(i.kind)}".`);
|
|
1813
|
-
if (!Array.isArray(i.changes) || i.changes.some((c) => !c || !str(c.field) || !optStr(c.before) || !optStr(c.after))) out.push(`${at3}: changes must be a list of {field, before, after}.`);
|
|
1814
|
-
if (i.variables !== void 0 && (!Array.isArray(i.variables) || i.variables.some((v) => !v || !str(v.path)))) out.push(`${at3}: variables must be a list of {path, before, after}.`);
|
|
1813
|
+
if (!Array.isArray(i.changes) || i.changes.some((c) => !c || !str$1(c.field) || !optStr(c.before) || !optStr(c.after))) out.push(`${at3}: changes must be a list of {field, before, after}.`);
|
|
1814
|
+
if (i.variables !== void 0 && (!Array.isArray(i.variables) || i.variables.some((v) => !v || !str$1(v.path)))) out.push(`${at3}: variables must be a list of {path, before, after}.`);
|
|
1815
1815
|
if (i.variables !== void 0 && i.scope !== "push") out.push(`${at3}: only a push item has variables.`);
|
|
1816
|
-
if (i.images !== void 0 && (!Array.isArray(i.images) || i.images.some((m) => !m || m.label !== "before" && m.label !== "after" || !str(m.url)))) out.push(`${at3}: images must be a list of {label: before or after, url}.`);
|
|
1817
|
-
if (!i.draft || !str(i.draft.title) || !str(i.draft.summary)) out.push(`${at3}: draft must hold a title and a summary.`);
|
|
1818
|
-
if (i.lines !== void 0 && (!Array.isArray(i.lines) || i.lines.some((l) => !l || !str(l.id) || !l.id || !str(l.line) || !optStr(l.title) || !Array.isArray(l.changes)))) out.push(`${at3}: lines must be a list of {id, changes, line, title}.`);
|
|
1816
|
+
if (i.images !== void 0 && (!Array.isArray(i.images) || i.images.some((m) => !m || m.label !== "before" && m.label !== "after" || !str$1(m.url)))) out.push(`${at3}: images must be a list of {label: before or after, url}.`);
|
|
1817
|
+
if (!i.draft || !str$1(i.draft.title) || !str$1(i.draft.summary)) out.push(`${at3}: draft must hold a title and a summary.`);
|
|
1818
|
+
if (i.lines !== void 0 && (!Array.isArray(i.lines) || i.lines.some((l) => !l || !str$1(l.id) || !l.id || !str$1(l.line) || !optStr(l.title) || !Array.isArray(l.changes)))) out.push(`${at3}: lines must be a list of {id, changes, line, title}.`);
|
|
1819
1819
|
}
|
|
1820
1820
|
if (p2.results !== void 0) {
|
|
1821
1821
|
if (!Array.isArray(p2.results)) out.push("results must be a list.");
|
|
1822
1822
|
else
|
|
1823
1823
|
for (const r of p2.results) {
|
|
1824
|
-
if (!r || !str(r.id) || !str(r.title) || !str(r.summary)) out.push("Each result needs an id, a title and a summary.");
|
|
1824
|
+
if (!r || !str$1(r.id) || !str$1(r.title) || !str$1(r.summary)) out.push("Each result needs an id, a title and a summary.");
|
|
1825
1825
|
else if (r.docs !== void 0 && (!r.docs || typeof r.docs !== "object" || Array.isArray(r.docs))) out.push("Result docs must be an object of sections.");
|
|
1826
1826
|
else if (!optStr(r.replacement)) out.push("A result replacement must be text.");
|
|
1827
|
-
else if (r.lines !== void 0 && (!Array.isArray(r.lines) || r.lines.some((l) => !l || !str(l.id) || !str(l.line) || !optStr(l.title)))) out.push("Result lines must be a list of {id, line, title}.");
|
|
1827
|
+
else if (r.lines !== void 0 && (!Array.isArray(r.lines) || r.lines.some((l) => !l || !str$1(l.id) || !str$1(l.line) || !optStr(l.title)))) out.push("Result lines must be a list of {id, line, title}.");
|
|
1828
1828
|
}
|
|
1829
1829
|
}
|
|
1830
1830
|
return out;
|
|
@@ -3210,6 +3210,149 @@ async function figmaPushStatusesOnGitHub(gh, numbers) {
|
|
|
3210
3210
|
);
|
|
3211
3211
|
return out;
|
|
3212
3212
|
}
|
|
3213
|
+
class StorybookIndexError extends Error {
|
|
3214
|
+
constructor(code2, message, status) {
|
|
3215
|
+
super(message);
|
|
3216
|
+
this.code = code2;
|
|
3217
|
+
this.status = status;
|
|
3218
|
+
this.name = "StorybookIndexError";
|
|
3219
|
+
}
|
|
3220
|
+
code;
|
|
3221
|
+
status;
|
|
3222
|
+
}
|
|
3223
|
+
const isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
3224
|
+
const str = (v) => typeof v === "string" && v.trim() ? v : void 0;
|
|
3225
|
+
function entryFrom(key, raw, v3) {
|
|
3226
|
+
if (!isObj(raw)) return null;
|
|
3227
|
+
const id = str(raw.id) ?? key;
|
|
3228
|
+
const title = str(raw.title) ?? str(raw.kind);
|
|
3229
|
+
const name = str(raw.name) ?? str(raw.story);
|
|
3230
|
+
if (!id || !title || !name) return null;
|
|
3231
|
+
const params = isObj(raw.parameters) ? raw.parameters : {};
|
|
3232
|
+
const type = raw.type === "docs" || raw.type === "story" ? raw.type : v3 && params.docsOnly === true ? "docs" : "story";
|
|
3233
|
+
const e = {
|
|
3234
|
+
id,
|
|
3235
|
+
title,
|
|
3236
|
+
name,
|
|
3237
|
+
type,
|
|
3238
|
+
importPath: str(raw.importPath) ?? str(params.fileName) ?? "",
|
|
3239
|
+
tags: Array.isArray(raw.tags) ? raw.tags.filter((t2) => typeof t2 === "string") : []
|
|
3240
|
+
};
|
|
3241
|
+
const subtype = str(raw.subtype);
|
|
3242
|
+
if (subtype) e.subtype = subtype;
|
|
3243
|
+
const exportName2 = str(raw.exportName);
|
|
3244
|
+
if (exportName2) e.exportName = exportName2;
|
|
3245
|
+
const componentPath = str(raw.componentPath);
|
|
3246
|
+
if (componentPath) e.componentPath = componentPath;
|
|
3247
|
+
return e;
|
|
3248
|
+
}
|
|
3249
|
+
function groupStorybookComponents(entries) {
|
|
3250
|
+
const byTitle = /* @__PURE__ */ new Map();
|
|
3251
|
+
for (const e of entries) {
|
|
3252
|
+
let c = byTitle.get(e.title);
|
|
3253
|
+
if (!c) {
|
|
3254
|
+
const parts = e.title.split("/").map((p2) => p2.trim()).filter(Boolean);
|
|
3255
|
+
c = { title: e.title, name: parts[parts.length - 1] ?? e.title, group: parts.slice(0, -1), stories: [], docs: [], tags: [] };
|
|
3256
|
+
byTitle.set(e.title, c);
|
|
3257
|
+
}
|
|
3258
|
+
if (e.type === "docs") c.docs.push(e);
|
|
3259
|
+
else if (e.subtype !== "test") c.stories.push(e);
|
|
3260
|
+
for (const t2 of e.tags) if (!c.tags.includes(t2)) c.tags.push(t2);
|
|
3261
|
+
}
|
|
3262
|
+
const out = [...byTitle.values()].filter((c) => c.stories.length || c.docs.length);
|
|
3263
|
+
for (const c of out) c.tags.sort();
|
|
3264
|
+
return out.sort((a2, b) => a2.title.localeCompare(b.title));
|
|
3265
|
+
}
|
|
3266
|
+
function parseStorybookIndex(json, source) {
|
|
3267
|
+
if (!isObj(json)) throw new StorybookIndexError("not-json", "The Storybook index is not a JSON object.");
|
|
3268
|
+
if (typeof json.loginUrl === "string" && !("entries" in json) && !("stories" in json)) {
|
|
3269
|
+
throw new StorybookIndexError("private", "This Storybook is private: it asks for a sign-in before showing its index.");
|
|
3270
|
+
}
|
|
3271
|
+
const map = isObj(json.entries) ? json.entries : isObj(json.stories) ? json.stories : null;
|
|
3272
|
+
if (!map) throw new StorybookIndexError("empty", "This file has no Storybook entries.");
|
|
3273
|
+
const v3 = !isObj(json.entries);
|
|
3274
|
+
const entries = Object.entries(map).map(([k, raw]) => entryFrom(k, raw, v3)).filter((e) => e !== null);
|
|
3275
|
+
if (!entries.length) throw new StorybookIndexError("empty", "This Storybook index lists no stories or docs.");
|
|
3276
|
+
const version = typeof json.v === "number" ? json.v : v3 ? 3 : 4;
|
|
3277
|
+
return { version, source: source ?? (v3 ? "stories.json" : "index.json"), entries, components: groupStorybookComponents(entries) };
|
|
3278
|
+
}
|
|
3279
|
+
function normalizeStorybookUrl(input) {
|
|
3280
|
+
let u;
|
|
3281
|
+
try {
|
|
3282
|
+
u = new URL(input.trim());
|
|
3283
|
+
} catch {
|
|
3284
|
+
throw new StorybookIndexError("invalid-url", "Enter the full Storybook address, for example https://storybook.example.com");
|
|
3285
|
+
}
|
|
3286
|
+
const local = u.hostname === "localhost" || u.hostname === "127.0.0.1" || u.hostname === "[::1]";
|
|
3287
|
+
if (u.protocol !== "https:" && !(u.protocol === "http:" && local)) {
|
|
3288
|
+
throw new StorybookIndexError("invalid-url", "The Storybook address must start with https://");
|
|
3289
|
+
}
|
|
3290
|
+
if (u.username || u.password) throw new StorybookIndexError("invalid-url", "Remove the user name and password from the address.");
|
|
3291
|
+
const path = u.pathname.replace(/\/(index\.html|iframe\.html|index\.json|stories\.json)$/i, "/").replace(/\/+$/, "");
|
|
3292
|
+
return `${u.protocol}//${u.host}${path}`;
|
|
3293
|
+
}
|
|
3294
|
+
const storybookIndexUrls = (base) => {
|
|
3295
|
+
const b = base.replace(/\/+$/, "");
|
|
3296
|
+
return [
|
|
3297
|
+
{ url: `${b}/index.json`, source: "index.json" },
|
|
3298
|
+
{ url: `${b}/stories.json`, source: "stories.json" }
|
|
3299
|
+
];
|
|
3300
|
+
};
|
|
3301
|
+
const pairs = (o) => Object.entries(o).map(([k, v]) => `${encodeURIComponent(k)}:${encodeURIComponent(v)}`).join(";");
|
|
3302
|
+
function storybookIframeUrl(base, id, o = {}) {
|
|
3303
|
+
let url = `${base.replace(/\/+$/, "")}/iframe.html?id=${encodeURIComponent(id)}&viewMode=${o.viewMode ?? "story"}`;
|
|
3304
|
+
if (o.globals && Object.keys(o.globals).length) url += `&globals=${pairs(o.globals)}`;
|
|
3305
|
+
if (o.args && Object.keys(o.args).length) url += `&args=${pairs(o.args)}`;
|
|
3306
|
+
return url;
|
|
3307
|
+
}
|
|
3308
|
+
function storybookManagerUrl(base, id, viewMode = "story") {
|
|
3309
|
+
return `${base.replace(/\/+$/, "")}/?path=/${viewMode}/${encodeURIComponent(id)}`;
|
|
3310
|
+
}
|
|
3311
|
+
async function fetchStorybookIndex(base, o = {}) {
|
|
3312
|
+
const doFetch = o.fetch ?? ((url, init) => fetch(url, init));
|
|
3313
|
+
const rank = { private: 6, http: 5, network: 4, empty: 3, "not-json": 2, "not-found": 1, "invalid-url": 0 };
|
|
3314
|
+
let worst = null;
|
|
3315
|
+
const keep = (e) => {
|
|
3316
|
+
if (!worst || rank[e.code] > rank[worst.code]) worst = e;
|
|
3317
|
+
};
|
|
3318
|
+
for (const { url, source } of storybookIndexUrls(base)) {
|
|
3319
|
+
let res;
|
|
3320
|
+
try {
|
|
3321
|
+
res = await doFetch(url, { headers: { accept: "application/json" }, ...o.signal ? { signal: o.signal } : {} });
|
|
3322
|
+
} catch (err) {
|
|
3323
|
+
if (o.signal?.aborted) throw err;
|
|
3324
|
+
keep(new StorybookIndexError("network", `Could not reach ${url}. The host may be down or may not allow reading from another site.`));
|
|
3325
|
+
continue;
|
|
3326
|
+
}
|
|
3327
|
+
if (res.status === 404 || res.status === 410) {
|
|
3328
|
+
keep(new StorybookIndexError("not-found", `No Storybook index at ${base}: neither index.json nor stories.json was found.`, res.status));
|
|
3329
|
+
continue;
|
|
3330
|
+
}
|
|
3331
|
+
if (res.status === 401 || res.status === 403) {
|
|
3332
|
+
keep(new StorybookIndexError("private", "This Storybook is private: it asks for a sign-in before showing its index.", res.status));
|
|
3333
|
+
continue;
|
|
3334
|
+
}
|
|
3335
|
+
if (!res.ok) {
|
|
3336
|
+
keep(new StorybookIndexError("http", `The Storybook host answered ${res.status} for ${url}.`, res.status));
|
|
3337
|
+
continue;
|
|
3338
|
+
}
|
|
3339
|
+
const text = await res.text();
|
|
3340
|
+
let json;
|
|
3341
|
+
try {
|
|
3342
|
+
json = JSON.parse(text);
|
|
3343
|
+
} catch {
|
|
3344
|
+
keep(new StorybookIndexError("not-json", `${url} is not a Storybook index (the host answered with a web page).`));
|
|
3345
|
+
continue;
|
|
3346
|
+
}
|
|
3347
|
+
try {
|
|
3348
|
+
return parseStorybookIndex(json, source);
|
|
3349
|
+
} catch (err) {
|
|
3350
|
+
if (err instanceof StorybookIndexError) keep(err);
|
|
3351
|
+
else throw err;
|
|
3352
|
+
}
|
|
3353
|
+
}
|
|
3354
|
+
throw worst ?? new StorybookIndexError("not-found", `No Storybook index at ${base}.`);
|
|
3355
|
+
}
|
|
3213
3356
|
export {
|
|
3214
3357
|
af as AAA_MIN,
|
|
3215
3358
|
ag as AA_MIN,
|
|
@@ -3326,6 +3469,7 @@ export {
|
|
|
3326
3469
|
aI2 as SUGGESTION_STATE_LABELS,
|
|
3327
3470
|
aJ2 as SUGGESTION_STATUS_LABEL,
|
|
3328
3471
|
aK2 as SUGGESTION_TOO_LARGE,
|
|
3472
|
+
StorybookIndexError,
|
|
3329
3473
|
aL2 as SuggestionError,
|
|
3330
3474
|
TIER_AXIS,
|
|
3331
3475
|
TIER_NAMES,
|
|
@@ -3515,6 +3659,7 @@ export {
|
|
|
3515
3659
|
explorationTestBuildOnGitHub,
|
|
3516
3660
|
explorationTryIt,
|
|
3517
3661
|
explorationTryItOnGitHub,
|
|
3662
|
+
fetchStorybookIndex,
|
|
3518
3663
|
fidelityComponentLine,
|
|
3519
3664
|
fidelityVerdict,
|
|
3520
3665
|
bb as fieldChanges,
|
|
@@ -3560,6 +3705,7 @@ export {
|
|
|
3560
3705
|
gitBlobSha,
|
|
3561
3706
|
gitHubHistoryBackend,
|
|
3562
3707
|
bl as globToRegExp,
|
|
3708
|
+
groupStorybookComponents,
|
|
3563
3709
|
bm as groupsPhrase,
|
|
3564
3710
|
bL2 as hasSuggestionBlock,
|
|
3565
3711
|
bM2 as hasWriteAccess,
|
|
@@ -3647,6 +3793,7 @@ export {
|
|
|
3647
3793
|
newDraftSessionId,
|
|
3648
3794
|
bC as nodesEqual,
|
|
3649
3795
|
bD as normalizeRights,
|
|
3796
|
+
normalizeStorybookUrl,
|
|
3650
3797
|
oklch,
|
|
3651
3798
|
oklchToLinear,
|
|
3652
3799
|
onlyTokens,
|
|
@@ -3683,6 +3830,7 @@ export {
|
|
|
3683
3830
|
parsePiecesRecord,
|
|
3684
3831
|
cd2 as parseRepo,
|
|
3685
3832
|
ce2 as parseRequestIssue,
|
|
3833
|
+
parseStorybookIndex,
|
|
3686
3834
|
cf2 as parseStructureChange,
|
|
3687
3835
|
cg2 as parseSuggestionAppliedComment,
|
|
3688
3836
|
ch2 as parseSuggestionIssue,
|
|
@@ -3705,11 +3853,11 @@ export {
|
|
|
3705
3853
|
planReferences,
|
|
3706
3854
|
cn2 as planRestore,
|
|
3707
3855
|
co2 as planRevert,
|
|
3708
|
-
|
|
3709
|
-
|
|
3856
|
+
cp2 as planSuggestionApply,
|
|
3857
|
+
cq2 as planToJson,
|
|
3710
3858
|
planTokenMerge,
|
|
3711
3859
|
planTokenProposal,
|
|
3712
|
-
|
|
3860
|
+
cr2 as prNumberFromSubject,
|
|
3713
3861
|
cs as prefillDocs,
|
|
3714
3862
|
bO as previewComment,
|
|
3715
3863
|
previewLinks,
|
|
@@ -3808,13 +3956,19 @@ export {
|
|
|
3808
3956
|
showShare,
|
|
3809
3957
|
slugify,
|
|
3810
3958
|
c3 as snapshotUrl,
|
|
3959
|
+
c4 as soloApprover,
|
|
3960
|
+
c5 as soloOwnerOf,
|
|
3961
|
+
c6 as soloOwnerSentence,
|
|
3811
3962
|
cO as specHash,
|
|
3812
3963
|
cP as specsUsage,
|
|
3813
3964
|
stableCommand,
|
|
3814
3965
|
startExplorationOnGitHub,
|
|
3815
3966
|
stateSentence,
|
|
3816
|
-
|
|
3817
|
-
|
|
3967
|
+
storybookIframeUrl,
|
|
3968
|
+
storybookIndexUrls,
|
|
3969
|
+
storybookManagerUrl,
|
|
3970
|
+
c7 as storybookUrl,
|
|
3971
|
+
c8 as suggestNearestComment,
|
|
3818
3972
|
suggestTokenProposalOnGitHub,
|
|
3819
3973
|
cQ as suggestionAllowedRoots,
|
|
3820
3974
|
cR as suggestionAppliedComment,
|
|
@@ -3834,33 +3988,33 @@ export {
|
|
|
3834
3988
|
d1 as summarizeCi,
|
|
3835
3989
|
summarizeComponent,
|
|
3836
3990
|
d2 as summarizeSuggestionApprovals,
|
|
3837
|
-
|
|
3991
|
+
c9 as summarizeTokenChange,
|
|
3838
3992
|
switchToPublishedOnGitHub,
|
|
3839
3993
|
d3 as syncSuggestionStateLabel,
|
|
3840
3994
|
takeMine,
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3995
|
+
ca as tarballAssetName,
|
|
3996
|
+
cb as tarballUrl,
|
|
3997
|
+
cc as teamKey,
|
|
3998
|
+
cd as teamKeyOf,
|
|
3999
|
+
ce as teamUnreadableMessage,
|
|
4000
|
+
cf as teamsIn,
|
|
3847
4001
|
threeWayDiff,
|
|
3848
4002
|
tintedNeutral,
|
|
3849
4003
|
d4 as titleOf,
|
|
3850
4004
|
titleWithJiraKey,
|
|
3851
|
-
|
|
4005
|
+
cg as toAlias,
|
|
3852
4006
|
d5 as toChangeSummary,
|
|
3853
4007
|
toConfigJson,
|
|
3854
4008
|
toHex,
|
|
3855
|
-
|
|
4009
|
+
ch as toMap,
|
|
3856
4010
|
toOklch,
|
|
3857
|
-
|
|
3858
|
-
|
|
4011
|
+
ci as toPlain,
|
|
4012
|
+
cj as tokenBump,
|
|
3859
4013
|
d6 as tokenCssVar,
|
|
3860
4014
|
tokenFilesOf,
|
|
3861
4015
|
d7 as tokenHistory,
|
|
3862
4016
|
t as tokenLabel,
|
|
3863
|
-
|
|
4017
|
+
ck as tokenNode,
|
|
3864
4018
|
tokenSuggestionPayload,
|
|
3865
4019
|
tokenUsage,
|
|
3866
4020
|
tokensPath,
|
|
@@ -3868,8 +4022,8 @@ export {
|
|
|
3868
4022
|
tryInProductUrl,
|
|
3869
4023
|
tryTogetherUrl,
|
|
3870
4024
|
unpicked,
|
|
3871
|
-
|
|
3872
|
-
|
|
4025
|
+
cl as unreadableShipTeams,
|
|
4026
|
+
cm as unreadableTeams,
|
|
3873
4027
|
d8 as unsafePathProblem,
|
|
3874
4028
|
updatePendingDrafts,
|
|
3875
4029
|
upsertToken,
|
|
@@ -3883,15 +4037,15 @@ export {
|
|
|
3883
4037
|
validatePendingDrafts,
|
|
3884
4038
|
validateProposal,
|
|
3885
4039
|
validateSet,
|
|
3886
|
-
|
|
3887
|
-
|
|
4040
|
+
cn as valueIn,
|
|
4041
|
+
co as valueToCss,
|
|
3888
4042
|
valuesEqual,
|
|
3889
4043
|
variantKeyOf,
|
|
3890
4044
|
dd as variantName,
|
|
3891
4045
|
de as versionTimeline,
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
4046
|
+
cp as visualImpactProblems,
|
|
4047
|
+
cq as whoCanShipSentence,
|
|
4048
|
+
cr as whyItExists,
|
|
3895
4049
|
df as withAuthorLine,
|
|
3896
4050
|
withFigmaOrigin,
|
|
3897
4051
|
withLink,
|