remarque-tokens 0.4.0 → 0.5.1

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 CHANGED
@@ -4,6 +4,48 @@ 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.5.1 — 2026-07-20
8
+
9
+ Two `remarque-audit` fixes found by the flagship site's adoption (its
10
+ first real-world run):
11
+
12
+ ### Fixed
13
+ - The file passed via `--palette` now always counts as a token file for
14
+ the oklch-literal scan — previously a consumer palette named
15
+ `global.css` produced ~200 false positives against its own token
16
+ declarations. `theme-deck.css`-style generated palette files are also
17
+ allowlisted.
18
+ - The `--src` scans strip comments (line numbers preserved) before
19
+ matching, so prose like `(issue #324)` in a comment no longer trips
20
+ the hex-color regex.
21
+
22
+ No token values changed.
23
+
24
+ ## 0.5.0 — 2026-07-20
25
+
26
+ Theme-convention unification (epic #47 item 4; ratified 3-0 by consensus
27
+ panel with conditions, all implemented).
28
+
29
+ ### Added
30
+ - **Dual dark selector**: the palette's manual-toggle block is now
31
+ `[data-theme="dark"], :root.dark` — `[data-theme]` stays canonical for
32
+ new sites; `:root.dark` is a compatibility bridge for class-keyed
33
+ consumers (sunset target: 1.0). Specificity asymmetry documented.
34
+ - **`remarque-audit` parses both conventions natively** (plus
35
+ `html.dark`/`.dark`), so class-keyed sites can adopt the audit with no
36
+ flags. Fixture tests for all three conventions + a must-fail case run
37
+ in CI.
38
+ - `exports` now includes `./package.json` (standard tooling expects
39
+ `require('remarque-tokens/package.json')`; previously blocked).
40
+
41
+ ### Fixed
42
+ - Parser bug: light-theme extraction matched any selector *containing*
43
+ `:root`, so a `:root.dark` block would have leaked dark values into
44
+ the light-theme audit and could mask light-theme contrast failures.
45
+ Selector matching is now exact per comma-separated part.
46
+
47
+ No token values changed in this release.
48
+
7
49
  ## 0.4.0 — 2026-07-20
8
50
 
9
51
  ### Added
package/REMARQUE.md CHANGED
@@ -43,7 +43,7 @@ Remarque projects should feel like a modern technical publication — not a gene
43
43
  - **CSS framework:** Tailwind CSS — v4 via the shipped `remarque-tokens/theme.css` (`@theme inline` adapter; utilities reference the runtime tokens), or v3 via the shipped `tailwind.config.js`. One mechanism per project, never both.
44
44
  - **Component primitives:** shadcn/ui (when reusable components are needed)
45
45
  - **Markup:** Semantic HTML with ARIA landmarks
46
- - **Theming:** Light and dark mode via `[data-theme]` attribute (system preference + manual toggle)
46
+ - **Theming:** Light and dark mode via the `[data-theme]` attribute (canonical; system preference + manual toggle). `:root.dark` is supported as a compatibility bridge for class-keyed sites (sunset: 1.0) — the audit parses both. Mind the specificity asymmetry: `[data-theme=\"dark\"]` is (0,1,0), `:root.dark` is (0,2,0). Platform endgame to watch: `color-scheme` + `light-dark()`
47
47
  - **Accessibility:** USWDS-informed. Keyboard navigation, skip-to-content link, ARIA labels, WCAG AA contrast compliance, 44px touch targets, 14px minimum small text
48
48
  - **Tokens:** Centralized CSS custom properties in two tiers — `tokens-core.css` (immutable identity) + `tokens-palette.css` (sanctioned personalization). `tokens.css` aggregates both. See "Token Tiers"
49
49
  - **Fonts:** Self-hosted woff2 (no CDN dependency). Preloaded via `<link rel="preload">`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remarque-tokens",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "engines": {
5
5
  "node": ">=18"
6
6
  },
@@ -42,7 +42,8 @@
42
42
  "./theme": "./theme.css",
43
43
  "./tokens.json": "./tokens.json",
44
44
  "./prose": "./prose.css",
45
- "./prose.css": "./prose.css"
45
+ "./prose.css": "./prose.css",
46
+ "./package.json": "./package.json"
46
47
  },
47
48
  "files": [
48
49
  "tokens.css",
package/scripts/audit.mjs CHANGED
@@ -152,11 +152,20 @@ console.log(`\nsource scans (${SRC})`);
152
152
  const FONT_FLOOR_REM = 0.8125, FONT_FLOOR_PX = 13;
153
153
  // tokens.astro is the token *reference page* — its job is displaying literal
154
154
  // values (issue #48 tracks generating it from a machine-readable source).
155
- const isTokenFile = (p) => /tokens(-core|-palette)?\.css$|fonts\.css$|globals\.css$|pages[\/\\]tokens\.astro$/.test(p);
155
+ // The file passed via --palette is BY DEFINITION a token file, whatever
156
+ // its name (a consumer's palette is often global.css or similar).
157
+ const paletteRel = relative('.', PALETTE);
158
+ const isTokenFile = (p) =>
159
+ p === paletteRel ||
160
+ /tokens(-core|-palette)?\.css$|fonts\.css$|globals?\.css$|theme-deck\.css$|pages[\/\\]tokens\.astro$/.test(p);
156
161
 
157
162
  for (const file of walk(SRC)) {
158
163
  const rel = relative('.', file);
159
- const text = readFileSync(file, 'utf8');
164
+ // Strip comments before scanning, preserving line numbers — otherwise
165
+ // prose like "(issue #324)" in a comment trips the hex-color regex.
166
+ const text = readFileSync(file, 'utf8')
167
+ .replace(/\/\*[\s\S]*?\*\//g, (m) => m.replace(/[^\n]/g, ' '))
168
+ .replace(/(^|[^:])\/\/[^\n]*/g, (m, p1) => p1 + ' '.repeat(m.length - p1.length));
160
169
  const lines = text.split('\n');
161
170
  lines.forEach((line, i) => {
162
171
  // 2. font-size floor (static rem/px values), plus statically
@@ -44,8 +44,17 @@ export function declsOf(blocks, filterFn) {
44
44
  return decls;
45
45
  }
46
46
 
47
- /* Standard tier filters */
48
- export const isLightRoot = (b) => b.context === '' && b.prelude.includes(':root');
47
+ /* Standard tier filters. Selector matching is exact per comma-separated
48
+ part `.includes(':root')` would wrongly classify `:root.dark` (a
49
+ dark block in the class convention) as light. */
50
+ const parts = (prelude) => prelude.split(',').map((s) => s.trim());
51
+
52
+ export const isLightRoot = (b) =>
53
+ b.context === '' && parts(b.prelude).some((s) => s === ':root' || s === ':root.light' || s === '[data-theme="light"]');
54
+
55
+ /* Dark: media-query :root, the canonical [data-theme="dark"], or the
56
+ class-convention :root.dark / html.dark (compatibility bridge). */
49
57
  export const isDarkBlock = (b) =>
50
- (b.context.includes('prefers-color-scheme') && b.context.includes('dark') && b.prelude.includes(':root')) ||
51
- b.prelude.includes('[data-theme="dark"]');
58
+ (b.context.includes('prefers-color-scheme') && b.context.includes('dark') &&
59
+ parts(b.prelude).some((s) => s === ':root')) ||
60
+ parts(b.prelude).some((s) => s === '[data-theme="dark"]' || s === ':root.dark' || s === 'html.dark' || s === '.dark');
@@ -106,8 +106,16 @@
106
106
  }
107
107
  }
108
108
 
109
- /* Manual dark mode toggle support */
110
- [data-theme="dark"] {
109
+ /* Manual dark mode toggle support.
110
+ CANONICAL convention: [data-theme="dark"] — use it for new sites.
111
+ :root.dark is a compatibility bridge for class-keyed consumers
112
+ (sunset target: 1.0). NOTE the specificity asymmetry: [data-theme]
113
+ is (0,1,0) but :root.dark is (0,2,0) — site overrides that beat one
114
+ can lose to the other; always override with at least (0,2,0) or use
115
+ cascade order. Platform endgame worth tracking: color-scheme +
116
+ light-dark(), which obsoletes both selectors. */
117
+ [data-theme="dark"],
118
+ :root.dark {
111
119
  --color-bg: oklch(0.16 0.01 80);
112
120
  --color-bg-subtle: oklch(0.19 0.01 80);
113
121
  --color-fg: oklch(0.90 0.005 80);
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.4.0",
5
+ "version": "0.5.1",
6
6
  "tiers": {
7
7
  "core": "immutable identity — overriding forks the system",
8
8
  "palette": "sanctioned personalization surface — override freely, then run remarque-audit"