build based on 57c8db5

This commit is contained in:
Documenter.jl
2025-08-27 09:46:20 +00:00
parent 4be9a0d169
commit 2c03eb8f46
59 changed files with 395 additions and 287 deletions

View File

@@ -104,7 +104,7 @@ $(document).on(
.prop("title", articleToggleTitle);
parent.siblings("section").slideToggle();
});
}
},
);
$(document).on("click", ".docs-article-toggle-button", function (event) {
@@ -239,6 +239,20 @@ $(document).ready(function () {
type: "click",
noToggleAnimation: true,
});
setTimeout(function () {
if (window.location.hash) {
const targetId = window.location.hash.substring(1);
const targetElement = document.getElementById(targetId);
if (targetElement) {
targetElement.scrollIntoView({
behavior: "smooth",
block: "center",
});
}
}
}, 100);
}
});
@@ -312,7 +326,7 @@ update_search
function worker_function(documenterSearchIndex, documenterBaseURL, filters) {
importScripts(
"https://cdn.jsdelivr.net/npm/minisearch@6.1.0/dist/umd/index.min.js"
"https://cdn.jsdelivr.net/npm/minisearch@6.1.0/dist/umd/index.min.js",
);
let data = documenterSearchIndex.map((x, key) => {
@@ -523,8 +537,8 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) {
Math.max(textindex.index - 100, 0),
Math.min(
textindex.index + querystring.length + 100,
result.text.length
)
result.text.length,
),
)
: ""; // cut-off text before and after from the match
@@ -534,7 +548,7 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) {
? "..." +
text.replace(
new RegExp(`${escape(searchstring)}`, "i"), // For first occurrence
'<span class="search-result-highlight py-1">$&</span>'
'<span class="search-result-highlight py-1">$&</span>',
) +
"..."
: ""; // highlights the match
@@ -547,7 +561,7 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) {
// We encode the full url to escape some special characters which can lead to broken links
let result_div = `
<a href="${encodeURI(
documenterBaseURL + "/" + result.location
documenterBaseURL + "/" + result.location,
)}" class="search-result-link w-100 is-flex is-flex-direction-column gap-2 px-4 py-2">
<div class="w-100 is-flex is-flex-wrap-wrap is-justify-content-space-between is-align-items-flex-start">
<div class="search-result-title has-text-weight-bold ${
@@ -612,176 +626,256 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) {
};
}
// `worker = Threads.@spawn worker_function(documenterSearchIndex)`, but in JavaScript!
const filters = [
...new Set(documenterSearchIndex["docs"].map((x) => x.category)),
];
const worker_str =
"(" +
worker_function.toString() +
")(" +
JSON.stringify(documenterSearchIndex["docs"]) +
"," +
JSON.stringify(documenterBaseURL) +
"," +
JSON.stringify(filters) +
")";
const worker_blob = new Blob([worker_str], { type: "text/javascript" });
const worker = new Worker(URL.createObjectURL(worker_blob));
/////// SEARCH MAIN ///////
// Whether the worker is currently handling a search. This is a boolean
// as the worker only ever handles 1 or 0 searches at a time.
var worker_is_running = false;
function runSearchMainCode() {
// `worker = Threads.@spawn worker_function(documenterSearchIndex)`, but in JavaScript!
const filters = [
...new Set(documenterSearchIndex["docs"].map((x) => x.category)),
];
const worker_str =
"(" +
worker_function.toString() +
")(" +
JSON.stringify(documenterSearchIndex["docs"]) +
"," +
JSON.stringify(documenterBaseURL) +
"," +
JSON.stringify(filters) +
")";
const worker_blob = new Blob([worker_str], { type: "text/javascript" });
const worker = new Worker(URL.createObjectURL(worker_blob));
// The last search text that was sent to the worker. This is used to determine
// if the worker should be launched again when it reports back results.
var last_search_text = "";
// Whether the worker is currently handling a search. This is a boolean
// as the worker only ever handles 1 or 0 searches at a time.
var worker_is_running = false;
// The results of the last search. This, in combination with the state of the filters
// in the DOM, is used compute the results to display on calls to update_search.
var unfiltered_results = [];
// The last search text that was sent to the worker. This is used to determine
// if the worker should be launched again when it reports back results.
var last_search_text = "";
// Which filter is currently selected
var selected_filter = "";
// The results of the last search. This, in combination with the state of the filters
// in the DOM, is used compute the results to display on calls to update_search.
var unfiltered_results = [];
$(document).on("input", ".documenter-search-input", function (event) {
if (!worker_is_running) {
launch_search();
}
});
// Which filter is currently selected
var selected_filter = "";
function launch_search() {
worker_is_running = true;
last_search_text = $(".documenter-search-input").val();
worker.postMessage(last_search_text);
}
worker.onmessage = function (e) {
if (last_search_text !== $(".documenter-search-input").val()) {
launch_search();
} else {
worker_is_running = false;
}
unfiltered_results = e.data;
update_search();
};
$(document).on("click", ".search-filter", function () {
if ($(this).hasClass("search-filter-selected")) {
document.addEventListener("reset-filter", function () {
selected_filter = "";
} else {
selected_filter = $(this).text().toLowerCase();
}
update_search();
});
// This updates search results and toggles classes for UI:
update_search();
});
//update the url with search query
function updateSearchURL(query) {
const url = new URL(window.location);
/**
* Make/Update the search component
*/
function update_search() {
let querystring = $(".documenter-search-input").val();
if (querystring.trim()) {
if (selected_filter == "") {
results = unfiltered_results;
if (query && query.trim() !== "") {
url.searchParams.set("q", query);
} else {
results = unfiltered_results.filter((result) => {
return selected_filter == result.category.toLowerCase();
});
// remove the 'q' param if it exists
if (url.searchParams.has("q")) {
url.searchParams.delete("q");
}
}
let search_result_container = ``;
let modal_filters = make_modal_body_filters();
let search_divider = `<div class="search-divider w-100"></div>`;
if (results.length) {
let links = [];
let count = 0;
let search_results = "";
for (var i = 0, n = results.length; i < n && count < 200; ++i) {
let result = results[i];
if (result.location && !links.includes(result.location)) {
search_results += result.div;
count++;
links.push(result.location);
}
// Add or remove the filter parameter based on selected_filter
if (selected_filter && selected_filter.trim() !== "") {
url.searchParams.set("filter", selected_filter);
} else {
// remove the 'filter' param if it exists
if (url.searchParams.has("filter")) {
url.searchParams.delete("filter");
}
}
if (count == 1) {
count_str = "1 result";
} else if (count == 200) {
count_str = "200+ results";
// Only update history if there are parameters, otherwise use the base URL
if (url.search) {
window.history.replaceState({}, "", url);
} else {
window.history.replaceState({}, "", url.pathname + url.hash);
}
}
$(document).on("input", ".documenter-search-input", function (event) {
if (!worker_is_running) {
launch_search();
}
});
function launch_search() {
worker_is_running = true;
last_search_text = $(".documenter-search-input").val();
updateSearchURL(last_search_text);
worker.postMessage(last_search_text);
}
worker.onmessage = function (e) {
if (last_search_text !== $(".documenter-search-input").val()) {
launch_search();
} else {
worker_is_running = false;
}
unfiltered_results = e.data;
update_search();
};
$(document).on("click", ".search-filter", function () {
let search_input = $(".documenter-search-input");
let cursor_position = search_input[0].selectionStart;
if ($(this).hasClass("search-filter-selected")) {
selected_filter = "";
} else {
selected_filter = $(this).text().toLowerCase();
}
// This updates search results and toggles classes for UI:
update_search();
search_input.focus();
search_input.setSelectionRange(cursor_position, cursor_position);
});
/**
* Make/Update the search component
*/
function update_search() {
let querystring = $(".documenter-search-input").val();
updateSearchURL(querystring);
if (querystring.trim()) {
if (selected_filter == "") {
results = unfiltered_results;
} else {
count_str = count + " results";
results = unfiltered_results.filter((result) => {
return selected_filter == result.category.toLowerCase();
});
}
let result_count = `<div class="is-size-6">${count_str}</div>`;
search_result_container = `
let search_result_container = ``;
let modal_filters = make_modal_body_filters();
let search_divider = `<div class="search-divider w-100"></div>`;
if (results.length) {
let links = [];
let count = 0;
let search_results = "";
for (var i = 0, n = results.length; i < n && count < 200; ++i) {
let result = results[i];
if (result.location && !links.includes(result.location)) {
search_results += result.div;
count++;
links.push(result.location);
}
}
if (count == 1) {
count_str = "1 result";
} else if (count == 200) {
count_str = "200+ results";
} else {
count_str = count + " results";
}
let result_count = `<div class="is-size-6">${count_str}</div>`;
search_result_container = `
<div class="is-flex is-flex-direction-column gap-2 is-align-items-flex-start">
${modal_filters}
${search_divider}
${result_count}
<div class="is-clipped w-100 is-flex is-flex-direction-column gap-2 is-align-items-flex-start has-text-justified mt-1">
${search_results}
</div>
</div>
`;
} else {
search_result_container = `
<div class="is-flex is-flex-direction-column gap-2 is-align-items-flex-start">
${modal_filters}
${search_divider}
${result_count}
<div class="is-clipped w-100 is-flex is-flex-direction-column gap-2 is-align-items-flex-start has-text-justified mt-1">
${search_results}
</div>
</div>
<div class="is-size-6">0 result(s)</div>
</div>
<div class="has-text-centered my-5 py-5">No result found!</div>
`;
}
if ($(".search-modal-card-body").hasClass("is-justify-content-center")) {
$(".search-modal-card-body").removeClass("is-justify-content-center");
}
$(".search-modal-card-body").html(search_result_container);
} else {
search_result_container = `
<div class="is-flex is-flex-direction-column gap-2 is-align-items-flex-start">
${modal_filters}
${search_divider}
<div class="is-size-6">0 result(s)</div>
</div>
<div class="has-text-centered my-5 py-5">No result found!</div>
`;
if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) {
$(".search-modal-card-body").addClass("is-justify-content-center");
}
$(".search-modal-card-body").html(`
<div class="has-text-centered my-5 py-5">Type something to get started!</div>
`);
}
}
//url param checking
function checkURLForSearch() {
const urlParams = new URLSearchParams(window.location.search);
const searchQuery = urlParams.get("q");
const filterParam = urlParams.get("filter");
// Set the selected filter if present in URL
if (filterParam) {
selected_filter = filterParam.toLowerCase();
}
if ($(".search-modal-card-body").hasClass("is-justify-content-center")) {
$(".search-modal-card-body").removeClass("is-justify-content-center");
// Trigger input event if there's a search query to perform the search
if (searchQuery) {
$(".documenter-search-input").val(searchQuery).trigger("input");
}
}
setTimeout(checkURLForSearch, 100);
$(".search-modal-card-body").html(search_result_container);
} else {
if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) {
$(".search-modal-card-body").addClass("is-justify-content-center");
}
/**
* Make the modal filter html
*
* @returns string
*/
function make_modal_body_filters() {
let str = filters
.map((val) => {
if (selected_filter == val.toLowerCase()) {
return `<a href="javascript:;" class="search-filter search-filter-selected"><span>${val}</span></a>`;
} else {
return `<a href="javascript:;" class="search-filter"><span>${val}</span></a>`;
}
})
.join("");
$(".search-modal-card-body").html(`
<div class="has-text-centered my-5 py-5">Type something to get started!</div>
`);
return `
<div class="is-flex gap-2 is-flex-wrap-wrap is-justify-content-flex-start is-align-items-center search-filters">
<span class="is-size-6">Filters:</span>
${str}
</div>`;
}
}
/**
* Make the modal filter html
*
* @returns string
*/
function make_modal_body_filters() {
let str = filters
.map((val) => {
if (selected_filter == val.toLowerCase()) {
return `<a href="javascript:;" class="search-filter search-filter-selected"><span>${val}</span></a>`;
} else {
return `<a href="javascript:;" class="search-filter"><span>${val}</span></a>`;
}
})
.join("");
return `
<div class="is-flex gap-2 is-flex-wrap-wrap is-justify-content-flex-start is-align-items-center search-filters">
<span class="is-size-6">Filters:</span>
${str}
</div>`;
function waitUntilSearchIndexAvailable() {
// It is possible that the documenter.js script runs before the page
// has finished loading and documenterSearchIndex gets defined.
// So we need to wait until the search index actually loads before setting
// up all the search-related stuff.
if (typeof documenterSearchIndex !== "undefined") {
runSearchMainCode();
} else {
console.warn("Search Index not available, waiting");
setTimeout(waitUntilSearchIndexAvailable, 1000);
}
}
// The actual entry point to the search code
waitUntilSearchIndexAvailable();
})
////////////////////////////////////////////////////////////////////////////////
require(['jquery'], function($) {
@@ -812,8 +906,9 @@ $(document).ready(function () {
<div class="field mb-0 w-100">
<p class="control has-icons-right">
<input class="input documenter-search-input" type="text" placeholder="Search" />
<span class="icon is-small is-right has-text-primary-dark">
<i class="fas fa-magnifying-glass"></i>
<span class="icon is-small is-right has-text-primary-dark gap-2">
<i class="fas fa-link link-icon is-clickable"></i>
<i class="fas fa-magnifying-glass mr-4"></i>
</span>
</p>
</div>
@@ -849,9 +944,22 @@ $(document).ready(function () {
${search_modal_footer}
</div>
</div>
`
`,
);
function checkURLForSearch() {
const urlParams = new URLSearchParams(window.location.search);
const searchQuery = urlParams.get("q");
if (searchQuery) {
//only if there is a search query, open the modal
openModal();
}
}
//this function will be called whenever the page will load
checkURLForSearch();
document.querySelector(".docs-search-query").addEventListener("click", () => {
openModal();
});
@@ -876,6 +984,25 @@ $(document).ready(function () {
return false;
});
//event listener for the link icon to copy the URL
$(document).on("click", ".link-icon", function () {
const currentUrl = window.location.href;
navigator.clipboard
.writeText(currentUrl)
.then(() => {
const $linkIcon = $(this);
$linkIcon.removeClass("fa-link").addClass("fa-check");
setTimeout(() => {
$linkIcon.removeClass("fa-check").addClass("fa-link");
}, 1000);
})
.catch((err) => {
console.error("Failed to copy URL: ", err);
});
});
// Functions to open and close a modal
function openModal() {
let searchModal = document.querySelector("#search-modal");
@@ -890,15 +1017,17 @@ $(document).ready(function () {
<div class="has-text-centered my-5 py-5">Type something to get started!</div>
`;
$(".documenter-search-input").val("");
$(".search-modal-card-body").html(initial_search_body);
document.dispatchEvent(new CustomEvent("reset-filter"));
searchModal.classList.remove("is-active");
document.querySelector(".documenter-search-input").blur();
if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) {
$(".search-modal-card-body").addClass("is-justify-content-center");
}
$(".documenter-search-input").val("");
$(".search-modal-card-body").html(initial_search_body);
}
document
@@ -1027,7 +1156,7 @@ $(document).ready(function () {
var option = $(
"<option value='#' selected='selected'>" +
DOCUMENTER_CURRENT_VERSION +
"</option>"
"</option>",
);
version_selector_select.append(option);
}
@@ -1044,7 +1173,7 @@ $(document).ready(function () {
// otherwise update the old option with the URL and enable it
if (existing_id == -1) {
var option = $(
"<option value='" + version_url + "'>" + each + "</option>"
"<option value='" + version_url + "'>" + each + "</option>",
);
version_selector_select.append(option);
} else {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,7 @@
function maybeAddWarning() {
// DOCUMENTER_NEWEST is defined in versions.js, DOCUMENTER_CURRENT_VERSION and DOCUMENTER_STABLE
// in siteinfo.js.
// If either of these are undefined something went horribly wrong, so we abort.
// in siteinfo.js. DOCUMENTER_IS_DEV_VERSION is optional and defined in siteinfo.js.
// If the required variables are undefined something went horribly wrong, so we abort.
if (
window.DOCUMENTER_NEWEST === undefined ||
window.DOCUMENTER_CURRENT_VERSION === undefined ||
@@ -30,17 +30,33 @@ function maybeAddWarning() {
}
const div = document.createElement("div");
div.classList.add("outdated-warning-overlay");
// Base class is added by default
div.classList.add("warning-overlay-base");
const closer = document.createElement("button");
closer.classList.add("outdated-warning-closer", "delete");
closer.addEventListener("click", function () {
document.body.removeChild(div);
});
const href = window.documenterBaseURL + "/../" + window.DOCUMENTER_STABLE;
div.innerHTML =
'This documentation is not for the latest stable release, but for either the development version or an older release.<br><a href="' +
// Determine if this is a development version or an older release
let warningMessage = "";
if (window.DOCUMENTER_IS_DEV_VERSION === true) {
div.classList.add("dev-warning-overlay");
warningMessage =
"This documentation is for the <strong>development version</strong> and may contain unstable or unreleased features.<br>";
} else {
div.classList.add("outdated-warning-overlay");
warningMessage =
"This documentation is for an <strong>older version</strong> that may be missing recent changes.<br>";
}
warningMessage +=
'<a href="' +
href +
'">Click here to go to the documentation for the latest stable release.</a>';
div.innerHTML = warningMessage;
div.appendChild(closer);
document.body.appendChild(div);
}