dark_mode.go RawHistoryFolder
1package webutil
2
3import "fmt"
4
5const darkModeScriptTemplate = `(function() {
6 var prefersDark = %t;
7 window.%s = prefersDark;
8 var originalMatchMedia = window.matchMedia.bind(window);
9
10 if (prefersDark) {
11 document.documentElement.classList.add('dark');
12 document.documentElement.classList.remove('light');
13 } else {
14 document.documentElement.classList.add('light');
15 document.documentElement.classList.remove('dark');
16 }
17
18 function isColorSchemeQuery(query, scheme) {
19 if (typeof query !== 'string') return false;
20 var normalized = query.replace(/\s+/g, '').toLowerCase();
21 return normalized.indexOf('prefers-color-scheme:' + scheme) !== -1;
22 }
23
24 function createFakeMediaQueryList(query, matches) {
25 var listeners = [];
26 var onchangeHandler = null;
27 return {
28 matches: matches,
29 media: query,
30 get onchange() { return onchangeHandler; },
31 set onchange(fn) { onchangeHandler = fn; },
32 addListener: function(cb) { if (typeof cb === 'function') listeners.push(cb); },
33 removeListener: function(cb) { var idx = listeners.indexOf(cb); if (idx !== -1) listeners.splice(idx, 1); },
34 addEventListener: function(type, cb) { if (type === 'change' && typeof cb === 'function') listeners.push(cb); },
35 removeEventListener: function(type, cb) {
36 if (type === 'change') { var idx = listeners.indexOf(cb); if (idx !== -1) listeners.splice(idx, 1); }
37 },
38 dispatchEvent: function(event) {
39 for (var i = 0; i < listeners.length; i++) { try { listeners[i](event); } catch (e) {} }
40 if (onchangeHandler) { try { onchangeHandler(event); } catch (e) {} }
41 return true;
42 }
43 };
44 }
45
46 window.matchMedia = function(query) {
47 if (isColorSchemeQuery(query, 'dark')) return createFakeMediaQueryList(query, prefersDark);
48 if (isColorSchemeQuery(query, 'light')) return createFakeMediaQueryList(query, !prefersDark);
49 return originalMatchMedia(query);
50 };
51})();`
52
53// DarkModeScript returns JS that patches matchMedia and sets dark/light
54// classes on <html>. The globalVar parameter names the window property
55// that stores the preference (engine-specific for debuggability).
56func DarkModeScript(prefersDark bool, globalVar string) string {
57 return fmt.Sprintf(darkModeScriptTemplate, prefersDark, globalVar)
58}