]> git.proxmox.com Git - rustc.git/blob - src/librustdoc/html/static/storage.js
New upstream version 1.54.0+dfsg1
[rustc.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) {
63 for (i = length - 1; i >= 0; --i) {
64 if (func(arr[i])) {
65 return true;
66 }
67 }
68 } else {
69 for (i = 0; i < length; ++i) {
70 if (func(arr[i])) {
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 hasOwnPropertyRustdoc(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) {
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) {
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 }