]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/html/static/storage.js
Auto merge of #84074 - notriddle:rustdoc-macro-visibility, r=jyn514
[rust.git] / src / librustdoc / html / static / storage.js
1 // From rust:
2 /* global resourcesSuffix */
3 var darkThemes = ["dark", "ayu"];
4 window.currentTheme = document.getElementById("themeStyle");
5 window.mainTheme = document.getElementById("mainThemeStyle");
6
7 var settingsDataset = (function () {
8     var settingsElement = document.getElementById("default-settings");
9     if (settingsElement === null) {
10         return null;
11     }
12     var dataset = settingsElement.dataset;
13     if (dataset === undefined) {
14         return null;
15     }
16     return dataset;
17 })();
18
19 function getSettingValue(settingName) {
20     var current = getCurrentValue('rustdoc-' + settingName);
21     if (current !== null) {
22         return current;
23     }
24     if (settingsDataset !== null) {
25         var def = settingsDataset[settingName.replace(/-/g,'_')];
26         if (def !== undefined) {
27             return def;
28         }
29     }
30     return null;
31 }
32
33 var localStoredTheme = getSettingValue("theme");
34
35 var savedHref = [];
36
37 // eslint-disable-next-line no-unused-vars
38 function hasClass(elem, className) {
39     return elem && elem.classList && elem.classList.contains(className);
40 }
41
42 // eslint-disable-next-line no-unused-vars
43 function addClass(elem, className) {
44     if (!elem || !elem.classList) {
45         return;
46     }
47     elem.classList.add(className);
48 }
49
50 // eslint-disable-next-line no-unused-vars
51 function removeClass(elem, className) {
52     if (!elem || !elem.classList) {
53         return;
54     }
55     elem.classList.remove(className);
56 }
57
58 function onEach(arr, func, reversed) {
59     if (arr && arr.length > 0 && func) {
60         var length = arr.length;
61         var i;
62         if (reversed !== true) {
63             for (i = 0; i < length; ++i) {
64                 if (func(arr[i]) === true) {
65                     return true;
66                 }
67             }
68         } else {
69             for (i = length - 1; i >= 0; --i) {
70                 if (func(arr[i]) === true) {
71                     return true;
72                 }
73             }
74         }
75     }
76     return false;
77 }
78
79 function onEachLazy(lazyArray, func, reversed) {
80     return onEach(
81         Array.prototype.slice.call(lazyArray),
82         func,
83         reversed);
84 }
85
86 // eslint-disable-next-line no-unused-vars
87 function hasOwnProperty(obj, property) {
88     return Object.prototype.hasOwnProperty.call(obj, property);
89 }
90
91 function updateLocalStorage(name, value) {
92     try {
93         window.localStorage.setItem(name, value);
94     } catch(e) {
95         // localStorage is not accessible, do nothing
96     }
97 }
98
99 function getCurrentValue(name) {
100     try {
101         return window.localStorage.getItem(name);
102     } catch(e) {
103         return null;
104     }
105 }
106
107 function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) {
108     var fullBasicCss = "rustdoc" + resourcesSuffix + ".css";
109     var fullNewTheme = newTheme + resourcesSuffix + ".css";
110     var newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme);
111
112     // If this new value comes from a system setting or from the previously
113     // saved theme, no need to save it.
114     if (saveTheme === true) {
115         updateLocalStorage("rustdoc-theme", newTheme);
116     }
117
118     if (styleElem.href === newHref) {
119         return;
120     }
121
122     var found = false;
123     if (savedHref.length === 0) {
124         onEachLazy(document.getElementsByTagName("link"), function(el) {
125             savedHref.push(el.href);
126         });
127     }
128     onEach(savedHref, function(el) {
129         if (el === newHref) {
130             found = true;
131             return true;
132         }
133     });
134     if (found === true) {
135         styleElem.href = newHref;
136     }
137 }
138
139 // This function is called from "main.js".
140 // eslint-disable-next-line no-unused-vars
141 function useSystemTheme(value) {
142     if (value === undefined) {
143         value = true;
144     }
145
146     updateLocalStorage("rustdoc-use-system-theme", value);
147
148     // update the toggle if we're on the settings page
149     var toggle = document.getElementById("use-system-theme");
150     if (toggle && toggle instanceof HTMLInputElement) {
151         toggle.checked = value;
152     }
153 }
154
155 var updateSystemTheme = (function() {
156     if (!window.matchMedia) {
157         // fallback to the CSS computed value
158         return function() {
159             var cssTheme = getComputedStyle(document.documentElement)
160                 .getPropertyValue('content');
161
162             switchTheme(
163                 window.currentTheme,
164                 window.mainTheme,
165                 JSON.parse(cssTheme) || "light",
166                 true
167             );
168         };
169     }
170
171     // only listen to (prefers-color-scheme: dark) because light is the default
172     var mql = window.matchMedia("(prefers-color-scheme: dark)");
173
174     function handlePreferenceChange(mql) {
175         // maybe the user has disabled the setting in the meantime!
176         if (getSettingValue("use-system-theme") !== "false") {
177             var lightTheme = getSettingValue("preferred-light-theme") || "light";
178             var darkTheme = getSettingValue("preferred-dark-theme") || "dark";
179
180             if (mql.matches) {
181                 // prefers a dark theme
182                 switchTheme(window.currentTheme, window.mainTheme, darkTheme, true);
183             } else {
184                 // prefers a light theme, or has no preference
185                 switchTheme(window.currentTheme, window.mainTheme, lightTheme, true);
186             }
187
188             // note: we save the theme so that it doesn't suddenly change when
189             // the user disables "use-system-theme" and reloads the page or
190             // navigates to another page
191         }
192     }
193
194     mql.addListener(handlePreferenceChange);
195
196     return function() {
197         handlePreferenceChange(mql);
198     };
199 })();
200
201 if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) {
202     // update the preferred dark theme if the user is already using a dark theme
203     // See https://github.com/rust-lang/rust/pull/77809#issuecomment-707875732
204     if (getSettingValue("use-system-theme") === null
205         && getSettingValue("preferred-dark-theme") === null
206         && darkThemes.indexOf(localStoredTheme) >= 0) {
207         updateLocalStorage("rustdoc-preferred-dark-theme", localStoredTheme);
208     }
209
210     // call the function to initialize the theme at least once!
211     updateSystemTheme();
212 } else {
213     switchTheme(
214         window.currentTheme,
215         window.mainTheme,
216         getSettingValue("theme") || "light",
217         false
218     );
219 }