From 6dc332fade071464d55d7e34a8eaa946465fff8a Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sun, 15 Nov 2020 13:29:50 +0100 Subject: [PATCH] Add a new preference, `viewerCssTheme`, to allow forcing the use of the light/dark viewer CSS themes (issue 12290) While this does work pretty well in my quick testing, it's *very much* a hack since as far as I can tell there's no support in the CSS specification for using e.g. a CSS variable to override a `@media (prefers-color-scheme: dark) {...}` block. The solution implemented here is thus to *edit* the viewer CSS, by either removing the entire `@media ...` block in light-mode or by ensuring that its rules become *unconditionally* applied in dark-mode. To simplify the overall implementation, since all of this does seem like somewhat of an edge-case, the `viewerCssTheme` preference will *only* be read during viewer initialization. (Similar to many other existing preferences, a reload is thus required when changing it.) --- extensions/chromium/preferences_schema.json | 9 ++++ web/app.js | 46 +++++++++++++++++++++ web/app_options.js | 5 +++ 3 files changed, 60 insertions(+) diff --git a/extensions/chromium/preferences_schema.json b/extensions/chromium/preferences_schema.json index 0723e6aede6c16..de2ae62dfb2018 100644 --- a/extensions/chromium/preferences_schema.json +++ b/extensions/chromium/preferences_schema.json @@ -198,6 +198,15 @@ 2 ], "default": -1 + }, + "viewerCssTheme": { + "type": "integer", + "enum": [ + 0, + 1, + 2 + ], + "default": 0 } } } diff --git a/web/app.js b/web/app.js index 0a2fa253207cb3..72d34c601b755c 100644 --- a/web/app.js +++ b/web/app.js @@ -90,6 +90,12 @@ const ViewOnLoad = { INITIAL: 1, }; +const ViewerCssTheme = { + AUTOMATIC: 0, // Default value. + LIGHT: 1, + DARK: 2, +}; + // Keep these in sync with mozilla-central's Histograms.json. const KNOWN_VERSIONS = [ "1.0", @@ -256,6 +262,7 @@ const PDFViewerApplication = { await this._readPreferences(); await this._parseHashParameters(); + this._forceCssTheme(); await this._initializeL10n(); if ( @@ -396,6 +403,45 @@ const PDFViewerApplication = { document.getElementsByTagName("html")[0].dir = dir; }, + /** + * @private + */ + _forceCssTheme() { + const cssTheme = AppOptions.get("viewerCssTheme"); + if ( + cssTheme === ViewerCssTheme.AUTOMATIC || + !Object.values(ViewerCssTheme).includes(cssTheme) + ) { + return; + } + const styleSheet = document.styleSheets[0]; + if (!styleSheet) { + return; + } + const cssRules = styleSheet.cssRules; + for (let i = 0, ii = cssRules.length; i < ii; i++) { + const rule = cssRules[i]; + if ( + rule instanceof CSSMediaRule && + rule.media[0] === "(prefers-color-scheme: dark)" + ) { + if (cssTheme === ViewerCssTheme.LIGHT) { + styleSheet.deleteRule(i); + return; + } + // cssTheme === ViewerCssTheme.DARK + const darkRules = /^@media \(prefers-color-scheme: dark\) {\n\s*([\w\s-.,:;/\\{}()]+)\n}$/.exec( + rule.cssText + ); + if (darkRules?.[1]) { + styleSheet.deleteRule(i); + styleSheet.insertRule(darkRules[1], i); + } + return; + } + } + }, + /** * @private */ diff --git a/web/app_options.js b/web/app_options.js index 2e04ed0a41fb81..e4931997b2f078 100644 --- a/web/app_options.js +++ b/web/app_options.js @@ -154,6 +154,11 @@ const defaultOptions = { value: false, kind: OptionKind.VIEWER + OptionKind.PREFERENCE, }, + viewerCssTheme: { + /** @type {number} */ + value: 0, + kind: OptionKind.VIEWER + OptionKind.PREFERENCE, + }, viewOnLoad: { /** @type {boolean} */ value: 0,