@certrev/cert-block 0.5.3 → 0.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -0
- package/README.md +12 -1
- package/dist/components/render-def.d.ts +11 -7
- package/dist/components/render-def.d.ts.map +1 -1
- package/dist/components/render-def.js +17 -9
- package/dist/components/render-def.js.map +1 -1
- package/package.json +10 -1
- package/src/__tests__/readme-version.test.ts +51 -0
- package/src/__tests__/render-def.test.tsx +14 -5
- package/src/components/render-def.ts +17 -9
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,51 @@ change the rendered cert output and never break a compiling integration** (regis
|
|
|
5
5
|
exports, types). Anything that would alter what a visitor sees — or require integration changes —
|
|
6
6
|
is announced loudly here first.
|
|
7
7
|
|
|
8
|
+
## 0.5.5 — 2026-07-31
|
|
9
|
+
|
|
10
|
+
- **New:** `repository`, `homepage`, and `bugs` in `package.json` — the npm page now links to the
|
|
11
|
+
public source mirror (`github.com/CertREV/cert-kit`, `packages/cert-block`) and to the issue
|
|
12
|
+
tracker, so the registry listing is no longer a dead end. Provenance metadata only: no code, no
|
|
13
|
+
exports, no dependency change.
|
|
14
|
+
- **Docs:** README gains a source-repo link and states the peer requirement explicitly — **React
|
|
15
|
+
`>=18`**. `peerDependencies.react` has enforced `>=18.0.0` since before 0.5.0 (and
|
|
16
|
+
`peerDependenciesMeta` marks it non-optional), but the README never said so; a consumer had to
|
|
17
|
+
read `package.json` to find the floor.
|
|
18
|
+
- Rendered output: **byte-identical to 0.5.4** (metadata and prose only — no file under `dist/`
|
|
19
|
+
changes).
|
|
20
|
+
|
|
21
|
+
## 0.5.4 — 2026-07-23
|
|
22
|
+
|
|
23
|
+
- **Backfilled — this release shipped with no entry.** 0.5.4 published 2026-07-23 and is the first
|
|
24
|
+
release after this file was written; every other version from 0.3.0 on has a section, including
|
|
25
|
+
0.5.2 (a no-op republish). It changed the public type surface without the notice the contract
|
|
26
|
+
above requires. The omission is recorded here rather than quietly closed.
|
|
27
|
+
- **Changed:** `FONT_SLOTS` / `FONT_STACKS` (`render-def`) widened 3 → 5 — `grotesk` (Plus Jakarta
|
|
28
|
+
Sans) and `mono` (JetBrains Mono) added at the shared guide values, byte-identical to this
|
|
29
|
+
package's `RENDER_BLOCK_FONT_STACKS`, the portal `FONT_SLOT_STACKS`, and the Liquid twin's
|
|
30
|
+
branches. Purely additive: `sans` / `serif` / `system` are untouched, so the card == modal
|
|
31
|
+
invariant holds. Shipped lockstep with the portal's Liquid + WordPress grotesk/mono wiring
|
|
32
|
+
(POR-10775 / POR-10721) — Phase-3 enablement of a vocabulary that was dormant on both engines,
|
|
33
|
+
not a repair of a live intra-page mismatch: before this release the Liquid card dropped
|
|
34
|
+
`grotesk`/`mono` too, and fell back exactly as the modal did.
|
|
35
|
+
- **Breaking (types) — belonged in a minor, with notice:** `FONT_SLOTS`, `FONT_STACKS`, `FontSlot`
|
|
36
|
+
and `isFontSlot` are public exports. Widening the `FontSlot` union 3 → 5 breaks any consumer
|
|
37
|
+
holding an exhaustive `Record<FontSlot, string>` or an exhaustive `switch` over the slots — a
|
|
38
|
+
break of a compiling integration (exports, types) under the semver contract at the top of this
|
|
39
|
+
file, shipped in a patch.
|
|
40
|
+
- Rendered output: the design-locked cert card and the modal bundle are **byte-identical to
|
|
41
|
+
0.5.3** — across the two published tarballs `dist/components/render-cert-block.js` (sha1
|
|
42
|
+
`22267d5d…`) and all 65 files under `dist/modal/` (`certrev-cert.js` sha1 `2013ebbe…`) are
|
|
43
|
+
unchanged, and neither resolves the shared `FONT_STACKS` (the card carries its own
|
|
44
|
+
`RENDER_BLOCK_FONT_STACKS`, which already listed all five slots; the modal consults no font map
|
|
45
|
+
at all). `<certrev-badge>` passes no `renderDef`, so it is unaffected by construction. Output can
|
|
46
|
+
differ on ONE path: a caller passing a `renderDef` with `fontSlot: 'grotesk' | 'mono'` into the
|
|
47
|
+
legacy `<CertBadge>` / `renderBadgeHtml`, where that slot now resolves to a `--certrev-font`
|
|
48
|
+
stack instead of being dropped as invalid. No brand could author those slots at release time (the
|
|
49
|
+
portal editor did not offer them; every known `render_def` writer emits `sans`), so no visitor's
|
|
50
|
+
render is known to have changed — that last point is inference from the call graph and the
|
|
51
|
+
authoring surface, not a production data check.
|
|
52
|
+
|
|
8
53
|
## 0.5.3 — 2026-07-22
|
|
9
54
|
|
|
10
55
|
- **New:** `certRevCertComponent` (`./builder`) — the drop-in gen2 registration entry, with the
|
package/README.md
CHANGED
|
@@ -226,6 +226,12 @@ RFC-8785 JCS implementation used for signature verification). To be clear about
|
|
|
226
226
|
**nothing cryptographic runs at card render** — the cert card draws purely from block options;
|
|
227
227
|
verification enters only with the modal / the `getVerifiedEnvelope` verify layer.
|
|
228
228
|
|
|
229
|
+
React is the one **peer** dependency left — **`react >=18.0.0`**, declared non-optional, so a
|
|
230
|
+
peer-enforcing resolver (npm 7+) fails the install on React 17 with `ERESOLVE` rather than
|
|
231
|
+
warning. Only the React entries need it: `./webcomponent` and `./modal` build React-free (no
|
|
232
|
+
`react/jsx-runtime`) and there is no `react-dom` peer. CI builds and runs the SSR tests on
|
|
233
|
+
React 18.3; the range admits 19.
|
|
234
|
+
|
|
229
235
|
## Known issues (upstream)
|
|
230
236
|
|
|
231
237
|
- `@builder.io/sdk-react@5.2.4` ships types that fail to compile under
|
|
@@ -251,7 +257,12 @@ Facts are mocked via `makeMockPayload` / `makeSignedEnvelope` (`src/contract/fix
|
|
|
251
257
|
|
|
252
258
|
## Version
|
|
253
259
|
|
|
254
|
-
`0.5.
|
|
260
|
+
`0.5.5` — see [CHANGELOG.md](./CHANGELOG.md) for the release history and the semver contract
|
|
255
261
|
(patch/minor never change the rendered cert output or break a compiling integration). Publishes
|
|
256
262
|
**publicly** to npm as `@certrev/cert-block` (`publishConfig.access: public`) via GitHub Actions
|
|
257
263
|
trusted publishing (OIDC); the internal `@certrev` GitHub-Packages channel mirrors it.
|
|
264
|
+
|
|
265
|
+
Source is public at [`CertREV/cert-kit`](https://github.com/CertREV/cert-kit) (MIT) — this
|
|
266
|
+
package is `packages/cert-block/`; report a vulnerability privately through that repo's
|
|
267
|
+
`SECURITY.md`. The tarball also ships `src/` alongside `dist/`, so a security review reads the
|
|
268
|
+
exact code for the version it installed.
|
|
@@ -41,15 +41,19 @@
|
|
|
41
41
|
* entry targets (edge / Workers / server / client).
|
|
42
42
|
*/
|
|
43
43
|
/** The font ENUM. Resolves to a FIXED slot stack — never a free-form family. */
|
|
44
|
-
export declare const FONT_SLOTS: readonly ["sans", "serif", "system"];
|
|
44
|
+
export declare const FONT_SLOTS: readonly ["sans", "serif", "system", "grotesk", "mono"];
|
|
45
45
|
export type FontSlot = (typeof FONT_SLOTS)[number];
|
|
46
46
|
/**
|
|
47
|
-
* The `fontSlot` → fixed font-stack literal
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
47
|
+
* The `fontSlot` → fixed font-stack literal — the render-def theme map the webcomponent MODAL
|
|
48
|
+
* (`resolveRenderTheme` → `renderBadgeHtml`) and the legacy `<CertBadge>` resolve. The three original
|
|
49
|
+
* slots (sans/serif/system) stay BYTE-IDENTICAL to the Shopify Liquid engine's stacks
|
|
50
|
+
* (`shopify/extensions/certrev-schema/snippets/certrev-badge.liquid`), so a themed brand's popup modal
|
|
51
|
+
* and its inline Liquid card paint the same typography — the load-bearing card==modal invariant.
|
|
52
|
+
* grotesk (Plus Jakarta Sans) + mono (JetBrains Mono) are ADDED at the shared guide values —
|
|
53
|
+
* byte-identical to portal `FONT_SLOT_STACKS`, this package's `RENDER_BLOCK_FONT_STACKS`, and the
|
|
54
|
+
* Liquid twin's added branches — so card == modal holds for them too. A raw family string in a
|
|
55
|
+
* `font-family` CSS var is a CSS-injection surface AND breaks the "CertREV hosts no fonts" invariant,
|
|
56
|
+
* so the enum → stack indirection is the security boundary.
|
|
53
57
|
*/
|
|
54
58
|
export declare const FONT_STACKS: Readonly<Record<FontSlot, string>>;
|
|
55
59
|
/** A fully-resolved themeable token set (a brand overrides a subset of these). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-def.d.ts","sourceRoot":"","sources":["../../src/components/render-def.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAMH,gFAAgF;AAChF,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"render-def.d.ts","sourceRoot":"","sources":["../../src/components/render-def.ts"],"names":[],"mappings":"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"}
|
|
@@ -44,19 +44,25 @@
|
|
|
44
44
|
// Themeable token vocabulary (mirrors portal src/lib/design-guide/tokens.ts)
|
|
45
45
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
46
46
|
/** The font ENUM. Resolves to a FIXED slot stack — never a free-form family. */
|
|
47
|
-
export const FONT_SLOTS = ['sans', 'serif', 'system'];
|
|
47
|
+
export const FONT_SLOTS = ['sans', 'serif', 'system', 'grotesk', 'mono'];
|
|
48
48
|
/**
|
|
49
|
-
* The `fontSlot` → fixed font-stack literal
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
49
|
+
* The `fontSlot` → fixed font-stack literal — the render-def theme map the webcomponent MODAL
|
|
50
|
+
* (`resolveRenderTheme` → `renderBadgeHtml`) and the legacy `<CertBadge>` resolve. The three original
|
|
51
|
+
* slots (sans/serif/system) stay BYTE-IDENTICAL to the Shopify Liquid engine's stacks
|
|
52
|
+
* (`shopify/extensions/certrev-schema/snippets/certrev-badge.liquid`), so a themed brand's popup modal
|
|
53
|
+
* and its inline Liquid card paint the same typography — the load-bearing card==modal invariant.
|
|
54
|
+
* grotesk (Plus Jakarta Sans) + mono (JetBrains Mono) are ADDED at the shared guide values —
|
|
55
|
+
* byte-identical to portal `FONT_SLOT_STACKS`, this package's `RENDER_BLOCK_FONT_STACKS`, and the
|
|
56
|
+
* Liquid twin's added branches — so card == modal holds for them too. A raw family string in a
|
|
57
|
+
* `font-family` CSS var is a CSS-injection surface AND breaks the "CertREV hosts no fonts" invariant,
|
|
58
|
+
* so the enum → stack indirection is the security boundary.
|
|
55
59
|
*/
|
|
56
60
|
export const FONT_STACKS = {
|
|
57
61
|
sans: "'DM Sans', system-ui, -apple-system, BlinkMacSystemFont, sans-serif",
|
|
58
62
|
serif: "'Playfair Display', Georgia, 'Times New Roman', serif",
|
|
59
63
|
system: "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
|
|
64
|
+
grotesk: "'Plus Jakarta Sans', system-ui, Helvetica, Arial, sans-serif",
|
|
65
|
+
mono: "'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
60
66
|
};
|
|
61
67
|
/** The badge fields a render-def may SUBTRACTIVELY hide (brand-toggleable, free). */
|
|
62
68
|
export const HIDEABLE_FIELDS = ['reviewerPhoto', 'memo'];
|
|
@@ -128,8 +134,10 @@ export function isFieldHidden(def, id) {
|
|
|
128
134
|
// above (which the legacy `<CertBadge>` uses): it mirrors the portal's FULL
|
|
129
135
|
// five-member `FontSlot` enum + the pre-computed `accentFg` ink, so the block can
|
|
130
136
|
// reproduce the guide's four-font design (DM Sans body, Playfair memo, JetBrains
|
|
131
|
-
// mono labels, Plus Jakarta wordmark).
|
|
132
|
-
//
|
|
137
|
+
// mono labels, Plus Jakarta wordmark). Its STACKS stay DISTINCT from `FONT_STACKS`
|
|
138
|
+
// above: both maps now span the same five `FontSlot`s, but `FONT_STACKS` pins
|
|
139
|
+
// sans/serif/system to the legacy Liquid table (the card==modal invariant) while this
|
|
140
|
+
// map pins them to the guide table; grotesk/mono are byte-identical across both.
|
|
133
141
|
/**
|
|
134
142
|
* The full portal font-slot enum (mirrors portal `src/lib/design-guide/tokens.ts`
|
|
135
143
|
* `FONT_SLOTS`). `grotesk` ⇐ the guide's wordmark slot; `mono` ⇐ the label slot.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-def.js","sourceRoot":"","sources":["../../src/components/render-def.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,gFAAgF;AAChF,6EAA6E;AAC7E,gFAAgF;AAEhF,gFAAgF;AAChF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"render-def.js","sourceRoot":"","sources":["../../src/components/render-def.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@certrev/cert-block",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.5",
|
|
4
4
|
"description": "Headless / crypto_verify render edge for the CertREV CertDeliveryEnvelope. SSR-safe React components (<CertBadge>/<ExpertBio>/<CertRevBacklink>), a deterministic schema.org JSON-LD projector, a fail-closed verify layer over the shared VerdictKernel, and a framework-agnostic <certrev-badge> Web Component. Sign once (portal), render everywhere (Hydrogen / Next / Builder / universal embed).",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/CertREV/cert-kit.git",
|
|
8
|
+
"directory": "packages/cert-block"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/CertREV/cert-kit/tree/HEAD/packages/cert-block#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/CertREV/cert-kit/issues"
|
|
13
|
+
},
|
|
5
14
|
"type": "module",
|
|
6
15
|
"main": "./dist/index.js",
|
|
7
16
|
"types": "./dist/index.d.ts",
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import { describe, expect, it } from 'vitest'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Both public packages open a `## Version` section with a bare version stamp, and both ship
|
|
6
|
+
* README.md inside the published tarball (`files`) — so the stamp is what a consumer reads
|
|
7
|
+
* after `npm i`, not just what a browser shows on GitHub.
|
|
8
|
+
*
|
|
9
|
+
* It has now drifted twice, in both packages:
|
|
10
|
+
* - cert-contract 0.5.1 was a docs-only release whose entire purpose was unsticking this
|
|
11
|
+
* stamp ("README Version section brought current (0.4.0 / 0.5.0 were missing)").
|
|
12
|
+
* - cert-block 0.5.4 bumped package.json and touched nothing else, so the published 0.5.4
|
|
13
|
+
* tarball ships a README claiming to be 0.5.3. That is live on npm right now.
|
|
14
|
+
*
|
|
15
|
+
* Nothing caught either one, because nothing was looking: the stamp is prose, and prose has
|
|
16
|
+
* no compiler. A release step nobody can forget beats a release step written down somewhere.
|
|
17
|
+
* This is that step.
|
|
18
|
+
*
|
|
19
|
+
* The two packages word the line differently ("`x.y.z` — see" vs "Current: `x.y.z` — see"),
|
|
20
|
+
* so the pattern below matches the first backticked token after the heading rather than a
|
|
21
|
+
* fixed sentence. If a README reshapes that section, update the pattern — do not delete the
|
|
22
|
+
* assertion; the drift it catches has shipped to npm twice.
|
|
23
|
+
*/
|
|
24
|
+
const PACKAGES = ['cert-block', 'cert-contract'] as const
|
|
25
|
+
|
|
26
|
+
describe.each(PACKAGES)('%s README version stamp', (pkgName) => {
|
|
27
|
+
const pkgUrl = new URL(`../../../${pkgName}/package.json`, import.meta.url)
|
|
28
|
+
const readmeUrl = new URL(`../../../${pkgName}/README.md`, import.meta.url)
|
|
29
|
+
|
|
30
|
+
const { version } = JSON.parse(readFileSync(pkgUrl, 'utf8')) as { version: string }
|
|
31
|
+
const readme = readFileSync(readmeUrl, 'utf8')
|
|
32
|
+
|
|
33
|
+
it('matches package.json — bump both, or neither', () => {
|
|
34
|
+
// First backticked token after the `## Version` heading.
|
|
35
|
+
const stamp = readme.match(/^## Version\s*\n+[^`\n]*`([^`]+)`/m)
|
|
36
|
+
|
|
37
|
+
expect(
|
|
38
|
+
stamp,
|
|
39
|
+
`${pkgName}: README has no \`## Version\` section opening with a backticked stamp. If the ` +
|
|
40
|
+
'section was renamed or reshaped, update this pattern to match the new shape rather ' +
|
|
41
|
+
'than deleting the assertion.',
|
|
42
|
+
).not.toBeNull()
|
|
43
|
+
|
|
44
|
+
expect(
|
|
45
|
+
stamp?.[1],
|
|
46
|
+
`${pkgName}: README's \`## Version\` stamp is ${stamp?.[1]} but package.json is ${version}. ` +
|
|
47
|
+
'README.md ships inside the npm tarball, so this mismatch gets published to consumers. ' +
|
|
48
|
+
`Bump the stamp in packages/${pkgName}/README.md.`,
|
|
49
|
+
).toBe(version)
|
|
50
|
+
})
|
|
51
|
+
})
|
|
@@ -67,9 +67,9 @@ describe('token validators (mirror portal src/lib/design-guide/tokens.ts)', () =
|
|
|
67
67
|
for (const bad of ['12', '12 px', 'calc(1px)', '1px 2px', '', 'px', '-4px']) expect(isCornerRadius(bad)).toBe(false)
|
|
68
68
|
})
|
|
69
69
|
|
|
70
|
-
it('isFontSlot admits
|
|
71
|
-
for (const ok of ['sans', 'serif', 'system']) expect(isFontSlot(ok)).toBe(true)
|
|
72
|
-
for (const bad of ['
|
|
70
|
+
it('isFontSlot admits the five enum members', () => {
|
|
71
|
+
for (const ok of ['sans', 'serif', 'system', 'grotesk', 'mono']) expect(isFontSlot(ok)).toBe(true)
|
|
72
|
+
for (const bad of ['Arial', '', 'SANS', 'wingdings']) expect(isFontSlot(bad)).toBe(false)
|
|
73
73
|
})
|
|
74
74
|
})
|
|
75
75
|
|
|
@@ -78,6 +78,10 @@ describe('FONT_STACKS — byte-identical to the Shopify Liquid engine literals',
|
|
|
78
78
|
expect(FONT_STACKS.sans).toBe("'DM Sans', system-ui, -apple-system, BlinkMacSystemFont, sans-serif")
|
|
79
79
|
expect(FONT_STACKS.serif).toBe("'Playfair Display', Georgia, 'Times New Roman', serif")
|
|
80
80
|
expect(FONT_STACKS.system).toBe("system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif")
|
|
81
|
+
// grotesk/mono added at the shared guide values — byte-identical to RENDER_BLOCK_FONT_STACKS
|
|
82
|
+
// and the portal FONT_SLOT_STACKS, so the modal + Liquid card paint the same typography.
|
|
83
|
+
expect(FONT_STACKS.grotesk).toBe("'Plus Jakarta Sans', system-ui, Helvetica, Arial, sans-serif")
|
|
84
|
+
expect(FONT_STACKS.mono).toBe("'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace")
|
|
81
85
|
})
|
|
82
86
|
})
|
|
83
87
|
|
|
@@ -96,13 +100,18 @@ describe('resolveRenderTheme — validates + drops (fail-safe)', () => {
|
|
|
96
100
|
})
|
|
97
101
|
})
|
|
98
102
|
|
|
103
|
+
it('resolves the ADDED grotesk/mono slots to their FONT_STACKS families (the modal themes all five)', () => {
|
|
104
|
+
expect(resolveRenderTheme({ tokens: { fontSlot: 'grotesk' } }).fontStack).toBe(FONT_STACKS.grotesk)
|
|
105
|
+
expect(resolveRenderTheme({ tokens: { fontSlot: 'mono' } }).fontStack).toBe(FONT_STACKS.mono)
|
|
106
|
+
})
|
|
107
|
+
|
|
99
108
|
it('DROPS every invalid token (alpha surface, function accent, calc radius, unknown slot)', () => {
|
|
100
109
|
const resolved = resolveRenderTheme({
|
|
101
110
|
tokens: {
|
|
102
111
|
accentColor: 'rgb(0,0,0)',
|
|
103
112
|
surface: '#ffffffaa',
|
|
104
113
|
cornerRadius: 'calc(1px)',
|
|
105
|
-
fontSlot: '
|
|
114
|
+
fontSlot: 'wingdings' as FontSlot,
|
|
106
115
|
},
|
|
107
116
|
version: 2,
|
|
108
117
|
})
|
|
@@ -251,7 +260,7 @@ describe('renderBadgeHtml themed (the crawlable string path)', () => {
|
|
|
251
260
|
accentColor: 'rgb(0,0,0)',
|
|
252
261
|
surface: '#ffffffaa',
|
|
253
262
|
cornerRadius: 'calc(1px)',
|
|
254
|
-
fontSlot: '
|
|
263
|
+
fontSlot: 'wingdings' as FontSlot,
|
|
255
264
|
},
|
|
256
265
|
},
|
|
257
266
|
})
|
|
@@ -46,21 +46,27 @@
|
|
|
46
46
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
47
47
|
|
|
48
48
|
/** The font ENUM. Resolves to a FIXED slot stack — never a free-form family. */
|
|
49
|
-
export const FONT_SLOTS = ['sans', 'serif', 'system'] as const
|
|
49
|
+
export const FONT_SLOTS = ['sans', 'serif', 'system', 'grotesk', 'mono'] as const
|
|
50
50
|
export type FontSlot = (typeof FONT_SLOTS)[number]
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
|
-
* The `fontSlot` → fixed font-stack literal
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
53
|
+
* The `fontSlot` → fixed font-stack literal — the render-def theme map the webcomponent MODAL
|
|
54
|
+
* (`resolveRenderTheme` → `renderBadgeHtml`) and the legacy `<CertBadge>` resolve. The three original
|
|
55
|
+
* slots (sans/serif/system) stay BYTE-IDENTICAL to the Shopify Liquid engine's stacks
|
|
56
|
+
* (`shopify/extensions/certrev-schema/snippets/certrev-badge.liquid`), so a themed brand's popup modal
|
|
57
|
+
* and its inline Liquid card paint the same typography — the load-bearing card==modal invariant.
|
|
58
|
+
* grotesk (Plus Jakarta Sans) + mono (JetBrains Mono) are ADDED at the shared guide values —
|
|
59
|
+
* byte-identical to portal `FONT_SLOT_STACKS`, this package's `RENDER_BLOCK_FONT_STACKS`, and the
|
|
60
|
+
* Liquid twin's added branches — so card == modal holds for them too. A raw family string in a
|
|
61
|
+
* `font-family` CSS var is a CSS-injection surface AND breaks the "CertREV hosts no fonts" invariant,
|
|
62
|
+
* so the enum → stack indirection is the security boundary.
|
|
59
63
|
*/
|
|
60
64
|
export const FONT_STACKS: Readonly<Record<FontSlot, string>> = {
|
|
61
65
|
sans: "'DM Sans', system-ui, -apple-system, BlinkMacSystemFont, sans-serif",
|
|
62
66
|
serif: "'Playfair Display', Georgia, 'Times New Roman', serif",
|
|
63
67
|
system: "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
|
|
68
|
+
grotesk: "'Plus Jakarta Sans', system-ui, Helvetica, Arial, sans-serif",
|
|
69
|
+
mono: "'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
64
70
|
}
|
|
65
71
|
|
|
66
72
|
/** A fully-resolved themeable token set (a brand overrides a subset of these). */
|
|
@@ -191,8 +197,10 @@ export function isFieldHidden(def: CertRenderDef | undefined, id: BadgeVisibilit
|
|
|
191
197
|
// above (which the legacy `<CertBadge>` uses): it mirrors the portal's FULL
|
|
192
198
|
// five-member `FontSlot` enum + the pre-computed `accentFg` ink, so the block can
|
|
193
199
|
// reproduce the guide's four-font design (DM Sans body, Playfair memo, JetBrains
|
|
194
|
-
// mono labels, Plus Jakarta wordmark).
|
|
195
|
-
//
|
|
200
|
+
// mono labels, Plus Jakarta wordmark). Its STACKS stay DISTINCT from `FONT_STACKS`
|
|
201
|
+
// above: both maps now span the same five `FontSlot`s, but `FONT_STACKS` pins
|
|
202
|
+
// sans/serif/system to the legacy Liquid table (the card==modal invariant) while this
|
|
203
|
+
// map pins them to the guide table; grotesk/mono are byte-identical across both.
|
|
196
204
|
|
|
197
205
|
/**
|
|
198
206
|
* The full portal font-slot enum (mirrors portal `src/lib/design-guide/tokens.ts`
|