fix(theme): declare the live colour scheme, so Dark Reader stands down
Dark Reader looks for `<meta name="color-scheme">` first. Finding none, it waits for a stylesheet and then samples text and background colours at several points of the screen, plus some further heuristics, to decide whether the page needs darkening. On the dark palette that verdict is wrong: it inverts an app that is already dark, a second time. So the tag now states which scheme is actually live. It ships in the markup as `light dark`, before any script runs; the pre-paint script narrows it to the one in use, and `applyResolvedTheme` keeps it there when the toggle moves — the same two-signal write as the `.dark` class, in both places. `var dark` moved out of the `try` in that script. It has to be readable after a throwing localStorage in order to set the meta, and false is the right value there: it is what `readThemePreference` -> "system" -> `prefersDark` resolves to on the module side, so the two still agree in the one case that cannot be read. Both setters create the tag when it is absent rather than skipping the write. A silent no-op leaves Dark Reader guessing, which is the bug. The drift guard now runs the real script, lifted out of the HTML, instead of matching its text — it asserts class and meta together for a stored dark, a stored light, and no preference at all. Text matching would have passed a script that declared the tag and never set it. Not `<meta name="darkreader-lock">`: that switches the extension off wholesale, including in light mode, where a user who installed it wants it working. Only the dark palette asks it to stand down. Verified in Chrome across stored dark, stored light, system-dark and a live toggle with no reload: one tag, content and computed `color-scheme` agreeing each time. Whether the extension honours it needs a human with Dark Reader installed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
acb4d97870
commit
d69e896c4c
@@ -67,4 +67,29 @@ export function resolveTheme(
|
||||
*/
|
||||
export function applyResolvedTheme(theme: ResolvedTheme): void {
|
||||
document.documentElement.classList.toggle("dark", theme === "dark");
|
||||
applyColorScheme(theme);
|
||||
}
|
||||
|
||||
/**
|
||||
* States the live scheme in `<meta name="color-scheme">`, kept in step with the
|
||||
* `color-scheme` declarations in index.css.
|
||||
*
|
||||
* The meta tag rather than the stylesheet alone, because of Dark Reader: it
|
||||
* reads this tag first, and failing to find one it samples text and background
|
||||
* colours off the painted page and applies its own inversion. On our dark
|
||||
* palette that is a second darkening of an already dark app. Declaring "dark"
|
||||
* is what tells it the app is already there.
|
||||
*
|
||||
* index.html ships the tag and the pre-paint script sets it, so this is
|
||||
* normally an update; it creates the tag if it is missing rather than silently
|
||||
* doing nothing, which would leave Dark Reader guessing again.
|
||||
*/
|
||||
function applyColorScheme(theme: ResolvedTheme): void {
|
||||
let meta = document.querySelector<HTMLMetaElement>('meta[name="color-scheme"]');
|
||||
if (!meta) {
|
||||
meta = document.createElement("meta");
|
||||
meta.name = "color-scheme";
|
||||
document.head.appendChild(meta);
|
||||
}
|
||||
meta.content = theme;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user