PageSourceSearch

https://thelordisnear.org/user/themes/typhoon/js/appearance.js

js thelordisnear.org collected 2026-09-24 14:26:39 UTC 2,748 bytes, 96 lines download raw bytes

1((function(global) {
2  const DATA = JSON.parse(document.documentElement.dataset.appearance || 'null');
3  const matchMedia = window.matchMedia('(prefers-color-scheme: dark)');
4
5  try {
6    // Chrome & Firefox
7    matchMedia.addEventListener('change', (event) => {
8      if (typhoonRetrieve().appearance === 'system') {
9        typhoonSetTheme(event.matches ? 'dark' : 'light', true);
10      }
11    });
12  } catch (fallback) {
13    try {
14      // Safari
15      matchMedia.addListener((event) => {
16        if (typhoonRetrieve().appearance === 'system') {
17          typhoonSetTheme(event.matches ? 'dark' : 'light', true);
18        }
19      });
20    } catch (error) {
21      console.error(error);
22    }
23  }
24
25  const typhoonStorage = {
26    set(value) {
27      const data = JSON.stringify(value);
28
29      if (DATA.type === 'cookie') {
30        Cookies.set('typhoon-appearance', data, { expires: 365 });
31      } else {
32        const STORAGE = DATA.store ? 'localStorage' : 'sessionStorage';
33        global[STORAGE].setItem('typhoon-appearance', data);
34      }
35    },
36    get() {
37      if (DATA.type === 'cookie') {
38        return JSON.parse(Cookies.get('typhoon-appearance') || 'null');
39      } else {
40        const STORAGE = DATA.store ? 'localStorage' : 'sessionStorage';
41        return JSON.parse(global[STORAGE].getItem('typhoon-appearance') || 'null');
42      }
43    },
44  }
45
46  global.typhoonStore = function(data) {
47    const theme = data.appearance === 'system' ? typhoonGetTheme() : data.appearance;
48    const config = Object.assign({}, typhoonRetrieve(), data, { theme: theme });
49
50    typhoonStorage.set(config);
51    typhoonSetTheme(theme, false);
52  }
53
54  global.typhoonRetrieve = function() {
55    const systemTheme = typhoonGetTheme();
56    const storage = typhoonStorage.get();
57
58    if (storage && storage.appearance === 'system') {
59      storage.theme = systemTheme;
60    }
61
62    return storage || {
63      theme: DATA.appearance === 'system' ? systemTheme : DATA.appearance,
64      appearance: DATA.appearance || 'system'
65    };
66  }
67
68  global.typhoonSetTheme = function(theme, store) {
69    const event = new CustomEvent('typhoon-theme', {
70      detail: {
71        theme: theme,
72        appearance: typhoonRetrieve().appearance
73      }
74    });
75
76    if (store) {
77      typhoonStore({ theme: theme || typhoonGetTheme() });
78    }
79
80    if (DATA.type === 'cookie') {
81      window.dispatchEvent(event);
82
83      setTimeout(() => {
84        document.documentElement.classList.remove('light', 'dark');
85        document.documentElement.classList.add(theme);
86      }, 0);
87    } else {
88      window.dispatchEvent(event);
89    }
90  }
91
92  global.typhoonGetTheme = function() {
93    return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
94  }
95
96})(window));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.