Merge pull request #2576 from tmandry/default-auto-switch

Add "Auto" theme selection which switches between default light and dark theme automatically
This commit is contained in:
Eric Huss 2025-03-31 18:56:39 +00:00 committed by GitHub
commit 4946c78e8c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 47 additions and 14 deletions

View file

@ -10,7 +10,7 @@
"require": "readonly" "require": "readonly"
}, },
"parserOptions": { "parserOptions": {
"ecmaVersion": 2018, "ecmaVersion": 2021,
"requireConfigFile": false, "requireConfigFile": false,
"sourceType": "module" "sourceType": "module"
}, },

View file

@ -1,6 +1,6 @@
'use strict'; 'use strict';
/* global default_theme, hljs, ClipboardJS */ /* global default_theme, default_dark_theme, default_light_theme, hljs, ClipboardJS */
// Fix back button cache problem // Fix back button cache problem
window.onunload = function() { }; window.onunload = function() { };
@ -329,7 +329,13 @@ aria-label="Show hidden lines"></button>';
themePopup.querySelectorAll('.theme-selected').forEach(function(el) { themePopup.querySelectorAll('.theme-selected').forEach(function(el) {
el.classList.remove('theme-selected'); el.classList.remove('theme-selected');
}); });
themePopup.querySelector('button#' + get_theme()).classList.add('theme-selected'); const selected = get_saved_theme() ?? 'default_theme';
let element = themePopup.querySelector('button#' + selected);
if (element === null) {
// Fall back in case there is no "Default" item.
element = themePopup.querySelector('button#' + get_theme());
}
element.classList.add('theme-selected');
} }
function hideThemes() { function hideThemes() {
@ -338,20 +344,37 @@ aria-label="Show hidden lines"></button>';
themeToggleButton.focus(); themeToggleButton.focus();
} }
function get_theme() { function get_saved_theme() {
let theme; let theme = null;
try { try {
theme = localStorage.getItem('mdbook-theme'); theme = localStorage.getItem('mdbook-theme');
} catch (e) { } catch (e) {
// ignore error. // ignore error.
} }
return theme;
}
function delete_saved_theme() {
localStorage.removeItem('mdbook-theme');
}
function get_theme() {
const theme = get_saved_theme();
if (theme === null || theme === undefined || !themeIds.includes(theme)) { if (theme === null || theme === undefined || !themeIds.includes(theme)) {
return default_theme; if (typeof default_dark_theme === 'undefined') {
// A customized index.hbs might not define this, so fall back to
// old behavior of determining the default on page load.
return default_theme;
}
return window.matchMedia('(prefers-color-scheme: dark)').matches
? default_dark_theme
: default_light_theme;
} else { } else {
return theme; return theme;
} }
} }
let previousTheme = default_theme;
function set_theme(theme, store = true) { function set_theme(theme, store = true) {
let ace_theme; let ace_theme;
@ -383,8 +406,6 @@ aria-label="Show hidden lines"></button>';
}); });
} }
const previousTheme = get_theme();
if (store) { if (store) {
try { try {
localStorage.setItem('mdbook-theme', theme); localStorage.setItem('mdbook-theme', theme);
@ -395,13 +416,17 @@ aria-label="Show hidden lines"></button>';
html.classList.remove(previousTheme); html.classList.remove(previousTheme);
html.classList.add(theme); html.classList.add(theme);
previousTheme = theme;
updateThemeSelected(); updateThemeSelected();
} }
// Set theme const query = window.matchMedia('(prefers-color-scheme: dark)');
const theme = get_theme(); query.onchange = function() {
set_theme(get_theme(), false);
};
set_theme(theme, false); // Set theme.
set_theme(get_theme(), false);
themeToggleButton.addEventListener('click', function() { themeToggleButton.addEventListener('click', function() {
if (themePopup.style.display === 'block') { if (themePopup.style.display === 'block') {
@ -420,7 +445,12 @@ aria-label="Show hidden lines"></button>';
} else { } else {
return; return;
} }
set_theme(theme); if (theme === 'default_theme' || theme === null) {
delete_saved_theme();
set_theme(get_theme(), false);
} else {
set_theme(theme);
}
}); });
themePopup.addEventListener('focusout', function(e) { themePopup.addEventListener('focusout', function(e) {

View file

@ -53,10 +53,11 @@
<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> <script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
{{/if}} {{/if}}
<!-- Provide site root to javascript --> <!-- Provide site root and default themes to javascript -->
<script> <script>
const path_to_root = "{{ path_to_root }}"; const path_to_root = "{{ path_to_root }}";
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "{{ preferred_dark_theme }}" : "{{ default_theme }}"; const default_light_theme = "{{ default_theme }}";
const default_dark_theme = "{{ preferred_dark_theme }}";
</script> </script>
<!-- Start loading toc.js asap --> <!-- Start loading toc.js asap -->
<script src="{{ resource "toc.js" }}"></script> <script src="{{ resource "toc.js" }}"></script>
@ -81,6 +82,7 @@
<!-- Set the theme before any content is loaded, prevents flash --> <!-- Set the theme before any content is loaded, prevents flash -->
<script> <script>
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
let theme; let theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { } try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; } if (theme === null || theme === undefined) { theme = default_theme; }
@ -132,6 +134,7 @@
<i class="fa fa-paint-brush"></i> <i class="fa fa-paint-brush"></i>
</button> </button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu"> <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="default_theme">Auto</button></li>
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li> <li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li> <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li> <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>