@certrev/cert-block 1.1.0 → 1.2.0-canary.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 (100) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/README.md +69 -9
  3. package/dist/builder/cert-chrome-data.d.ts +10 -0
  4. package/dist/builder/cert-chrome-data.d.ts.map +1 -1
  5. package/dist/builder/cert-chrome-data.js.map +1 -1
  6. package/dist/builder/cert-review-card.d.ts.map +1 -1
  7. package/dist/builder/cert-review-card.js +22 -2
  8. package/dist/builder/cert-review-card.js.map +1 -1
  9. package/dist/builder/envelope-face.d.ts +25 -1
  10. package/dist/builder/envelope-face.d.ts.map +1 -1
  11. package/dist/builder/envelope-face.js +40 -0
  12. package/dist/builder/envelope-face.js.map +1 -1
  13. package/dist/builder/index.d.ts +1 -1
  14. package/dist/builder/index.d.ts.map +1 -1
  15. package/dist/builder/index.js +1 -1
  16. package/dist/builder/index.js.map +1 -1
  17. package/dist/components/render-cert-block.d.ts.map +1 -1
  18. package/dist/components/render-cert-block.js +3 -6
  19. package/dist/components/render-cert-block.js.map +1 -1
  20. package/dist/modal/certrev-cert-modal.d.ts +34 -1
  21. package/dist/modal/certrev-cert-modal.d.ts.map +1 -1
  22. package/dist/modal/certrev-cert-modal.js +40 -2
  23. package/dist/modal/certrev-cert-modal.js.map +1 -1
  24. package/dist/modal/certrev-cert.entry.d.ts.map +1 -1
  25. package/dist/modal/certrev-cert.entry.js +2 -4
  26. package/dist/modal/certrev-cert.entry.js.map +1 -1
  27. package/dist/modal/certrev-cert.js +4 -4
  28. package/dist/modal/deprecated.d.ts +15 -0
  29. package/dist/modal/deprecated.d.ts.map +1 -0
  30. package/dist/modal/deprecated.js +22 -0
  31. package/dist/modal/deprecated.js.map +1 -0
  32. package/dist/modal/ftc-disclosure.d.ts +7 -3
  33. package/dist/modal/ftc-disclosure.d.ts.map +1 -1
  34. package/dist/modal/ftc-disclosure.js +7 -3
  35. package/dist/modal/ftc-disclosure.js.map +1 -1
  36. package/dist/modal/index.d.ts +4 -3
  37. package/dist/modal/index.d.ts.map +1 -1
  38. package/dist/modal/index.js +4 -3
  39. package/dist/modal/index.js.map +1 -1
  40. package/dist/modal/interactions.d.ts +20 -4
  41. package/dist/modal/interactions.d.ts.map +1 -1
  42. package/dist/modal/interactions.js +34 -7
  43. package/dist/modal/interactions.js.map +1 -1
  44. package/dist/reader/face.d.ts +12 -0
  45. package/dist/reader/face.d.ts.map +1 -0
  46. package/dist/reader/face.js +19 -0
  47. package/dist/reader/face.js.map +1 -0
  48. package/dist/reader/helpers.d.ts +48 -0
  49. package/dist/reader/helpers.d.ts.map +1 -0
  50. package/dist/reader/helpers.js +166 -0
  51. package/dist/reader/helpers.js.map +1 -0
  52. package/dist/reader/index.d.ts +10 -0
  53. package/dist/reader/index.d.ts.map +1 -0
  54. package/dist/reader/index.js +10 -0
  55. package/dist/reader/index.js.map +1 -0
  56. package/dist/reader/logo.d.ts +4 -0
  57. package/dist/reader/logo.d.ts.map +1 -0
  58. package/dist/reader/logo.js +23 -0
  59. package/dist/reader/logo.js.map +1 -0
  60. package/dist/reader/reader-css.generated.d.ts +2 -0
  61. package/dist/reader/reader-css.generated.d.ts.map +1 -0
  62. package/dist/reader/reader-css.generated.js +6 -0
  63. package/dist/reader/reader-css.generated.js.map +1 -0
  64. package/dist/reader/render.d.ts +26 -0
  65. package/dist/reader/render.d.ts.map +1 -0
  66. package/dist/reader/render.js +230 -0
  67. package/dist/reader/render.js.map +1 -0
  68. package/dist/reader/tokens.d.ts +8 -0
  69. package/dist/reader/tokens.d.ts.map +1 -0
  70. package/dist/reader/tokens.js +65 -0
  71. package/dist/reader/tokens.js.map +1 -0
  72. package/dist/verify/get-verified-delivery.d.ts.map +1 -1
  73. package/dist/verify/get-verified-delivery.js +5 -1
  74. package/dist/verify/get-verified-delivery.js.map +1 -1
  75. package/package.json +7 -1
  76. package/src/builder/cert-chrome-data.ts +10 -0
  77. package/src/builder/cert-review-card.tsx +31 -2
  78. package/src/builder/envelope-face.ts +54 -5
  79. package/src/builder/index.tsx +3 -0
  80. package/src/components/render-cert-block.ts +3 -6
  81. package/src/modal/certrev-cert-modal.ts +45 -2
  82. package/src/modal/certrev-cert.entry.ts +2 -4
  83. package/src/modal/deprecated.ts +25 -0
  84. package/src/modal/ftc-disclosure.ts +7 -3
  85. package/src/modal/index.ts +4 -3
  86. package/src/modal/interactions.ts +37 -7
  87. package/src/reader/face.ts +35 -0
  88. package/src/reader/helpers.ts +178 -0
  89. package/src/reader/index.ts +14 -0
  90. package/src/reader/logo.ts +28 -0
  91. package/src/reader/reader-css.generated.ts +5 -0
  92. package/src/reader/reader.css +550 -0
  93. package/src/reader/render.ts +319 -0
  94. package/src/reader/tokens.ts +76 -0
  95. package/src/verify/get-verified-delivery.ts +5 -1
  96. package/dist/modal/ftc-guard.d.ts +0 -85
  97. package/dist/modal/ftc-guard.d.ts.map +0 -1
  98. package/dist/modal/ftc-guard.js +0 -150
  99. package/dist/modal/ftc-guard.js.map +0 -1
  100. package/src/modal/ftc-guard.ts +0 -174
@@ -0,0 +1,26 @@
1
+ import type { CertContent } from '../contract/kernel.js';
2
+ export type ReaderLayout = 'banner' | 'sidebar' | 'floating';
3
+ /** Which of the banner's two cards to paint: both (the page default), the byline card alone, or the memo card alone. */
4
+ export type ReaderPart = 'full' | 'header' | 'memo';
5
+ export interface ReaderFaceInput {
6
+ /** The verified envelope's `payload.content`. */
7
+ readonly content: CertContent;
8
+ /** The delivered render def (already known to say `face: 'reader'`); read for tokens and `hidden`. */
9
+ readonly def?: unknown;
10
+ readonly layout: ReaderLayout;
11
+ /** Banner only; the sidebar and the floating pill are one section each. Defaults to `full`. */
12
+ readonly part?: ReaderPart;
13
+ /** The envelope's `payload.certId`, stamped as `data-certrev-cert-id` (the revalidation hook reads it). */
14
+ readonly certId?: string;
15
+ /** A CertREV preview (never a live page): label a cue-less article "Illustrative example". */
16
+ readonly illustrative?: boolean;
17
+ }
18
+ /**
19
+ * The reader face's HTML for one layout. '' where the face paints nothing (no reviewer name; a pill with no safe
20
+ * verify URL; a banner `part` that has no block): the caller treats '' as "render nothing", never as an empty section.
21
+ *
22
+ * A def with no `layout` meaning here (`custom`, or any value that is not banner, sidebar or floating) is the
23
+ * caller's to resolve before it calls: this takes the layout it will paint.
24
+ */
25
+ export declare function renderReaderFace(input: ReaderFaceInput): string;
26
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/reader/render.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAmBxD,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAA;AAE5D,wHAAwH;AACxH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAA;AAEnD,MAAM,WAAW,eAAe;IAC/B,iDAAiD;IACjD,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,sGAAsG;IACtG,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;IAC7B,+FAA+F;IAC/F,QAAQ,CAAC,IAAI,CAAC,EAAE,UAAU,CAAA;IAC1B,2GAA2G;IAC3G,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,8FAA8F;IAC9F,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAC/B;AA2OD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAQ/D"}
@@ -0,0 +1,230 @@
1
+ /**
2
+ * ─────────────────────────────────────────────────────────────────────────────
3
+ * `renderReaderFace` — the certrev.com "reader" face, as the Builder card paints it (1.2.0)
4
+ * ─────────────────────────────────────────────────────────────────────────────
5
+ *
6
+ * The same markup, byte for byte, as the Shopify `certrev-reader-{banner,memo,sidebar,pill}` snippets, which are the
7
+ * portal's canonical render of the face (the "What your reader sees" demo on certrev.com). Styling is `reader.css`
8
+ * (the generated reader section of the Shopify stylesheet, `READER_CSS`); this file only emits the DOM it targets.
9
+ * The golden tests compare the sections to the portal's golden pages, and the differential tests compare edge cases to
10
+ * the portal's own Liquid harness output, so the two renderers cannot drift without a test saying so.
11
+ *
12
+ * It is a NEW face, selected only by a delivered render def that says `face: 'reader'` (see `envelopeCardHtml`).
13
+ * Nothing in the legacy `renderCertBlock` is read or changed here.
14
+ *
15
+ * The facts are read exactly as the snippets read the same envelope:
16
+ * - the card renders only with a reviewer name (the memo and sidebar too); the pill needs only a verify URL;
17
+ * - the credential is each credential's `cardLabel` (else `abbreviation`), joined; the "Credential verified by CertREV"
18
+ * attribution is gated on a displayed credential, and "on {date}" binds `expert.credentialVerifiedAt` and nothing
19
+ * else (no fallback to the certified date: with no date only the undated, still-true attribution prints);
20
+ * - the compensation cue renders ONLY when the envelope carries `expert.compensationCue`; the def cannot hide it, and
21
+ * its words are fixed. `illustrative` (a CertREV preview, never a live page) fills the cue's slot with the demo's
22
+ * "Illustrative example" label when the envelope has no cue; a real cue always wins the slot;
23
+ * - the scope line is never hideable: the card carries it when there is no memo, the memo card and the sidebar always;
24
+ * - the def's `hidden` set removes the avatars (`reviewerPhoto`), `display.showExpertPhoto === false` keeps the
25
+ * silhouette and never requests the photo, `display.showAuthor === false` drops the author column.
26
+ *
27
+ * Every interpolated field is escaped and every URL passes `safeUrl`. A hostile type (a number, an object) renders as
28
+ * nothing, never as a throw: see `helpers.ts`.
29
+ */
30
+ import { asText } from '../components/escape.js';
31
+ import { CERTREV_LINK_REL } from '../components/rel.js';
32
+ import { CERT_SCOPE_LINE, CERT_STRINGS_VERSION, COMPENSATED_EXPERT_CUE } from '../components/render-def.js';
33
+ import { readerFace } from './face.js';
34
+ import { cleaned, contains, esc, firstName, isBlank, isPresent, isTruthy, longDate, rec, safeUrl, textOr, } from './helpers.js';
35
+ import { readerLogo } from './logo.js';
36
+ import { readerTokens } from './tokens.js';
37
+ function readFacts(input) {
38
+ const content = rec(input.content);
39
+ const expert = rec(content.expert);
40
+ const disp = rec(content.display);
41
+ const def = input.def;
42
+ const rd = rec(def);
43
+ const hideAvatar = contains(rd.hidden, 'reviewerPhoto');
44
+ const showPhoto = disp.showExpertPhoto !== false && !hideAvatar;
45
+ // POR-9738: each credential's cardLabel over its bare abbreviation, joined with ', ' (labels are not trimmed).
46
+ const labels = [];
47
+ if (Array.isArray(expert.credentials)) {
48
+ for (const credential of expert.credentials) {
49
+ const cr = rec(credential);
50
+ const label = asText(isPresent(cr.cardLabel) ? cr.cardLabel : cr.abbreviation);
51
+ if (!isBlank(label))
52
+ labels.push(label);
53
+ }
54
+ }
55
+ const hasCue = isPresent(expert.compensationCue);
56
+ const { style, fg } = readerTokens(def);
57
+ return {
58
+ content,
59
+ expert,
60
+ disp,
61
+ def,
62
+ certId: asText(input.certId),
63
+ ename: textOr(expert.displayName),
64
+ hideAvatar,
65
+ showPhoto,
66
+ creds: labels.join(', '),
67
+ hasCue,
68
+ illus: input.illustrative === true && !hasCue,
69
+ noMemo: isBlank(content.memo),
70
+ purl: cleaned(safeUrl(expert.profileUrl)),
71
+ vurl: cleaned(safeUrl(content.verifyUrl)),
72
+ style,
73
+ fg,
74
+ };
75
+ }
76
+ /** The `<section>` open tag every reader section shares. `badge` is the `.certrev-badge` hook the revalidation reads. */
77
+ function sectionOpen(f, badge, aria) {
78
+ const cls = badge ? 'certrev-reader certrev-badge' : 'certrev-reader';
79
+ // `{% if rd %}`: any def that is not nil/false stamps its version.
80
+ const version = isTruthy(f.def) ? ` data-certrev-def-version="${esc(rec(f.def).v)}"` : '';
81
+ return (`<section class="${cls}" style="${f.style}"${version} data-certrev-strings-version="${CERT_STRINGS_VERSION}" ` +
82
+ `data-certrev-cert-id="${esc(f.certId)}" aria-label="${esc(aria)}">`);
83
+ }
84
+ const anchor = (href, modal, label) => `<a href="${esc(href)}" target="_blank" rel="${CERTREV_LINK_REL}" data-certrev-modal-open${modal}>${label}</a>`;
85
+ /** The words the memo-less banner and the memo link row use for the profile link. */
86
+ function profileLabel(f) {
87
+ const first = cleaned(firstName(f.ename));
88
+ return first !== '' ? `View ${esc(first)}&rsquo;s profile` : 'View profile';
89
+ }
90
+ const credentialAria = (f) => `Content reviewed by ${f.ename}${f.creds !== '' ? `, ${f.creds}` : ''}`;
91
+ /** The compensation cue's slot at the head of the scope line (memo footer, sidebar). */
92
+ function scopeLead(f) {
93
+ if (f.hasCue)
94
+ return `<em>${COMPENSATED_EXPERT_CUE}</em> · `;
95
+ if (f.illus)
96
+ return '<em>Illustrative example</em> · ';
97
+ return '';
98
+ }
99
+ const SCOPE = `<span data-ftc-line>${CERT_SCOPE_LINE}</span>`;
100
+ /** The "{credential} · Credential verified by CertREV[ on {date}]" muted line (the credential part is the caller's). */
101
+ function verifiedLine(f, withCredentials) {
102
+ if (f.creds === '')
103
+ return '';
104
+ const date = cleaned(isBlank(f.expert.credentialVerifiedAt) ? '' : longDate(f.expert.credentialVerifiedAt));
105
+ const on = date !== '' ? ` on ${esc(date)}` : '';
106
+ const lead = withCredentials ? `${esc(f.creds)} · ` : '';
107
+ return `<em>${lead}Credential verified by CertREV${on}</em>`;
108
+ }
109
+ // ─────────────────────────────────────────────────────────────────────────────
110
+ // Banner: the "Expert reviewed & certified" card, and the expert memo card beneath it
111
+ // ─────────────────────────────────────────────────────────────────────────────
112
+ function bannerCard(f) {
113
+ if (f.ename === '')
114
+ return '';
115
+ const author = rec(f.content.author);
116
+ const authorName = textOr(author.name);
117
+ const authorTitle = textOr(author.title);
118
+ const hasAuthor = f.disp.showAuthor !== false && authorName !== '' && authorName !== f.ename;
119
+ const avatar = (photo, size) => f.hideAvatar ? '' : readerFace({ photo, show: f.showPhoto, size, width: 84 });
120
+ const authorBy = hasAuthor
121
+ ? `<div class="certrev-r-by">${avatar(author.photoUrl, 'sm')}<div>\n <b>${esc(authorName)}</b>` +
122
+ `${authorTitle !== '' ? `<em>${esc(authorTitle)}</em>` : ''}<span class="certrev-r-role">Written by</span>\n </div>\n </div>`
123
+ : '';
124
+ const expertBy = `<div class="certrev-r-by">${avatar(f.expert.photoUrl, '')}<div>\n <b>${esc(f.ename)}</b>` +
125
+ `${verifiedLine(f, true)}<span class="certrev-r-role on">Reviewed by</span>\n </div>\n </div>`;
126
+ const certifiedAt = f.content.certifiedAt;
127
+ const certified = isBlank(certifiedAt) ? '' : cleaned(longDate(certifiedAt));
128
+ // A memo-less article gets the profile and certificate row, so the certificate stays reachable.
129
+ let links = '';
130
+ if (f.noMemo && (f.purl !== '' || f.vurl !== '')) {
131
+ links =
132
+ '<div class="certrev-r-links">' +
133
+ (f.purl !== '' ? anchor(f.purl, '="expert"', profileLabel(f)) : '') +
134
+ (f.vurl !== '' ? anchor(f.vurl, '', 'View certificate') : '') +
135
+ '</div>';
136
+ }
137
+ const hasFoot = certified !== '' || f.hasCue || f.illus;
138
+ const rule = hasFoot || f.noMemo ? '<div class="certrev-r-rule"></div>' : '';
139
+ let foot = '';
140
+ if (hasFoot) {
141
+ const when = certified !== ''
142
+ ? `<span><em>Certified</em><time datetime="${esc(certifiedAt)}">${esc(certified)}</time></span>`
143
+ : '<span></span>';
144
+ let cue = '';
145
+ if (f.hasCue) {
146
+ cue = `<span>Compensated ${f.purl !== '' ? anchor(f.purl, '="expert"', 'expert') : 'expert'}</span>`;
147
+ }
148
+ else if (f.illus) {
149
+ cue = '<span>Illustrative example</span>';
150
+ }
151
+ foot = `<div class="certrev-r-foot">${when}${cue}</div>`;
152
+ }
153
+ // POR-9317: the memo card carries the scope line when there is a memo; with none this card is the sole claim face.
154
+ const scope = f.noMemo ? `<div class="certrev-r-scope" data-ftc-disclosure>${SCOPE}</div>` : '';
155
+ return (`${sectionOpen(f, true, credentialAria(f))}\n <div class="certrev-r-card">\n` +
156
+ ` <div class="certrev-r-cap">${readerLogo(f.fg === '#ffffff' ? 'white' : 'mono', 18, 'CertREV')}Expert reviewed &amp; certified</div>\n` +
157
+ ` <div class="certrev-r-cap-body">\n <div class="certrev-r-bys${hasAuthor ? '' : ' solo'}">${authorBy}${expertBy}\n </div>` +
158
+ `${links}${rule}${foot}${scope}</div>\n </div>\n</section>`);
159
+ }
160
+ function bannerMemo(f) {
161
+ if (f.ename === '' || isBlank(f.content.memo))
162
+ return '';
163
+ const links = f.purl !== '' || f.vurl !== ''
164
+ ? '<div class="certrev-r-links">' +
165
+ (f.purl !== '' ? anchor(f.purl, '="expert"', profileLabel(f)) : '') +
166
+ (f.vurl !== '' ? anchor(f.vurl, '', 'View certificate') : '') +
167
+ '</div>'
168
+ : '';
169
+ const avatar = f.hideAvatar ? '' : readerFace({ photo: f.expert.photoUrl, show: f.showPhoto, size: 'lg', width: 112 });
170
+ return (`${sectionOpen(f, false, `Expert memo by ${f.ename}`)}\n <div class="certrev-r-card pad">\n` +
171
+ ' <div class="certrev-r-kick">Expert memo</div>\n' +
172
+ ` <div class="certrev-r-memo">${avatar}<div>\n` +
173
+ ` <div class="certrev-r-memo-name"><b>${esc(f.ename)}</b>${f.creds !== '' ? `, ${esc(f.creds)}` : ''}</div>\n` +
174
+ ` <blockquote>${esc(f.content.memo)}</blockquote>${links}</div>\n </div>\n` +
175
+ ' <div class="certrev-r-rule"></div>\n <div class="certrev-r-vfoot">\n' +
176
+ ` <span class="certrev-r-verified">${readerLogo('mono', 17, '')}Verified by <b>CertREV</b></span>\n` +
177
+ ` <span class="certrev-r-scope" data-ftc-disclosure>${scopeLead(f)}${SCOPE}</span>\n </div>\n </div>\n</section>`);
178
+ }
179
+ // ─────────────────────────────────────────────────────────────────────────────
180
+ // Sidebar and floating pill
181
+ // ─────────────────────────────────────────────────────────────────────────────
182
+ function sidebar(f) {
183
+ if (f.ename === '')
184
+ return '';
185
+ const bio = f.disp.showBio !== false && !isBlank(f.expert.bio) ? asText(f.expert.bio) : '';
186
+ const avatar = f.hideAvatar ? '' : readerFace({ photo: f.expert.photoUrl, show: f.showPhoto, size: 'lg', width: 112 });
187
+ const both = f.purl !== '' && f.vurl !== '';
188
+ const links = f.purl !== '' || f.vurl !== ''
189
+ ? `<div class="certrev-r-side-links${both ? '' : ' single'}">` +
190
+ (f.purl !== '' ? anchor(f.purl, '="expert"', 'View Profile') : '') +
191
+ (f.vurl !== '' ? anchor(f.vurl, '', 'View Certificate') : '') +
192
+ '</div>'
193
+ : '';
194
+ return (`${sectionOpen(f, true, credentialAria(f))}\n <div class="certrev-r-side">\n` +
195
+ ` <div class="certrev-r-cap center">${readerLogo(f.fg === '#ffffff' ? 'white' : 'mono', 18, 'CertREV')}Expert reviewed</div>\n` +
196
+ ` <div class="certrev-r-side-body">\n <div class="certrev-r-by">${avatar}<div>\n` +
197
+ ` <b>${esc(f.ename)}${f.creds !== '' ? `, ${esc(f.creds)}` : ''}</b>${verifiedLine(f, false)}</div>\n </div>` +
198
+ `${bio !== '' ? `<p>${esc(bio)}</p>` : ''}` +
199
+ `${isBlank(f.content.memo) ? '' : `<blockquote>${esc(f.content.memo)}</blockquote>`}` +
200
+ `<div class="certrev-r-scope" data-ftc-disclosure>${scopeLead(f)}${SCOPE}</div>\n </div>` +
201
+ `${links}</div>\n</section>`);
202
+ }
203
+ function pill(f) {
204
+ if (f.vurl === '')
205
+ return '';
206
+ const profile = f.purl !== '' ? `${anchor(f.purl, '="expert"', 'Profile')}<i aria-hidden="true">·</i>` : '';
207
+ return (`${sectionOpen(f, true, 'Expert reviewed')}\n <div class="certrev-r-pill">\n <span>Expert reviewed:</span>` +
208
+ `${profile}${anchor(f.vurl, '', 'Certificate')}\n </div>\n</section>`);
209
+ }
210
+ /**
211
+ * The reader face's HTML for one layout. '' where the face paints nothing (no reviewer name; a pill with no safe
212
+ * verify URL; a banner `part` that has no block): the caller treats '' as "render nothing", never as an empty section.
213
+ *
214
+ * A def with no `layout` meaning here (`custom`, or any value that is not banner, sidebar or floating) is the
215
+ * caller's to resolve before it calls: this takes the layout it will paint.
216
+ */
217
+ export function renderReaderFace(input) {
218
+ const f = readFacts(input);
219
+ if (input.layout === 'sidebar')
220
+ return sidebar(f);
221
+ if (input.layout === 'floating')
222
+ return pill(f);
223
+ const part = input.part ?? 'full';
224
+ if (part === 'header')
225
+ return bannerCard(f);
226
+ if (part === 'memo')
227
+ return bannerMemo(f);
228
+ return [bannerCard(f), bannerMemo(f)].filter((block) => block !== '').join('\n');
229
+ }
230
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/reader/render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export interface ReaderTokens {
2
+ /** The value of the section's `style` attribute. */
3
+ readonly style: string;
4
+ /** The ink on the accent: `#ffffff` or `#141414`. The logo is white on the first and mono on the second. */
5
+ readonly fg: string;
6
+ }
7
+ export declare function readerTokens(def: unknown): ReaderTokens;
8
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/reader/tokens.ts"],"names":[],"mappings":"AAgDA,MAAM,WAAW,YAAY;IAC5B,oDAAoD;IACpD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,4GAA4G;IAC5G,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,CAoBvD"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * `certrev-reader-tokens`: the four CSS custom properties a reader section carries on its root, from the render def.
3
+ *
4
+ * --cr-ba the accent the card cap and pill paint: the def's `barInk`, else its `accentColor`, else navy
5
+ * --cr-ba-fg the ink on that accent: white, or `#141414` when the def baked it for the colour that painted
6
+ * --cr-br the corner radius
7
+ * --cr-bf the font stack for the brand's `fontSlot`
8
+ *
9
+ * The values land inside a double-quoted `style` attribute, so a colour or radius that could break out of it
10
+ * (`; ( ) { } < > "` or a space) is dropped to its default rather than escaped into something half valid. The variable
11
+ * names are the reader stylesheet's (`reader.css`), which `.certrev-reader` declares defaults for.
12
+ */
13
+ import { asText } from '../components/escape.js';
14
+ import { esc, rec, textOr } from './helpers.js';
15
+ /** The accent when the def has none: CertREV navy. */
16
+ const DEFAULT_ACCENT = '#0A1B3F';
17
+ const DEFAULT_RADIUS = '14px';
18
+ /** The foreground the def bakes for a light accent; anything else is the white default. */
19
+ const DARK_INK = '#141414';
20
+ /**
21
+ * The font stack per `fontSlot`, in one table so the Liquid `certrev-reader-tokens` snippet and this one are compared
22
+ * on a single list. An unknown or missing slot is the sans stack, as in the snippet. The serif and grotesk stacks name
23
+ * the reader's own `@font-face` aliases first ("CertREV Reader Serif" / "CertREV Reader Grotesk", declared in
24
+ * `reader.css`), then the legacy family and the generic fallbacks, as the snippet's `--cr-bf` does.
25
+ */
26
+ function fontStack(slot) {
27
+ switch (slot) {
28
+ case 'serif':
29
+ return "'CertREV Reader Serif', 'Playfair Display', ui-serif, Georgia, serif";
30
+ case 'grotesk':
31
+ return "'CertREV Reader Grotesk', 'Plus Jakarta Sans', ui-sans-serif, system-ui, sans-serif";
32
+ case 'mono':
33
+ return "'JetBrains Mono', ui-monospace, monospace";
34
+ case 'system':
35
+ return "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif";
36
+ default:
37
+ return "'DM Sans', ui-sans-serif, system-ui, sans-serif";
38
+ }
39
+ }
40
+ /** A token value that cannot leave the style attribute, or '' (which the caller defaults). */
41
+ function guarded(value) {
42
+ const text = textOr(value);
43
+ return /[;(){}<>" ]/.test(text) ? '' : text;
44
+ }
45
+ export function readerTokens(def) {
46
+ const rd = rec(def);
47
+ const tokens = rec(rd.tokens);
48
+ const barInk = guarded(tokens.barInk);
49
+ const accent = guarded(tokens.accentColor);
50
+ const ba = barInk || accent || DEFAULT_ACCENT;
51
+ // The ink follows the value that painted the accent: a def with a bar ink takes the foreground baked for it
52
+ // (barInkFg); one that paints its accent colour takes the one baked for that colour (accentFg).
53
+ let fg = '#ffffff';
54
+ if (barInk !== '') {
55
+ if (rd.barInkFg === DARK_INK)
56
+ fg = DARK_INK;
57
+ }
58
+ else if (accent !== '' && rd.accentFg === DARK_INK) {
59
+ fg = DARK_INK;
60
+ }
61
+ const br = guarded(tokens.cornerRadius) || DEFAULT_RADIUS;
62
+ const bf = fontStack(asText(tokens.fontSlot));
63
+ return { style: `--cr-ba:${esc(ba)};--cr-ba-fg:${fg};--cr-br:${esc(br)};--cr-bf:${bf}`, fg };
64
+ }
65
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/reader/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAChD,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAE/C,sDAAsD;AACtD,MAAM,cAAc,GAAG,SAAS,CAAA;AAChC,MAAM,cAAc,GAAG,MAAM,CAAA;AAC7B,2FAA2F;AAC3F,MAAM,QAAQ,GAAG,SAAS,CAAA;AAE1B;;;;;GAKG;AACH,SAAS,SAAS,CAAC,IAAY;IAC9B,QAAQ,IAAI,EAAE,CAAC;QACd,KAAK,OAAO;YACX,OAAO,sEAAsE,CAAA;QAC9E,KAAK,SAAS;YACb,OAAO,qFAAqF,CAAA;QAC7F,KAAK,MAAM;YACV,OAAO,2CAA2C,CAAA;QACnD,KAAK,QAAQ;YACZ,OAAO,8EAA8E,CAAA;QACtF;YACC,OAAO,iDAAiD,CAAA;IAC1D,CAAC;AACF,CAAC;AAED,8FAA8F;AAC9F,SAAS,OAAO,CAAC,KAAc;IAC9B,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAC1B,OAAO,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;AAC5C,CAAC;AASD,MAAM,UAAU,YAAY,CAAC,GAAY;IACxC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,CAAA;IACnB,MAAM,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAA;IAE7B,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACrC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;IAC1C,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,IAAI,cAAc,CAAA;IAE7C,4GAA4G;IAC5G,gGAAgG;IAChG,IAAI,EAAE,GAAG,SAAS,CAAA;IAClB,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;QACnB,IAAI,EAAE,CAAC,QAAQ,KAAK,QAAQ;YAAE,EAAE,GAAG,QAAQ,CAAA;IAC5C,CAAC;SAAM,IAAI,MAAM,KAAK,EAAE,IAAI,EAAE,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACtD,EAAE,GAAG,QAAQ,CAAA;IACd,CAAC;IAED,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,cAAc,CAAA;IACzD,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC7C,OAAO,EAAE,KAAK,EAAE,WAAW,GAAG,CAAC,EAAE,CAAC,eAAe,EAAE,YAAY,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE,EAAE,EAAE,EAAE,CAAA;AAC7F,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"get-verified-delivery.d.ts","sourceRoot":"","sources":["../../src/verify/get-verified-delivery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AACzE,OAAO,KAAK,EAEX,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,qBAAqB,EACrB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAGrC,qGAAqG;AACrG,MAAM,MAAM,cAAc,GACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAA;CAAE,GAC5G;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,CAAA;AAEvE,mGAAmG;AACnG,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,iGAAiG;IACjG,QAAQ,CAAC,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAA;CAC9C;AAED,MAAM,WAAW,0BAA0B;IAC1C,mGAAmG;IACnG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,mEAAmE;IACnE,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAA;IAC1C,8FAA8F;IAC9F,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACjC,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAA;IACzC,mGAAmG;IACnG,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,kFAAkF;AAClF,QAAA,MAAM,mBAAmB,0BAAwE,CAAA;AAMjG,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAGzF;AAED,wGAAwG;AACxG,wBAAgB,gBAAgB,CAC/B,IAAI,EAAE,IAAI,CAAC,0BAA0B,EAAE,SAAS,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,CAAC,GACvF,MAAM,CAER;AAKD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,GAAG,IAAI,CA4BzE;AAyCD,iGAAiG;AACjG,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,aAAa,GAAG,gBAAgB,CAI/F;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,OAAO,CAAC,gBAAgB,CAAC,CASrG;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CACnC,IAAI,EAAE,IAAI,CAAC,0BAA0B,EAAE,SAAS,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC,GACjG,gBAAgB,GAAG,SAAS,CAG9B;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CACjC,IAAI,EAAE,IAAI,CAAC,0BAA0B,EAAE,SAAS,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,CAAC,EACzF,KAAK,GAAE,QAAQ,CAAC,cAAc,CAAuB,GACnD,IAAI,CAEN;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAA"}
1
+ {"version":3,"file":"get-verified-delivery.d.ts","sourceRoot":"","sources":["../../src/verify/get-verified-delivery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AACzE,OAAO,KAAK,EAEX,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,qBAAqB,EACrB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAGrC,qGAAqG;AACrG,MAAM,MAAM,cAAc,GACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAA;CAAE,GAC5G;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,CAAA;AAEvE,mGAAmG;AACnG,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,iGAAiG;IACjG,QAAQ,CAAC,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAA;CAC9C;AAED,MAAM,WAAW,0BAA0B;IAC1C,mGAAmG;IACnG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,mEAAmE;IACnE,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAA;IAC1C,8FAA8F;IAC9F,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACjC,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAA;IACzC,mGAAmG;IACnG,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,kFAAkF;AAClF,QAAA,MAAM,mBAAmB,0BAAwE,CAAA;AAMjG,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAGzF;AAED,wGAAwG;AACxG,wBAAgB,gBAAgB,CAC/B,IAAI,EAAE,IAAI,CAAC,0BAA0B,EAAE,SAAS,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,CAAC,GACvF,MAAM,CAER;AAKD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,GAAG,IAAI,CAgCzE;AAyCD,iGAAiG;AACjG,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,aAAa,GAAG,gBAAgB,CAI/F;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,OAAO,CAAC,gBAAgB,CAAC,CASrG;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CACnC,IAAI,EAAE,IAAI,CAAC,0BAA0B,EAAE,SAAS,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC,GACjG,gBAAgB,GAAG,SAAS,CAG9B;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CACjC,IAAI,EAAE,IAAI,CAAC,0BAA0B,EAAE,SAAS,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,CAAC,EACzF,KAAK,GAAE,QAAQ,CAAC,cAAc,CAAuB,GACnD,IAAI,CAEN;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAA"}
@@ -52,7 +52,7 @@ const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v)
52
52
  export function parseRenderDef(value) {
53
53
  if (!isRecord(value))
54
54
  return null;
55
- const { v, preset, rung, tokens, hidden, barInkFg, layout, customFace } = value;
55
+ const { v, preset, rung, tokens, hidden, barInkFg, accentFg, face: faceName, layout, customFace } = value;
56
56
  if (typeof v !== 'number' || !Number.isFinite(v))
57
57
  return null;
58
58
  if (!isString(preset) || !isString(rung) || !isRecord(tokens))
@@ -79,6 +79,10 @@ export function parseRenderDef(value) {
79
79
  rung,
80
80
  tokens: tokenOut,
81
81
  ...(barInkFg === '#141414' || barInkFg === '#ffffff' ? { barInkFg } : {}),
82
+ // 1.2.0: the reader face's two keys. 1.1.x dropped both; they are kept only when well-formed, so a def that
83
+ // carries neither parses to exactly the object 1.1.1 returned for it.
84
+ ...(accentFg === '#141414' || accentFg === '#ffffff' ? { accentFg } : {}),
85
+ ...(isString(faceName) ? { face: faceName } : {}),
82
86
  hidden: [...hidden],
83
87
  ...(layout !== undefined ? { layout } : {}),
84
88
  ...(face ? { customFace: face } : {}),
@@ -1 +1 @@
1
- {"version":3,"file":"get-verified-delivery.js","sourceRoot":"","sources":["../../src/verify/get-verified-delivery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"get-verified-delivery.js","sourceRoot":"","sources":["../../src/verify/get-verified-delivery.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@certrev/cert-block",
3
- "version": "1.1.0",
3
+ "version": "1.2.0-canary.0",
4
4
  "description": "Headless render edge for the CertREV CertDeliveryEnvelope: SSR-safe React cert components, a framework-agnostic <certrev-badge> Web Component, a schema.org JSON-LD projector, and a fail-closed verify layer over the shared VerdictKernel.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -27,6 +27,11 @@
27
27
  "types": "./dist/builder/envelope-face.d.ts",
28
28
  "default": "./dist/builder/envelope-face.js"
29
29
  },
30
+ "./reader": {
31
+ "types": "./dist/reader/index.d.ts",
32
+ "default": "./dist/reader/index.js"
33
+ },
34
+ "./reader.css": "./src/reader/reader.css",
30
35
  "./webcomponent": {
31
36
  "types": "./dist/webcomponent/certrev-badge.d.ts",
32
37
  "default": "./dist/webcomponent/certrev-badge.js"
@@ -65,6 +70,7 @@
65
70
  "scripts": {
66
71
  "build": "tsc && pnpm build:modal-bundle",
67
72
  "build:modal-bundle": "pnpm dlx esbuild@0.27.7 src/modal/certrev-cert.entry.ts --bundle --minify --target=es2020 --format=iife --legal-comments=none --tsconfig-raw='{\"compilerOptions\":{\"target\":\"ES2017\",\"module\":\"esnext\",\"strict\":true}}' --banner:js='/* biome-ignore-all format: generated cert-badge bundle, see @certrev/cert-block src/modal/ */ /* biome-ignore-all lint: generated cert-badge bundle, see @certrev/cert-block src/modal/ */' --outfile=dist/modal/certrev-cert.js",
73
+ "refresh:reader": "node scripts/refresh-reader.mjs",
68
74
  "typecheck": "tsc --noEmit",
69
75
  "test": "vitest run"
70
76
  },
@@ -47,6 +47,16 @@ export interface CertChromeRenderDef {
47
47
  }
48
48
  /** The auto-contrast bar foreground — present only on a barInk-themed face (v2). */
49
49
  readonly barInkFg?: '#141414' | '#ffffff'
50
+ /**
51
+ * The ink painted over the ACCENT fill, as the portal derived it (1.2.0, reader face). Only the reader face reads
52
+ * it: the legacy face re-derives its own accent ink from `tokens.accentColor` and ignores this.
53
+ */
54
+ readonly accentFg?: '#141414' | '#ffffff'
55
+ /**
56
+ * The face the brand chose (1.2.0). `'reader'` selects the certrev.com reader face; absent, or any other value,
57
+ * paints the face 1.1.1 paints (unknown faces degrade to the legacy face, never to nothing).
58
+ */
59
+ readonly face?: string
50
60
  /** The subtractive field-visibility hide-set. */
51
61
  readonly hidden: readonly string[]
52
62
  /**
@@ -23,11 +23,12 @@ import { Suspense } from 'react'
23
23
  import { memoToggleFor, toggleMemo } from '../components/memo-toggle.js'
24
24
  import { type CertBlockMode, renderCertBlock } from '../components/render-cert-block.js'
25
25
  import { CERT_STRINGS_VERSION, type ResolvedBlockTheme } from '../components/render-def.js'
26
+ import { READER_CSS } from '../reader/reader-css.generated.js'
26
27
  import { getVerifiedDelivery, peekVerifiedDelivery, type VerifiedDelivery } from '../verify/get-verified-delivery.js'
27
28
  import type { BuilderCertChromeData } from './cert-chrome-data.js'
28
29
  import { BUILDER_CERT_CHROME_KEYS } from './cert-chrome-data.js'
29
30
  import { cardDeliveryRuntime } from './delivery-runtime.js'
30
- import { envelopeCardInput } from './envelope-face.js'
31
+ import { envelopeCardHtml, envelopeCardInput, isReaderFaceDef } from './envelope-face.js'
31
32
 
32
33
  /**
33
34
  * The canonical Builder block name. A brand's registration + the portal
@@ -147,8 +148,17 @@ function suspendOn(key: string, start: () => Promise<VerifiedDelivery>): Verifie
147
148
  * in; the button is native, so Enter and Space reach it as clicks. Bound after hydration only: the
148
149
  * server HTML is the collapsed face, which is also what a reader without JS keeps (the whole memo
149
150
  * is still in the text for a screen reader, and the desktop never clamps it).
151
+ *
152
+ * `reader` (1.2.0) is true ONLY for a def whose `face` is `'reader'`; it adds two things to the wrapper and nothing to
153
+ * any other face: `data-certrev-face="reader"` and `display: flow-root`. The reader sidebar card is a right float, and
154
+ * on a Shopify page the placement script and its wrapper contain it; a Builder block has no such ancestor, so the
155
+ * wrapper contains the float itself and the block keeps its own box in the page.
150
156
  */
151
- function EnvelopeFace(props: { readonly html: string; readonly defVersion: number | undefined }) {
157
+ function EnvelopeFace(props: {
158
+ readonly html: string
159
+ readonly defVersion: number | undefined
160
+ readonly reader?: boolean
161
+ }) {
152
162
  const ref = React.useRef<HTMLDivElement>(null)
153
163
  React.useEffect(() => {
154
164
  const el = ref.current
@@ -169,6 +179,7 @@ function EnvelopeFace(props: { readonly html: string; readonly defVersion: numbe
169
179
  data-certrev-delivery=""
170
180
  data-certrev-strings-version={CERT_STRINGS_VERSION}
171
181
  data-certrev-def-version={props.defVersion}
182
+ {...(props.reader ? { 'data-certrev-face': 'reader', style: { display: 'flow-root' } } : {})}
172
183
  // biome-ignore lint/security/noDangerouslySetInnerHtml: renderCertBlock is the escaping-safe SSR string renderer
173
184
  dangerouslySetInnerHTML={{ __html: props.html }}
174
185
  />
@@ -192,6 +203,24 @@ function EnvelopeCertReviewCard(props: {
192
203
  )
193
204
  // Revoked, expired, unverifiable, for another entry, or unreachable: nothing at all.
194
205
  if (settled.verdict.decision !== 'render') return null
206
+ // The reader face is opt-in by the def's own `face` and is chosen HERE and nowhere else on this path; every other
207
+ // def (no face, an unknown face) falls through to the legacy lines below, untouched since 1.1.1.
208
+ if (isReaderFaceDef(settled.renderDef)) {
209
+ const reader = envelopeCardHtml(settled.verdict.payload.content, settled.renderDef, {
210
+ mode: props.mode,
211
+ part: props.part,
212
+ certId: settled.verdict.payload.certId,
213
+ })
214
+ if (!reader) return null
215
+ return (
216
+ <EnvelopeFace
217
+ reader
218
+ // The stylesheet rides inside the face, once per card; it is the portal's reader CSS byte for byte.
219
+ html={`<style data-certrev-reader-css>${READER_CSS}</style>${reader}`}
220
+ defVersion={settled.renderDef ? settled.renderDef.v : undefined}
221
+ />
222
+ )
223
+ }
195
224
  const input = envelopeCardInput(settled.verdict.payload.content, settled.renderDef, {
196
225
  mode: props.mode,
197
226
  part: props.part,
@@ -26,14 +26,16 @@
26
26
  * it only returns null when the verified content cannot make a face (no reviewer, no verify URL).
27
27
  */
28
28
 
29
- import type {
30
- CertBlockFace,
31
- CertBlockLayout,
32
- CertBlockMode,
33
- RenderCertBlockInput,
29
+ import {
30
+ type CertBlockFace,
31
+ type CertBlockLayout,
32
+ type CertBlockMode,
33
+ type RenderCertBlockInput,
34
+ renderCertBlock,
34
35
  } from '../components/render-cert-block.js'
35
36
  import { accentFg, HIDEABLE_FIELDS, isOpaqueHexColor, type ResolvedBlockTheme } from '../components/render-def.js'
36
37
  import type { CertContent } from '../contract/kernel.js'
38
+ import { type ReaderLayout, renderReaderFace } from '../reader/render.js'
37
39
  import type { CertChromeRenderDef } from './cert-chrome-data.js'
38
40
 
39
41
  /**
@@ -74,6 +76,10 @@ export interface EnvelopeCardOptions {
74
76
  readonly mode?: unknown
75
77
  /** Banner memo placement, passed through as on the options path. */
76
78
  readonly part?: unknown
79
+ /** The verified payload's `certId`: stamped on the reader face (`data-certrev-cert-id`). The legacy face ignores it. */
80
+ readonly certId?: unknown
81
+ /** A CertREV preview, never a live page: the reader face words the cue's empty slot as the demo does. Only `true` counts. */
82
+ readonly illustrative?: unknown
77
83
  }
78
84
 
79
85
  /** The def's theme tokens as `renderCertBlock` theme input, with the accent ink derived. */
@@ -171,3 +177,46 @@ export function envelopeCardInput(
171
177
  },
172
178
  }
173
179
  }
180
+
181
+ /** The def `face` that selects the certrev.com reader face (1.2.0). Nothing else does. */
182
+ export const READER_FACE = 'reader'
183
+
184
+ /** Whether a def asks for the reader face: `face === 'reader'`, exactly. Absent or any other value is the legacy face. */
185
+ export function isReaderFaceDef(def: CertChromeRenderDef | null | undefined): boolean {
186
+ return def?.face === READER_FACE
187
+ }
188
+
189
+ /**
190
+ * The card's HTML for a verified envelope's content and the brand's def, or '' when nothing paints.
191
+ *
192
+ * THE ONE SELECTION POINT between the two faces, react-free so the portal's preview reaches it too:
193
+ * - `renderDef.face === 'reader'` paints the reader face (`renderReaderFace`), the same bytes as the Shopify reader
194
+ * snippets for the same facts;
195
+ * - EVERY other def (no `face`, `face: 'legacy'`, a face this version has never heard of, no def at all) paints
196
+ * exactly `renderCertBlock(envelopeCardInput(...))`, byte for byte what 1.1.1 paints. An unknown face degrades to
197
+ * the face the page had before, never to nothing and never to the reader.
198
+ * The reader branch sits BESIDE the legacy one; `envelopeCardInput` and `renderCertBlock` are not touched.
199
+ *
200
+ * Both faces keep the one gate they share: a content with no reviewer name or no certificate URL cannot make a face.
201
+ * The reader's layout is `layoutFor` (an editor mode wins, then the def's own layout, else banner); the legacy-only
202
+ * `custom` composition has no reader twin and paints the reader banner.
203
+ */
204
+ export function envelopeCardHtml(
205
+ content: CertContent,
206
+ renderDef: CertChromeRenderDef | null,
207
+ options: EnvelopeCardOptions = {},
208
+ ): string {
209
+ const input = envelopeCardInput(content, renderDef, options)
210
+ if (!input) return ''
211
+ if (!isReaderFaceDef(renderDef)) return renderCertBlock(input)
212
+ const chosen = layoutFor(renderDef, options.mode)
213
+ const layout: ReaderLayout = chosen === 'custom' ? 'banner' : chosen
214
+ return renderReaderFace({
215
+ content,
216
+ def: renderDef,
217
+ layout,
218
+ part: input.part,
219
+ certId: typeof options.certId === 'string' ? options.certId : undefined,
220
+ illustrative: options.illustrative === true,
221
+ })
222
+ }