remarque-tokens 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +81 -0
- package/README.md +7 -0
- package/REMARQUE.md +109 -1
- package/package.json +12 -3
- package/scripts/audit.mjs +9 -0
- package/scripts/theme.mjs +118 -6
- package/scripts/tokens-json.mjs +156 -10
- package/tokens-palette.css +41 -0
- package/tokens.d.ts +344 -0
- package/tokens.json +82 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,87 @@ All notable changes to `remarque-tokens` are documented here. Token value
|
|
|
4
4
|
changes always state the design rationale — downstream sites pin against
|
|
5
5
|
these entries when syncing.
|
|
6
6
|
|
|
7
|
+
## 0.13.0 — 2026-07-23
|
|
8
|
+
|
|
9
|
+
Syntax-highlighting palette — 9 `--color-syntax-*` slots, ANSI-derived, golden-gated (closes #53; consensus-ratified 3-0 with a binding taxonomy design record, 2026-07-23).
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- **`--color-syntax-keyword/string/constant/comment/function/type/punctuation/variable/link`** —
|
|
13
|
+
9 new palette-tier slots in `tokens-palette.css`, hand-authored in both
|
|
14
|
+
themes, quiet/low-chroma (chroma capped at 0.14, the same ceiling as
|
|
15
|
+
`--color-accent`). Every slot is ≥ 4.5:1 against `--color-code-bg`
|
|
16
|
+
(not `--color-bg`) in both themes — a new dimension the audit didn't
|
|
17
|
+
cover before this release.
|
|
18
|
+
- **`scripts/audit.mjs`** — 9 new `CHECKS` pairings (each syntax slot vs.
|
|
19
|
+
`color-code-bg`, 4.5:1, both themes). `scripts/test-audit.mjs`'s
|
|
20
|
+
fixture palettes carry the 9 slots and a new must-fail case proves
|
|
21
|
+
they're actually wired into `CHECKS`, not just parsed.
|
|
22
|
+
- **`scripts/theme.mjs` (`remarque-theme`)** — derives all 9 slots from a
|
|
23
|
+
source theme's 16 ANSI colors (`keyword`←blue, `string`←green,
|
|
24
|
+
`constant`←yellow, `function`←purple, `type`←cyan, `comment`←`brightBlack`
|
|
25
|
+
in dark themes / a solved muted neutral in light themes,
|
|
26
|
+
`punctuation`←a derived neutral, `variable`←fg-adjacent,
|
|
27
|
+
`link`←the derived accent, aliased when it clears 4.5:1 on `code-bg`),
|
|
28
|
+
same keep-if-passing-else-solve pattern and in-gamut chroma clamping as
|
|
29
|
+
every other slot. `scripts/test-theme.mjs`'s 61-pair corpus (every
|
|
30
|
+
counterpart-paired theme in the installed `oklch-terminal-themes`
|
|
31
|
+
dataset) now runs the extended audit — 61/61 pass.
|
|
32
|
+
- **`scripts/palette-golden.mjs`** — extends the ΔE2000 ≤ 2.0 golden gate
|
|
33
|
+
to the 9 syntax slots (now 24 `--color-*` tokens × 2 themes). The
|
|
34
|
+
hand-authored defaults are the cleaned round-number serialization of
|
|
35
|
+
values derived from `remarque-light`/`remarque-dark`'s ANSI colors,
|
|
36
|
+
same identity/serialization contract as the rest of the default
|
|
37
|
+
palette (#76).
|
|
38
|
+
- **REMARQUE.md "Syntax Highlighting"** — the slot table with Shiki
|
|
39
|
+
`createCssVariablesTheme` and Prism class mappings, the exact Astro
|
|
40
|
+
wiring snippet (pass the theme *object*, never the `'css-variables'`
|
|
41
|
+
string — Astro renames its prefix), the CSS variable bridge required
|
|
42
|
+
to make that wiring actually render (Shiki's `variablePrefix` prepends
|
|
43
|
+
rather than renames its internal `token-*` names), a full Prism CSS
|
|
44
|
+
mapping block, the three documented divergences (`type` ≡ `function`
|
|
45
|
+
under Shiki, plain operators inherit foreground, diff markers out of
|
|
46
|
+
scope), and the comment-contrast policy (4.5:1 held; GitHub
|
|
47
|
+
light/dark-default and VS Code Dark+ all clear it).
|
|
48
|
+
- **Demo site (`site/`)** — wired `astro.config.mjs`'s `markdown.shikiConfig`
|
|
49
|
+
and the Type Specimen page's new "Syntax Highlighting" section with
|
|
50
|
+
the `createCssVariablesTheme` recipe and its CSS bridge
|
|
51
|
+
(`site/src/styles/globals.css`), so at least one built page exercises
|
|
52
|
+
every slot in both themes. `shiki` added as an explicit `site`
|
|
53
|
+
devDependency (Astro already carries it transitively; pinned
|
|
54
|
+
explicitly so the resolution is intentional, not an accident of
|
|
55
|
+
hoisting). Playwright baselines updated for the 4 `specimen-*`
|
|
56
|
+
screenshots (the only page with a highlighted code block); the other
|
|
57
|
+
16 baselines are unchanged.
|
|
58
|
+
|
|
59
|
+
## 0.12.0 — 2026-07-23
|
|
60
|
+
|
|
61
|
+
TypeScript types and a README "Used By" section (closes #34, closes #35).
|
|
62
|
+
|
|
63
|
+
### Added
|
|
64
|
+
- **`tokens.d.ts`** — generated from `tokens.json` by `scripts/tokens-json.mjs`
|
|
65
|
+
(regenerates in the same run as `tokens.json`; `--check` verifies both are
|
|
66
|
+
fresh, wired into the same `deploy.yml` CI step). Ships literal-union types
|
|
67
|
+
for every token name (`RemarqueCoreToken`, `RemarquePaletteToken`,
|
|
68
|
+
`RemarqueToken`), a `RemarqueCssVar` template-literal type
|
|
69
|
+
(`` `--${RemarqueToken}` ``), structural interfaces matching tokens.json's
|
|
70
|
+
actual shape (`RemarqueTokensFile`, `RemarqueCoreTokenEntry`,
|
|
71
|
+
`RemarquePaletteTokenEntry`), a `RemarqueTokenValues` interface with the
|
|
72
|
+
live value of every token as a literal type, and an ambient
|
|
73
|
+
`declare module 'remarque-tokens/tokens.json'` so
|
|
74
|
+
`import tokens from 'remarque-tokens/tokens.json'` is precisely typed
|
|
75
|
+
without depending on the consumer's `resolveJsonModule`. This package has
|
|
76
|
+
no JS entry point — the types exist for editors/TS consumers who author
|
|
77
|
+
Remarque token names or read `tokens.json` programmatically.
|
|
78
|
+
`package.json` wires `types`, an `./tokens.d.ts` export, and a `types`
|
|
79
|
+
condition on the existing `./tokens.json` export; `scripts/test-types.mjs`
|
|
80
|
+
gates token-name coverage, the exported type surface, and the
|
|
81
|
+
`package.json` wiring (string assertions, no `typescript` dependency
|
|
82
|
+
added).
|
|
83
|
+
- **README "Used By" section** — the demo site, `williamzujkowski.github.io`
|
|
84
|
+
(core-tier npm consumer), `tsundoku` (full-palette npm consumer, custom
|
|
85
|
+
accent hue), and `remarque-starter` (template repo), one line each on how
|
|
86
|
+
they consume the package.
|
|
87
|
+
|
|
7
88
|
## 0.11.0 — 2026-07-23
|
|
8
89
|
|
|
9
90
|
Palette golden gate: the default palette is now bound, by CI, to the
|
package/README.md
CHANGED
|
@@ -19,6 +19,13 @@ Most developer sites inherit the visual language of SaaS dashboards or component
|
|
|
19
19
|
- **Self-hosted fonts** — no Google CDN dependency. Strict CSP. GDPR-compliant.
|
|
20
20
|
- **AI-native** — designed to be consumed by Claude Code, Cursor, Copilot, and other AI coding tools with zero aesthetic drift.
|
|
21
21
|
|
|
22
|
+
## Used By
|
|
23
|
+
|
|
24
|
+
- **[Remarque demo site](https://williamzujkowski.github.io/remarque/)** — the `site/` directory in this repo; reference implementation of all four demoed archetypes, deployed to GitHub Pages.
|
|
25
|
+
- **[williamzujkowski.github.io](https://github.com/williamzujkowski/williamzujkowski.github.io)** — flagship personal site; core-tier npm consumer (`remarque-tokens/core` from npm, hand-authored palette layer on top).
|
|
26
|
+
- **[tsundoku](https://github.com/williamzujkowski/tsundoku)** — bookshelf/reading-log site; full-palette npm consumer, custom terracotta "book cloth" accent hue over the default palette for its card-catalog identity.
|
|
27
|
+
- **[remarque-starter](https://github.com/williamzujkowski/remarque-starter)** — template repo; Astro scaffold pulling `remarque-tokens` from npm with the audit wired into CI, meant to be forked.
|
|
28
|
+
|
|
22
29
|
## Install
|
|
23
30
|
|
|
24
31
|
```bash
|
package/REMARQUE.md
CHANGED
|
@@ -80,7 +80,7 @@ The palette tier (all `--color-*` tokens) can be *supplied* rather than hand-aut
|
|
|
80
80
|
npx remarque-theme <light-slug> [--dark <dark-slug>] [-o palette-override.css]
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
-
Terminal themes carry only `background/foreground/cursor/selection` + 16 ANSI slots — a few of Remarque's
|
|
83
|
+
Terminal themes carry only `background/foreground/cursor/selection` + 16 ANSI slots — a few of Remarque's 24 semantic slots map directly, and most themes fail the AAA `fg-muted` 7:1 line as authored. So `remarque-theme` *derives* rather than maps: **hue and chroma carry the theme's personality; lightness is KEEP-IF-PASSING**. For the slots that have a meaningful "theme's own value" — `fg`, `accent`, `accent-hover`, and (in dark) `selection-fg`/`code-fg` — the theme's own authored lightness is kept as-is when it already clears the slot's contrast target; lightness is solved (binary search, same targets as the Enforcement Checklist below, with in-gamut chroma clamping) *only* when it doesn't. Every other slot (`fg-muted`, `muted`, `border-bold`, the bg ladder, `selection-bg`, `accent-subtle`) is solved/derived unconditionally, as it always was — those don't carry an independent authored value to preserve. This means a well-designed input theme comes through close to its own feel instead of being flattened to the exact threshold; a theme that fails a target still gets a value that passes, exactly as before. The accent hue comes from the theme's cursor color if it's chromatic, otherwise the most saturated classic ANSI color, and is kept consistent between the light and dark half of a pair.
|
|
84
84
|
|
|
85
85
|
The audit remains the gate regardless of provenance — `remarque-theme` self-verifies its own output against the same checks before it will emit anything, but a site that hand-edits a generated palette (or points at a provider with pathological input colors) still runs through `remarque-audit` in CI like any other palette.
|
|
86
86
|
|
|
@@ -231,6 +231,113 @@ Charts are not yet a first-class Remarque surface, but tools built with the syst
|
|
|
231
231
|
|
|
232
232
|
---
|
|
233
233
|
|
|
234
|
+
## Syntax Highlighting
|
|
235
|
+
|
|
236
|
+
Code blocks are a first-class Remarque surface, not a place to reach for a vendor Shiki/Prism theme: `tokens-palette.css` defines 9 `--color-syntax-*` slots, hand-authored in both themes and golden-gated against the upstream `remarque-light`/`remarque-dark` themes' ANSI colors the same way the rest of the default palette is (issue #53). Because they are ordinary palette-tier tokens, they inherit palette swaps and theme-deck runtime switches for free — a vendor theme never does.
|
|
237
|
+
|
|
238
|
+
### Slots
|
|
239
|
+
|
|
240
|
+
| Slot | Shiki (`createCssVariablesTheme`) | Prism |
|
|
241
|
+
|---|---|---|
|
|
242
|
+
| `--color-syntax-keyword` | `token-keyword` | `.keyword`, `.atrule` |
|
|
243
|
+
| `--color-syntax-string` | `token-string` + `token-string-expression` (aliased — regex/template/interpolated are string-like) | `.string`, `.char`, `.attr-value` |
|
|
244
|
+
| `--color-syntax-constant` | `token-constant` | `.number`, `.boolean`, `.constant`, `.symbol` |
|
|
245
|
+
| `--color-syntax-comment` | `token-comment` | `.comment`, `.prolog`, `.doctype`, `.cdata` |
|
|
246
|
+
| `--color-syntax-function` | `token-function` | `.function` |
|
|
247
|
+
| `--color-syntax-type` | (same Shiki variable as `function` — see divergence below) | `.class-name` |
|
|
248
|
+
| `--color-syntax-punctuation` | `token-punctuation` | `.operator`, `.punctuation` |
|
|
249
|
+
| `--color-syntax-variable` | `token-parameter` | `.variable`, `.property`, `.tag`, `.attr-name` |
|
|
250
|
+
| `--color-syntax-link` | `token-link` | `.url` |
|
|
251
|
+
|
|
252
|
+
Slot names were validated against Shiki's `theme-css-variables.ts` and Prism's reference-theme token vocabulary before being frozen (panel condition on #53) — every name above maps to a real token both highlighters actually emit.
|
|
253
|
+
|
|
254
|
+
### Derivation
|
|
255
|
+
|
|
256
|
+
`remarque-theme` derives all 9 slots from the source theme's 16 ANSI colors — the same keep-if-passing-else-solve pattern as every other slot, targeted at `--color-code-bg` (not `--color-bg`) at 4.5:1: `keyword`←blue, `string`←green, `constant`←yellow (the terminal convention for numbers/booleans), `function`←purple, `type`←cyan, `comment`←`brightBlack` in dark themes (solved to a muted neutral on the theme's own fg hue in light themes, where `brightBlack` is often too pale to clear 4.5:1 on `code-bg`), `punctuation`←a derived neutral in the muted family, `variable`←the theme's own fg hue/chroma with a slight lightness offset, and `link`←the already-derived accent triple, aliased with `var(--color-accent)` when it clears 4.5:1 on `code-bg` (solved standalone when it doesn't — accent's guarantee is against `--color-bg`, and `code-bg` sits close enough to drift below the line on some corpus themes). Chroma is capped at 0.14, the same ceiling as `--color-accent`, so syntax colors stay in the system's quiet, one-accent register. `scripts/palette-golden.mjs` extends its ΔE2000 ≤ 2.0 gate to all 9 slots, exactly like the rest of the default palette.
|
|
257
|
+
|
|
258
|
+
### Astro / Shiki wiring
|
|
259
|
+
|
|
260
|
+
Shiki v1+ ships `createCssVariablesTheme` — pass it as an object, not the `'css-variables'` string (Astro renames the string form's variable prefix to `--astro-code-*`, which silently breaks the mapping):
|
|
261
|
+
|
|
262
|
+
```js
|
|
263
|
+
import { createCssVariablesTheme } from 'shiki'; // or '@shikijs/core'
|
|
264
|
+
|
|
265
|
+
const theme = createCssVariablesTheme({
|
|
266
|
+
name: 'remarque',
|
|
267
|
+
variablePrefix: '--color-syntax-',
|
|
268
|
+
fontStyle: true,
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// markdown/MDX: { shikiConfig: { theme } }
|
|
272
|
+
// <Code> component: <Code code={...} lang="..." theme={theme} />
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**The CSS bridge (required, not optional):** `createCssVariablesTheme`'s `variablePrefix` is a plain string prepend, not a rename — Shiki's own internal slot names already start with `token-` (`token-keyword`, `token-string-expression`, `token-constant`, …) plus a bare `foreground`/`background`, so `variablePrefix: '--color-syntax-'` makes Shiki bake `color:var(--color-syntax-token-keyword)` into every span, not `var(--color-syntax-keyword)`. Left undefined, that variable resolves to nothing and the span silently inherits its parent's color — the highlighting looks like it's missing, not broken. One small bridge block closes the gap (Astro's Shiki integration puts an `.astro-code` class on the `<pre>`; scope to it so these implementation-detail names don't leak into the page's global custom-property namespace):
|
|
276
|
+
|
|
277
|
+
```css
|
|
278
|
+
.astro-code {
|
|
279
|
+
--color-syntax-foreground: var(--color-code-fg);
|
|
280
|
+
--color-syntax-background: var(--color-code-bg);
|
|
281
|
+
--color-syntax-token-keyword: var(--color-syntax-keyword);
|
|
282
|
+
--color-syntax-token-string: var(--color-syntax-string);
|
|
283
|
+
--color-syntax-token-string-expression: var(--color-syntax-string);
|
|
284
|
+
--color-syntax-token-constant: var(--color-syntax-constant);
|
|
285
|
+
--color-syntax-token-comment: var(--color-syntax-comment);
|
|
286
|
+
--color-syntax-token-function: var(--color-syntax-function);
|
|
287
|
+
--color-syntax-token-parameter: var(--color-syntax-variable);
|
|
288
|
+
--color-syntax-token-punctuation: var(--color-syntax-punctuation);
|
|
289
|
+
--color-syntax-token-link: var(--color-syntax-link);
|
|
290
|
+
/* token-inserted/-deleted/-changed intentionally left undefined —
|
|
291
|
+
diff markers, out of scope (see "Documented divergences" below);
|
|
292
|
+
they fall back to inherited foreground, which is a safe default. */
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
There is no separate `token-type` — see the `type` ≡ `function` divergence below; `--color-syntax-type` is real for Prism but never appears as a Shiki variable.
|
|
297
|
+
|
|
298
|
+
### Prism CSS mapping
|
|
299
|
+
|
|
300
|
+
Prism ships no CSS-variables mode — wire the classes directly:
|
|
301
|
+
|
|
302
|
+
```css
|
|
303
|
+
.token.keyword,
|
|
304
|
+
.token.atrule { color: var(--color-syntax-keyword); }
|
|
305
|
+
.token.string,
|
|
306
|
+
.token.char,
|
|
307
|
+
.token.attr-value { color: var(--color-syntax-string); }
|
|
308
|
+
.token.number,
|
|
309
|
+
.token.boolean,
|
|
310
|
+
.token.constant,
|
|
311
|
+
.token.symbol { color: var(--color-syntax-constant); }
|
|
312
|
+
.token.comment,
|
|
313
|
+
.token.prolog,
|
|
314
|
+
.token.doctype,
|
|
315
|
+
.token.cdata { color: var(--color-syntax-comment); }
|
|
316
|
+
.token.function { color: var(--color-syntax-function); }
|
|
317
|
+
.token.class-name { color: var(--color-syntax-type); }
|
|
318
|
+
.token.operator,
|
|
319
|
+
.token.punctuation { color: var(--color-syntax-punctuation); }
|
|
320
|
+
.token.variable,
|
|
321
|
+
.token.property,
|
|
322
|
+
.token.tag,
|
|
323
|
+
.token.attr-name { color: var(--color-syntax-variable); }
|
|
324
|
+
.token.url { color: var(--color-syntax-link); }
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Documented divergences
|
|
328
|
+
|
|
329
|
+
These are deliberate, not bugs:
|
|
330
|
+
|
|
331
|
+
- **`type` ≡ `function` under Shiki.** Shiki's css-variables mode folds `entity.name.type` into the function-scoped variable, so the two slots render identically in Shiki output even though Prism (`.class-name` vs. `.function`) distinguishes them. The tokens stay separate because Prism needs them separate.
|
|
332
|
+
- **Plain operators inherit the foreground.** Shiki has no scope for a bare operator token; it renders in `--color-fg` like surrounding text rather than `--color-syntax-punctuation`. Prism's `.operator` class does map to punctuation.
|
|
333
|
+
- **Diff markers are out of scope.** `token-inserted`/`token-deleted`/`token-changed` (Shiki) and equivalent Prism diff classes are not covered by this token set — a future `--color-diff-*` family would own them if a concrete consumer needs one.
|
|
334
|
+
|
|
335
|
+
### Comment-contrast policy
|
|
336
|
+
|
|
337
|
+
The 4.5:1 floor is held, not relaxed, for `--color-syntax-comment` — muted comments are an editorial convention, not a license to fail AA. Survey of shipping syntax themes: GitHub's light-default theme holds 4.55:1, GitHub's dark-default holds 6.15:1, and VS Code's Dark+ holds 5.0:1 — all pass. Only legacy/neglected themes fail (Prism's own default theme sits at 3.64:1; the legacy `github-dark` theme sits at 3.05:1). A muted-comment convention is achievable within AA; Remarque does not carry a documented exception for this slot.
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
234
341
|
## Motion Rules
|
|
235
342
|
|
|
236
343
|
Motion in Remarque is nearly invisible. The only permitted motion:
|
|
@@ -303,6 +410,7 @@ Every PR that ships Remarque pages MUST pass (`npm run audit` automates the colo
|
|
|
303
410
|
- [ ] `font-variant-numeric: tabular-nums lining-nums` on all metadata that mixes with dates/counts.
|
|
304
411
|
- [ ] No hardcoded hex/rgb colors — only `var(--color-*)` tokens.
|
|
305
412
|
- [ ] Body line-height ≥ 1.5 (Remarque target: 1.75).
|
|
413
|
+
- [ ] Every `--color-syntax-*` slot ≥ 4.5:1 against `--color-code-bg` in both themes (see "Syntax Highlighting").
|
|
306
414
|
|
|
307
415
|
Agents reviewing PRs should reject changes that violate any line above without explicit rationale.
|
|
308
416
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "remarque-tokens",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=18"
|
|
6
6
|
},
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
"homepage": "https://williamzujkowski.github.io/remarque/",
|
|
23
23
|
"main": "tokens.css",
|
|
24
|
+
"types": "./tokens.d.ts",
|
|
24
25
|
"bin": {
|
|
25
26
|
"remarque-audit": "scripts/audit.mjs",
|
|
26
27
|
"remarque-drift": "scripts/drift-check.mjs",
|
|
@@ -43,7 +44,10 @@
|
|
|
43
44
|
}
|
|
44
45
|
},
|
|
45
46
|
"exports": {
|
|
46
|
-
".":
|
|
47
|
+
".": {
|
|
48
|
+
"types": "./tokens.d.ts",
|
|
49
|
+
"default": "./tokens.css"
|
|
50
|
+
},
|
|
47
51
|
"./tokens": "./tokens.css",
|
|
48
52
|
"./tokens.css": "./tokens.css",
|
|
49
53
|
"./core": "./tokens-core.css",
|
|
@@ -55,7 +59,11 @@
|
|
|
55
59
|
"./tailwind": "./tailwind.config.js",
|
|
56
60
|
"./theme.css": "./theme.css",
|
|
57
61
|
"./theme": "./theme.css",
|
|
58
|
-
"./tokens.json":
|
|
62
|
+
"./tokens.json": {
|
|
63
|
+
"types": "./tokens.d.ts",
|
|
64
|
+
"default": "./tokens.json"
|
|
65
|
+
},
|
|
66
|
+
"./tokens.d.ts": "./tokens.d.ts",
|
|
59
67
|
"./prose": "./prose.css",
|
|
60
68
|
"./prose.css": "./prose.css",
|
|
61
69
|
"./print": "./print.css",
|
|
@@ -80,6 +88,7 @@
|
|
|
80
88
|
"CHANGELOG.md",
|
|
81
89
|
"theme.css",
|
|
82
90
|
"tokens.json",
|
|
91
|
+
"tokens.d.ts",
|
|
83
92
|
"scripts/tokens-json.mjs",
|
|
84
93
|
"prose.css",
|
|
85
94
|
"print.css",
|
package/scripts/audit.mjs
CHANGED
|
@@ -113,6 +113,15 @@ const CHECKS = [
|
|
|
113
113
|
['color-code-fg', 'color-code-bg', 4.5, 'code text'],
|
|
114
114
|
['color-border-bold', 'color-bg', 3.0, 'functional borders (WCAG 1.4.11)'],
|
|
115
115
|
['color-selection-fg', 'color-selection-bg', 4.5, 'selected text'],
|
|
116
|
+
['color-syntax-keyword', 'color-code-bg', 4.5, 'syntax: keyword'],
|
|
117
|
+
['color-syntax-string', 'color-code-bg', 4.5, 'syntax: string'],
|
|
118
|
+
['color-syntax-constant', 'color-code-bg', 4.5, 'syntax: constant'],
|
|
119
|
+
['color-syntax-comment', 'color-code-bg', 4.5, 'syntax: comment'],
|
|
120
|
+
['color-syntax-function', 'color-code-bg', 4.5, 'syntax: function'],
|
|
121
|
+
['color-syntax-type', 'color-code-bg', 4.5, 'syntax: type'],
|
|
122
|
+
['color-syntax-punctuation', 'color-code-bg', 4.5, 'syntax: punctuation'],
|
|
123
|
+
['color-syntax-variable', 'color-code-bg', 4.5, 'syntax: variable'],
|
|
124
|
+
['color-syntax-link', 'color-code-bg', 4.5, 'syntax: link'],
|
|
116
125
|
];
|
|
117
126
|
|
|
118
127
|
for (const [themeName, decls] of [['light', lightDecls], ['dark', darkDecls]]) {
|
package/scripts/theme.mjs
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* npx remarque-theme <light-slug> --dark <dark-slug> [-o out.css]
|
|
8
8
|
*
|
|
9
9
|
* Terminal themes carry only background/foreground/cursor/selection + 16
|
|
10
|
-
* ANSI slots — most of Remarque's
|
|
10
|
+
* ANSI slots — most of Remarque's 24 semantic slots don't map directly,
|
|
11
11
|
* and most themes fail the AAA fg-muted 7:1 line as authored. So this
|
|
12
12
|
* DERIVES rather than maps: hue + chroma come from the theme (its
|
|
13
13
|
* personality); lightness is KEEP-IF-PASSING — a few load-bearing slots
|
|
@@ -19,9 +19,11 @@
|
|
|
19
19
|
* still gets a value that passes, same as before (#76). Every other
|
|
20
20
|
* slot (fg-muted, muted, border-bold, the bg ladder, selection-bg,
|
|
21
21
|
* accent-subtle) is solved/derived as before — those don't have a
|
|
22
|
-
* meaningful "theme's own value" to preserve.
|
|
23
|
-
*
|
|
24
|
-
*
|
|
22
|
+
* meaningful "theme's own value" to preserve. The 9 --color-syntax-*
|
|
23
|
+
* slots (issue #53) are derived straight from the theme's 16 ANSI
|
|
24
|
+
* colors instead — see the "Syntax-highlighting slots" section below.
|
|
25
|
+
* Output passes remarque-audit BY CONSTRUCTION — this script
|
|
26
|
+
* self-verifies the same pairings before it will emit anything.
|
|
25
27
|
*
|
|
26
28
|
* Security (non-negotiable, per the panel security review on #75):
|
|
27
29
|
* - Both slugs are checked against the package's own index.json BEFORE
|
|
@@ -325,6 +327,66 @@ function withHeadroom([L0, , H], delta, dir, C) {
|
|
|
325
327
|
return [L, fitChroma(L, C, H), r1(H)];
|
|
326
328
|
}
|
|
327
329
|
|
|
330
|
+
/* ── Syntax-highlighting slots (issue #53) ───────────────────────────
|
|
331
|
+
* Terminal ANSI colors ARE syntax colors in their native domain, so the
|
|
332
|
+
* 9 --color-syntax-* slots are derived straight from a theme's 16 ANSI
|
|
333
|
+
* colors rather than invented fresh — zero new upstream schema work.
|
|
334
|
+
* Every slot targets --color-code-bg (not --color-bg) at 4.5:1, same
|
|
335
|
+
* keep-if-passing-else-solve pattern as every other slot above: the
|
|
336
|
+
* ANSI color's own lightness is kept when it already clears the ratio,
|
|
337
|
+
* solved (same binary search, same in-gamut chroma clamping) only when
|
|
338
|
+
* it doesn't. Chroma is capped at 0.14 — the same ceiling already used
|
|
339
|
+
* for --color-accent — so syntax colors stay in the system's "quiet,
|
|
340
|
+
* one-accent" register rather than turning carnival-bright. */
|
|
341
|
+
|
|
342
|
+
const SYNTAX_CHROMA_CAP = 0.14;
|
|
343
|
+
|
|
344
|
+
/* keyword/string/constant/function/type: a direct ANSI slot, kept if it
|
|
345
|
+
* already passes vs code-bg, solved (same hue) if it doesn't. */
|
|
346
|
+
function deriveSyntaxAnsi(t, ansiName, label, codeBg, dir) {
|
|
347
|
+
const [L0, C0, H0] = slotLch(t, ansiName, label);
|
|
348
|
+
const C = Math.min(C0, SYNTAX_CHROMA_CAP);
|
|
349
|
+
return keepOrSolve(L0, C, H0, codeBg, 4.5, dir);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/* comment: brightBlack in dark themes (the ANSI convention); in light
|
|
353
|
+
* themes brightBlack is often too pale to hold 4.5:1 on code-bg, so the
|
|
354
|
+
* fallback solves a muted neutral on the theme's own fg hue instead of
|
|
355
|
+
* brightBlack's hue. */
|
|
356
|
+
function deriveSyntaxComment(t, label, codeBg, dir, fallbackC, fallbackH) {
|
|
357
|
+
const [L0, C0, H0] = slotLch(t, 'brightBlack', label);
|
|
358
|
+
const C = Math.min(C0, SYNTAX_CHROMA_CAP);
|
|
359
|
+
const L = r3(Math.min(1, Math.max(0, L0)));
|
|
360
|
+
const c = fitChroma(L, C, H0);
|
|
361
|
+
if (ratio([L, c, H0], codeBg) >= 4.5) return [L, c, r1(H0)];
|
|
362
|
+
return solveL(fallbackC, fallbackH, codeBg, 4.5, dir);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/* punctuation: a derived neutral in the muted family (fg hue, low
|
|
366
|
+
* chroma), targeted at code-bg rather than surface. */
|
|
367
|
+
function deriveSyntaxPunctuation(fgC, fgH, codeBg, dir) {
|
|
368
|
+
return solveL(Math.min(fgC, 0.02), fgH, codeBg, 4.5, dir);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/* variable: fg-adjacent — the theme's own fg hue/chroma, offset a little
|
|
372
|
+
* so it reads as "quieter than plain text," verified (and solved if
|
|
373
|
+
* needed) against code-bg rather than assumed from the fg/surface pass. */
|
|
374
|
+
function deriveSyntaxVariable(fg, codeBg, dir, offset) {
|
|
375
|
+
return keepOrSolve(fg[0] + offset, fg[1], fg[2], codeBg, 4.5, dir);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/* link: alias the already-derived accent triple when it clears 4.5:1 on
|
|
379
|
+
* code-bg (accent is only guaranteed against --color-bg, and code-bg
|
|
380
|
+
* sits a little off from bg, so this isn't automatic) — solve a
|
|
381
|
+
* standalone value at the accent's own hue/chroma only when it doesn't,
|
|
382
|
+
* same as every other slot. Aliasing means a site's accent-hue swap
|
|
383
|
+
* (REMARQUE.md "Changing the Accent Hue") carries the link color with
|
|
384
|
+
* it for free whenever the alias holds. */
|
|
385
|
+
function deriveSyntaxLink(accent, codeBg, dir) {
|
|
386
|
+
if (ratio(accent, codeBg) >= 4.5) return { ref: 'color-accent' };
|
|
387
|
+
return keepOrSolve(accent[0], accent[1], accent[2], codeBg, 4.5, dir);
|
|
388
|
+
}
|
|
389
|
+
|
|
328
390
|
/* ── LIGHT derivation ─────────────────────────────────────────────── */
|
|
329
391
|
|
|
330
392
|
function deriveLight(t) {
|
|
@@ -351,6 +413,18 @@ function deriveLight(t) {
|
|
|
351
413
|
// accent-hover: still the designed -0.08 offset from accent, but that
|
|
352
414
|
// offset is verified against 4.5:1 on bg and solve-adjusted if it breaks.
|
|
353
415
|
const accentHover = keepOrSolve(accent[0] - 0.08, acC * 0.8, ac.h, bg, 4.5, 'darker');
|
|
416
|
+
const codeBg = [r3(bg[0] - 0.03), bg[1], bg[2]];
|
|
417
|
+
// Syntax-highlighting slots (issue #53) — see the derivation helpers
|
|
418
|
+
// above. All verified against code-bg (not bg) at 4.5:1.
|
|
419
|
+
const synKeyword = deriveSyntaxAnsi(t, 'blue', 'light', codeBg, 'darker');
|
|
420
|
+
const synString = deriveSyntaxAnsi(t, 'green', 'light', codeBg, 'darker');
|
|
421
|
+
const synConstant = deriveSyntaxAnsi(t, 'yellow', 'light', codeBg, 'darker');
|
|
422
|
+
const synFunction = deriveSyntaxAnsi(t, 'purple', 'light', codeBg, 'darker');
|
|
423
|
+
const synType = deriveSyntaxAnsi(t, 'cyan', 'light', codeBg, 'darker');
|
|
424
|
+
const synComment = deriveSyntaxComment(t, 'light', codeBg, 'darker', fgC, fgH);
|
|
425
|
+
const synPunctuation = deriveSyntaxPunctuation(fgC, fgH, codeBg, 'darker');
|
|
426
|
+
const synVariable = deriveSyntaxVariable(fg, codeBg, 'darker', 0.08);
|
|
427
|
+
const synLink = deriveSyntaxLink(accent, codeBg, 'darker');
|
|
354
428
|
const raw = {
|
|
355
429
|
'color-bg': bg,
|
|
356
430
|
'color-bg-subtle': [r3(bg[0] - 0.02), bg[1], bg[2]],
|
|
@@ -365,8 +439,17 @@ function deriveLight(t) {
|
|
|
365
439
|
'color-accent-subtle': [0.95, fitChroma(0.95, 0.02, ac.h), r1(ac.h)],
|
|
366
440
|
'color-selection-bg': [0.92, fitChroma(0.92, 0.04, ac.h), r1(ac.h)],
|
|
367
441
|
'color-selection-fg': { ref: 'color-fg' },
|
|
368
|
-
'color-code-bg':
|
|
442
|
+
'color-code-bg': codeBg,
|
|
369
443
|
'color-code-fg': { ref: 'color-fg' },
|
|
444
|
+
'color-syntax-keyword': synKeyword,
|
|
445
|
+
'color-syntax-string': synString,
|
|
446
|
+
'color-syntax-constant': synConstant,
|
|
447
|
+
'color-syntax-comment': synComment,
|
|
448
|
+
'color-syntax-function': synFunction,
|
|
449
|
+
'color-syntax-type': synType,
|
|
450
|
+
'color-syntax-punctuation': synPunctuation,
|
|
451
|
+
'color-syntax-variable': synVariable,
|
|
452
|
+
'color-syntax-link': synLink,
|
|
370
453
|
};
|
|
371
454
|
const tokens = {};
|
|
372
455
|
for (const [name, v] of Object.entries(raw)) tokens[name] = v.ref ? `var(--${v.ref})` : fmt(v);
|
|
@@ -409,6 +492,17 @@ function deriveDark(t, accentHueLight) {
|
|
|
409
492
|
// code-fg: "slightly dimmer than fg" — same pattern, -0.02, verified
|
|
410
493
|
// against the AAA 7:1 line on code-bg.
|
|
411
494
|
const codeFg = keepOrSolve(fg[0] - 0.02, fg[1], fg[2], codeBg, 7.0, 'lighter');
|
|
495
|
+
// Syntax-highlighting slots (issue #53) — mirrors the light derivation,
|
|
496
|
+
// direction flipped ('lighter': text on a dark code-bg).
|
|
497
|
+
const synKeyword = deriveSyntaxAnsi(t, 'blue', 'dark', codeBg, 'lighter');
|
|
498
|
+
const synString = deriveSyntaxAnsi(t, 'green', 'dark', codeBg, 'lighter');
|
|
499
|
+
const synConstant = deriveSyntaxAnsi(t, 'yellow', 'dark', codeBg, 'lighter');
|
|
500
|
+
const synFunction = deriveSyntaxAnsi(t, 'purple', 'dark', codeBg, 'lighter');
|
|
501
|
+
const synType = deriveSyntaxAnsi(t, 'cyan', 'dark', codeBg, 'lighter');
|
|
502
|
+
const synComment = deriveSyntaxComment(t, 'dark', codeBg, 'lighter', fgC, fgH);
|
|
503
|
+
const synPunctuation = deriveSyntaxPunctuation(fgC, fgH, codeBg, 'lighter');
|
|
504
|
+
const synVariable = deriveSyntaxVariable(fg, codeBg, 'lighter', -0.08);
|
|
505
|
+
const synLink = deriveSyntaxLink(accent, codeBg, 'lighter');
|
|
412
506
|
const raw = {
|
|
413
507
|
'color-bg': bg,
|
|
414
508
|
'color-bg-subtle': surface,
|
|
@@ -425,9 +519,18 @@ function deriveDark(t, accentHueLight) {
|
|
|
425
519
|
'color-selection-fg': selFg,
|
|
426
520
|
'color-code-bg': codeBg,
|
|
427
521
|
'color-code-fg': codeFg,
|
|
522
|
+
'color-syntax-keyword': synKeyword,
|
|
523
|
+
'color-syntax-string': synString,
|
|
524
|
+
'color-syntax-constant': synConstant,
|
|
525
|
+
'color-syntax-comment': synComment,
|
|
526
|
+
'color-syntax-function': synFunction,
|
|
527
|
+
'color-syntax-type': synType,
|
|
528
|
+
'color-syntax-punctuation': synPunctuation,
|
|
529
|
+
'color-syntax-variable': synVariable,
|
|
530
|
+
'color-syntax-link': synLink,
|
|
428
531
|
};
|
|
429
532
|
const tokens = {};
|
|
430
|
-
for (const [name, v] of Object.entries(raw)) tokens[name] = fmt(v);
|
|
533
|
+
for (const [name, v] of Object.entries(raw)) tokens[name] = v.ref ? `var(--${v.ref})` : fmt(v);
|
|
431
534
|
tokens['weight-display'] = '500';
|
|
432
535
|
return { raw, tokens };
|
|
433
536
|
}
|
|
@@ -452,6 +555,15 @@ const CHECKS = [
|
|
|
452
555
|
['color-code-fg', 'color-code-bg', 4.5, 'code text'],
|
|
453
556
|
['color-border-bold', 'color-bg', 3.0, 'functional borders (WCAG 1.4.11)'],
|
|
454
557
|
['color-selection-fg', 'color-selection-bg', 4.5, 'selected text'],
|
|
558
|
+
['color-syntax-keyword', 'color-code-bg', 4.5, 'syntax: keyword'],
|
|
559
|
+
['color-syntax-string', 'color-code-bg', 4.5, 'syntax: string'],
|
|
560
|
+
['color-syntax-constant', 'color-code-bg', 4.5, 'syntax: constant'],
|
|
561
|
+
['color-syntax-comment', 'color-code-bg', 4.5, 'syntax: comment'],
|
|
562
|
+
['color-syntax-function', 'color-code-bg', 4.5, 'syntax: function'],
|
|
563
|
+
['color-syntax-type', 'color-code-bg', 4.5, 'syntax: type'],
|
|
564
|
+
['color-syntax-punctuation', 'color-code-bg', 4.5, 'syntax: punctuation'],
|
|
565
|
+
['color-syntax-variable', 'color-code-bg', 4.5, 'syntax: variable'],
|
|
566
|
+
['color-syntax-link', 'color-code-bg', 4.5, 'syntax: link'],
|
|
455
567
|
];
|
|
456
568
|
|
|
457
569
|
function resolveRaw(raw, name, seen = new Set()) {
|
package/scripts/tokens-json.mjs
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/*
|
|
3
|
-
* Generates tokens.json (W3C design-tokens flavored)
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Generates tokens.json (W3C design-tokens flavored) and tokens.d.ts
|
|
4
|
+
* (TypeScript literal-union types) FROM the CSS — tokens-core.css and
|
|
5
|
+
* tokens-palette.css remain the single source of truth; both files
|
|
6
|
+
* here are derived output for tooling, AI agents, and TS editors.
|
|
6
7
|
*
|
|
7
|
-
* node scripts/tokens-json.mjs # (re)write tokens.json
|
|
8
|
-
* node scripts/tokens-json.mjs --check # exit 1 if
|
|
8
|
+
* node scripts/tokens-json.mjs # (re)write tokens.json + tokens.d.ts
|
|
9
|
+
* node scripts/tokens-json.mjs --check # exit 1 if either is stale (CI)
|
|
9
10
|
*
|
|
10
11
|
* Multi-theme values use per-token light/dark groups with $value on each
|
|
11
12
|
* (the W3C spec has no native theming; this follows its $extensions
|
|
@@ -70,14 +71,159 @@ for (const [name, value] of Object.entries(lightDecls)) {
|
|
|
70
71
|
|
|
71
72
|
const json = JSON.stringify(out, null, 2) + '\n';
|
|
72
73
|
|
|
74
|
+
/* ── tokens.d.ts ──────────────────────────────────────────────────────
|
|
75
|
+
* Literal-union types + a typed shape for tokens.json, generated from
|
|
76
|
+
* the same in-memory `out` object that produces tokens.json — so the
|
|
77
|
+
* two derived files can never disagree with each other, only (briefly,
|
|
78
|
+
* until regenerated) with the CSS. The package ships no JS entry point;
|
|
79
|
+
* this file exists purely for editors/TS consumers that either author
|
|
80
|
+
* Remarque token names (`RemarqueToken`, `RemarqueCssVar`) or read
|
|
81
|
+
* tokens.json programmatically (`RemarqueTokensFile`, wired via the
|
|
82
|
+
* ambient `declare module 'remarque-tokens/tokens.json'` below).
|
|
83
|
+
*/
|
|
84
|
+
function tsLiteral(value) {
|
|
85
|
+
return typeof value === 'number' ? String(value) : JSON.stringify(value);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function renderDts(tokens, pkgVersion) {
|
|
89
|
+
const coreNames = Object.keys(tokens.core);
|
|
90
|
+
const paletteNames = Object.keys(tokens.palette);
|
|
91
|
+
|
|
92
|
+
const coreUnion = coreNames.map((n) => ` | '${n}'`).join('\n');
|
|
93
|
+
const paletteUnion = paletteNames.map((n) => ` | '${n}'`).join('\n');
|
|
94
|
+
|
|
95
|
+
const coreValues = coreNames
|
|
96
|
+
.map((n) => ` readonly '${n}': ${tsLiteral(tokens.core[n].$value)};`)
|
|
97
|
+
.join('\n');
|
|
98
|
+
const paletteValues = paletteNames
|
|
99
|
+
.map((n) => {
|
|
100
|
+
const t = tokens.palette[n];
|
|
101
|
+
return ` readonly '${n}': {\n readonly light: ${tsLiteral(t.light.$value)};\n readonly dark: ${tsLiteral(t.dark.$value)};\n };`;
|
|
102
|
+
})
|
|
103
|
+
.join('\n');
|
|
104
|
+
|
|
105
|
+
return `/*
|
|
106
|
+
* Remarque design tokens — GENERATED from tokens.json by
|
|
107
|
+
* scripts/tokens-json.mjs (v${pkgVersion}). Do not edit — the CSS
|
|
108
|
+
* (tokens-core.css + tokens-palette.css) is the source of truth;
|
|
109
|
+
* tokens.json is the intermediate machine-readable form this file is
|
|
110
|
+
* generated from. Regenerate with: node scripts/tokens-json.mjs
|
|
111
|
+
*
|
|
112
|
+
* This package has no JS entry point — these types exist for editors
|
|
113
|
+
* and TypeScript consumers that either author Remarque token names
|
|
114
|
+
* (RemarqueToken, RemarqueCssVar) or read tokens.json programmatically
|
|
115
|
+
* (RemarqueTokensFile / RemarqueTokenValues, and the ambient module
|
|
116
|
+
* declaration below for \`import tokens from 'remarque-tokens/tokens.json'\`).
|
|
117
|
+
*/
|
|
118
|
+
|
|
119
|
+
/** All core-tier token names (tokens-core.css). Never overridden. */
|
|
120
|
+
export type RemarqueCoreToken =
|
|
121
|
+
${coreUnion};
|
|
122
|
+
|
|
123
|
+
/** All palette-tier token names (tokens-palette.css). The sanctioned personalization surface. */
|
|
124
|
+
export type RemarquePaletteToken =
|
|
125
|
+
${paletteUnion};
|
|
126
|
+
|
|
127
|
+
/** Every Remarque token name, core + palette. */
|
|
128
|
+
export type RemarqueToken = RemarqueCoreToken | RemarquePaletteToken;
|
|
129
|
+
|
|
130
|
+
/** A Remarque token name as its CSS custom-property form, e.g. \`--text-body\`. */
|
|
131
|
+
export type RemarqueCssVar = \`--${'$'}{RemarqueToken}\`;
|
|
132
|
+
|
|
133
|
+
/** W3C design-tokens \`$type\` values used across tokens.json. */
|
|
134
|
+
export type RemarqueTokenType =
|
|
135
|
+
| 'color'
|
|
136
|
+
| 'dimension'
|
|
137
|
+
| 'number'
|
|
138
|
+
| 'fontFamily'
|
|
139
|
+
| 'fontWeight'
|
|
140
|
+
| 'duration'
|
|
141
|
+
| 'string';
|
|
142
|
+
|
|
143
|
+
/** Shape of a single core-tier entry in tokens.json's \`core\` map. */
|
|
144
|
+
export interface RemarqueCoreTokenEntry {
|
|
145
|
+
readonly $value: string | number;
|
|
146
|
+
readonly $type: RemarqueTokenType;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** Shape of one theme side (\`light\`/\`dark\`) of a palette-tier entry. */
|
|
150
|
+
export interface RemarquePaletteTokenSideValue {
|
|
151
|
+
readonly $value: string | number;
|
|
152
|
+
readonly $extensions?: {
|
|
153
|
+
readonly remarque?: {
|
|
154
|
+
readonly inheritedFromLight?: boolean;
|
|
155
|
+
};
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Shape of a single palette-tier entry in tokens.json's \`palette\` map. */
|
|
160
|
+
export interface RemarquePaletteTokenEntry {
|
|
161
|
+
readonly $type: RemarqueTokenType;
|
|
162
|
+
readonly light: RemarquePaletteTokenSideValue;
|
|
163
|
+
readonly dark: RemarquePaletteTokenSideValue;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Typed shape of tokens.json's default export — the whole generated
|
|
168
|
+
* file, structurally. Use this when reading tokens.json dynamically
|
|
169
|
+
* (\`JSON.parse\`, a bundler JSON import without the ambient module
|
|
170
|
+
* below applying, etc).
|
|
171
|
+
*/
|
|
172
|
+
export interface RemarqueTokensFile {
|
|
173
|
+
readonly $description: string;
|
|
174
|
+
readonly $extensions: {
|
|
175
|
+
readonly remarque: {
|
|
176
|
+
readonly version: string;
|
|
177
|
+
readonly tiers: {
|
|
178
|
+
readonly core: string;
|
|
179
|
+
readonly palette: string;
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
readonly core: { readonly [K in RemarqueCoreToken]: RemarqueCoreTokenEntry };
|
|
184
|
+
readonly palette: { readonly [K in RemarquePaletteToken]: RemarquePaletteTokenEntry };
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* The actual current value of every token, as literal types — precise
|
|
189
|
+
* autocomplete for "what is \`--text-body\` right now", not just "what
|
|
190
|
+
* are its shape and type". Regenerated alongside tokens.json, so these
|
|
191
|
+
* literals track the live CSS across releases.
|
|
192
|
+
*/
|
|
193
|
+
export interface RemarqueTokenValues {
|
|
194
|
+
readonly core: {
|
|
195
|
+
${coreValues}
|
|
196
|
+
};
|
|
197
|
+
readonly palette: {
|
|
198
|
+
${paletteValues}
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Precise types for \`import tokens from 'remarque-tokens/tokens.json'\`
|
|
203
|
+
// (and any other bundler-JSON-import path resolving through this
|
|
204
|
+
// subpath) without depending on the consumer's \`resolveJsonModule\`.
|
|
205
|
+
declare module 'remarque-tokens/tokens.json' {
|
|
206
|
+
const tokens: RemarqueTokensFile;
|
|
207
|
+
export default tokens;
|
|
208
|
+
}
|
|
209
|
+
`;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const dts = renderDts(out, version);
|
|
213
|
+
|
|
73
214
|
if (process.argv.includes('--check')) {
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
215
|
+
const currentJson = existsSync('tokens.json') ? readFileSync('tokens.json', 'utf8') : '';
|
|
216
|
+
const currentDts = existsSync('tokens.d.ts') ? readFileSync('tokens.d.ts', 'utf8') : '';
|
|
217
|
+
const staleJson = currentJson !== json;
|
|
218
|
+
const staleDts = currentDts !== dts;
|
|
219
|
+
if (staleJson || staleDts) {
|
|
220
|
+
if (staleJson) console.error('tokens.json is stale — run: node scripts/tokens-json.mjs');
|
|
221
|
+
if (staleDts) console.error('tokens.d.ts is stale — run: node scripts/tokens-json.mjs');
|
|
77
222
|
process.exit(1);
|
|
78
223
|
}
|
|
79
|
-
console.log('tokens.json
|
|
224
|
+
console.log('tokens.json and tokens.d.ts are fresh ✓');
|
|
80
225
|
} else {
|
|
81
226
|
writeFileSync('tokens.json', json);
|
|
82
|
-
|
|
227
|
+
writeFileSync('tokens.d.ts', dts);
|
|
228
|
+
console.log(`tokens.json + tokens.d.ts written — ${Object.keys(out.core).length} core + ${Object.keys(out.palette).length} palette tokens (v${version})`);
|
|
83
229
|
}
|
package/tokens-palette.css
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* - Colors: every replacement palette must pass the contrast audit
|
|
17
17
|
* (npm run audit) — fg-muted ≥ 7:1, muted ≥ 4.5:1 on bg AND
|
|
18
18
|
* surface, accent + accent-hover ≥ 4.5:1, border-bold ≥ 3:1,
|
|
19
|
+
* every --color-syntax-* slot ≥ 4.5:1 on --color-code-bg,
|
|
19
20
|
* in BOTH themes.
|
|
20
21
|
* - Accent: change the hue by re-deriving accent/accent-hover/
|
|
21
22
|
* accent-subtle/selection at the SAME lightness values used here,
|
|
@@ -77,6 +78,22 @@
|
|
|
77
78
|
--color-selection-fg: var(--color-fg);
|
|
78
79
|
--color-code-bg: oklch(0.945 0.005 80); /* inline code background */
|
|
79
80
|
--color-code-fg: var(--color-fg);
|
|
81
|
+
|
|
82
|
+
/* Syntax highlighting (issue #53) — quiet, low-chroma slots derived
|
|
83
|
+
from remarque-light's ANSI colors (scripts/theme.mjs), serialized
|
|
84
|
+
as round numbers (golden-gated: scripts/palette-golden.mjs). Every
|
|
85
|
+
slot ≥ 4.5:1 on --color-code-bg. Mapping recipe (Shiki css-variables
|
|
86
|
+
+ Prism) is documented in REMARQUE.md's "Syntax Highlighting"
|
|
87
|
+
section. */
|
|
88
|
+
--color-syntax-keyword: oklch(0.51 0.12 250); /* ANSI blue — 4.88:1 on code-bg */
|
|
89
|
+
--color-syntax-string: oklch(0.50 0.12 145); /* ANSI green — 4.85:1 */
|
|
90
|
+
--color-syntax-constant: oklch(0.51 0.105 85); /* ANSI yellow (numbers/booleans convention) — 4.94:1 */
|
|
91
|
+
--color-syntax-comment: oklch(0.52 0.01 80); /* solved muted neutral (fg hue) — brightBlack is too pale on code-bg here — 4.69:1 */
|
|
92
|
+
--color-syntax-function: oklch(0.52 0.12 310); /* ANSI purple — 4.96:1 */
|
|
93
|
+
--color-syntax-type: oklch(0.50 0.085 196); /* ANSI cyan — 4.90:1 */
|
|
94
|
+
--color-syntax-punctuation: oklch(0.52 0.01 80); /* derived neutral, muted family — 4.69:1 */
|
|
95
|
+
--color-syntax-variable: oklch(0.26 0.01 80); /* fg-adjacent (slight L offset) — 13.23:1 */
|
|
96
|
+
--color-syntax-link: var(--color-accent); /* accent already clears code-bg — 4.5:1+ */
|
|
80
97
|
}
|
|
81
98
|
|
|
82
99
|
/* ─── Color: Dark theme ─────────────────────────────────── */
|
|
@@ -110,6 +127,18 @@
|
|
|
110
127
|
--color-selection-fg: oklch(0.92 0.005 80);
|
|
111
128
|
--color-code-bg: oklch(0.20 0.005 80);
|
|
112
129
|
--color-code-fg: oklch(0.88 0.005 80);
|
|
130
|
+
|
|
131
|
+
/* Syntax highlighting (issue #53) — derived from remarque-dark's
|
|
132
|
+
ANSI colors; see the light block above for the full rationale. */
|
|
133
|
+
--color-syntax-keyword: oklch(0.61 0.11 250); /* ANSI blue — 4.80:1 on code-bg */
|
|
134
|
+
--color-syntax-string: oklch(0.60 0.11 145); /* ANSI green — 4.80:1 */
|
|
135
|
+
--color-syntax-constant: oklch(0.61 0.11 84); /* ANSI yellow — 4.73:1 */
|
|
136
|
+
--color-syntax-comment: oklch(0.60 0.005 80); /* ANSI brightBlack — 4.59:1 */
|
|
137
|
+
--color-syntax-function: oklch(0.62 0.11 310); /* ANSI purple — 4.75:1 */
|
|
138
|
+
--color-syntax-type: oklch(0.60 0.10 195); /* ANSI cyan — 4.81:1 */
|
|
139
|
+
--color-syntax-punctuation: oklch(0.60 0.005 80); /* derived neutral, muted family — 4.59:1 */
|
|
140
|
+
--color-syntax-variable: oklch(0.82 0.005 80); /* fg-adjacent (slight L offset) — 10.37:1 */
|
|
141
|
+
--color-syntax-link: var(--color-accent); /* accent already clears code-bg */
|
|
113
142
|
}
|
|
114
143
|
}
|
|
115
144
|
|
|
@@ -141,4 +170,16 @@
|
|
|
141
170
|
--color-selection-fg: oklch(0.92 0.005 80);
|
|
142
171
|
--color-code-bg: oklch(0.20 0.005 80);
|
|
143
172
|
--color-code-fg: oklch(0.88 0.005 80);
|
|
173
|
+
|
|
174
|
+
/* Syntax highlighting (issue #53) — derived from remarque-dark's
|
|
175
|
+
ANSI colors; see the light block above for the full rationale. */
|
|
176
|
+
--color-syntax-keyword: oklch(0.61 0.11 250);
|
|
177
|
+
--color-syntax-string: oklch(0.60 0.11 145);
|
|
178
|
+
--color-syntax-constant: oklch(0.61 0.11 84);
|
|
179
|
+
--color-syntax-comment: oklch(0.60 0.005 80);
|
|
180
|
+
--color-syntax-function: oklch(0.62 0.11 310);
|
|
181
|
+
--color-syntax-type: oklch(0.60 0.10 195);
|
|
182
|
+
--color-syntax-punctuation: oklch(0.60 0.005 80);
|
|
183
|
+
--color-syntax-variable: oklch(0.82 0.005 80);
|
|
184
|
+
--color-syntax-link: var(--color-accent);
|
|
144
185
|
}
|
package/tokens.d.ts
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Remarque design tokens — GENERATED from tokens.json by
|
|
3
|
+
* scripts/tokens-json.mjs (v0.13.0). Do not edit — the CSS
|
|
4
|
+
* (tokens-core.css + tokens-palette.css) is the source of truth;
|
|
5
|
+
* tokens.json is the intermediate machine-readable form this file is
|
|
6
|
+
* generated from. Regenerate with: node scripts/tokens-json.mjs
|
|
7
|
+
*
|
|
8
|
+
* This package has no JS entry point — these types exist for editors
|
|
9
|
+
* and TypeScript consumers that either author Remarque token names
|
|
10
|
+
* (RemarqueToken, RemarqueCssVar) or read tokens.json programmatically
|
|
11
|
+
* (RemarqueTokensFile / RemarqueTokenValues, and the ambient module
|
|
12
|
+
* declaration below for `import tokens from 'remarque-tokens/tokens.json'`).
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** All core-tier token names (tokens-core.css). Never overridden. */
|
|
16
|
+
export type RemarqueCoreToken =
|
|
17
|
+
| 'text-display'
|
|
18
|
+
| 'text-title'
|
|
19
|
+
| 'text-section'
|
|
20
|
+
| 'text-body-lg'
|
|
21
|
+
| 'text-body'
|
|
22
|
+
| 'text-meta'
|
|
23
|
+
| 'text-micro'
|
|
24
|
+
| 'leading-display'
|
|
25
|
+
| 'leading-title'
|
|
26
|
+
| 'leading-section'
|
|
27
|
+
| 'leading-body'
|
|
28
|
+
| 'leading-meta'
|
|
29
|
+
| 'tracking-display'
|
|
30
|
+
| 'tracking-title'
|
|
31
|
+
| 'tracking-body'
|
|
32
|
+
| 'tracking-meta'
|
|
33
|
+
| 'tracking-caps'
|
|
34
|
+
| 'weight-regular'
|
|
35
|
+
| 'weight-medium'
|
|
36
|
+
| 'weight-semibold'
|
|
37
|
+
| 'space-1'
|
|
38
|
+
| 'space-2'
|
|
39
|
+
| 'space-3'
|
|
40
|
+
| 'space-4'
|
|
41
|
+
| 'space-5'
|
|
42
|
+
| 'space-6'
|
|
43
|
+
| 'space-7'
|
|
44
|
+
| 'space-8'
|
|
45
|
+
| 'space-9'
|
|
46
|
+
| 'space-10'
|
|
47
|
+
| 'space-11'
|
|
48
|
+
| 'space-12'
|
|
49
|
+
| 'content-standard'
|
|
50
|
+
| 'content-wide'
|
|
51
|
+
| 'radius-sm'
|
|
52
|
+
| 'radius-md'
|
|
53
|
+
| 'radius-none'
|
|
54
|
+
| 'border-width'
|
|
55
|
+
| 'border-style'
|
|
56
|
+
| 'motion-fast'
|
|
57
|
+
| 'motion-normal'
|
|
58
|
+
| 'motion-easing';
|
|
59
|
+
|
|
60
|
+
/** All palette-tier token names (tokens-palette.css). The sanctioned personalization surface. */
|
|
61
|
+
export type RemarquePaletteToken =
|
|
62
|
+
| 'font-display'
|
|
63
|
+
| 'font-body'
|
|
64
|
+
| 'font-mono'
|
|
65
|
+
| 'content-reading'
|
|
66
|
+
| 'weight-display'
|
|
67
|
+
| 'color-bg'
|
|
68
|
+
| 'color-bg-subtle'
|
|
69
|
+
| 'color-fg'
|
|
70
|
+
| 'color-fg-muted'
|
|
71
|
+
| 'color-muted'
|
|
72
|
+
| 'color-border'
|
|
73
|
+
| 'color-border-bold'
|
|
74
|
+
| 'color-surface'
|
|
75
|
+
| 'color-accent'
|
|
76
|
+
| 'color-accent-hover'
|
|
77
|
+
| 'color-accent-subtle'
|
|
78
|
+
| 'color-link'
|
|
79
|
+
| 'color-link-hover'
|
|
80
|
+
| 'color-focus-ring'
|
|
81
|
+
| 'color-selection-bg'
|
|
82
|
+
| 'color-selection-fg'
|
|
83
|
+
| 'color-code-bg'
|
|
84
|
+
| 'color-code-fg'
|
|
85
|
+
| 'color-syntax-keyword'
|
|
86
|
+
| 'color-syntax-string'
|
|
87
|
+
| 'color-syntax-constant'
|
|
88
|
+
| 'color-syntax-comment'
|
|
89
|
+
| 'color-syntax-function'
|
|
90
|
+
| 'color-syntax-type'
|
|
91
|
+
| 'color-syntax-punctuation'
|
|
92
|
+
| 'color-syntax-variable'
|
|
93
|
+
| 'color-syntax-link';
|
|
94
|
+
|
|
95
|
+
/** Every Remarque token name, core + palette. */
|
|
96
|
+
export type RemarqueToken = RemarqueCoreToken | RemarquePaletteToken;
|
|
97
|
+
|
|
98
|
+
/** A Remarque token name as its CSS custom-property form, e.g. `--text-body`. */
|
|
99
|
+
export type RemarqueCssVar = `--${RemarqueToken}`;
|
|
100
|
+
|
|
101
|
+
/** W3C design-tokens `$type` values used across tokens.json. */
|
|
102
|
+
export type RemarqueTokenType =
|
|
103
|
+
| 'color'
|
|
104
|
+
| 'dimension'
|
|
105
|
+
| 'number'
|
|
106
|
+
| 'fontFamily'
|
|
107
|
+
| 'fontWeight'
|
|
108
|
+
| 'duration'
|
|
109
|
+
| 'string';
|
|
110
|
+
|
|
111
|
+
/** Shape of a single core-tier entry in tokens.json's `core` map. */
|
|
112
|
+
export interface RemarqueCoreTokenEntry {
|
|
113
|
+
readonly $value: string | number;
|
|
114
|
+
readonly $type: RemarqueTokenType;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Shape of one theme side (`light`/`dark`) of a palette-tier entry. */
|
|
118
|
+
export interface RemarquePaletteTokenSideValue {
|
|
119
|
+
readonly $value: string | number;
|
|
120
|
+
readonly $extensions?: {
|
|
121
|
+
readonly remarque?: {
|
|
122
|
+
readonly inheritedFromLight?: boolean;
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Shape of a single palette-tier entry in tokens.json's `palette` map. */
|
|
128
|
+
export interface RemarquePaletteTokenEntry {
|
|
129
|
+
readonly $type: RemarqueTokenType;
|
|
130
|
+
readonly light: RemarquePaletteTokenSideValue;
|
|
131
|
+
readonly dark: RemarquePaletteTokenSideValue;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Typed shape of tokens.json's default export — the whole generated
|
|
136
|
+
* file, structurally. Use this when reading tokens.json dynamically
|
|
137
|
+
* (`JSON.parse`, a bundler JSON import without the ambient module
|
|
138
|
+
* below applying, etc).
|
|
139
|
+
*/
|
|
140
|
+
export interface RemarqueTokensFile {
|
|
141
|
+
readonly $description: string;
|
|
142
|
+
readonly $extensions: {
|
|
143
|
+
readonly remarque: {
|
|
144
|
+
readonly version: string;
|
|
145
|
+
readonly tiers: {
|
|
146
|
+
readonly core: string;
|
|
147
|
+
readonly palette: string;
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
readonly core: { readonly [K in RemarqueCoreToken]: RemarqueCoreTokenEntry };
|
|
152
|
+
readonly palette: { readonly [K in RemarquePaletteToken]: RemarquePaletteTokenEntry };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* The actual current value of every token, as literal types — precise
|
|
157
|
+
* autocomplete for "what is `--text-body` right now", not just "what
|
|
158
|
+
* are its shape and type". Regenerated alongside tokens.json, so these
|
|
159
|
+
* literals track the live CSS across releases.
|
|
160
|
+
*/
|
|
161
|
+
export interface RemarqueTokenValues {
|
|
162
|
+
readonly core: {
|
|
163
|
+
readonly 'text-display': "clamp(2.75rem, 5.5vw, 5rem)";
|
|
164
|
+
readonly 'text-title': "clamp(1.875rem, 3.5vw, 3rem)";
|
|
165
|
+
readonly 'text-section': "clamp(1.375rem, 2.25vw, 2rem)";
|
|
166
|
+
readonly 'text-body-lg': "1.1875rem";
|
|
167
|
+
readonly 'text-body': "1.0625rem";
|
|
168
|
+
readonly 'text-meta': "0.875rem";
|
|
169
|
+
readonly 'text-micro': "0.8125rem";
|
|
170
|
+
readonly 'leading-display': 1.05;
|
|
171
|
+
readonly 'leading-title': 1.15;
|
|
172
|
+
readonly 'leading-section': 1.2;
|
|
173
|
+
readonly 'leading-body': 1.75;
|
|
174
|
+
readonly 'leading-meta': 1.5;
|
|
175
|
+
readonly 'tracking-display': "-0.02em";
|
|
176
|
+
readonly 'tracking-title': "-0.015em";
|
|
177
|
+
readonly 'tracking-body': "0em";
|
|
178
|
+
readonly 'tracking-meta': "0.02em";
|
|
179
|
+
readonly 'tracking-caps': "0.06em";
|
|
180
|
+
readonly 'weight-regular': 400;
|
|
181
|
+
readonly 'weight-medium': 500;
|
|
182
|
+
readonly 'weight-semibold': 600;
|
|
183
|
+
readonly 'space-1': "0.25rem";
|
|
184
|
+
readonly 'space-2': "0.5rem";
|
|
185
|
+
readonly 'space-3': "0.75rem";
|
|
186
|
+
readonly 'space-4': "1rem";
|
|
187
|
+
readonly 'space-5': "1.5rem";
|
|
188
|
+
readonly 'space-6': "2rem";
|
|
189
|
+
readonly 'space-7': "3rem";
|
|
190
|
+
readonly 'space-8': "4rem";
|
|
191
|
+
readonly 'space-9': "6rem";
|
|
192
|
+
readonly 'space-10': "8rem";
|
|
193
|
+
readonly 'space-11': "10rem";
|
|
194
|
+
readonly 'space-12': "12rem";
|
|
195
|
+
readonly 'content-standard': "72rem";
|
|
196
|
+
readonly 'content-wide': "88rem";
|
|
197
|
+
readonly 'radius-sm': "0.25rem";
|
|
198
|
+
readonly 'radius-md': "0.5rem";
|
|
199
|
+
readonly 'radius-none': "0";
|
|
200
|
+
readonly 'border-width': "1px";
|
|
201
|
+
readonly 'border-style': "solid";
|
|
202
|
+
readonly 'motion-fast': "120ms";
|
|
203
|
+
readonly 'motion-normal': "180ms";
|
|
204
|
+
readonly 'motion-easing': "ease-out";
|
|
205
|
+
};
|
|
206
|
+
readonly palette: {
|
|
207
|
+
readonly 'font-display': {
|
|
208
|
+
readonly light: "\"Newsreader\", Georgia, \"Times New Roman\", serif";
|
|
209
|
+
readonly dark: "\"Newsreader\", Georgia, \"Times New Roman\", serif";
|
|
210
|
+
};
|
|
211
|
+
readonly 'font-body': {
|
|
212
|
+
readonly light: "\"Inter\", ui-sans-serif, system-ui, -apple-system, sans-serif";
|
|
213
|
+
readonly dark: "\"Inter\", ui-sans-serif, system-ui, -apple-system, sans-serif";
|
|
214
|
+
};
|
|
215
|
+
readonly 'font-mono': {
|
|
216
|
+
readonly light: "\"JetBrains Mono\", ui-monospace, \"Cascadia Code\", \"Fira Code\", monospace";
|
|
217
|
+
readonly dark: "\"JetBrains Mono\", ui-monospace, \"Cascadia Code\", \"Fira Code\", monospace";
|
|
218
|
+
};
|
|
219
|
+
readonly 'content-reading': {
|
|
220
|
+
readonly light: "46rem";
|
|
221
|
+
readonly dark: "46rem";
|
|
222
|
+
};
|
|
223
|
+
readonly 'weight-display': {
|
|
224
|
+
readonly light: 400;
|
|
225
|
+
readonly dark: 500;
|
|
226
|
+
};
|
|
227
|
+
readonly 'color-bg': {
|
|
228
|
+
readonly light: "oklch(0.975 0.005 80)";
|
|
229
|
+
readonly dark: "oklch(0.16 0.01 80)";
|
|
230
|
+
};
|
|
231
|
+
readonly 'color-bg-subtle': {
|
|
232
|
+
readonly light: "oklch(0.955 0.005 80)";
|
|
233
|
+
readonly dark: "oklch(0.19 0.01 80)";
|
|
234
|
+
};
|
|
235
|
+
readonly 'color-fg': {
|
|
236
|
+
readonly light: "oklch(0.18 0.01 80)";
|
|
237
|
+
readonly dark: "oklch(0.90 0.005 80)";
|
|
238
|
+
};
|
|
239
|
+
readonly 'color-fg-muted': {
|
|
240
|
+
readonly light: "oklch(0.43 0.015 80)";
|
|
241
|
+
readonly dark: "oklch(0.70 0.01 80)";
|
|
242
|
+
};
|
|
243
|
+
readonly 'color-muted': {
|
|
244
|
+
readonly light: "oklch(0.54 0.01 80)";
|
|
245
|
+
readonly dark: "oklch(0.60 0.01 80)";
|
|
246
|
+
};
|
|
247
|
+
readonly 'color-border': {
|
|
248
|
+
readonly light: "oklch(0.88 0.005 80)";
|
|
249
|
+
readonly dark: "oklch(0.25 0.005 80)";
|
|
250
|
+
};
|
|
251
|
+
readonly 'color-border-bold': {
|
|
252
|
+
readonly light: "oklch(0.62 0.01 80)";
|
|
253
|
+
readonly dark: "oklch(0.50 0.01 80)";
|
|
254
|
+
};
|
|
255
|
+
readonly 'color-surface': {
|
|
256
|
+
readonly light: "oklch(0.965 0.005 80)";
|
|
257
|
+
readonly dark: "oklch(0.19 0.01 80)";
|
|
258
|
+
};
|
|
259
|
+
readonly 'color-accent': {
|
|
260
|
+
readonly light: "oklch(0.50 0.14 250)";
|
|
261
|
+
readonly dark: "oklch(0.68 0.12 250)";
|
|
262
|
+
};
|
|
263
|
+
readonly 'color-accent-hover': {
|
|
264
|
+
readonly light: "oklch(0.42 0.11 250)";
|
|
265
|
+
readonly dark: "oklch(0.75 0.12 250)";
|
|
266
|
+
};
|
|
267
|
+
readonly 'color-accent-subtle': {
|
|
268
|
+
readonly light: "oklch(0.95 0.02 250)";
|
|
269
|
+
readonly dark: "oklch(0.22 0.04 250)";
|
|
270
|
+
};
|
|
271
|
+
readonly 'color-link': {
|
|
272
|
+
readonly light: "var(--color-accent)";
|
|
273
|
+
readonly dark: "var(--color-accent)";
|
|
274
|
+
};
|
|
275
|
+
readonly 'color-link-hover': {
|
|
276
|
+
readonly light: "var(--color-accent-hover)";
|
|
277
|
+
readonly dark: "var(--color-accent-hover)";
|
|
278
|
+
};
|
|
279
|
+
readonly 'color-focus-ring': {
|
|
280
|
+
readonly light: "var(--color-accent)";
|
|
281
|
+
readonly dark: "var(--color-accent)";
|
|
282
|
+
};
|
|
283
|
+
readonly 'color-selection-bg': {
|
|
284
|
+
readonly light: "oklch(0.92 0.04 250)";
|
|
285
|
+
readonly dark: "oklch(0.30 0.06 250)";
|
|
286
|
+
};
|
|
287
|
+
readonly 'color-selection-fg': {
|
|
288
|
+
readonly light: "var(--color-fg)";
|
|
289
|
+
readonly dark: "oklch(0.92 0.005 80)";
|
|
290
|
+
};
|
|
291
|
+
readonly 'color-code-bg': {
|
|
292
|
+
readonly light: "oklch(0.945 0.005 80)";
|
|
293
|
+
readonly dark: "oklch(0.20 0.005 80)";
|
|
294
|
+
};
|
|
295
|
+
readonly 'color-code-fg': {
|
|
296
|
+
readonly light: "var(--color-fg)";
|
|
297
|
+
readonly dark: "oklch(0.88 0.005 80)";
|
|
298
|
+
};
|
|
299
|
+
readonly 'color-syntax-keyword': {
|
|
300
|
+
readonly light: "oklch(0.51 0.12 250)";
|
|
301
|
+
readonly dark: "oklch(0.61 0.11 250)";
|
|
302
|
+
};
|
|
303
|
+
readonly 'color-syntax-string': {
|
|
304
|
+
readonly light: "oklch(0.50 0.12 145)";
|
|
305
|
+
readonly dark: "oklch(0.60 0.11 145)";
|
|
306
|
+
};
|
|
307
|
+
readonly 'color-syntax-constant': {
|
|
308
|
+
readonly light: "oklch(0.51 0.105 85)";
|
|
309
|
+
readonly dark: "oklch(0.61 0.11 84)";
|
|
310
|
+
};
|
|
311
|
+
readonly 'color-syntax-comment': {
|
|
312
|
+
readonly light: "oklch(0.52 0.01 80)";
|
|
313
|
+
readonly dark: "oklch(0.60 0.005 80)";
|
|
314
|
+
};
|
|
315
|
+
readonly 'color-syntax-function': {
|
|
316
|
+
readonly light: "oklch(0.52 0.12 310)";
|
|
317
|
+
readonly dark: "oklch(0.62 0.11 310)";
|
|
318
|
+
};
|
|
319
|
+
readonly 'color-syntax-type': {
|
|
320
|
+
readonly light: "oklch(0.50 0.085 196)";
|
|
321
|
+
readonly dark: "oklch(0.60 0.10 195)";
|
|
322
|
+
};
|
|
323
|
+
readonly 'color-syntax-punctuation': {
|
|
324
|
+
readonly light: "oklch(0.52 0.01 80)";
|
|
325
|
+
readonly dark: "oklch(0.60 0.005 80)";
|
|
326
|
+
};
|
|
327
|
+
readonly 'color-syntax-variable': {
|
|
328
|
+
readonly light: "oklch(0.26 0.01 80)";
|
|
329
|
+
readonly dark: "oklch(0.82 0.005 80)";
|
|
330
|
+
};
|
|
331
|
+
readonly 'color-syntax-link': {
|
|
332
|
+
readonly light: "var(--color-accent)";
|
|
333
|
+
readonly dark: "var(--color-accent)";
|
|
334
|
+
};
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Precise types for `import tokens from 'remarque-tokens/tokens.json'`
|
|
339
|
+
// (and any other bundler-JSON-import path resolving through this
|
|
340
|
+
// subpath) without depending on the consumer's `resolveJsonModule`.
|
|
341
|
+
declare module 'remarque-tokens/tokens.json' {
|
|
342
|
+
const tokens: RemarqueTokensFile;
|
|
343
|
+
export default tokens;
|
|
344
|
+
}
|
package/tokens.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$description": "Remarque design tokens — GENERATED from tokens-core.css + tokens-palette.css by scripts/tokens-json.mjs. Do not edit; the CSS is the source of truth.",
|
|
3
3
|
"$extensions": {
|
|
4
4
|
"remarque": {
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.13.0",
|
|
6
6
|
"tiers": {
|
|
7
7
|
"core": "immutable identity — overriding forks the system",
|
|
8
8
|
"palette": "sanctioned personalization surface — override freely, then run remarque-audit"
|
|
@@ -421,6 +421,87 @@
|
|
|
421
421
|
"dark": {
|
|
422
422
|
"$value": "oklch(0.88 0.005 80)"
|
|
423
423
|
}
|
|
424
|
+
},
|
|
425
|
+
"color-syntax-keyword": {
|
|
426
|
+
"$type": "color",
|
|
427
|
+
"light": {
|
|
428
|
+
"$value": "oklch(0.51 0.12 250)"
|
|
429
|
+
},
|
|
430
|
+
"dark": {
|
|
431
|
+
"$value": "oklch(0.61 0.11 250)"
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
"color-syntax-string": {
|
|
435
|
+
"$type": "color",
|
|
436
|
+
"light": {
|
|
437
|
+
"$value": "oklch(0.50 0.12 145)"
|
|
438
|
+
},
|
|
439
|
+
"dark": {
|
|
440
|
+
"$value": "oklch(0.60 0.11 145)"
|
|
441
|
+
}
|
|
442
|
+
},
|
|
443
|
+
"color-syntax-constant": {
|
|
444
|
+
"$type": "color",
|
|
445
|
+
"light": {
|
|
446
|
+
"$value": "oklch(0.51 0.105 85)"
|
|
447
|
+
},
|
|
448
|
+
"dark": {
|
|
449
|
+
"$value": "oklch(0.61 0.11 84)"
|
|
450
|
+
}
|
|
451
|
+
},
|
|
452
|
+
"color-syntax-comment": {
|
|
453
|
+
"$type": "color",
|
|
454
|
+
"light": {
|
|
455
|
+
"$value": "oklch(0.52 0.01 80)"
|
|
456
|
+
},
|
|
457
|
+
"dark": {
|
|
458
|
+
"$value": "oklch(0.60 0.005 80)"
|
|
459
|
+
}
|
|
460
|
+
},
|
|
461
|
+
"color-syntax-function": {
|
|
462
|
+
"$type": "color",
|
|
463
|
+
"light": {
|
|
464
|
+
"$value": "oklch(0.52 0.12 310)"
|
|
465
|
+
},
|
|
466
|
+
"dark": {
|
|
467
|
+
"$value": "oklch(0.62 0.11 310)"
|
|
468
|
+
}
|
|
469
|
+
},
|
|
470
|
+
"color-syntax-type": {
|
|
471
|
+
"$type": "color",
|
|
472
|
+
"light": {
|
|
473
|
+
"$value": "oklch(0.50 0.085 196)"
|
|
474
|
+
},
|
|
475
|
+
"dark": {
|
|
476
|
+
"$value": "oklch(0.60 0.10 195)"
|
|
477
|
+
}
|
|
478
|
+
},
|
|
479
|
+
"color-syntax-punctuation": {
|
|
480
|
+
"$type": "color",
|
|
481
|
+
"light": {
|
|
482
|
+
"$value": "oklch(0.52 0.01 80)"
|
|
483
|
+
},
|
|
484
|
+
"dark": {
|
|
485
|
+
"$value": "oklch(0.60 0.005 80)"
|
|
486
|
+
}
|
|
487
|
+
},
|
|
488
|
+
"color-syntax-variable": {
|
|
489
|
+
"$type": "color",
|
|
490
|
+
"light": {
|
|
491
|
+
"$value": "oklch(0.26 0.01 80)"
|
|
492
|
+
},
|
|
493
|
+
"dark": {
|
|
494
|
+
"$value": "oklch(0.82 0.005 80)"
|
|
495
|
+
}
|
|
496
|
+
},
|
|
497
|
+
"color-syntax-link": {
|
|
498
|
+
"$type": "color",
|
|
499
|
+
"light": {
|
|
500
|
+
"$value": "var(--color-accent)"
|
|
501
|
+
},
|
|
502
|
+
"dark": {
|
|
503
|
+
"$value": "var(--color-accent)"
|
|
504
|
+
}
|
|
424
505
|
}
|
|
425
506
|
}
|
|
426
507
|
}
|