1
Fork 0

Generate scraped examples buttons in JS

This commit is contained in:
Guillaume Gomez 2024-09-07 15:11:18 +02:00
parent 59d4114b2d
commit 1ca3e90db9
5 changed files with 44 additions and 38 deletions

View file

@ -2537,7 +2537,6 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &c
&cx.root_path(), &cx.root_path(),
highlight::DecorationInfo(decoration_info), highlight::DecorationInfo(decoration_info),
sources::SourceContext::Embedded(sources::ScrapedInfo { sources::SourceContext::Embedded(sources::ScrapedInfo {
needs_prev_next_buttons: line_ranges.len() > 1,
needs_expansion, needs_expansion,
offset: line_min, offset: line_min,
name: &call_data.display_name, name: &call_data.display_name,

View file

@ -292,7 +292,6 @@ where
pub(crate) struct ScrapedInfo<'a> { pub(crate) struct ScrapedInfo<'a> {
pub(crate) offset: usize, pub(crate) offset: usize,
pub(crate) needs_prev_next_buttons: bool,
pub(crate) name: &'a str, pub(crate) name: &'a str,
pub(crate) url: &'a str, pub(crate) url: &'a str,
pub(crate) title: &'a str, pub(crate) title: &'a str,

View file

@ -1855,12 +1855,8 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
// Since the button will be added, no need to keep this listener around. // Since the button will be added, no need to keep this listener around.
elem.removeEventListener("mouseover", addCopyButton); elem.removeEventListener("mouseover", addCopyButton);
// If this is a scrapped example, there will already be a "button-holder" element. const parent = document.createElement("div");
let parent = elem.querySelector(".button-holder"); parent.className = "button-holder";
if (!parent) {
parent = document.createElement("div");
parent.className = "button-holder";
}
const runButton = elem.querySelector(".test-arrow"); const runButton = elem.querySelector(".test-arrow");
if (runButton !== null) { if (runButton !== null) {
@ -1876,6 +1872,12 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
copyButtonAnimation(copyButton); copyButtonAnimation(copyButton);
}); });
parent.appendChild(copyButton); parent.appendChild(copyButton);
if (!elem.parentElement.classList.contains("scraped-example")) {
return;
}
const scrapedWrapped = elem.parentElement;
window.updateScrapedExample(scrapedWrapped, parent);
} }
function showHideCodeExampleButtons(event) { function showHideCodeExampleButtons(event) {

View file

@ -36,13 +36,30 @@
elt.querySelector(".rust").scrollTo(0, scrollOffset); elt.querySelector(".rust").scrollTo(0, scrollOffset);
} }
function updateScrapedExample(example, isHidden) { function createScrapeButton(parent, className, content) {
const locs = JSON.parse(example.attributes.getNamedItem("data-locs").textContent); const button = document.createElement("button");
button.className = className;
button.innerText = content;
parent.insertBefore(button, parent.firstChild);
return button;
}
window.updateScrapedExample = (example, buttonHolder) => {
let locIndex = 0; let locIndex = 0;
const highlights = Array.prototype.slice.call(example.querySelectorAll(".highlight")); const highlights = Array.prototype.slice.call(example.querySelectorAll(".highlight"));
const link = example.querySelector(".scraped-example-title a"); const link = example.querySelector(".scraped-example-title a");
let expandButton = null;
if (!example.classList.contains("expanded")) {
expandButton = createScrapeButton(buttonHolder, "expand", "↕");
}
const isHidden = example.parentElement.classList.contains("more-scraped-examples");
const locs = example.locs;
if (locs.length > 1) { if (locs.length > 1) {
const next = createScrapeButton(buttonHolder, "next", "≻");
const prev = createScrapeButton(buttonHolder, "prev", "≺");
// Toggle through list of examples in a given file // Toggle through list of examples in a given file
const onChangeLoc = changeIndex => { const onChangeLoc = changeIndex => {
removeClass(highlights[locIndex], "focus"); removeClass(highlights[locIndex], "focus");
@ -57,22 +74,19 @@
link.innerHTML = title; link.innerHTML = title;
}; };
example.querySelector(".prev") prev.addEventListener("click", () => {
.addEventListener("click", () => { onChangeLoc(() => {
onChangeLoc(() => { locIndex = (locIndex - 1 + locs.length) % locs.length;
locIndex = (locIndex - 1 + locs.length) % locs.length;
});
}); });
});
example.querySelector(".next") next.addEventListener("click", () => {
.addEventListener("click", () => { onChangeLoc(() => {
onChangeLoc(() => { locIndex = (locIndex + 1) % locs.length;
locIndex = (locIndex + 1) % locs.length;
});
}); });
});
} }
const expandButton = example.querySelector(".expand");
if (expandButton) { if (expandButton) {
expandButton.addEventListener("click", () => { expandButton.addEventListener("click", () => {
if (hasClass(example, "expanded")) { if (hasClass(example, "expanded")) {
@ -83,13 +97,16 @@
} }
}); });
} }
};
function setupLoc(example, isHidden) {
example.locs = JSON.parse(example.attributes.getNamedItem("data-locs").textContent);
// Start with the first example in view // Start with the first example in view
scrollToLoc(example, locs[0][0], isHidden); scrollToLoc(example, example.locs[0][0], isHidden);
} }
const firstExamples = document.querySelectorAll(".scraped-example-list > .scraped-example"); const firstExamples = document.querySelectorAll(".scraped-example-list > .scraped-example");
onEachLazy(firstExamples, el => updateScrapedExample(el, false)); onEachLazy(firstExamples, el => setupLoc(el, false));
onEachLazy(document.querySelectorAll(".more-examples-toggle"), toggle => { onEachLazy(document.querySelectorAll(".more-examples-toggle"), toggle => {
// Allow users to click the left border of the <details> section to close it, // Allow users to click the left border of the <details> section to close it,
// since the section can be large and finding the [+] button is annoying. // since the section can be large and finding the [+] button is annoying.
@ -102,11 +119,11 @@
const moreExamples = toggle.querySelectorAll(".scraped-example"); const moreExamples = toggle.querySelectorAll(".scraped-example");
toggle.querySelector("summary").addEventListener("click", () => { toggle.querySelector("summary").addEventListener("click", () => {
// Wrapping in setTimeout ensures the update happens after the elements are actually // Wrapping in setTimeout ensures the update happens after the elements are actually
// visible. This is necessary since updateScrapedExample calls scrollToLoc which // visible. This is necessary since setupLoc calls scrollToLoc which
// depends on offsetHeight, a property that requires an element to be visible to // depends on offsetHeight, a property that requires an element to be visible to
// compute correctly. // compute correctly.
setTimeout(() => { setTimeout(() => {
onEachLazy(moreExamples, el => updateScrapedExample(el, true)); onEachLazy(moreExamples, el => setupLoc(el, true));
}); });
}, {once: true}); }, {once: true});
}); });

View file

@ -1,8 +1,8 @@
<div class="scraped-example{% if !info.needs_expansion +%} expanded{% endif %}" data-locs="{{info.locations}}"> {# #} <div class="scraped-example{% if !info.needs_expansion +%} expanded{% endif %}" data-locs="{{info.locations}}"> {# #}
<div class="scraped-example-title"> <div class="scraped-example-title">
{{info.name +}} (<a href="{{info.url}}">{{info.title}}</a>) {# #} {{info.name +}} (<a href="{{info.url}}">{{info.title}}</a>) {# #}
</div> </div> {# #}
<div class="example-wrap"> {# #} <div class="example-wrap">
{# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr {# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr
Do not show "1 2 3 4 5 ..." in web search results. #} Do not show "1 2 3 4 5 ..." in web search results. #}
<div class="src-line-numbers" data-nosnippet> {# #} <div class="src-line-numbers" data-nosnippet> {# #}
@ -18,16 +18,5 @@
{{code_html|safe}} {{code_html|safe}}
</code> {# #} </code> {# #}
</pre> {# #} </pre> {# #}
{% if info.needs_prev_next_buttons || info.needs_expansion %}
<div class="button-holder">
{% if info.needs_prev_next_buttons %}
<button class="prev">&pr;</button> {# #}
<button class="next">&sc;</button>
{% endif %}
{% if info.needs_expansion %}
<button class="expand">&varr;</button>
{% endif %}
</div>
{% endif %}
</div> {# #} </div> {# #}
</div> {# #} </div> {# #}