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