@certrev/cert-block 1.2.0-canary.1 → 1.2.0-canary.2

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.
@@ -21,6 +21,11 @@
21
21
  * its words are fixed. `illustrative` (a CertREV preview, never a live page) fills the cue's slot with the demo's
22
22
  * "Illustrative example" label when the envelope has no cue; a real cue always wins the slot;
23
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 text leaves are the demo's (what React server-renders): the memo name is the name, "," and the credential; the
25
+ * profile link is "View", the first name and "’s profile"; the sidebar name is the name, "," and the credential in
26
+ * one `<b>`; the certified date is direct text of its span beside the "Certified" cue (no `<time>`); the scope
27
+ * sentence is direct text of the scope element, which carries `data-ftc-line` itself. The `<!-- -->` marks between
28
+ * adjacent leaves are React's, kept so the bytes equal the Liquid snippets' and the portal's goldens;
24
29
  * - the def's `hidden` set removes the avatars (`reviewerPhoto`), `display.showExpertPhoto === false` keeps the
25
30
  * silhouette and never requests the photo, `display.showAuthor === false` drops the author column.
26
31
  *
@@ -153,10 +158,14 @@ function sectionOpen(f: Facts, badge: boolean, aria: string): string {
153
158
  const anchor = (href: string, modal: string, label: string): string =>
154
159
  `<a href="${esc(href)}" target="_blank" rel="${CERTREV_LINK_REL}" data-certrev-modal-open${modal}>${label}</a>`
155
160
 
156
- /** The words the memo-less banner and the memo link row use for the profile link. */
161
+ /**
162
+ * The words the memo-less banner and the memo link row use for the profile link: the demo's three leaves ("View", the
163
+ * first name, "’s profile"), set apart by the `<!-- -->` React paints between adjacent text expressions. With no first
164
+ * name the wording stays one leaf.
165
+ */
157
166
  function profileLabel(f: Facts): string {
158
167
  const first = cleaned(firstName(f.ename))
159
- return first !== '' ? `View ${esc(first)}&rsquo;s profile` : 'View profile'
168
+ return first !== '' ? `View <!-- -->${esc(first)}<!-- -->&rsquo;s profile` : 'View profile'
160
169
  }
161
170
 
162
171
  const credentialAria = (f: Facts): string => `Content reviewed by ${f.ename}${f.creds !== '' ? `, ${f.creds}` : ''}`
@@ -168,7 +177,12 @@ function scopeLead(f: Facts): string {
168
177
  return ''
169
178
  }
170
179
 
171
- const SCOPE = `<span data-ftc-line>${CERT_SCOPE_LINE}</span>`
180
+ /**
181
+ * The scope sentence is DIRECT text of the scope element (the demo's `<span class="dg-scope">`), which carries the
182
+ * `data-ftc-line` marker itself: no inner span, so the element's `.certrev-r-scope em` cue and the sentence are leaves of
183
+ * one element, as the demo paints them. The marker is on exactly one element per render, as before.
184
+ */
185
+ const SCOPE = CERT_SCOPE_LINE
172
186
 
173
187
  /**
174
188
  * The muted credential line, empty when the reviewer has no displayed credential (so no "verified" claim prints).
@@ -225,10 +239,9 @@ function bannerCard(f: Facts): string {
225
239
 
226
240
  let foot = ''
227
241
  if (hasFoot) {
228
- const when =
229
- certified !== ''
230
- ? `<span><em>Certified</em><time datetime="${esc(certifiedAt)}">${esc(certified)}</time></span>`
231
- : '<span></span>'
242
+ // The demo's `<span><em>Certified</em>{date}</span>`: the date is direct text of the span (no `<time>`), so the
243
+ // span paints the mono cue and the date's own face.
244
+ const when = certified !== '' ? `<span><em>Certified</em>${esc(certified)}</span>` : '<span></span>'
232
245
  let cue = ''
233
246
  if (f.hasCue) {
234
247
  cue = `<span>Compensated ${f.purl !== '' ? anchor(f.purl, '="expert"', 'expert') : 'expert'}</span>`
@@ -239,7 +252,7 @@ function bannerCard(f: Facts): string {
239
252
  }
240
253
 
241
254
  // POR-9317: the memo card carries the scope line when there is a memo; with none this card is the sole claim face.
242
- const scope = f.noMemo ? `<div class="certrev-r-scope" data-ftc-disclosure>${SCOPE}</div>` : ''
255
+ const scope = f.noMemo ? `<div class="certrev-r-scope" data-ftc-disclosure data-ftc-line>${SCOPE}</div>` : ''
243
256
 
244
257
  return (
245
258
  `${sectionOpen(f, true, credentialAria(f))}\n <div class="certrev-r-card">\n` +
@@ -263,11 +276,11 @@ function bannerMemo(f: Facts): string {
263
276
  `${sectionOpen(f, false, `Expert memo by ${f.ename}`)}\n <div class="certrev-r-card pad">\n` +
264
277
  ' <div class="certrev-r-kick">Expert memo</div>\n' +
265
278
  ` <div class="certrev-r-memo">${avatar}<div>\n` +
266
- ` <div class="certrev-r-memo-name"><b>${esc(f.ename)}</b>${f.creds !== '' ? `, ${esc(f.creds)}` : ''}</div>\n` +
279
+ ` <div class="certrev-r-memo-name"><b>${esc(f.ename)}</b>${f.creds !== '' ? `, <!-- -->${esc(f.creds)}` : ''}</div>\n` +
267
280
  ` <blockquote>${esc(f.content.memo)}</blockquote>${links}</div>\n </div>\n` +
268
281
  ' <div class="certrev-r-rule"></div>\n <div class="certrev-r-vfoot">\n' +
269
282
  ` <span class="certrev-r-verified">${readerLogo('mono', 17, '')}Verified by <b>CertREV</b></span>\n` +
270
- ` <span class="certrev-r-scope" data-ftc-disclosure>${scopeLead(f)}${SCOPE}</span>\n </div>\n </div>\n</section>`
283
+ ` <span class="certrev-r-scope" data-ftc-disclosure data-ftc-line>${scopeLead(f)}${SCOPE}</span>\n </div>\n </div>\n</section>`
271
284
  )
272
285
  }
273
286
 
@@ -291,10 +304,10 @@ function sidebar(f: Facts): string {
291
304
  `${sectionOpen(f, true, credentialAria(f))}\n <div class="certrev-r-side">\n` +
292
305
  ` <div class="certrev-r-cap center">${readerLogo(f.fg === '#ffffff' ? 'white' : 'mono', 18, 'CertREV')}Expert reviewed</div>\n` +
293
306
  ` <div class="certrev-r-side-body">\n <div class="certrev-r-by">${avatar}<div>\n` +
294
- ` <b>${esc(f.ename)}${f.creds !== '' ? `, ${esc(f.creds)}` : ''}</b>${verifiedLine(f, false)}</div>\n </div>` +
307
+ ` <b>${esc(f.ename)}${f.creds !== '' ? `<!-- -->, <!-- -->${esc(f.creds)}` : ''}</b>${verifiedLine(f, false)}</div>\n </div>` +
295
308
  `${bio !== '' ? `<p>${esc(bio)}</p>` : ''}` +
296
309
  `${isBlank(f.content.memo) ? '' : `<blockquote>${esc(f.content.memo)}</blockquote>`}` +
297
- `<div class="certrev-r-scope" data-ftc-disclosure>${scopeLead(f)}${SCOPE}</div>\n </div>` +
310
+ `<div class="certrev-r-scope" data-ftc-disclosure data-ftc-line>${scopeLead(f)}${SCOPE}</div>\n </div>` +
298
311
  `${links}</div>\n</section>`
299
312
  )
300
313
  }
@@ -24,16 +24,17 @@ const DARK_INK = '#141414'
24
24
 
25
25
  /**
26
26
  * The font stack per `fontSlot`, in one table so the Liquid `certrev-reader-tokens` snippet and this one are compared
27
- * on a single list. An unknown or missing slot is the sans stack, as in the snippet. The serif and grotesk stacks name
28
- * the reader's own `@font-face` aliases first ("CertREV Reader Serif" / "CertREV Reader Grotesk", declared in
29
- * `reader.css`), then the legacy family and the generic fallbacks, as the snippet's `--cr-bf` does.
27
+ * on a single list. An unknown or missing slot is the sans stack, as in the snippet. The stacks are the demo's own, byte
28
+ * for byte: the reader block of `reader.css` declares certrev.com's own faces under these family names (DM Sans,
29
+ * Playfair Display, Plus Jakarta Sans, JetBrains Mono) at `font-stretch: 101%`, which the reader root asks for, so the
30
+ * legacy faces a page may also load are untouched. `system` has no demo stack and keeps the legacy one.
30
31
  */
31
32
  function fontStack(slot: string): string {
32
33
  switch (slot) {
33
34
  case 'serif':
34
- return "'CertREV Reader Serif', 'Playfair Display', ui-serif, Georgia, serif"
35
+ return "'Playfair Display', ui-serif, Georgia, serif"
35
36
  case 'grotesk':
36
- return "'CertREV Reader Grotesk', 'Plus Jakarta Sans', ui-sans-serif, system-ui, sans-serif"
37
+ return "'Plus Jakarta Sans', ui-sans-serif, system-ui, sans-serif"
37
38
  case 'mono':
38
39
  return "'JetBrains Mono', ui-monospace, monospace"
39
40
  case 'system':