Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

[Feature Request] Keep dynamic fixes active after dark theme detector stand-down ("theme off, fixes on")

オープン
#15,992 コメント 4 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
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 の本文から書いたものです。

説明

enhancement
Prerequisites
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_THEME handler). The fix database is structurally empty exactly where it is needed.
  • The NO DARK THEME hint forces Dark Reader to keep transforming — rejected in #15959 as an anti-pattern, and rightly so.
  • The TARGET/MATCH hint 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 insertRule recorder: light rule at ~1195 ms, dark variant of the same component at ~1352 ms.
  • Out of the box (detectDarkTheme defaults to true), both the generic path (runCheck() checks document.documentElement.dataset.theme === 'dark' in src/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 before canCheckForStyle() would let runCheck() 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_UP sequence.
  • 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)

  1. 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?
  2. Runtime theme flips (e.g. the user switches the site to light mode and MATCH stops matching): should detection re-run, and should the kept fixes be re-evaluated or removed?
  3. 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?
  4. Fix-rot: the 2020 pixiv entry targeted styled-components hash classes that no longer exist. Is dynamic-theme-fixes still 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 (detectDarkTheme off) — 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_INDEX undefined — 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時間 34分
マージ済み PR(30日)
59

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

darkreader/darkreader のほかの issue

darkreader/darkreader の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。