Skip to content

Commit f04c935

Browse files
authored
Rollup merge of #139274 - lolbinarycat:rustdoc-js-less-expect-error-part5, r=notriddle
Rustdoc: typecheck settings.js This makes the file fully typechecked with no instances of ``````@ts-expect-error`````` and no type casts. r? `````@notriddle`````
2 parents ae745a0 + 4435c99 commit f04c935

File tree

3 files changed

+100
-46
lines changed

3 files changed

+100
-46
lines changed

src/librustdoc/html/static/js/main.js

+1-4
Original file line numberDiff line numberDiff line change
@@ -1101,7 +1101,6 @@ function preLoadCss(cssUrl) {
11011101
});
11021102
}());
11031103

1104-
// @ts-expect-error
11051104
window.rustdoc_add_line_numbers_to_examples = () => {
11061105
// @ts-expect-error
11071106
function generateLine(nb) {
@@ -1123,7 +1122,6 @@ function preLoadCss(cssUrl) {
11231122
});
11241123
};
11251124

1126-
// @ts-expect-error
11271125
window.rustdoc_remove_line_numbers_from_examples = () => {
11281126
onEachLazy(
11291127
document.querySelectorAll(".rustdoc:not(.src) :not(.scraped-example) > .example-wrap"),
@@ -1132,7 +1130,6 @@ function preLoadCss(cssUrl) {
11321130
};
11331131

11341132
if (getSettingValue("line-numbers") === "true") {
1135-
// @ts-expect-error
11361133
window.rustdoc_add_line_numbers_to_examples();
11371134
}
11381135

@@ -1596,7 +1593,7 @@ function preLoadCss(cssUrl) {
15961593
/**
15971594
* Hide popover menus, clickable tooltips, and the sidebar (if applicable).
15981595
*
1599-
* Pass "true" to reset focus for tooltip popovers.
1596+
* Pass `true` to reset focus for tooltip popovers.
16001597
*/
16011598
window.hideAllModals = switchFocus => {
16021599
hideSidebar();

src/librustdoc/html/static/js/rustdoc.d.ts

+14
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ declare global {
3030
currentCrate: string|null;
3131
/**
3232
* Hide popovers, tooltips, or the mobile sidebar.
33+
*
34+
* Pass `true` to reset focus for tooltip popovers.
3335
*/
3436
hideAllModals: function(boolean),
3537
/**
@@ -78,6 +80,8 @@ declare global {
7880
pending_implementors?: rustdoc.Implementors,
7981
register_type_impls?: function(rustdoc.TypeImpls): void,
8082
pending_type_impls?: rustdoc.TypeImpls,
83+
rustdoc_add_line_numbers_to_examples?: function(),
84+
rustdoc_remove_line_numbers_from_examples?: function(),
8185
}
8286
interface HTMLElement {
8387
/** Used by the popover tooltip code. */
@@ -477,4 +481,14 @@ declare namespace rustdoc {
477481
* is a tuple of (filename, subdirs, filenames).
478482
*/
479483
type Dir = [string, rustdoc.Dir[], string[]]
484+
485+
/**
486+
* Indivitual setting object, used in `settings.js`
487+
*/
488+
interface Setting {
489+
js_name: string,
490+
name: string,
491+
options?: string[],
492+
default: string | boolean,
493+
}
480494
}

src/librustdoc/html/static/js/settings.js

+85-42
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,39 @@
11
// Local js definitions:
22
/* global getSettingValue, updateLocalStorage, updateTheme */
33
/* global addClass, removeClass, onEach, onEachLazy */
4-
/* global MAIN_ID, getVar, getSettingsButton, getHelpButton */
5-
6-
// Eventually fix this.
7-
// @ts-nocheck
4+
/* global MAIN_ID, getVar, getSettingsButton, getHelpButton, nonnull */
85

96
"use strict";
107

118
(function() {
129
const isSettingsPage = window.location.pathname.endsWith("/settings.html");
1310

11+
/**
12+
* @param {Element} elem
13+
* @param {EventTarget|null} target
14+
*/
15+
function elemContainsTarget(elem, target) {
16+
if (target instanceof Node) {
17+
return elem.contains(target);
18+
} else {
19+
return false;
20+
}
21+
}
22+
23+
/**
24+
* @overload {"theme"|"preferred-dark-theme"|"preferred-light-theme"}
25+
* @param {string} settingName
26+
* @param {string} value
27+
* @returns
28+
* @param {string} settingName
29+
* @param {string|boolean} value
30+
*/
1431
function changeSetting(settingName, value) {
1532
if (settingName === "theme") {
1633
const useSystem = value === "system preference" ? "true" : "false";
1734
updateLocalStorage("use-system-theme", useSystem);
1835
}
19-
updateLocalStorage(settingName, value);
36+
updateLocalStorage(settingName, "" + value);
2037

2138
switch (settingName) {
2239
case "theme":
@@ -27,9 +44,15 @@
2744
break;
2845
case "line-numbers":
2946
if (value === true) {
30-
window.rustdoc_add_line_numbers_to_examples();
47+
const f = window.rustdoc_add_line_numbers_to_examples;
48+
if (f !== undefined) {
49+
f();
50+
}
3151
} else {
32-
window.rustdoc_remove_line_numbers_from_examples();
52+
const f = window.rustdoc_remove_line_numbers_from_examples;
53+
if (f !== undefined) {
54+
f();
55+
}
3356
}
3457
break;
3558
case "hide-sidebar":
@@ -89,6 +112,9 @@
89112
}
90113
}
91114

115+
/**
116+
* @param {HTMLElement} settingsElement
117+
*/
92118
function setEvents(settingsElement) {
93119
updateLightAndDark();
94120
onEachLazy(settingsElement.querySelectorAll("input[type=\"checkbox\"]"), toggle => {
@@ -101,43 +127,42 @@
101127
changeSetting(toggle.id, toggle.checked);
102128
};
103129
});
104-
onEachLazy(settingsElement.querySelectorAll("input[type=\"radio\"]"), elem => {
105-
const settingId = elem.name;
106-
let settingValue = getSettingValue(settingId);
107-
if (settingId === "theme") {
108-
const useSystem = getSettingValue("use-system-theme");
109-
if (useSystem === "true" || settingValue === null) {
110-
// "light" is the default theme
111-
settingValue = useSystem === "false" ? "light" : "system preference";
130+
onEachLazy(
131+
settingsElement.querySelectorAll("input[type=\"radio\"]"),
132+
/** @param {HTMLInputElement} elem */
133+
elem => {
134+
const settingId = elem.name;
135+
let settingValue = getSettingValue(settingId);
136+
if (settingId === "theme") {
137+
const useSystem = getSettingValue("use-system-theme");
138+
if (useSystem === "true" || settingValue === null) {
139+
// "light" is the default theme
140+
settingValue = useSystem === "false" ? "light" : "system preference";
141+
}
112142
}
113-
}
114-
if (settingValue !== null && settingValue !== "null") {
115-
elem.checked = settingValue === elem.value;
116-
}
117-
elem.addEventListener("change", ev => {
118-
changeSetting(ev.target.name, ev.target.value);
119-
});
120-
});
143+
if (settingValue !== null && settingValue !== "null") {
144+
elem.checked = settingValue === elem.value;
145+
}
146+
elem.addEventListener("change", () => {
147+
changeSetting(elem.name, elem.value);
148+
});
149+
},
150+
);
121151
}
122152

123153
/**
124154
* This function builds the sections inside the "settings page". It takes a `settings` list
125155
* as argument which describes each setting and how to render it. It returns a string
126156
* representing the raw HTML.
127157
*
128-
* @param {Array<Object>} settings
158+
* @param {Array<rustdoc.Setting>} settings
129159
*
130160
* @return {string}
131161
*/
132162
function buildSettingsPageSections(settings) {
133163
let output = "";
134164

135165
for (const setting of settings) {
136-
if (setting === "hr") {
137-
output += "<hr>";
138-
continue;
139-
}
140-
141166
const js_data_name = setting["js_name"];
142167
const setting_name = setting["name"];
143168

@@ -182,7 +207,9 @@
182207
* @return {HTMLElement}
183208
*/
184209
function buildSettingsPage() {
185-
const theme_names = getVar("themes").split(",").filter(t => t);
210+
const theme_list = getVar("themes");
211+
const theme_names = (theme_list === null ? "" : theme_list)
212+
.split(",").filter(t => t);
186213
theme_names.push("light", "dark", "ayu");
187214

188215
const settings = [
@@ -272,10 +299,16 @@
272299
el.innerHTML = innerHTML;
273300

274301
if (isSettingsPage) {
275-
document.getElementById(MAIN_ID).appendChild(el);
302+
const mainElem = document.getElementById(MAIN_ID);
303+
if (mainElem !== null) {
304+
mainElem.appendChild(el);
305+
}
276306
} else {
277307
el.setAttribute("tabindex", "-1");
278-
getSettingsButton().appendChild(el);
308+
const settingsBtn = getSettingsButton();
309+
if (settingsBtn !== null) {
310+
settingsBtn.appendChild(el);
311+
}
279312
}
280313
return el;
281314
}
@@ -293,34 +326,44 @@
293326
});
294327
}
295328

329+
/**
330+
* @param {FocusEvent} event
331+
*/
296332
function settingsBlurHandler(event) {
297-
if (!getHelpButton().contains(document.activeElement) &&
298-
!getHelpButton().contains(event.relatedTarget) &&
299-
!getSettingsButton().contains(document.activeElement) &&
300-
!getSettingsButton().contains(event.relatedTarget)
301-
) {
333+
const helpBtn = getHelpButton();
334+
const settingsBtn = getSettingsButton();
335+
const helpUnfocused = helpBtn === null ||
336+
(!helpBtn.contains(document.activeElement) &&
337+
!elemContainsTarget(helpBtn, event.relatedTarget));
338+
const settingsUnfocused = settingsBtn === null ||
339+
(!settingsBtn.contains(document.activeElement) &&
340+
!elemContainsTarget(settingsBtn, event.relatedTarget));
341+
if (helpUnfocused && settingsUnfocused) {
302342
window.hidePopoverMenus();
303343
}
304344
}
305345

306346
if (!isSettingsPage) {
307347
// We replace the existing "onclick" callback.
308-
const settingsButton = getSettingsButton();
309-
const settingsMenu = document.getElementById("settings");
348+
// These elements must exist, as (outside of the settings page)
349+
// `settings.js` is only loaded after the settings button is clicked.
350+
const settingsButton = nonnull(getSettingsButton());
351+
const settingsMenu = nonnull(document.getElementById("settings"));
310352
settingsButton.onclick = event => {
311-
if (settingsMenu.contains(event.target)) {
353+
if (elemContainsTarget(settingsMenu, event.target)) {
312354
return;
313355
}
314356
event.preventDefault();
315357
const shouldDisplaySettings = settingsMenu.style.display === "none";
316358

317-
window.hideAllModals();
359+
window.hideAllModals(false);
318360
if (shouldDisplaySettings) {
319361
displaySettings();
320362
}
321363
};
322364
settingsButton.onblur = settingsBlurHandler;
323-
settingsButton.querySelector("a").onblur = settingsBlurHandler;
365+
// the settings button should always have a link in it
366+
nonnull(settingsButton.querySelector("a")).onblur = settingsBlurHandler;
324367
onEachLazy(settingsMenu.querySelectorAll("input"), el => {
325368
el.onblur = settingsBlurHandler;
326369
});

0 commit comments

Comments
 (0)