@certrev/cert-block 0.1.2 → 0.2.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.
Files changed (47) hide show
  1. package/dist/builder/index.d.ts +54 -52
  2. package/dist/builder/index.d.ts.map +1 -1
  3. package/dist/builder/index.js +64 -47
  4. package/dist/builder/index.js.map +1 -1
  5. package/dist/components/CertBadge.d.ts +18 -3
  6. package/dist/components/CertBadge.d.ts.map +1 -1
  7. package/dist/components/CertBadge.js +8 -2
  8. package/dist/components/CertBadge.js.map +1 -1
  9. package/dist/components/CertReview.d.ts +7 -0
  10. package/dist/components/CertReview.d.ts.map +1 -1
  11. package/dist/components/CertReview.js +1 -1
  12. package/dist/components/CertReview.js.map +1 -1
  13. package/dist/components/format.d.ts +14 -2
  14. package/dist/components/format.d.ts.map +1 -1
  15. package/dist/components/format.js +18 -5
  16. package/dist/components/format.js.map +1 -1
  17. package/dist/components/render-cert-block.d.ts +89 -0
  18. package/dist/components/render-cert-block.d.ts.map +1 -0
  19. package/dist/components/render-cert-block.js +282 -0
  20. package/dist/components/render-cert-block.js.map +1 -0
  21. package/dist/components/render-def.d.ts +178 -0
  22. package/dist/components/render-def.d.ts.map +1 -0
  23. package/dist/components/render-def.js +204 -0
  24. package/dist/components/render-def.js.map +1 -0
  25. package/dist/index.d.ts +2 -0
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +4 -0
  28. package/dist/index.js.map +1 -1
  29. package/dist/webcomponent/render-badge-html.d.ts +8 -0
  30. package/dist/webcomponent/render-badge-html.d.ts.map +1 -1
  31. package/dist/webcomponent/render-badge-html.js +31 -4
  32. package/dist/webcomponent/render-badge-html.js.map +1 -1
  33. package/package.json +3 -2
  34. package/src/__tests__/__snapshots__/render-cert-block.test.ts.snap +13 -0
  35. package/src/__tests__/components.test.tsx +16 -1
  36. package/src/__tests__/render-cert-block.test.ts +259 -0
  37. package/src/__tests__/render-def.test.tsx +286 -0
  38. package/src/__tests__/webcomponent.test.tsx +10 -0
  39. package/src/builder/__tests__/builder.test.tsx +38 -51
  40. package/src/builder/index.tsx +86 -64
  41. package/src/components/CertBadge.tsx +56 -4
  42. package/src/components/CertReview.tsx +8 -0
  43. package/src/components/format.ts +22 -5
  44. package/src/components/render-cert-block.ts +403 -0
  45. package/src/components/render-def.ts +286 -0
  46. package/src/index.ts +35 -0
  47. package/src/webcomponent/render-badge-html.ts +46 -4
@@ -1,73 +1,75 @@
1
1
  /**
2
- * @certrev/cert-block/builder — the Builder.io adapter for the cert-block render edge.
2
+ * @certrev/cert-block/builder — Builder.io adapter, "ambient-URL anchor" model.
3
3
  *
4
- * Lets a Builder.io content editor place a "CertREV Review" block into a page; the
5
- * headless app's loader (Hydrogen/Next/Remix) crypto-verifies that placement's signed
6
- * envelope and supplies the verdict via React context; this block renders cert-block's
7
- * <CertReview> from the VERIFIED verdict — and renders NOTHING (fail-closed) on any
8
- * suppress or unknown placement.
4
+ * Validated by an independent architecture panel (Codex gpt-5.5 + Gemini, blind): a visual
5
+ * page builder must NOT choose WHICH credential renders — that invites cross-article misuse and
6
+ * re-opens the wrong-subject surface. Instead:
7
+ * • the CMS controls LAYOUT — an editor drags a ZERO-INPUT <CertRevAnchor/> to position the
8
+ * badge on the page;
9
+ * • the SYSTEM controls TRUTH — the headless loader resolves THIS page's credential from its
10
+ * own URL (Track-1 delivery), crypto-verifies it (fail-closed VerdictKernel), and supplies
11
+ * the verdict via context.
12
+ * The anchor renders the current page's verified badge or NOTHING. It cannot be pointed at
13
+ * another article, and there is no `placementId` input to forge or mis-select.
9
14
  *
10
- * THE TRUST BOUNDARY: the credential is never trusted from CMS content. A Builder block
11
- * only carries an opaque `placementId` pointer; the authority comes solely from the
12
- * loader-side WebCrypto verdict supplied through <CertVerifyProvider>. So a revoked /
13
- * tampered / expired / wrong-subject placement that an editor drops into Builder renders
14
- * nothing, even though the block is present in the published content.
15
+ * JSON-LD is DECOUPLED (panel finding): the anchor renders the BADGE only (`omitJsonLd`). The
16
+ * article template emits the schema.org JSON-LD server-side from the same verified verdict, so a
17
+ * page builder can't duplicate, move, or omit structured data. (See the route example.)
15
18
  *
16
- * cert-block carries NO dependency on `@builder.io/sdk-react` — the registration's shape is
17
- * declared structurally below, so the emitted JS pulls no Builder code and the type resolves
18
- * without Builder installed. The consumer (who already has Builder) passes
19
- * `certReviewBuilderComponent` to Builder's `<Content customComponents={[...]}>`; it is
20
- * assignable to Builder's `RegisteredComponent` there.
19
+ * EDGE-CACHE DISCIPLINE (panel finding): the consumer's loader MUST verify per request as a
20
+ * dynamic edge subrequest and must NOT long-cache the rendered badge HTML — a revoked/expired
21
+ * credential sitting in a stale edge cache would defeat fail-closed. Bound any positive-verdict
22
+ * cache by min(expiry, revocation-TTL, content-version).
23
+ *
24
+ * cert-block carries no Builder dependency: the registration shape is declared structurally, and
25
+ * `isEditing` is a passed-in flag (the consumer supplies Builder's `isPreviewing()`).
21
26
  */
22
27
  import { type ReactNode } from 'react';
23
28
  import type { CertVerdict } from '../contract/kernel.js';
24
- /** A loader-verified placement: the verdict cert-block renders from, plus the canonical
25
- * page URL for JSON-LD @id alignment. */
26
- export interface VerifiedPlacement {
29
+ /** The current page's credential, resolved + verified by the loader (Track-1 delivery). */
30
+ export interface CurrentCredential {
27
31
  readonly verdict: CertVerdict;
32
+ /** Canonical page URL for JSON-LD @id alignment (used by the server-side JSON-LD, not the anchor). */
28
33
  readonly pageUrl?: string;
29
34
  }
30
- /** Map of `placementId` → the loader's verified result. Built server-side in the loader
31
- * (it crypto-verifies each placement) and handed to <CertVerifyProvider>. */
32
- export type VerifiedPlacements = Record<string, VerifiedPlacement>;
33
- /** Wraps Builder's <Content>; carries the loader's verified verdicts down to every
34
- * CertReview block, keyed by `placementId`. */
35
- export declare function CertVerifyProvider({ value, children, }: {
36
- readonly value: VerifiedPlacements;
35
+ /**
36
+ * Supplies THIS page's loader-verified credential to the anchor. `current` is the verdict for
37
+ * the current page (or null if the page has no delivered credential). `isEditing` is the
38
+ * consumer's Builder `isPreviewing()` result — it ONLY toggles a design-time placeholder and
39
+ * NEVER affects the published render.
40
+ */
41
+ export declare function CertRevProvider({ current, isEditing, children, }: {
42
+ readonly current: CurrentCredential | null;
43
+ readonly isEditing?: boolean;
37
44
  readonly children: ReactNode;
38
45
  }): import("react").JSX.Element;
39
- export interface CertReviewBlockProps {
40
- /** The CertREV placement id the editor set on this Builder block. */
41
- readonly placementId?: string;
42
- }
43
46
  /**
44
- * The component Builder renders for a "CertREV Review" block. It pulls the loader-verified
45
- * verdict for its `placementId` from context and renders <CertReview>. Unknown placement
46
- * OR a non-`render` verdict → renders nothing. cert-block's <CertReview> ALSO suppresses on
47
- * a non-render verdict, so the boundary fails closed twice over (defense in depth).
47
+ * Design-time placeholder shown ONLY in the Builder editor when the current page has no live
48
+ * verified credential. Truthful (never a fake badge), emits NO JSON-LD, and never renders in
49
+ * production — so it cannot leak to or be crawled on the live site.
50
+ */
51
+ export declare function CertRevEditorPlaceholder(): import("react").JSX.Element;
52
+ /**
53
+ * The Builder block. ZERO inputs — a layout anchor only. Renders the current page's VERIFIED
54
+ * badge (badge only; JSON-LD is emitted server-side), the editor placeholder in design mode, or
55
+ * NOTHING in production (fail-closed). The credential is whatever Track-1 delivered + verified for
56
+ * THIS page; the editor can neither choose nor forge it.
48
57
  */
49
- export declare function CertReviewBlock({ placementId }: CertReviewBlockProps): import("react").JSX.Element | null;
58
+ export declare function CertRevAnchor(): import("react").JSX.Element | null;
50
59
  /**
51
- * Structural shape of `@builder.io/sdk-react`'s `RegisteredComponent` — exactly the subset
52
- * cert-block populates. Declared locally (not imported) so cert-block needs no Builder
53
- * build- or runtime-dependency; the object below is assignable to Builder's
54
- * `RegisteredComponent` at the consumer's `<Content customComponents={[...]}>` call site.
60
+ * Structural shape of `@builder.io/sdk-react`'s `RegisteredComponent` — the subset cert-block
61
+ * populates. Declared locally so cert-block needs no Builder build/runtime dependency; assignable
62
+ * to Builder's `RegisteredComponent` at the consumer's `<Content customComponents={[...]}>`.
55
63
  */
56
- export interface CertReviewBuilderRegistration {
57
- component: typeof CertReviewBlock;
64
+ export interface CertRevBuilderRegistration {
65
+ component: typeof CertRevAnchor;
58
66
  name: string;
59
- inputs: Array<{
60
- name: string;
61
- type: 'string';
62
- required?: boolean;
63
- helperText?: string;
64
- }>;
67
+ inputs: never[];
65
68
  }
66
69
  /**
67
- * The registration object to pass to Builder's `<Content customComponents={[...]}>`.
68
- * Editors see a "CertREV Review" component with one input — the placement id. Because the
69
- * block is matched by NAME at render time, this also works for content created via the
70
- * Builder Write API (no visual-editor registration required for rendering).
70
+ * The registration to pass to Builder's `<Content customComponents={[...]}>`. ZERO inputs by
71
+ * design — the editor places it (layout); the system resolves the credential from the page URL
72
+ * (truth). Matched by NAME at render, so Write-API content works without visual-editor setup.
71
73
  */
72
- export declare const certReviewBuilderComponent: CertReviewBuilderRegistration;
74
+ export declare const certRevAnchorComponent: CertRevBuilderRegistration;
73
75
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builder/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAiB,KAAK,SAAS,EAAc,MAAM,OAAO,CAAA;AAEjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD;0CAC0C;AAC1C,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;8EAC8E;AAC9E,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;AAIlE;gDACgD;AAChD,wBAAgB,kBAAkB,CAAC,EAClC,KAAK,EACL,QAAQ,GACR,EAAE;IACF,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAA;IAClC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;CAC5B,+BAEA;AAED,MAAM,WAAW,oBAAoB;IACpC,qEAAqE;IACrE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAAE,WAAW,EAAE,EAAE,oBAAoB,sCAKpE;AAED;;;;;GAKG;AACH,MAAM,WAAW,6BAA6B;IAC7C,SAAS,EAAE,OAAO,eAAe,CAAA;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACxF;AAED;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,EAAE,6BAaxC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builder/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAiB,KAAK,SAAS,EAAc,MAAM,OAAO,CAAA;AAEjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,2FAA2F;AAC3F,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,sGAAsG;IACtG,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CACzB;AASD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAC/B,OAAO,EACP,SAAiB,EACjB,QAAQ,GACR,EAAE;IACF,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAC1C,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;CAC5B,+BAEA;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,gCAiBvC;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,uCAO5B;AAED;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IAC1C,SAAS,EAAE,OAAO,aAAa,CAAA;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,KAAK,EAAE,CAAA;CACf;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,0BAIpC,CAAA"}
@@ -1,63 +1,80 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /**
3
- * @certrev/cert-block/builder — the Builder.io adapter for the cert-block render edge.
3
+ * @certrev/cert-block/builder — Builder.io adapter, "ambient-URL anchor" model.
4
4
  *
5
- * Lets a Builder.io content editor place a "CertREV Review" block into a page; the
6
- * headless app's loader (Hydrogen/Next/Remix) crypto-verifies that placement's signed
7
- * envelope and supplies the verdict via React context; this block renders cert-block's
8
- * <CertReview> from the VERIFIED verdict — and renders NOTHING (fail-closed) on any
9
- * suppress or unknown placement.
5
+ * Validated by an independent architecture panel (Codex gpt-5.5 + Gemini, blind): a visual
6
+ * page builder must NOT choose WHICH credential renders — that invites cross-article misuse and
7
+ * re-opens the wrong-subject surface. Instead:
8
+ * • the CMS controls LAYOUT — an editor drags a ZERO-INPUT <CertRevAnchor/> to position the
9
+ * badge on the page;
10
+ * • the SYSTEM controls TRUTH — the headless loader resolves THIS page's credential from its
11
+ * own URL (Track-1 delivery), crypto-verifies it (fail-closed VerdictKernel), and supplies
12
+ * the verdict via context.
13
+ * The anchor renders the current page's verified badge or NOTHING. It cannot be pointed at
14
+ * another article, and there is no `placementId` input to forge or mis-select.
10
15
  *
11
- * THE TRUST BOUNDARY: the credential is never trusted from CMS content. A Builder block
12
- * only carries an opaque `placementId` pointer; the authority comes solely from the
13
- * loader-side WebCrypto verdict supplied through <CertVerifyProvider>. So a revoked /
14
- * tampered / expired / wrong-subject placement that an editor drops into Builder renders
15
- * nothing, even though the block is present in the published content.
16
+ * JSON-LD is DECOUPLED (panel finding): the anchor renders the BADGE only (`omitJsonLd`). The
17
+ * article template emits the schema.org JSON-LD server-side from the same verified verdict, so a
18
+ * page builder can't duplicate, move, or omit structured data. (See the route example.)
16
19
  *
17
- * cert-block carries NO dependency on `@builder.io/sdk-react` — the registration's shape is
18
- * declared structurally below, so the emitted JS pulls no Builder code and the type resolves
19
- * without Builder installed. The consumer (who already has Builder) passes
20
- * `certReviewBuilderComponent` to Builder's `<Content customComponents={[...]}>`; it is
21
- * assignable to Builder's `RegisteredComponent` there.
20
+ * EDGE-CACHE DISCIPLINE (panel finding): the consumer's loader MUST verify per request as a
21
+ * dynamic edge subrequest and must NOT long-cache the rendered badge HTML — a revoked/expired
22
+ * credential sitting in a stale edge cache would defeat fail-closed. Bound any positive-verdict
23
+ * cache by min(expiry, revocation-TTL, content-version).
24
+ *
25
+ * cert-block carries no Builder dependency: the registration shape is declared structurally, and
26
+ * `isEditing` is a passed-in flag (the consumer supplies Builder's `isPreviewing()`).
22
27
  */
23
28
  import { createContext, useContext } from 'react';
24
29
  import { CertReview } from '../components/CertReview.js';
25
- const CertVerifyContext = createContext({});
26
- /** Wraps Builder's <Content>; carries the loader's verified verdicts down to every
27
- * CertReview block, keyed by `placementId`. */
28
- export function CertVerifyProvider({ value, children, }) {
29
- return _jsx(CertVerifyContext.Provider, { value: value, children: children });
30
+ const CertRevContext = createContext({ current: null, isEditing: false });
31
+ /**
32
+ * Supplies THIS page's loader-verified credential to the anchor. `current` is the verdict for
33
+ * the current page (or null if the page has no delivered credential). `isEditing` is the
34
+ * consumer's Builder `isPreviewing()` result — it ONLY toggles a design-time placeholder and
35
+ * NEVER affects the published render.
36
+ */
37
+ export function CertRevProvider({ current, isEditing = false, children, }) {
38
+ return _jsx(CertRevContext.Provider, { value: { current, isEditing }, children: children });
39
+ }
40
+ /**
41
+ * Design-time placeholder shown ONLY in the Builder editor when the current page has no live
42
+ * verified credential. Truthful (never a fake badge), emits NO JSON-LD, and never renders in
43
+ * production — so it cannot leak to or be crawled on the live site.
44
+ */
45
+ export function CertRevEditorPlaceholder() {
46
+ return (_jsxs("div", { "data-certrev-editor-placeholder": "", style: {
47
+ border: '1px dashed #e6007e',
48
+ borderRadius: 8,
49
+ padding: '10px 14px',
50
+ font: '13px system-ui',
51
+ color: '#6b7280',
52
+ background: '#fff5fa',
53
+ }, children: ["CertREV Review \u2014 ", _jsx("b", { children: "resolves at publish" }), " from issuer verification. The expert badge appears here once this page\u2019s article is certified, and only while the credential is valid."] }));
30
54
  }
31
55
  /**
32
- * The component Builder renders for a "CertREV Review" block. It pulls the loader-verified
33
- * verdict for its `placementId` from context and renders <CertReview>. Unknown placement
34
- * OR a non-`render` verdict → renders nothing. cert-block's <CertReview> ALSO suppresses on
35
- * a non-render verdict, so the boundary fails closed twice over (defense in depth).
56
+ * The Builder block. ZERO inputs — a layout anchor only. Renders the current page's VERIFIED
57
+ * badge (badge only; JSON-LD is emitted server-side), the editor placeholder in design mode, or
58
+ * NOTHING in production (fail-closed). The credential is whatever Track-1 delivered + verified for
59
+ * THIS page; the editor can neither choose nor forge it.
36
60
  */
37
- export function CertReviewBlock({ placementId }) {
38
- const placements = useContext(CertVerifyContext);
39
- const placement = placementId ? placements[placementId] : undefined;
40
- if (!placement)
41
- return null;
42
- return _jsx(CertReview, { verdict: placement.verdict, pageUrl: placement.pageUrl });
61
+ export function CertRevAnchor() {
62
+ const { current, isEditing } = useContext(CertRevContext);
63
+ if (current && current.verdict.decision === 'render') {
64
+ return _jsx(CertReview, { verdict: current.verdict, pageUrl: current.pageUrl, omitJsonLd: true });
65
+ }
66
+ if (isEditing)
67
+ return _jsx(CertRevEditorPlaceholder, {});
68
+ return null;
43
69
  }
44
70
  /**
45
- * The registration object to pass to Builder's `<Content customComponents={[...]}>`.
46
- * Editors see a "CertREV Review" component with one input — the placement id. Because the
47
- * block is matched by NAME at render time, this also works for content created via the
48
- * Builder Write API (no visual-editor registration required for rendering).
71
+ * The registration to pass to Builder's `<Content customComponents={[...]}>`. ZERO inputs by
72
+ * design — the editor places it (layout); the system resolves the credential from the page URL
73
+ * (truth). Matched by NAME at render, so Write-API content works without visual-editor setup.
49
74
  */
50
- export const certReviewBuilderComponent = {
51
- component: CertReviewBlock,
75
+ export const certRevAnchorComponent = {
76
+ component: CertRevAnchor,
52
77
  name: 'CertREV Review',
53
- inputs: [
54
- {
55
- name: 'placementId',
56
- type: 'string',
57
- required: true,
58
- helperText: 'CertREV placement id (which certified article this badge attests). The headless ' +
59
- 'loader verifies that placement’s signed envelope; only a render-verdict shows a badge.',
60
- },
61
- ],
78
+ inputs: [],
62
79
  };
63
80
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/builder/index.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,aAAa,EAAkB,UAAU,EAAE,MAAM,OAAO,CAAA;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;AAcxD,MAAM,iBAAiB,GAAG,aAAa,CAAqB,EAAE,CAAC,CAAA;AAE/D;gDACgD;AAChD,MAAM,UAAU,kBAAkB,CAAC,EAClC,KAAK,EACL,QAAQ,GAIR;IACA,OAAO,KAAC,iBAAiB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAA8B,CAAA;AACzF,CAAC;AAOD;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,EAAE,WAAW,EAAwB;IACpE,MAAM,UAAU,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAA;IAChD,MAAM,SAAS,GAAG,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IACnE,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAA;IAC3B,OAAO,KAAC,UAAU,IAAC,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,GAAI,CAAA;AAC9E,CAAC;AAcD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAkC;IACxE,SAAS,EAAE,eAAe;IAC1B,IAAI,EAAE,gBAAgB;IACtB,MAAM,EAAE;QACP;YACC,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,IAAI;YACd,UAAU,EACT,kFAAkF;gBAClF,wFAAwF;SACzF;KACD;CACD,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/builder/index.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAE,aAAa,EAAkB,UAAU,EAAE,MAAM,OAAO,CAAA;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;AAexD,MAAM,cAAc,GAAG,aAAa,CAAsB,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAA;AAE9F;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,EAC/B,OAAO,EACP,SAAS,GAAG,KAAK,EACjB,QAAQ,GAKR;IACA,OAAO,KAAC,cAAc,CAAC,QAAQ,IAAC,KAAK,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,YAAG,QAAQ,GAA2B,CAAA;AACpG,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB;IACvC,OAAO,CACN,kDACiC,EAAE,EAClC,KAAK,EAAE;YACN,MAAM,EAAE,oBAAoB;YAC5B,YAAY,EAAE,CAAC;YACf,OAAO,EAAE,WAAW;YACpB,IAAI,EAAE,gBAAgB;YACtB,KAAK,EAAE,SAAS;YAChB,UAAU,EAAE,SAAS;SACrB,uCAEgB,8CAA0B,oJAEtC,CACN,CAAA;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa;IAC5B,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,UAAU,CAAC,cAAc,CAAC,CAAA;IACzD,IAAI,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACtD,OAAO,KAAC,UAAU,IAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,UAAU,SAAG,CAAA;IACrF,CAAC;IACD,IAAI,SAAS;QAAE,OAAO,KAAC,wBAAwB,KAAG,CAAA;IAClD,OAAO,IAAI,CAAA;AACZ,CAAC;AAaD;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAA+B;IACjE,SAAS,EAAE,aAAa;IACxB,IAAI,EAAE,gBAAgB;IACtB,MAAM,EAAE,EAAE;CACV,CAAA"}
@@ -11,19 +11,34 @@
11
11
  * an inline custom property (no color-only meaning — the credential text carries it), an
12
12
  * expert photo with meaningful alt text, and a verify link with a descriptive label.
13
13
  *
14
- * `badgeStyle: 'compact'` collapses to a single line (name + credentials + verify link);
15
- * `'full'` shows the photo, certified/updated dates, and the memo (per display flags).
14
+ * `badgeStyle: 'compact'` collapses the reviewer block to a single line (name + credentials);
15
+ * `'full'` shows the photo, certified/updated dates, and the memo (per display flags). BOTH
16
+ * styles carry the compensation cue + FTC scope line (the always-on compliance disclosures).
17
+ *
18
+ * THEMING (WS6): presentation defaults come from `payload.content.display`; an optional
19
+ * `renderDef` prop layers a brand's validated themeable tokens (emitted as `--certrev-*`
20
+ * CSS custom properties) and its subtractive field-visibility on top. No `renderDef` → the
21
+ * CertREV preset default (theme output byte-identical to un-themed).
16
22
  */
17
23
  import type { CertPayload } from '../contract/kernel.js';
24
+ import { type CertRenderDef } from './render-def.js';
18
25
  export interface CertBadgeProps {
19
26
  /** The cryptographically-verified payload (from `getVerifiedEnvelope`). */
20
27
  readonly payload: CertPayload;
21
- /** Optional accent override (else `display.accentColor`, else CertREV default). */
28
+ /** Optional accent override (else render-def, else `display.accentColor`, else CertREV default). */
22
29
  readonly accentColor?: string;
23
30
  /** Extra class names appended to the root element's class list. */
24
31
  readonly className?: string;
25
32
  /** Override the badge style independent of the signed display config. */
26
33
  readonly badgeStyle?: 'full' | 'compact';
34
+ /**
35
+ * The brand render-def (WS6). ABSENT → the badge renders the CertREV preset
36
+ * default (fail-safe; theme output byte-identical to un-themed). PRESENT → its
37
+ * validated themeable tokens are emitted as `--certrev-*` CSS custom properties
38
+ * and its subtractive hide-set removes brand-toggleable fields. Invalid tokens
39
+ * are dropped (defense-in-depth over the write-path gate).
40
+ */
41
+ readonly renderDef?: CertRenderDef;
27
42
  }
28
43
  export declare function CertBadge(props: CertBadgeProps): import("react").JSX.Element;
29
44
  //# sourceMappingURL=CertBadge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CertBadge.d.ts","sourceRoot":"","sources":["../../src/components/CertBadge.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAe,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAIrE,MAAM,WAAW,cAAc;IAC9B,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,mFAAmF;IACnF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,mEAAmE;IACnE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACxC;AAuCD,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,+BA8F9C"}
1
+ {"version":3,"file":"CertBadge.d.ts","sourceRoot":"","sources":["../../src/components/CertBadge.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAe,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAGrE,OAAO,EAGN,KAAK,aAAa,EAGlB,MAAM,iBAAiB,CAAA;AAExB,MAAM,WAAW,cAAc;IAC9B,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,oGAAoG;IACpG,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,mEAAmE;IACnE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACxC;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAA;CAClC;AAuCD,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,+BA6H9C"}
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { safeHttpUrl } from './escape.js';
3
3
  import { credentialSuffix, expertNameWithCredentials, formatDate, resolveDisplay } from './format.js';
4
+ import { CERT_SCOPE_LINE, CERT_STRINGS_VERSION, resolveRenderTheme, themeCssVarDeclarations, } from './render-def.js';
4
5
  const ROOT_CLASS = 'certrev-badge';
5
6
  /** Inline-SVG verified checkmark — no external asset, accent-tinted, decorative. */
6
7
  function VerifiedMark({ accent }) {
@@ -15,7 +16,8 @@ function ExpertPhoto({ content, show }) {
15
16
  export function CertBadge(props) {
16
17
  const { payload } = props;
17
18
  const content = payload.content;
18
- const display = resolveDisplay(content.display, props.accentColor);
19
+ const display = resolveDisplay(content.display, props.accentColor, props.renderDef);
20
+ const theme = resolveRenderTheme(props.renderDef);
19
21
  const style = props.badgeStyle ?? display.badgeStyle;
20
22
  const verifyUrl = safeHttpUrl(content.verifyUrl);
21
23
  const profileUrl = safeHttpUrl(content.expert.profileUrl);
@@ -26,11 +28,15 @@ export function CertBadge(props) {
26
28
  const rootClass = `${ROOT_CLASS} ${ROOT_CLASS}--${style}${props.className ? ` ${props.className}` : ''}`;
27
29
  // Accent is exposed as a custom property so brand themes can read it, and applied
28
30
  // directly to the accent border so the component is self-styling without a stylesheet.
31
+ // A THEMED brand additionally emits the surface/radius/font vars; with no render-def
32
+ // `themeCssVarDeclarations` is empty, so the un-themed style is byte-identical.
29
33
  const rootStyle = {
30
34
  ['--certrev-accent']: accent,
31
35
  borderInlineStartColor: accent,
32
36
  };
37
+ for (const [name, value] of themeCssVarDeclarations(theme))
38
+ rootStyle[name] = value;
33
39
  const expertName = (_jsxs("span", { className: `${ROOT_CLASS}__expert-name`, children: [content.expert.displayName, suffix ? _jsxs("span", { className: `${ROOT_CLASS}__credentials`, children: [", ", suffix] }) : null] }));
34
- return (_jsxs("section", { className: rootClass, style: rootStyle, "data-certrev-cert-id": payload.certId, "aria-label": `Content reviewed by ${expertNameWithCredentials(content)}`, children: [_jsxs("div", { className: `${ROOT_CLASS}__header`, children: [_jsx(VerifiedMark, { accent: accent }), style === 'full' ? _jsx(ExpertPhoto, { content: content, show: display.showExpertPhoto }) : null, _jsxs("div", { className: `${ROOT_CLASS}__heading`, children: [_jsx("span", { className: `${ROOT_CLASS}__eyebrow`, children: "Expert reviewed" }), _jsxs("span", { className: `${ROOT_CLASS}__byline`, children: ["Reviewed by", ' ', profileUrl ? (_jsx("a", { className: `${ROOT_CLASS}__expert-link`, href: profileUrl, rel: "noopener", children: expertName })) : (expertName)] })] })] }), style === 'full' ? (_jsxs(_Fragment, { children: [display.showMemo && content.memo ? _jsx("p", { className: `${ROOT_CLASS}__memo`, children: content.memo }) : null, display.showAuthor && content.author.name && content.author.name !== content.expert.displayName ? (_jsxs("p", { className: `${ROOT_CLASS}__author`, children: ["Written by ", content.author.name, content.author.title ? `, ${content.author.title}` : ''] })) : null, _jsxs("dl", { className: `${ROOT_CLASS}__dates`, children: [certifiedLabel ? (_jsxs("div", { className: `${ROOT_CLASS}__date`, children: [_jsx("dt", { children: "Certified" }), _jsx("dd", { children: _jsx("time", { dateTime: content.certifiedAt, children: certifiedLabel }) })] })) : null, updatedLabel ? (_jsxs("div", { className: `${ROOT_CLASS}__date`, children: [_jsx("dt", { children: "Last updated" }), _jsx("dd", { children: _jsx("time", { dateTime: content.contentModifiedAt ?? undefined, children: updatedLabel }) })] })) : null] })] })) : null, verifyUrl ? (_jsx("a", { className: `${ROOT_CLASS}__verify`, href: verifyUrl, rel: "noopener", "aria-label": "Verify this certification on CertREV", children: "Verify on CertREV" })) : null] }));
40
+ return (_jsxs("section", { className: rootClass, style: rootStyle, "data-certrev-cert-id": payload.certId, "data-certrev-strings-version": CERT_STRINGS_VERSION, "data-certrev-def-version": theme.version, "aria-label": `Content reviewed by ${expertNameWithCredentials(content)}`, children: [_jsxs("div", { className: `${ROOT_CLASS}__header`, children: [_jsx(VerifiedMark, { accent: accent }), style === 'full' ? _jsx(ExpertPhoto, { content: content, show: display.showExpertPhoto }) : null, _jsxs("div", { className: `${ROOT_CLASS}__heading`, children: [_jsx("span", { className: `${ROOT_CLASS}__eyebrow`, children: "Expert reviewed" }), _jsxs("span", { className: `${ROOT_CLASS}__byline`, children: ["Reviewed by", ' ', profileUrl ? (_jsx("a", { className: `${ROOT_CLASS}__expert-link`, href: profileUrl, rel: "noopener", children: expertName })) : (expertName)] })] })] }), style === 'full' ? (_jsxs(_Fragment, { children: [display.showMemo && content.memo ? _jsx("p", { className: `${ROOT_CLASS}__memo`, children: content.memo }) : null, display.showAuthor && content.author.name && content.author.name !== content.expert.displayName ? (_jsxs("p", { className: `${ROOT_CLASS}__author`, children: ["Written by ", content.author.name, content.author.title ? `, ${content.author.title}` : ''] })) : null, _jsxs("dl", { className: `${ROOT_CLASS}__dates`, children: [certifiedLabel ? (_jsxs("div", { className: `${ROOT_CLASS}__date`, children: [_jsx("dt", { children: "Certified" }), _jsx("dd", { children: _jsx("time", { dateTime: content.certifiedAt, children: certifiedLabel }) })] })) : null, updatedLabel ? (_jsxs("div", { className: `${ROOT_CLASS}__date`, children: [_jsx("dt", { children: "Last updated" }), _jsx("dd", { children: _jsx("time", { dateTime: content.contentModifiedAt ?? undefined, children: updatedLabel }) })] })) : null] })] })) : null, _jsxs("div", { className: `${ROOT_CLASS}__disclosure`, children: [_jsxs("span", { className: `${ROOT_CLASS}__compensated-cue`, children: ["Compensated", ' ', profileUrl ? (_jsx("a", { className: `${ROOT_CLASS}__cue-link`, href: profileUrl, rel: "noopener", children: "expert" })) : ('expert')] }), _jsx("p", { className: `${ROOT_CLASS}__ftc`, "data-ftc-disclosure": true, children: _jsx("span", { "data-ftc-line": true, children: CERT_SCOPE_LINE }) })] }), verifyUrl ? (_jsx("a", { className: `${ROOT_CLASS}__verify`, href: verifyUrl, rel: "noopener", "aria-label": "Verify this certification on CertREV", children: "Verify on CertREV" })) : null] }));
35
41
  }
36
42
  //# sourceMappingURL=CertBadge.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CertBadge.js","sourceRoot":"","sources":["../../src/components/CertBadge.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CertBadge.js","sourceRoot":"","sources":["../../src/components/CertBadge.tsx"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@
8
8
  * expert bio + backlink remain separately placeable for brands that want finer control.
9
9
  */
10
10
  import type { CertVerdict } from '../contract/kernel.js';
11
+ import type { CertRenderDef } from './render-def.js';
11
12
  export interface CertReviewProps {
12
13
  /** The verdict from `getVerifiedEnvelope` (or a direct kernel call). */
13
14
  readonly verdict: CertVerdict;
@@ -16,6 +17,12 @@ export interface CertReviewProps {
16
17
  readonly accentColor?: string;
17
18
  readonly className?: string;
18
19
  readonly badgeStyle?: 'full' | 'compact';
20
+ /**
21
+ * The brand render-def (WS6). Forwarded to `<CertBadge>` for themeable-token
22
+ * emission + subtractive visibility; absent → the CertREV preset default. The
23
+ * JSON-LD is presentation-blind, so the def never touches the structured data.
24
+ */
25
+ readonly renderDef?: CertRenderDef;
19
26
  /** Omit the JSON-LD (e.g. the page already emits it elsewhere). Default false. */
20
27
  readonly omitJsonLd?: boolean;
21
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"CertReview.d.ts","sourceRoot":"","sources":["../../src/components/CertReview.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAIxD,MAAM,WAAW,eAAe;IAC/B,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,uFAAuF;IACvF,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACxC,kFAAkF;IAClF,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAC7B;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,sCAehD"}
1
+ {"version":3,"file":"CertReview.d.ts","sourceRoot":"","sources":["../../src/components/CertReview.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAGxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAEpD,MAAM,WAAW,eAAe;IAC/B,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,uFAAuF;IACvF,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACxC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAA;IAClC,kFAAkF;IAClF,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAC7B;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,sCAgBhD"}
@@ -6,6 +6,6 @@ export function CertReview(props) {
6
6
  if (props.verdict.decision !== 'render')
7
7
  return null;
8
8
  const payload = props.verdict.payload;
9
- return (_jsxs(_Fragment, { children: [_jsx(CertBadge, { payload: payload, accentColor: props.accentColor, className: props.className, badgeStyle: props.badgeStyle }), props.omitJsonLd ? null : _jsx(CertJsonLd, { payload: payload, pageUrl: props.pageUrl })] }));
9
+ return (_jsxs(_Fragment, { children: [_jsx(CertBadge, { payload: payload, accentColor: props.accentColor, className: props.className, badgeStyle: props.badgeStyle, renderDef: props.renderDef }), props.omitJsonLd ? null : _jsx(CertJsonLd, { payload: payload, pageUrl: props.pageUrl })] }));
10
10
  }
11
11
  //# sourceMappingURL=CertReview.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CertReview.js","sourceRoot":"","sources":["../../src/components/CertReview.tsx"],"names":[],"mappings":";AAWA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAc5C,MAAM,UAAU,UAAU,CAAC,KAAsB;IAChD,yEAAyE;IACzE,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IACpD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAA;IACrC,OAAO,CACN,8BACC,KAAC,SAAS,IACT,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,KAAK,CAAC,WAAW,EAC9B,SAAS,EAAE,KAAK,CAAC,SAAS,EAC1B,UAAU,EAAE,KAAK,CAAC,UAAU,GAC3B,EACD,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAC,UAAU,IAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,GAAI,IACjF,CACH,CAAA;AACF,CAAC"}
1
+ {"version":3,"file":"CertReview.js","sourceRoot":"","sources":["../../src/components/CertReview.tsx"],"names":[],"mappings":";AAWA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAqB5C,MAAM,UAAU,UAAU,CAAC,KAAsB;IAChD,yEAAyE;IACzE,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IACpD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAA;IACrC,OAAO,CACN,8BACC,KAAC,SAAS,IACT,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,KAAK,CAAC,WAAW,EAC9B,SAAS,EAAE,KAAK,CAAC,SAAS,EAC1B,UAAU,EAAE,KAAK,CAAC,UAAU,EAC5B,SAAS,EAAE,KAAK,CAAC,SAAS,GACzB,EACD,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAC,UAAU,IAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,GAAI,IACjF,CACH,CAAA;AACF,CAAC"}
@@ -3,6 +3,7 @@
3
3
  * no React — so the same formatting drives JSX and the hand-built Web Component string.
4
4
  */
5
5
  import type { CertContent, CertDisplayConfig } from '../contract/kernel.js';
6
+ import { type CertRenderDef } from './render-def.js';
6
7
  /** Default accent if the brand didn't pin one (CertREV teal). */
7
8
  export declare const DEFAULT_ACCENT = "#0f766e";
8
9
  export interface ResolvedDisplay {
@@ -12,8 +13,19 @@ export interface ResolvedDisplay {
12
13
  readonly showMemo: boolean;
13
14
  readonly badgeStyle: 'full' | 'compact';
14
15
  }
15
- /** Resolve the optional display config to concrete presentation flags + accent. */
16
- export declare function resolveDisplay(display: CertDisplayConfig | undefined, accentOverride?: string): ResolvedDisplay;
16
+ /**
17
+ * Resolve the optional display config + optional brand render-def to concrete
18
+ * presentation flags + accent.
19
+ *
20
+ * Accent PRECEDENCE mirrors the Shopify Liquid engine exactly: an explicit
21
+ * `accentOverride` (a block/prop override) wins, then the render-def's validated
22
+ * accent (a THEMED brand), then the signed display's accent, else the CertREV
23
+ * default. Visibility is SUBTRACTIVE: the render-def's hide-set can only turn a
24
+ * preset-placed field OFF (never on) — a hidden `reviewerPhoto` / `memo` wins over
25
+ * a display flag that shows it. When no render-def is supplied the theme resolves
26
+ * empty, so accent + visibility are byte-identical to the pre-theming behavior.
27
+ */
28
+ export declare function resolveDisplay(display: CertDisplayConfig | undefined, accentOverride?: string, renderDef?: CertRenderDef): ResolvedDisplay;
17
29
  export declare function formatDate(iso: string | null | undefined): string | null;
18
30
  /** "PhD, RD" — the expert's credential abbreviations, comma-joined. */
19
31
  export declare function credentialSuffix(content: CertContent): string;
@@ -1 +1 @@
1
- {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/components/format.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAE3E,iEAAiE;AACjE,eAAO,MAAM,cAAc,YAAY,CAAA;AAEvC,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAA;IACjC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;CACvC;AAED,mFAAmF;AACnF,wBAAgB,cAAc,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,eAAe,CAQ/G;AAUD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAMxE;AAED,uEAAuE;AACvE,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAE7D;AAED,8EAA8E;AAC9E,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAGtE"}
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/components/format.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAC3E,OAAO,EAAE,KAAK,aAAa,EAAqC,MAAM,iBAAiB,CAAA;AAEvF,iEAAiE;AACjE,eAAO,MAAM,cAAc,YAAY,CAAA;AAEvC,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAA;IACjC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;CACvC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC7B,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,cAAc,CAAC,EAAE,MAAM,EACvB,SAAS,CAAC,EAAE,aAAa,GACvB,eAAe,CASjB;AAUD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAMxE;AAED,uEAAuE;AACvE,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAE7D;AAED,8EAA8E;AAC9E,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAGtE"}
@@ -2,15 +2,28 @@
2
2
  * Presentation helpers shared by the React components + Web Component. Pure, no DOM,
3
3
  * no React — so the same formatting drives JSX and the hand-built Web Component string.
4
4
  */
5
+ import { isFieldHidden, resolveRenderTheme } from './render-def.js';
5
6
  /** Default accent if the brand didn't pin one (CertREV teal). */
6
7
  export const DEFAULT_ACCENT = '#0f766e';
7
- /** Resolve the optional display config to concrete presentation flags + accent. */
8
- export function resolveDisplay(display, accentOverride) {
8
+ /**
9
+ * Resolve the optional display config + optional brand render-def to concrete
10
+ * presentation flags + accent.
11
+ *
12
+ * Accent PRECEDENCE mirrors the Shopify Liquid engine exactly: an explicit
13
+ * `accentOverride` (a block/prop override) wins, then the render-def's validated
14
+ * accent (a THEMED brand), then the signed display's accent, else the CertREV
15
+ * default. Visibility is SUBTRACTIVE: the render-def's hide-set can only turn a
16
+ * preset-placed field OFF (never on) — a hidden `reviewerPhoto` / `memo` wins over
17
+ * a display flag that shows it. When no render-def is supplied the theme resolves
18
+ * empty, so accent + visibility are byte-identical to the pre-theming behavior.
19
+ */
20
+ export function resolveDisplay(display, accentOverride, renderDef) {
21
+ const theme = resolveRenderTheme(renderDef);
9
22
  return {
10
- accentColor: accentOverride ?? display?.accentColor ?? DEFAULT_ACCENT,
11
- showExpertPhoto: display?.showExpertPhoto ?? true,
23
+ accentColor: accentOverride ?? theme.accent ?? display?.accentColor ?? DEFAULT_ACCENT,
24
+ showExpertPhoto: (display?.showExpertPhoto ?? true) && !isFieldHidden(renderDef, 'reviewerPhoto'),
12
25
  showAuthor: display?.showAuthor ?? true,
13
- showMemo: display?.showMemo ?? true,
26
+ showMemo: (display?.showMemo ?? true) && !isFieldHidden(renderDef, 'memo'),
14
27
  badgeStyle: display?.badgeStyle ?? 'full',
15
28
  };
16
29
  }
@@ -1 +1 @@
1
- {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/components/format.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,iEAAiE;AACjE,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAA;AAUvC,mFAAmF;AACnF,MAAM,UAAU,cAAc,CAAC,OAAsC,EAAE,cAAuB;IAC7F,OAAO;QACN,WAAW,EAAE,cAAc,IAAI,OAAO,EAAE,WAAW,IAAI,cAAc;QACrE,eAAe,EAAE,OAAO,EAAE,eAAe,IAAI,IAAI;QACjD,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,IAAI;QACvC,QAAQ,EAAE,OAAO,EAAE,QAAQ,IAAI,IAAI;QACnC,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,MAAM;KACzC,CAAA;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;AAEnG,MAAM,UAAU,UAAU,CAAC,GAA8B;IACxD,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAA;IACrB,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC1B,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAAE,OAAO,IAAI,CAAA;IACjC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAA;IACtB,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,cAAc,EAAE,EAAE,CAAA;AAC7E,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,gBAAgB,CAAC,OAAoB;IACpD,OAAO,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACxE,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,yBAAyB,CAAC,OAAoB;IAC7D,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACxC,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAA;AACxF,CAAC"}
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/components/format.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAsB,aAAa,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAEvF,iEAAiE;AACjE,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAA;AAUvC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAC7B,OAAsC,EACtC,cAAuB,EACvB,SAAyB;IAEzB,MAAM,KAAK,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAA;IAC3C,OAAO;QACN,WAAW,EAAE,cAAc,IAAI,KAAK,CAAC,MAAM,IAAI,OAAO,EAAE,WAAW,IAAI,cAAc;QACrF,eAAe,EAAE,CAAC,OAAO,EAAE,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,eAAe,CAAC;QACjG,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,IAAI;QACvC,QAAQ,EAAE,CAAC,OAAO,EAAE,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,MAAM,CAAC;QAC1E,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,MAAM;KACzC,CAAA;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;AAEnG,MAAM,UAAU,UAAU,CAAC,GAA8B;IACxD,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAA;IACrB,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC1B,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAAE,OAAO,IAAI,CAAA;IACjC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAA;IACtB,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,cAAc,EAAE,EAAE,CAAA;AAC7E,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,gBAAgB,CAAC,OAAoB;IACpD,OAAO,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACxE,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,yBAAyB,CAAC,OAAoB;IAC7D,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACxC,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAA;AACxF,CAAC"}