feat(html): read a document in the dark - #698
Merged
Merged
Conversation
`HtmlConfig::color_scheme` is `light` — a white page, what every document has rendered against until now — or `dark`, or `system`, which follows the reader's `prefers-color-scheme`. It reaches every document type: a text document flowing or paged, a sheet, a slide, a drawing. The colors a file authors arrive as inline styles, which no media query can reach, so a dark scheme cannot drop them as the file is read: a document setting `fo:color="#000000"` would render black on black. `dark.css` overrides them instead — every fill gives way to the page and every run of text to one legible against it, which costs a slide its own fills and is what keeps its text readable. A `background-image` is left alone: a page printed on a picture keeps it. Rather than writing every rule twice, once plain and once inside a query, the stylesheet is written once and the element carrying it is gated — `<style media="(prefers-color-scheme: dark)">`, or the same attribute on the `<link>` where the config links shipped resources. One asset, one cascade, both modes, and `light` emits nothing at all: it declares no `color-scheme` either, so a reader whose webview darkens the page for them keeps that until the apps offer the setting. Reflowed to the viewport, a text document also gets 3mm of padding. It had none: there is no page box to inset it there, and the body carries no margin of its own, so the text began at the first pixel of the screen. A page's own margin is a physical measure and so is this one, rather than a `ch` of whatever font the browser happens to default to. Mirrored in the python, wasm, jni and apple bindings as `HtmlColorScheme`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017rD1SK4k5Y6GQSzbCeKExY
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f7d106b57a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Only the document views had a dark palette. Every view but the pdf one has one now — a text file and its gutter, a source view and its six syntax cuts, a file listing and its washes, an image, a font specimen — each written straight after the sheet it restates and gated the same way. The media view is black in any scheme and keeps no dark sheet of its own. The pdf view is left out: it paints its page backgrounds itself, and turning those over is a different job. The one dark stylesheet is split along the same lines its light counterparts already follow, `document-dark.css` beside `document.css` and so on, so a page carries the dark palette of the views it is, not of all of them. A view writing its style inline rather than as a shipped asset asks `writes_dark_style` and `dark_style_media` for the same gating. A shape's fill is not a background: `translate_drawing_style` writes it as the svg `fill` that the rect or circle inside inherits, so clearing `background-color` left a light-filled text box light while the ink above it turned white — the title of an odg read as white on white. The fill gives way like a background does. The stroke is left as the file set it: it is the shape's line, not its ground. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017rD1SK4k5Y6GQSzbCeKExY
`FileTypeCapabilities::color_scheme` answers for a file type what `translate_html` answers about rendering at all: whether the view it renders as honors `HtmlConfig::color_scheme`. A caller can offer the setting for the files it applies to rather than for all of them, before it holds one. True for every type that renders but a pdf, whose pages carry their own painted backgrounds, and audio and video, which are black in any scheme. A decoded file narrows it the way it narrows `translate_html`: a scheme only reaches html there is. The declaration is held against the renderer rather than maintained by hand: the new test renders a file of each type in `light` and in `dark` and asserts that the two differ exactly where the table says they should — flipping the pdf row to claim support fails it. Mirrored in the python, wasm, jni and apple bindings beside the capabilities already there. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017rD1SK4k5Y6GQSzbCeKExY
Trim the comments and changelog entries added with the color scheme down to the point they make. Also drops a wrong line in ODRHtml.h: the source view and the file listing do honor the scheme. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEQYAReR6DqLpHFSisoehj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 Generated with Claude Code
Following user feedback:
Two things, and they trace to the same corner of the renderer.
The white background
body{margin:0;background:#fff}landed in #683. Before itdocument_cssdeclared no background at all, so whatever dark theming the reader's webview applied showed through — that is the "old way" the feedback misses. Core has never had a colour scheme of its own.HtmlConfig::color_schemeis nowlight(what it has always been),dark, orsystem, which followsprefers-color-scheme. It reaches every document type: a text document flowing or paged, a sheet, a slide, a drawing.The colours a file authors arrive as inline styles, which no media query can reach — so a dark scheme cannot simply drop them as the file is read, and a document setting
fo:color="#000000"would render black on black.dark.cssoverrides them instead: every fill gives way to the page and every run of text to one legible against it. Abackground-imageis left alone, so a page printed on a picture keeps it.Rather than writing every rule twice — once plain, once inside a query — the stylesheet is written once and the element carrying it is gated:
<style media="(prefers-color-scheme: dark)">, or the same attribute on the<link>where the config links shipped resources. One asset, one cascade, both modes.lightemits nothing at all, and deliberately declares nocolor-schemeeither, so a reader whose webview darkens the page for them keeps that until the apps offer the setting.Mirrored in the python, wasm, jni and apple bindings as
HtmlColorScheme.The screen edge
With page margins off the text went into a bare
<div>; there is no page box to inset it there, andbody{margin:0}left nothing else, so it began at the first pixel of the screen. That div is now.odr-text-flow{padding:3mm}— a physical measure, like a page's own margin, rather than achof whatever font the browser happens to default to.Trade-off worth knowing
A slide loses its own fills in dark mode. That falls out of overriding the document's colours across every document type, and it is what keeps text over a light-filled shape readable. The pdf, source, text-file and file-listing views are untouched — they bring their own styling, and the pdf pipeline paints its own page backgrounds.
Testing
dark.csskeeps its media query and is served.compare-htmlcompares rendered pages, and the only light-path change selects.odr-text-flow, which that suite never emits — it renders withtext_document_margin = true.wasm/tests/enums.test.mjs.The apps now need to surface
colorSchemenext to the existing page-edges toggle.