[Feature Request] Keep dynamic fixes active after dark theme detector stand-down ("theme off, fixes on")
还没有人认领这个 Issue。
评估
- 难度
- 5/5
- 预计耗时
- 一周以上
- 新手友好度
- 42/100
- Issue 类型
- 功能
- 描述清晰度
- 基本清楚
- 活跃度
- 活跃
- 技术栈
- typescript
- 领域
- frontend
调研方向
从 src/inject/detector.ts、detector-hints.config 格式以及 src/inject/index.ts 中的 ADD_DYNAMIC_THEME handler 开始。跟踪当前 dark 检测的停用流程,并确定 opt-in KEEP FIXES 指令如何在不使用主题的 UA-stylesheet 覆盖的情况下保留 URL 匹配的 fixes。完成的标准是:该指令得到明确支持,现有网站保持当前行为,并且 detector 生命周期有测试覆盖。
由索引模型根据 Issue 内容生成。
描述
Prerequisites
- I searched for any existing report about this feature request to avoid opening a duplicate.
Is this feature request related to a problem?
Yes
Feature Request Description
Problem
Dark Reader's dark theme detector is strictly binary: when it concludes a site ships its own dark theme, it performs a full stand-down (removeDynamicTheme() + CLEAN_UP), discarding everything — including URL-matched dynamic fixes. That verdict is architecturally correct (a native dark theme should not be double-transformed), but it leaves a real class of sites unpatchable: natively dark sites whose dark theme itself has a first-paint / hydration bug. This pattern is common in SPAs with CSS-in-JS theme contexts that initialize after hydration. On such sites:
- No dynamic fix can help, because fixes are torn down together with the theme at the moment of stand-down (
src/inject/index.ts,ADD_DYNAMIC_THEMEhandler). The fix database is structurally empty exactly where it is needed. - The
NO DARK THEMEhint forces Dark Reader to keep transforming — rejected in #15959 as an anti-pattern, and rightly so. - The
TARGET/MATCHhint merged in #15959 cannot express it either (see below).
So today there is no mechanism that can say: "trust this site's dark theme, but keep the documented fix entries to patch its broken first paint."
Concrete example: pixiv.net
- An inline head script sets
<html data-theme="dark">before first paint — correct. - But the React theme context initially renders styled-components with light values and only syncs to dark after hydration. Captured with an
insertRulerecorder: light rule at ~1195 ms, dark variant of the same component at ~1352 ms. - Out of the box (
detectDarkThemedefaults totrue), both the generic path (runCheck()checksdocument.documentElement.dataset.theme === 'dark'insrc/inject/detector.ts) and the merged hint detect the site as dark and Dark Reader stands down entirely — leaving the white window exposed on every warm-start load. - The merged
TARGET html+MATCH [data-theme="dark"]hint is behaviorally a no-op here: it matches the same attribute on the same element the generic path already checks. Its only effect is timing —detectUsingHint()can fire beforecanCheckForStyle()would letrunCheck()run, so the stand-down happens earlier and covers less of the race window. (Repro is timing-dependent: on MV3 cold start, service-worker wake-up can push the inject → detect cycle past the hydration window, which is likely why the flash did not reproduce during review.)
Proposed solution
A new opt-in directive in detector-hints.config — KEEP FIXES, usable alongside TARGET/MATCH:
- On dark detection for a hinted site, the content script drops the generated theme but keeps the URL's dynamic fix entries applied ("theme off, fixes on"), instead of the current
removeDynamicTheme()+DARK_THEME_DETECTED→CLEAN_UPsequence. - A fixes-only rebuild should skip the UA-stylesheet overrides an active theme injects (e.g.
html { background-color }/color-scheme), since the native theme already handles those. - Everything remains opt-in: sites without the directive behave exactly as today.
This directly resolves the anti-pattern concern from #15959 — Dark Reader no longer transforms native dark stylesheets, it only applies explicitly documented per-site patches — and it gives the fix database an actual role on native-dark sites. Without it, writing a per-site fix for pixiv is pointless, because no such fix can survive the stand-down.
Design questions (cc @alexanderby)
- Is a hint directive the right shape, or would you prefer fixes to live in a separate stylesheet channel from the start, so stand-down removes only the theme channel?
- Runtime theme flips (e.g. the user switches the site to light mode and
MATCHstops matching): should detection re-run, and should the kept fixes be re-evaluated or removed? - After
DARK_THEME_DETECTED, the background currently treats the tab like a dark-listed site (isURLEnabled()). Should the fixes-only state persist across navigations in the same way? - Fix-rot: the 2020 pixiv entry targeted styled-components hash classes that no longer exist. Is
dynamic-theme-fixesstill the right home for such patches, or should they belong to static themes / a new category?
Screenshots
- insertRule recording of the pixiv.net hydration race: light rule inserted at ~1195 ms, dark variant of the same component at ~1352 ms (attached).
- Console trace of the warm-start sequence: DR theme injected → detector matches
html[data-theme="dark"]→ theme removed → white components visible until hydration completes. - Control: same load with the detector disabled (
detectDarkThemeoff) — no flash, Dark Reader's near-identity transform covers the window.
Additional Context
- Background discussion: #15959 (pixiv.net detector hint; includes the hydration-race analysis and the review conversation with @Myshor, who suggested opening this issue: "Proposing a new engine behavior or config directive ... affects core Dark Reader architecture beyond just pixiv.net").
Related issues (searched before filing; no duplicate of this proposal found):
-
Same code path, state lifecycle: #15509 (dark-detected / NO DARK THEME state not re-evaluated during in-site navigation), #15913 + #15990 (cold-start race leaving
DETECTOR_HINTS_INDEXundefined — also why detector-related flashes reproduce inconsistently). -
Hint DSL extensions currently in flight: #15929, #15930 (
MATCH SYSTEM DARK/LIGHT) — this proposal adds a post-verdict directive rather than another matching mode. -
Verdict-accuracy requests, different problem: #1327, #10792, #13160, #12238, #15033 — these concern whether a site is dark; this proposal concerns what Dark Reader retains after a correct verdict.
-
Likely unattributed instances of the same symptom: #4180 (Google Search), #13823 (addons.mozilla.org), #3307 (git.sr.ht).
-
Tested with a dev build of main (~4.9.130), Chrome XX (MV3), Windows 11. Repro: load https://pixiv.net with default settings on a warm start.
-
Happy to implement the directive and tests if the direction looks acceptable.
- 主要语言
- TypeScript
- 星标
- 22.4k
- 派生
- 2.8k
- 平均合并
- 23 小时 35 分钟
- 30 天内合并 PR
- 57
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
darkreader/darkreader 的其他 Issue
-
Broken Website
难度 2/5 1-3 小时 新手友好度 72/100
darkreader/darkreader#15999 · 5 条评论 ·
-
难度 1/5 1 小时以内 新手友好度 88/100
darkreader/darkreader#15570 ·
-
enhancement
难度 1/5 1 小时以内 新手友好度 64/100
darkreader/darkreader#13250 ·
-
难度 4/5 3-5 天 新手友好度 55/100
darkreader/darkreader#16024 · 3 条评论 ·
-
access needed Broken Website
难度 3/5 1-2 天 新手友好度 48/100
darkreader/darkreader#16014 · 1 条评论 ·
查看 darkreader/darkreader 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 84/100
receptron/mulmoterminal#2264 ·
-
documentation
难度 2/5 1-3 小时 新手友好度 78/100
components-web-app/docs#96 ·
-
enhancement
难度 2/5 1-3 小时 新手友好度 78/100
-
难度 2/5 1-3 小时 新手友好度 68/100
simonsobs/tileviewer#114 ·
-
难度 2/5 1-3 小时 新手友好度 75/100