mirror of
https://github.com/hectorqin/reader.git
synced 2026-11-11 05:20:54 +08:00
ui.md's four type roles only governed the reading side; the media sheets used every integer from 8 to 24px plus dozens of rem values. Every font size up to 24px now reads one of --text-display/title/body/ui/label/meta/micro. - --text-ui (14px) is the media list/settings body; --text-display (22px) the page hero; --text-micro (10px) only for cover/icon badges. - --text-meta moves 0.72rem -> 0.75rem, so the 200+ media 12px lines land on it unchanged and the reading side's meta grows by half a pixel. - Inputs that were 16px land on --text-title (16.8px), keeping the iOS focus-zoom floor; ui.md says so explicitly. - Sizes above 24px (player initials, hero numerals) and the decorative serif shorthands stay literal; the token test rejects literals <= 24px. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
37 lines
1.6 KiB
TypeScript
37 lines
1.6 KiB
TypeScript
import { readdirSync, readFileSync } from 'node:fs';
|
|
import { join, relative } from 'node:path';
|
|
import { describe, expect, it } from 'vitest';
|
|
|
|
/**
|
|
* ui.md §2: the interface layer reads its scales from tokens. This keeps the radius
|
|
* scale from drifting back to "one more pixel" literals one rule at a time.
|
|
*/
|
|
const root = join(import.meta.dirname, '..', 'src');
|
|
const stylesheets = (dir: string): string[] => readdirSync(dir, { withFileTypes: true }).flatMap(entry => {
|
|
const path = join(dir, entry.name);
|
|
return entry.isDirectory() ? stylesheets(path) : entry.name.endsWith('.css') ? [path] : [];
|
|
});
|
|
|
|
describe('design tokens', () => {
|
|
it('uses --radius-* instead of literal corner radii (ui.md §2.6)', () => {
|
|
const offenders = stylesheets(root).flatMap(file => {
|
|
const source = readFileSync(file, 'utf8');
|
|
return [...source.matchAll(/border-radius:\s*[^;}]*?\b\d*\.?\d+(?:px|rem)[^;}]*/g)]
|
|
.map(match => match[0].trim())
|
|
.map(declaration => `${relative(root, file)}: ${declaration}`);
|
|
});
|
|
expect(offenders).toEqual([]);
|
|
});
|
|
|
|
it('uses --text-* instead of literal font sizes up to 24px (ui.md §2.2)', () => {
|
|
// Above 24px is decorative (a player's initial, a hero numeral) and stays literal.
|
|
const offenders = stylesheets(root).flatMap(file => {
|
|
const source = readFileSync(file, 'utf8');
|
|
return [...source.matchAll(/font-size:\s*(\d*\.?\d+)(px|rem)/g)]
|
|
.filter(([, size, unit]) => (unit === 'rem' ? Number(size) * 16 : Number(size)) <= 24)
|
|
.map(match => `${relative(root, file)}: ${match[0]}`);
|
|
});
|
|
expect(offenders).toEqual([]);
|
|
});
|
|
});
|