Public: anyone can read this; the crew can change it.
An app's /__forge/ door reads in the reader's colour scheme, dark included #6670
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/6653-an-app-s-forge-door-reads-in-the-reader → main 1 commit fork
2 files
changed +23
−1
src/apps/door.ts +2 −1
| @@ -32,7 +32,8 @@ export const DOOR_PULL_LIMIT = 5; | ||
| 32 | 32 | export type DoorPullLine = { number: number; title: string; check: string; href: string }; |
| 33 | 33 | |
| 34 | 34 | const STYLE = |
| 35 | "body{font:16px/1.5 system-ui,sans-serif;max-width:32rem;margin:3rem auto;padding:0 1rem}li{margin:.4rem 0}pre{overflow-x:auto;padding:.6rem;background:#eee;color:#111;user-select:all}"; | |
| 35 | "html{color-scheme:light dark}body{font:16px/1.5 system-ui,sans-serif;max-width:32rem;margin:3rem auto;padding:0 1rem}li{margin:.4rem 0}pre{overflow-x:auto;padding:.6rem;background:#eee;color:#111;user-select:all}" + | |
| 36 | "@media (prefers-color-scheme: dark){body{background:#111;color:#eee}a{color:#8ab4f8}a:visited{color:#c4a7e7}pre{background:#222;color:#eee}}"; | |
| 36 | 37 | const STYLE_HASH = createHash("sha256").update(STYLE).digest("base64"); |
| 37 | 38 | |
| 38 | 39 | /** The same words as the pill's accessible name. */ |
test/door-scheme.test.ts added +21
| @@ -0,0 +1,21 @@ | ||
| 1 | /** The door follows the reader's colour scheme, and its CSP hash is derived from its style (#6653). */ | |
| 2 | ||
| 3 | import { expect, test } from "bun:test"; | |
| 4 | import { createHash } from "node:crypto"; | |
| 5 | import { doorPage } from "../src/apps/door.ts"; | |
| 6 | ||
| 7 | test("the door's style-src hash matches its one <style> block, and a dark rule is present", async () => { | |
| 8 | const res = doorPage( | |
| 9 | { where: { app: "lab", env: "production" }, forgeUrl: "https://forge.test", ssh: "ssh -p 2222 lab@localhost" }, | |
| 10 | false, | |
| 11 | ); | |
| 12 | const html = await res.text(); | |
| 13 | const blocks = [...html.matchAll(/<style>([\s\S]*?)<\/style>/g)]; | |
| 14 | expect(blocks.length).toBe(1); | |
| 15 | const css = blocks[0]![1]!; | |
| 16 | const hash = createHash("sha256").update(css).digest("base64"); | |
| 17 | expect(res.headers.get("content-security-policy")).toContain(`style-src 'sha256-${hash}'`); | |
| 18 | expect(css).toContain("color-scheme:light dark"); | |
| 19 | expect(css).toMatch(/@media \(prefers-color-scheme: dark\)\{[^]*body\{[^}]*background[^}]*\}[^]*a\{[^}]*\}[^]*pre\{[^}]*\}/); | |
| 20 | expect(html).not.toContain("<script"); | |
| 21 | }); |
new above
offline