Skip to content

Commit

Permalink
Fix expand/collapse all on site, make highlightjs lazier (#14038)
Browse files Browse the repository at this point in the history
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 #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
  • Loading branch information
blyxyas authored Feb 1, 2025
2 parents 7e5cfbe + 33bb8af commit c607f78
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 46 deletions.
23 changes: 11 additions & 12 deletions util/gh-pages/index_template.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,29 @@
<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> {# #}
<option value="navy">Navy</option> {# #}
<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"> {# #}
Expand Down Expand Up @@ -133,10 +136,10 @@ <h1>Clippy Lints</h1> {# #}
</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> {# #}
Expand All @@ -145,13 +148,13 @@ <h1>Clippy Lints</h1> {# #}
{% 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> {# #}
Expand Down Expand Up @@ -227,9 +230,5 @@ <h2 class="panel-title"> {# #}
></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> {# #}
87 changes: 59 additions & 28 deletions util/gh-pages/script.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use strict";

window.searchState = {
timeout: null,
inputElem: document.getElementById("search-input"),
Expand Down Expand Up @@ -124,31 +126,16 @@ 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) {
func(el);
}
}

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) {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand All @@ -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.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;

document.addEventListener("keypress", handleShortcut);
document.addEventListener("keydown", handleShortcut);
addListeners();
highlightLazily();

generateSettings();
generateSearch();
Expand Down
8 changes: 2 additions & 6 deletions util/gh-pages/style.css
Original file line number Diff line number Diff line change
@@ -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);
Expand Down Expand Up @@ -188,8 +184,8 @@ details {
padding: .5em .5em 0;
}

code {
white-space: pre !important;
pre {
padding: 0;
}

summary {
Expand Down
9 changes: 9 additions & 0 deletions util/gh-pages/theme.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use strict";

function storeValue(settingName, value) {
try {
localStorage.setItem(`clippy-lint-list-${settingName}`, value);
Expand Down Expand Up @@ -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);
});
})();

0 comments on commit c607f78

Please sign in to comment.