|
1 | 1 | (function () { |
2 | | - const themeKey = "antora-theme"; |
| 2 | + const MODE_KEY = "antora-theme-mode"; |
| 3 | + const LEGACY_KEY = "antora-theme"; |
3 | 4 | const html = document.documentElement; |
4 | 5 | const darkThemeClass = "dark-theme"; |
5 | 6 |
|
6 | | - function setTheme(theme) { |
7 | | - if (theme === "dark") { |
| 7 | + function getMode() { |
| 8 | + const m = localStorage.getItem(MODE_KEY); |
| 9 | + if (m === "system" || m === "dark" || m === "light") return m; |
| 10 | + const leg = localStorage.getItem(LEGACY_KEY); |
| 11 | + if (leg === "dark" || leg === "light") { |
| 12 | + localStorage.setItem(MODE_KEY, leg); |
| 13 | + localStorage.removeItem(LEGACY_KEY); |
| 14 | + return leg; |
| 15 | + } |
| 16 | + return "system"; |
| 17 | + } |
| 18 | + |
| 19 | + function applyVisibleTheme() { |
| 20 | + const mode = getMode(); |
| 21 | + let useDark; |
| 22 | + if (mode === "system") { |
| 23 | + useDark = window.matchMedia("(prefers-color-scheme: dark)").matches; |
| 24 | + } else { |
| 25 | + useDark = mode === "dark"; |
| 26 | + } |
| 27 | + if (useDark) { |
8 | 28 | html.classList.add(darkThemeClass); |
9 | 29 | } else { |
10 | 30 | html.classList.remove(darkThemeClass); |
11 | 31 | } |
12 | | - localStorage.setItem(themeKey, theme); |
13 | 32 | updateToggleLabel(); |
14 | 33 | } |
15 | 34 |
|
| 35 | + function setMode(next) { |
| 36 | + if (next === "system") { |
| 37 | + localStorage.setItem(MODE_KEY, "system"); |
| 38 | + } else { |
| 39 | + localStorage.setItem(MODE_KEY, next); |
| 40 | + } |
| 41 | + applyVisibleTheme(); |
| 42 | + } |
| 43 | + |
16 | 44 | function isDark() { |
17 | 45 | return html.classList.contains(darkThemeClass); |
18 | 46 | } |
|
23 | 51 | if (isDark()) { |
24 | 52 | toggle.innerHTML = |
25 | 53 | '<svg class="theme-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>'; |
26 | | - toggle.setAttribute("aria-label", "Light mode"); |
| 54 | + toggle.setAttribute("aria-label", "Switch to light mode"); |
27 | 55 | } else { |
28 | 56 | toggle.innerHTML = |
29 | 57 | '<svg class="theme-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>'; |
30 | | - toggle.setAttribute("aria-label", "Dark mode"); |
| 58 | + toggle.setAttribute("aria-label", "Switch to dark mode"); |
31 | 59 | } |
32 | 60 | } |
33 | 61 |
|
34 | 62 | function toggleTheme() { |
35 | | - setTheme(isDark() ? "light" : "dark"); |
36 | | - // Avoid :focus “stuck” hover look after mouse click (button stays focused) |
| 63 | + setMode(isDark() ? "light" : "dark"); |
37 | 64 | const toggle = document.getElementById("theme-toggle"); |
38 | 65 | if (toggle) toggle.blur(); |
39 | 66 | } |
40 | 67 |
|
41 | | - function applyInitialTheme() { |
42 | | - const savedTheme = localStorage.getItem(themeKey); |
43 | | - if (savedTheme === "dark" || savedTheme === "light") { |
44 | | - setTheme(savedTheme); |
45 | | - return; |
| 68 | + function onSystemThemeChange() { |
| 69 | + const mode = getMode(); |
| 70 | + if (mode === "system") { |
| 71 | + applyVisibleTheme(); |
| 72 | + } else { |
| 73 | + setMode("system"); |
46 | 74 | } |
47 | | - if (window.matchMedia("(prefers-color-scheme: dark)").matches) { |
48 | | - setTheme("dark"); |
| 75 | + } |
| 76 | + |
| 77 | + function applyInitialTheme() { |
| 78 | + applyVisibleTheme(); |
| 79 | + const mq = window.matchMedia("(prefers-color-scheme: dark)"); |
| 80 | + if (typeof mq.addEventListener === "function") { |
| 81 | + mq.addEventListener("change", onSystemThemeChange); |
49 | 82 | } else { |
50 | | - setTheme("light"); |
| 83 | + mq.addListener(onSystemThemeChange); |
51 | 84 | } |
52 | 85 | } |
53 | 86 |
|
|
93 | 126 | function getRepoUrl() { |
94 | 127 | const meta = document.querySelector('meta[name="antora-repo-url"]'); |
95 | 128 | if (meta && meta.content) return meta.content; |
96 | | - const editLink = document.querySelector('.navbar-end a[href*="/edit/"], .navbar-end a[href*="/-/edit/"], .navbar-end a[href*="/blob/"]'); |
| 129 | + const editLink = document.querySelector( |
| 130 | + '.navbar-end a[href*="/edit/"], .navbar-end a[href*="/-/edit/"], .navbar-end a[href*="/blob/"], a.ftn-edit-inline-link[href*="/"]' |
| 131 | + ); |
97 | 132 | if (editLink && editLink.href) { |
98 | 133 | try { |
99 | 134 | const u = new URL(editLink.href); |
100 | 135 | const pathParts = u.pathname.split("/").filter(Boolean); |
101 | | - if (u.hostname.includes("github") && pathParts.length >= 2) return u.origin + "/" + pathParts.slice(0, 2).join("/"); |
102 | | - if (u.hostname.includes("gitlab") && pathParts.length >= 2) return u.origin + "/" + pathParts.slice(0, 2).join("/"); |
103 | | - if (u.hostname.includes("bitbucket") && pathParts.length >= 2) return u.origin + "/" + pathParts.slice(0, 2).join("/"); |
| 136 | + if (u.hostname.includes("github") && pathParts.length >= 2) { |
| 137 | + return u.origin + "/" + pathParts.slice(0, 2).join("/"); |
| 138 | + } |
| 139 | + if (u.hostname.includes("gitlab") && pathParts.length >= 2) { |
| 140 | + return u.origin + "/" + pathParts.slice(0, 2).join("/"); |
| 141 | + } |
| 142 | + if (u.hostname.includes("bitbucket") && pathParts.length >= 2) { |
| 143 | + return u.origin + "/" + pathParts.slice(0, 2).join("/"); |
| 144 | + } |
104 | 145 | if (pathParts.length >= 2) return u.origin + "/" + pathParts.slice(0, 2).join("/"); |
105 | | - } catch {} |
| 146 | + } catch { |
| 147 | + // ignore |
| 148 | + } |
106 | 149 | } |
107 | 150 | return null; |
108 | 151 | } |
|
116 | 159 | const u = new URL(script.src); |
117 | 160 | u.pathname = u.pathname.replace(/\/[^/]*$/, "/"); |
118 | 161 | return u.pathname + u.search || "."; |
119 | | - } catch (_e) {} |
| 162 | + } catch (_e) { |
| 163 | + // ignore |
| 164 | + } |
120 | 165 | } |
121 | 166 | return "."; |
122 | 167 | } |
|
0 commit comments