Fix expand/collapse all on site, make highlightjs lazier (#14038)

This fixes the buttons that expand/collapse all the lints in the list,
it also makes code block syntax highlighting only happen when the
specific lint enters the viewport since highlighting them all at once
was fairly heavy

There's also a few miscellaneous inline event handler removals

`script.js` and highlightjs are now loaded with `defer` so that the
download can start earlier

Also fixes https://github.com/rust-lang/rust-clippy/issues/14048, we
were calling highlight on the `pre` in `<pre><code>...</code></pre>` but
highlightjs wants us to call it on the `code` element

changelog: none
This commit is contained in:
Alejandra González 2025-02-01 19:02:22 +00:00 committed by GitHub
commit c607f78f34
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 81 additions and 46 deletions

View file

@ -24,14 +24,16 @@ Otherwise, have a great day =^.^=
<link id="styleNight" rel="stylesheet" href="https://rust-lang.github.io/mdBook/tomorrow-night.css" disabled="true"> {# #}
<link id="styleAyu" rel="stylesheet" href="https://rust-lang.github.io/mdBook/ayu-highlight.css" disabled="true"> {# #}
<link rel="stylesheet" href="style.css"> {# #}
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js" defer></script> {# #}
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/languages/rust.min.js" defer></script> {# #}
<script src="script.js" defer></script> {# #}
</head> {# #}
<body> {# #}
<script src="theme.js"></script> {# #}
<div id="settings-dropdown"> {# #}
<button class="settings-icon" tabindex="-1"></button> {# #}
<div class="settings-menu" tabindex="-1"> {# #}
<div class="setting-radio-name">Theme</div> {# #}
<select id="theme-choice" onchange="setTheme(this.value, true)"> {# #}
<select id="theme-choice"> {# #}
<option value="ayu">Ayu</option> {# #}
<option value="coal">Coal</option> {# #}
<option value="light">Light</option> {# #}
@ -39,11 +41,12 @@ Otherwise, have a great day =^.^=
<option value="rust">Rust</option> {# #}
</select> {# #}
<label> {# #}
<input type="checkbox" id="disable-shortcuts" onchange="changeSetting(this)"> {#+ #}
<input type="checkbox" id="disable-shortcuts"> {#+ #}
<span>Disable keyboard shortcuts</span> {# #}
</label> {# #}
</div> {# #}
</div> {# #}
<script src="theme.js"></script> {# #}
<div class="container"> {# #}
<div class="page-header"> {# #}
@ -133,10 +136,10 @@ Otherwise, have a great day =^.^=
</div> {# #}
</div> {# #}
<div class="col-12 col-md-2 btn-group expansion-group"> {# #}
<button title="Collapse All" class="btn btn-default expansion-control" type="button" onclick="toggleExpansion(false)"> {# #}
<button title="Collapse All" class="btn btn-default expansion-control" type="button" id="collapse-all"> {# #}
<span class="glyphicon glyphicon-collapse-up"></span> {# #}
</button> {# #}
<button title="Expand All" class="btn btn-default expansion-control" type="button" onclick="toggleExpansion(true)"> {# #}
<button title="Expand All" class="btn btn-default expansion-control" type="button" id="expand-all"> {# #}
<span class="glyphicon glyphicon-collapse-down"></span> {# #}
</button> {# #}
</div> {# #}
@ -145,13 +148,13 @@ Otherwise, have a great day =^.^=
{% for lint in lints %}
<article class="panel panel-default" id="{{lint.id}}"> {# #}
<input id="label-{{lint.id}}" type="checkbox"> {# #}
<label for="label-{{lint.id}}" onclick="highlightIfNeeded('{{lint.id}}')"> {# #}
<label for="label-{{lint.id}}"> {# #}
<header class="panel-heading"> {# #}
<h2 class="panel-title"> {# #}
<div class="panel-title-name" id="lint-{{lint.id}}"> {# #}
<span>{{lint.id}}</span> {#+ #}
<a href="#{{lint.id}}" onclick="lintAnchor(event)" class="anchor label label-default">&para;</a> {#+ #}
<a href="" class="anchor label label-default" onclick="copyToClipboard(event)"> {# #}
<a href="#{{lint.id}}" class="lint-anchor anchor label label-default">&para;</a> {#+ #}
<a href="" class="copy-to-clipboard anchor label label-default"> {# #}
&#128203; {# #}
</a> {# #}
</div> {# #}
@ -227,9 +230,5 @@ Otherwise, have a great day =^.^=
></path> {# #}
</svg> {# #}
</a> {# #}
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js"></script> {# #}
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/languages/rust.min.js"></script> {# #}
<script src="script.js"></script> {# #}
</body> {# #}
</html> {# #}

View file

@ -1,3 +1,5 @@
"use strict";
window.searchState = {
timeout: null,
inputElem: document.getElementById("search-input"),
@ -124,13 +126,6 @@ function toggleElements(filter, value) {
}
}
function changeSetting(elem) {
if (elem.id === "disable-shortcuts") {
disableShortcuts = elem.checked;
storeValue(elem.id, elem.checked);
}
}
function onEachLazy(lazyArray, func) {
const arr = Array.prototype.slice.call(lazyArray);
for (const el of arr) {
@ -138,17 +133,9 @@ function onEachLazy(lazyArray, func) {
}
}
function highlightIfNeeded(lintId) {
onEachLazy(document.querySelectorAll(`#${lintId} pre > code:not(.hljs)`), el => {
hljs.highlightElement(el.parentElement)
el.classList.add("highlighted");
});
}
function expandLint(lintId) {
const elem = document.querySelector(`#${lintId} > input[type="checkbox"]`);
elem.checked = true;
highlightIfNeeded(lintId);
}
function lintAnchor(event) {
@ -194,13 +181,9 @@ function handleBlur(event, elementId) {
}
function toggleExpansion(expand) {
onEachLazy(
document.querySelectorAll("article"),
expand ? el => {
el.classList.remove("collapsed");
highlightIfNeeded(el);
} : el => el.classList.add("collapsed"),
);
for (const checkbox of document.querySelectorAll("article input[type=checkbox]")) {
checkbox.checked = expand;
}
}
// Returns the current URL without any query parameter or hash.
@ -535,7 +518,7 @@ function parseURLFilters() {
for (const [corres_key, corres_value] of Object.entries(URL_PARAMS_CORRESPONDENCE)) {
if (corres_value === key) {
if (key !== "versions") {
const settings = new Set(value.split(","));
const settings = new Set(value.split(","));
onEachLazy(document.querySelectorAll(`#lint-${key} ul input`), elem => {
elem.checked = settings.has(elem.getAttribute("data-value"));
updateFilter(elem, corres_key, true);
@ -555,12 +538,60 @@ function parseURLFilters() {
}
}
document.getElementById(`theme-choice`).value = loadValue("theme");
let disableShortcuts = loadValue('disable-shortcuts') === "true";
document.getElementById("disable-shortcuts").checked = disableShortcuts;
function addListeners() {
disableShortcutsButton.addEventListener("change", () => {
disableShortcuts = disableShortcutsButton.checked;
storeValue("disable-shortcuts", disableShortcuts);
});
document.addEventListener("keypress", handleShortcut);
document.addEventListener("keydown", handleShortcut);
document.getElementById("expand-all").addEventListener("click", () => toggleExpansion(true));
document.getElementById("collapse-all").addEventListener("click", () => toggleExpansion(false));
// A delegated listener to avoid the upfront cost of >1000 listeners
document.addEventListener("click", event => {
if (!event.target instanceof HTMLAnchorElement) {
return;
}
if (event.target.classList.contains("lint-anchor")) {
lintAnchor(event);
} else if (event.target.classList.contains("copy-to-clipboard")) {
copyToClipboard(event);
}
});
document.addEventListener("keypress", handleShortcut);
document.addEventListener("keydown", handleShortcut);
}
// Highlight code blocks only when they approach the viewport so that clicking the "Expand All"
// button doesn't take a long time
function highlightLazily() {
if (!'IntersectionObserver' in window) {
return;
}
const observer = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
observer.unobserve(entry.target);
for (const code of entry.target.querySelectorAll("pre code")) {
hljs.highlightElement(code);
}
}
}
});
for (const docs of document.querySelectorAll(".lint-docs")) {
observer.observe(docs);
}
}
let disableShortcuts = loadValue("disable-shortcuts") === "true";
const disableShortcutsButton = document.getElementById("disable-shortcuts");
disableShortcutsButton.checked = disableShortcuts;
addListeners();
highlightLazily();
generateSettings();
generateSearch();

View file

@ -1,9 +1,5 @@
blockquote { font-size: 1em; }
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
}
.dropdown-menu {
color: var(--fg);
background: var(--theme-popup-bg);
@ -188,8 +184,8 @@ details {
padding: .5em .5em 0;
}
code {
white-space: pre !important;
pre {
padding: 0;
}
summary {

View file

@ -1,3 +1,5 @@
"use strict";
function storeValue(settingName, value) {
try {
localStorage.setItem(`clippy-lint-list-${settingName}`, value);
@ -57,4 +59,11 @@ function setTheme(theme, store) {
} else {
setTheme(theme, false);
}
const themeChoice = document.getElementById("theme-choice");
themeChoice.value = loadValue("theme");
document.getElementById("theme-choice").addEventListener("change", (e) => {
setTheme(themeChoice.value, true);
});
})();