update template

This commit is contained in:
2024-08-25 21:35:42 +08:00
parent 6e7e207274
commit 8882726770
15 changed files with 464 additions and 130 deletions
File diff suppressed because one or more lines are too long
@@ -81,6 +81,7 @@ code span.st {
code span.cf {
color: #003B4F;
font-weight: bold;
font-style: inherit;
}
@@ -189,6 +190,7 @@ code span.dv {
code span.kw {
color: #003B4F;
font-weight: bold;
font-style: inherit;
}
+25 -6
View File
@@ -9,7 +9,7 @@ const layoutMarginEls = () => {
// Find any conflicting margin elements and add margins to the
// top to prevent overlap
const marginChildren = window.document.querySelectorAll(
".column-margin.column-container > * "
".column-margin.column-container > *, .margin-caption, .aside"
);
let lastBottom = 0;
@@ -19,7 +19,9 @@ const layoutMarginEls = () => {
marginChild.style.marginTop = null;
const top = marginChild.getBoundingClientRect().top + window.scrollY;
if (top < lastBottom) {
const margin = lastBottom - top;
const marginChildStyle = window.getComputedStyle(marginChild);
const marginBottom = parseFloat(marginChildStyle["marginBottom"]);
const margin = lastBottom - top + marginBottom;
marginChild.style.marginTop = `${margin}px`;
}
const styles = window.getComputedStyle(marginChild);
@@ -33,7 +35,15 @@ window.document.addEventListener("DOMContentLoaded", function (_event) {
// Recompute the position of margin elements anytime the body size changes
if (window.ResizeObserver) {
const resizeObserver = new window.ResizeObserver(
throttle(layoutMarginEls, 50)
throttle(() => {
layoutMarginEls();
if (
window.document.body.getBoundingClientRect().width < 990 &&
isReaderMode()
) {
quartoToggleReader();
}
}, 50)
);
resizeObserver.observe(window.document.body);
}
@@ -84,7 +94,7 @@ window.document.addEventListener("DOMContentLoaded", function (_event) {
if (link.href.indexOf("#") !== -1) {
const anchor = link.href.split("#")[1];
const heading = window.document.querySelector(
`[data-anchor-id=${anchor}]`
`[data-anchor-id="${anchor}"]`
);
if (heading) {
// Add the class
@@ -124,8 +134,10 @@ window.document.addEventListener("DOMContentLoaded", function (_event) {
window.innerHeight + window.pageYOffset >=
window.document.body.offsetHeight
) {
// This is the no-scroll case where last section should be the active one
sectionIndex = 0;
} else {
// This finds the last section visible on screen that should be made active
sectionIndex = [...sections].reverse().findIndex((section) => {
if (section) {
return window.pageYOffset >= section.offsetTop - sectionMargin;
@@ -307,6 +319,7 @@ window.document.addEventListener("DOMContentLoaded", function (_event) {
for (const child of el.children) {
child.style.opacity = 0;
child.style.overflow = "hidden";
child.style.pointerEvents = "none";
}
nexttick(() => {
@@ -348,6 +361,7 @@ window.document.addEventListener("DOMContentLoaded", function (_event) {
const clone = child.cloneNode(true);
clone.style.opacity = 1;
clone.style.pointerEvents = null;
clone.style.display = null;
toggleContents.append(clone);
}
@@ -422,6 +436,7 @@ window.document.addEventListener("DOMContentLoaded", function (_event) {
for (const child of el.children) {
child.style.opacity = 1;
child.style.overflow = null;
child.style.pointerEvents = null;
}
const placeholderEl = window.document.getElementById(
@@ -729,6 +744,7 @@ window.document.addEventListener("DOMContentLoaded", function (_event) {
// Process the collapse state if this is an UL
if (el.tagName === "UL") {
if (tocOpenDepth === -1 && depth > 1) {
// toc-expand: false
el.classList.add("collapse");
} else if (
depth <= tocOpenDepth ||
@@ -747,10 +763,9 @@ window.document.addEventListener("DOMContentLoaded", function (_event) {
};
// walk the TOC and expand / collapse any items that should be shown
if (tocEl) {
walk(tocEl, 0);
updateActiveLink();
walk(tocEl, 0);
}
// Throttle the scroll event and walk peridiocally
@@ -769,6 +784,10 @@ window.document.addEventListener("DOMContentLoaded", function (_event) {
window.addEventListener(
"resize",
throttle(() => {
if (tocEl) {
updateActiveLink();
walk(tocEl, 0);
}
if (!isReaderMode()) {
hideOverlappedSidebars();
}
+49 -1
View File
@@ -5,9 +5,45 @@ const headroomChanged = new CustomEvent("quarto-hrChanged", {
composed: false,
});
const announceDismiss = () => {
const annEl = window.document.getElementById("quarto-announcement");
if (annEl) {
annEl.remove();
const annId = annEl.getAttribute("data-announcement-id");
window.localStorage.setItem(`quarto-announce-${annId}`, "true");
}
};
const announceRegister = () => {
const annEl = window.document.getElementById("quarto-announcement");
if (annEl) {
const annId = annEl.getAttribute("data-announcement-id");
const isDismissed =
window.localStorage.getItem(`quarto-announce-${annId}`) || false;
if (isDismissed) {
announceDismiss();
return;
} else {
annEl.classList.remove("hidden");
}
const actionEl = annEl.querySelector(".quarto-announcement-action");
if (actionEl) {
actionEl.addEventListener("click", function (e) {
e.preventDefault();
// Hide the bar immediately
announceDismiss();
});
}
}
};
window.document.addEventListener("DOMContentLoaded", function () {
let init = false;
announceRegister();
// Manage the back to top button, if one is present.
let lastScrollTop = window.pageYOffset || document.documentElement.scrollTop;
const scrollDownBuffer = 5;
@@ -85,6 +121,17 @@ window.document.addEventListener("DOMContentLoaded", function () {
}
}
function dashboardOffset() {
const dashboardNavEl = window.document.getElementById(
"quarto-dashboard-header"
);
if (dashboardNavEl !== null) {
return dashboardNavEl.clientHeight;
} else {
return 0;
}
}
function updateDocumentOffsetWithoutAnimation() {
updateDocumentOffset(false);
}
@@ -92,7 +139,7 @@ window.document.addEventListener("DOMContentLoaded", function () {
function updateDocumentOffset(animated) {
// set body offset
const topOffset = headerOffset();
const bodyOffset = topOffset + footerOffset();
const bodyOffset = topOffset + footerOffset() + dashboardOffset();
const bodyEl = window.document.body;
bodyEl.setAttribute("data-bs-offset", topOffset);
bodyEl.style.paddingTop = topOffset + "px";
@@ -226,6 +273,7 @@ window.document.addEventListener("DOMContentLoaded", function () {
const links = window.document.querySelectorAll("a");
for (let i = 0; i < links.length; i++) {
if (links[i].href) {
links[i].dataset.originalHref = links[i].href;
links[i].href = links[i].href.replace(/\/index\.html/, "/");
}
}
+63 -14
View File
@@ -98,6 +98,7 @@ window.document.addEventListener("DOMContentLoaded", function (_event) {
classNames: {
form: "d-flex",
},
placeholder: language["search-text-placeholder"],
translations: {
clearButtonTitle: language["search-clear-button-title"],
detachedCancelButtonText: language["search-detached-cancel-button-title"],
@@ -392,7 +393,12 @@ window.document.addEventListener("DOMContentLoaded", function (_event) {
return focusedEl.tagName.toLowerCase() === tag;
});
if (kbds && kbds.includes(key) && !isFormElFocused) {
if (
kbds &&
kbds.includes(key) &&
!isFormElFocused &&
!document.activeElement.isContentEditable
) {
event.preventDefault();
window.quartoOpenSearch();
}
@@ -669,6 +675,18 @@ function showCopyLink(query, options) {
// create the index
var fuseIndex = undefined;
var shownWarning = false;
// fuse index options
const kFuseIndexOptions = {
keys: [
{ name: "title", weight: 20 },
{ name: "section", weight: 20 },
{ name: "text", weight: 10 },
],
ignoreLocation: true,
threshold: 0.1,
};
async function readSearchData() {
// Initialize the search index on demand
if (fuseIndex === undefined) {
@@ -679,17 +697,7 @@ async function readSearchData() {
shownWarning = true;
return;
}
// create fuse index
const options = {
keys: [
{ name: "title", weight: 20 },
{ name: "section", weight: 20 },
{ name: "text", weight: 10 },
],
ignoreLocation: true,
threshold: 0.1,
};
const fuse = new window.Fuse([], options);
const fuse = new window.Fuse([], kFuseIndexOptions);
// fetch the main search.json
const response = await fetch(offsetURL("search.json"));
@@ -1220,8 +1228,34 @@ function algoliaSearch(query, limit, algoliaOptions) {
});
}
function fuseSearch(query, fuse, fuseOptions) {
return fuse.search(query, fuseOptions).map((result) => {
let subSearchTerm = undefined;
let subSearchFuse = undefined;
const kFuseMaxWait = 125;
async function fuseSearch(query, fuse, fuseOptions) {
let index = fuse;
// Fuse.js using the Bitap algorithm for text matching which runs in
// O(nm) time (no matter the structure of the text). In our case this
// means that long search terms mixed with large index gets very slow
//
// This injects a subIndex that will be used once the terms get long enough
// Usually making this subindex is cheap since there will typically be
// a subset of results matching the existing query
if (subSearchFuse !== undefined && query.startsWith(subSearchTerm)) {
// Use the existing subSearchFuse
index = subSearchFuse;
} else if (subSearchFuse !== undefined) {
// The term changed, discard the existing fuse
subSearchFuse = undefined;
subSearchTerm = undefined;
}
// Search using the active fuse
const then = performance.now();
const resultsRaw = await index.search(query, fuseOptions);
const now = performance.now();
const results = resultsRaw.map((result) => {
const addParam = (url, name, value) => {
const anchorParts = url.split("#");
const baseUrl = anchorParts[0];
@@ -1238,4 +1272,19 @@ function fuseSearch(query, fuse, fuseOptions) {
crumbs: result.item.crumbs,
};
});
// If we don't have a subfuse and the query is long enough, go ahead
// and create a subfuse to use for subsequent queries
if (
now - then > kFuseMaxWait &&
subSearchFuse === undefined &&
resultsRaw.length < fuseOptions.limit
) {
subSearchTerm = query;
subSearchFuse = new window.Fuse([], kFuseIndexOptions);
resultsRaw.forEach((rr) => {
subSearchFuse.add(rr.item);
});
}
return results;
}