Something went wrong. Try again.
Web frontend and supporting services for lance.blue
Something went wrong. Try again.
2.8 kB · 70 lines
JavaScript
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071/** * The camo editor has to survive light mode, and the way it stops doing so is * always the same: a rule pairs a theme colour with a literal one. * * That is how the three roll buttons came to be `color: var(--ink)` on a fixed * near-black. In dark mode --ink is pale and the button reads; in light mode * --ink is near-black too and the button vanishes into its own background. * Nothing errors, no test that renders the page fails, and the control is * simply not there. * * So the rule this checks is structural rather than visual: inside the * editor's section of the stylesheet, a colour is a custom property. The * literals live in one token block at the top, each one a light-dark() pair, * and every rule below reads them. Anything else is the bug above waiting to * happen again. * * Run with `npm test`. */import { test } from "node:test";import assert from "node:assert/strict";import { readFile } from "node:fs/promises";import { join } from "node:path";
const web = join(new URL(".", import.meta.url).pathname, "..");const css = await readFile(join(web, "src/styles.css"), "utf8");
const START = "/* --- camo editor";const start = css.indexOf(START);assert.notEqual(start, -1, "the camo editor section moved or was renamed");
// The section runs to the sign-in dialog, which is shared with the masthead// and is not the editor's to theme.const end = css.indexOf("/* --- the sign-in dialog", start);assert.notEqual(end, -1, "the section after the camo editor moved");const section = css.slice(start, end);
// The one place literals are allowed: the token block, which is the whole// point of having them.const tokensEnd = section.indexOf(".camo-editor canvas");assert.notEqual(tokensEnd, -1, "the editor token block moved");const rules = section.slice(tokensEnd);
test("the editor defines its surfaces in both schemes", () => { const tokens = section.slice(0, tokensEnd); const declarations = [...tokens.matchAll(/(--camo-[a-z-]+):\s*([^;]+);/g)]; assert.ok(declarations.length >= 5, "expected a block of --camo-* tokens");
for (const [, name, value] of declarations) { // --camo-chip-ink is deliberately one value in both schemes: it forwards // to --ink, which the site already flips. if (name === "--camo-chip-ink") continue; assert.match( value.trim(), /^light-dark\(.+,.+\)$/, `${name} is not a light-dark() pair, so it keeps one value in both schemes`, ); }});
test("no rule in the editor hardcodes a colour", () => { const literals = [ ...rules.matchAll(/#[0-9a-fA-F]{3,8}\b/g), ...rules.matchAll(/\b(?:rgba?|hsla?)\(/g), ].map((m) => m[0]); assert.deepEqual( literals, [], "use a --camo-* token (or a site token) so light mode follows", );});