From ab1869569f042f188c95117df8a703b49cd9964f Mon Sep 17 00:00:00 2001 From: Maksym Stoianov Date: Wed, 23 Sep 2026 22:11:56 +0200 Subject: [PATCH 1/2] fix(docs): mount the header controls reliably, and put the notice in the article MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neither landed on the published site, and the live page said why. The header can finish rendering between the check for it and the observer armed when the check fails, and then no mutation ever follows to react to — so the controls stayed at the bottom of the viewport. The observer is still there for the common case, but a poll every 150ms now closes that gap, with one deadline to stop both. The notice was inserted before , where the application's own layout places it at the top of the page rather than after the text. It goes inside the article now, as its last paragraph, and falls back to the end of the body only where a page has no article. Refs #539 --- docs/writerside-de/search.html | 40 +++++++++++++++++++++------- docs/writerside-fr/search.html | 40 +++++++++++++++++++++------- docs/writerside-ru/search.html | 40 +++++++++++++++++++++------- docs/writerside-uk/search.html | 40 +++++++++++++++++++++------- docs/writerside/search.html | 40 +++++++++++++++++++++------- scripts/docs/assets/search-widget.js | 40 +++++++++++++++++++++------- scripts/docs/finalize-site.mjs | 14 ++++++---- 7 files changed, 195 insertions(+), 59 deletions(-) diff --git a/docs/writerside-de/search.html b/docs/writerside-de/search.html index 3cf9da14..52d0cc0d 100644 --- a/docs/writerside-de/search.html +++ b/docs/writerside-de/search.html @@ -512,6 +512,12 @@ * its own classes. Until it appears — or if it never does — they stay the * floating pair they were. */ + var watcher = null; + + var poll = 0; + + var deadline = 0; + function mountInHeader() { var switchers = document.querySelector(".wh-header__switchers"); @@ -537,18 +543,34 @@ } if (!mountInHeader()) { - var watcher = new MutationObserver(function () { - if (mountInHeader()) { - watcher.disconnect(); - } - }); + // The header can finish rendering between the check above and the observer + // below, and then no mutation ever follows to react to — which is exactly + // what happened on the published site. Polling closes that gap; the + // observer keeps the common case instant. + watcher = new MutationObserver(check); + + poll = window.setInterval(check, 150); + + deadline = window.setTimeout(stop, 15000); - watcher.observe(document.body, { childList: true, subtree: true }); + watcher.observe(document.documentElement, { childList: true, subtree: true }); - // A header that has not arrived within a few seconds is not coming. - window.setTimeout(function () { + check(); + } + + function check() { + if (mountInHeader()) { + stop(); + } + } + + function stop() { + if (watcher) { watcher.disconnect(); - }, 8000); + } + + window.clearInterval(poll); + window.clearTimeout(deadline); } /** diff --git a/docs/writerside-fr/search.html b/docs/writerside-fr/search.html index 64ca7bef..d8d0833c 100644 --- a/docs/writerside-fr/search.html +++ b/docs/writerside-fr/search.html @@ -512,6 +512,12 @@ * its own classes. Until it appears — or if it never does — they stay the * floating pair they were. */ + var watcher = null; + + var poll = 0; + + var deadline = 0; + function mountInHeader() { var switchers = document.querySelector(".wh-header__switchers"); @@ -537,18 +543,34 @@ } if (!mountInHeader()) { - var watcher = new MutationObserver(function () { - if (mountInHeader()) { - watcher.disconnect(); - } - }); + // The header can finish rendering between the check above and the observer + // below, and then no mutation ever follows to react to — which is exactly + // what happened on the published site. Polling closes that gap; the + // observer keeps the common case instant. + watcher = new MutationObserver(check); + + poll = window.setInterval(check, 150); + + deadline = window.setTimeout(stop, 15000); - watcher.observe(document.body, { childList: true, subtree: true }); + watcher.observe(document.documentElement, { childList: true, subtree: true }); - // A header that has not arrived within a few seconds is not coming. - window.setTimeout(function () { + check(); + } + + function check() { + if (mountInHeader()) { + stop(); + } + } + + function stop() { + if (watcher) { watcher.disconnect(); - }, 8000); + } + + window.clearInterval(poll); + window.clearTimeout(deadline); } /** diff --git a/docs/writerside-ru/search.html b/docs/writerside-ru/search.html index 43c0c34b..d544ae03 100644 --- a/docs/writerside-ru/search.html +++ b/docs/writerside-ru/search.html @@ -512,6 +512,12 @@ * its own classes. Until it appears — or if it never does — they stay the * floating pair they were. */ + var watcher = null; + + var poll = 0; + + var deadline = 0; + function mountInHeader() { var switchers = document.querySelector(".wh-header__switchers"); @@ -537,18 +543,34 @@ } if (!mountInHeader()) { - var watcher = new MutationObserver(function () { - if (mountInHeader()) { - watcher.disconnect(); - } - }); + // The header can finish rendering between the check above and the observer + // below, and then no mutation ever follows to react to — which is exactly + // what happened on the published site. Polling closes that gap; the + // observer keeps the common case instant. + watcher = new MutationObserver(check); + + poll = window.setInterval(check, 150); + + deadline = window.setTimeout(stop, 15000); - watcher.observe(document.body, { childList: true, subtree: true }); + watcher.observe(document.documentElement, { childList: true, subtree: true }); - // A header that has not arrived within a few seconds is not coming. - window.setTimeout(function () { + check(); + } + + function check() { + if (mountInHeader()) { + stop(); + } + } + + function stop() { + if (watcher) { watcher.disconnect(); - }, 8000); + } + + window.clearInterval(poll); + window.clearTimeout(deadline); } /** diff --git a/docs/writerside-uk/search.html b/docs/writerside-uk/search.html index 773bcbfe..010510fc 100644 --- a/docs/writerside-uk/search.html +++ b/docs/writerside-uk/search.html @@ -512,6 +512,12 @@ * its own classes. Until it appears — or if it never does — they stay the * floating pair they were. */ + var watcher = null; + + var poll = 0; + + var deadline = 0; + function mountInHeader() { var switchers = document.querySelector(".wh-header__switchers"); @@ -537,18 +543,34 @@ } if (!mountInHeader()) { - var watcher = new MutationObserver(function () { - if (mountInHeader()) { - watcher.disconnect(); - } - }); + // The header can finish rendering between the check above and the observer + // below, and then no mutation ever follows to react to — which is exactly + // what happened on the published site. Polling closes that gap; the + // observer keeps the common case instant. + watcher = new MutationObserver(check); + + poll = window.setInterval(check, 150); + + deadline = window.setTimeout(stop, 15000); - watcher.observe(document.body, { childList: true, subtree: true }); + watcher.observe(document.documentElement, { childList: true, subtree: true }); - // A header that has not arrived within a few seconds is not coming. - window.setTimeout(function () { + check(); + } + + function check() { + if (mountInHeader()) { + stop(); + } + } + + function stop() { + if (watcher) { watcher.disconnect(); - }, 8000); + } + + window.clearInterval(poll); + window.clearTimeout(deadline); } /** diff --git a/docs/writerside/search.html b/docs/writerside/search.html index 0f87cb97..2b02fcf7 100644 --- a/docs/writerside/search.html +++ b/docs/writerside/search.html @@ -512,6 +512,12 @@ * its own classes. Until it appears — or if it never does — they stay the * floating pair they were. */ + var watcher = null; + + var poll = 0; + + var deadline = 0; + function mountInHeader() { var switchers = document.querySelector(".wh-header__switchers"); @@ -537,18 +543,34 @@ } if (!mountInHeader()) { - var watcher = new MutationObserver(function () { - if (mountInHeader()) { - watcher.disconnect(); - } - }); + // The header can finish rendering between the check above and the observer + // below, and then no mutation ever follows to react to — which is exactly + // what happened on the published site. Polling closes that gap; the + // observer keeps the common case instant. + watcher = new MutationObserver(check); + + poll = window.setInterval(check, 150); + + deadline = window.setTimeout(stop, 15000); - watcher.observe(document.body, { childList: true, subtree: true }); + watcher.observe(document.documentElement, { childList: true, subtree: true }); - // A header that has not arrived within a few seconds is not coming. - window.setTimeout(function () { + check(); + } + + function check() { + if (mountInHeader()) { + stop(); + } + } + + function stop() { + if (watcher) { watcher.disconnect(); - }, 8000); + } + + window.clearInterval(poll); + window.clearTimeout(deadline); } /** diff --git a/scripts/docs/assets/search-widget.js b/scripts/docs/assets/search-widget.js index 2a24c6bc..b7d2d2c7 100644 --- a/scripts/docs/assets/search-widget.js +++ b/scripts/docs/assets/search-widget.js @@ -243,6 +243,12 @@ * its own classes. Until it appears — or if it never does — they stay the * floating pair they were. */ + var watcher = null; + + var poll = 0; + + var deadline = 0; + function mountInHeader() { var switchers = document.querySelector(".wh-header__switchers"); @@ -268,18 +274,34 @@ } if (!mountInHeader()) { - var watcher = new MutationObserver(function () { - if (mountInHeader()) { - watcher.disconnect(); - } - }); + // The header can finish rendering between the check above and the observer + // below, and then no mutation ever follows to react to — which is exactly + // what happened on the published site. Polling closes that gap; the + // observer keeps the common case instant. + watcher = new MutationObserver(check); + + poll = window.setInterval(check, 150); + + deadline = window.setTimeout(stop, 15000); - watcher.observe(document.body, { childList: true, subtree: true }); + watcher.observe(document.documentElement, { childList: true, subtree: true }); - // A header that has not arrived within a few seconds is not coming. - window.setTimeout(function () { + check(); + } + + function check() { + if (mountInHeader()) { + stop(); + } + } + + function stop() { + if (watcher) { watcher.disconnect(); - }, 8000); + } + + window.clearInterval(poll); + window.clearTimeout(deadline); } /** diff --git a/scripts/docs/finalize-site.mjs b/scripts/docs/finalize-site.mjs index 03101c31..e7ca2630 100644 --- a/scripts/docs/finalize-site.mjs +++ b/scripts/docs/finalize-site.mjs @@ -155,14 +155,18 @@ for (const page of pages) { } } - // Said once at the end of every page, in that page's language. + // Said once at the end of every page, in that page's language. It goes + // inside the article: a paragraph left at the end of `body` is laid out by + // the application's own grid and lands at the top of the page. if (!html.includes("asu-ai-notice")) { - const body = html.lastIndexOf(""); + const notice = `

${language.strings.aiNotice}

`; - if (body !== -1) { - const notice = `

${language.strings.aiNotice}

`; + const article = html.lastIndexOf(""); + + const at = article === -1 ? html.lastIndexOf("") : article; - html = `${html.slice(0, body)}${notice}\n${html.slice(body)}`; + if (at !== -1) { + html = `${html.slice(0, at)}${notice}\n${html.slice(at)}`; } } From f880ce8d80822a7913a1354fe7e1b2e226a6c3cf Mon Sep 17 00:00:00 2001 From: Maksym Stoianov Date: Wed, 23 Sep 2026 22:18:36 +0200 Subject: [PATCH 2/2] feat(docs): link the translations under the breadcrumbs, and say once at the end that AI wrote this MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The floating pair is gone: no language button, no search button, and with them the widget, its script and the profile entry that pointed at it. Two plain blocks take their place, written into every built page and needing no JavaScript at all — a reader without it, and a crawler that runs none, see both: - a row of links at the top of the article, which is directly under the breadcrumbs, carrying the same page in the other four languages, the current one named but not linked; - the notice at the end of the article, above the footer, in that page's language. The assembled job checks for those two instead of the controls it used to. Refs #539 --- .github/workflows/docs.yml | 2 +- docs/writerside-de/search.html | 657 --------------------------- docs/writerside-fr/search.html | 657 --------------------------- docs/writerside-ru/search.html | 657 --------------------------- docs/writerside-uk/search.html | 657 --------------------------- docs/writerside/search.html | 657 --------------------------- scripts/docs/assets/search-widget.js | 387 ---------------- scripts/docs/finalize-site.mjs | 40 +- scripts/docs/generate-topics.mjs | 3 +- scripts/docs/site.mjs | 257 ----------- 10 files changed, 30 insertions(+), 3944 deletions(-) delete mode 100644 docs/writerside-de/search.html delete mode 100644 docs/writerside-fr/search.html delete mode 100644 docs/writerside-ru/search.html delete mode 100644 docs/writerside-uk/search.html delete mode 100644 docs/writerside/search.html delete mode 100644 scripts/docs/assets/search-widget.js diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 9c1fb831..baeb70a7 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -183,7 +183,7 @@ jobs: missing=0 for page in dir/overview.html dir/ru/overview.html dir/appendcolumns.html; do - for marker in 'rel="canonical"' 'asu-fab' 'asu-language-open' 'SoftwareSourceCode'; do + for marker in 'rel="canonical"' 'asu-languages' 'asu-ai-notice' 'SoftwareSourceCode'; do if ! grep -qF "$marker" "$page"; then echo "::error::${page} is missing ${marker}" missing=1 diff --git a/docs/writerside-de/search.html b/docs/writerside-de/search.html deleted file mode 100644 index 52d0cc0d..00000000 --- a/docs/writerside-de/search.html +++ /dev/null @@ -1,657 +0,0 @@ - - - - - - - - - - - diff --git a/docs/writerside-fr/search.html b/docs/writerside-fr/search.html deleted file mode 100644 index d8d0833c..00000000 --- a/docs/writerside-fr/search.html +++ /dev/null @@ -1,657 +0,0 @@ - - - - - - - - - - - diff --git a/docs/writerside-ru/search.html b/docs/writerside-ru/search.html deleted file mode 100644 index d544ae03..00000000 --- a/docs/writerside-ru/search.html +++ /dev/null @@ -1,657 +0,0 @@ - - - - - - - - - - - diff --git a/docs/writerside-uk/search.html b/docs/writerside-uk/search.html deleted file mode 100644 index 010510fc..00000000 --- a/docs/writerside-uk/search.html +++ /dev/null @@ -1,657 +0,0 @@ - - - - - - - - - - - diff --git a/docs/writerside/search.html b/docs/writerside/search.html deleted file mode 100644 index 2b02fcf7..00000000 --- a/docs/writerside/search.html +++ /dev/null @@ -1,657 +0,0 @@ - - - - - - - - - - - diff --git a/scripts/docs/assets/search-widget.js b/scripts/docs/assets/search-widget.js deleted file mode 100644 index b7d2d2c7..00000000 --- a/scripts/docs/assets/search-widget.js +++ /dev/null @@ -1,387 +0,0 @@ -/** - * The search widget and language switcher injected into every published page. - * - * `scripts/docs/site.mjs` reads this file and replaces `__ASU_STRINGS__` with - * the labels of the language being built. Keeping it a real file, rather than a - * string inside the generator, is what keeps its regular expressions intact. - */ - -/* global __ASU_STRINGS__ */ - -(function () { - var strings = __ASU_STRINGS__; - - var dialog = document.getElementById("asu-search-dialog"); - - var panel = document.getElementById("asu-search-panel"); - - var input = document.getElementById("asu-search-input"); - - var list = document.getElementById("asu-search-results"); - - var status = document.getElementById("asu-search-status"); - - var open = document.getElementById("asu-search-open"); - - var languageButton = document.getElementById("asu-language-open"); - - var languageMenu = document.getElementById("asu-language-menu"); - - var index = null; - - var loading = null; - - var hits = []; - - var cursor = 0; - - // Every language publishes the same file names, so a language link keeps the - // reader on the page they were reading. - Array.prototype.forEach.call(languageMenu.querySelectorAll("a"), function (link) { - var file = window.location.pathname.split("/").pop(); - - if (file && file.indexOf(".html") !== -1) { - link.href = link.getAttribute("href") + file; - } - }); - - function base() { - var path = window.location.pathname; - - return path.slice(0, path.lastIndexOf("/") + 1); - } - - function load() { - if (loading) { - return loading; - } - - loading = fetch(base() + "search-index.json") - .then(function (response) { - if (!response.ok) { - throw new Error(String(response.status)); - } - - return response.json(); - }) - .then(function (data) { - index = data; - - return data; - }) - .catch(function () { - index = []; - status.textContent = strings.missing; - - return []; - }); - - return loading; - } - - function escapeHtml(text) { - return text.replace(/[&<>"]/g, function (character) { - return { "&": "&", "<": "<", ">": ">", '"': """ }[character]; - }); - } - - function highlight(text, terms) { - var html = escapeHtml(text); - - terms.forEach(function (term) { - var pattern = new RegExp("(" + term.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + ")", "ig"); - - html = html.replace(pattern, "$1"); - }); - - return html; - } - - function snippetOf(entry, terms) { - var text = entry.text || ""; - - var at = -1; - - terms.some(function (term) { - at = text.toLowerCase().indexOf(term); - - return at !== -1; - }); - - if (at === -1) { - return entry.summary || text.slice(0, 140); - } - - var from = Math.max(0, at - 60); - - return (from > 0 ? "…" : "") + text.slice(from, from + 160) + "…"; - } - - function score(entry, terms) { - var title = (entry.title || "").toLowerCase(); - - var text = ((entry.summary || "") + " " + (entry.text || "")).toLowerCase(); - - var total = 0; - - for (var i = 0; i < terms.length; i += 1) { - var term = terms[i]; - - if (title === term) { - total += 120; - } else if (title.indexOf(term) === 0) { - total += 60; - } else if (title.indexOf(term) !== -1) { - total += 30; - } else if (text.indexOf(term) !== -1) { - total += 5; - } else { - return 0; - } - } - - return total; - } - - function render(terms) { - list.innerHTML = ""; - - hits.forEach(function (entry, position) { - var item = document.createElement("li"); - - item.setAttribute("role", "option"); - item.setAttribute("aria-selected", position === cursor ? "true" : "false"); - - var link = document.createElement("a"); - - link.href = base() + entry.url; - link.innerHTML = - '' + - highlight(entry.title, terms) + - "" + - '
' + - highlight(snippetOf(entry, terms), terms) + - "
"; - - item.appendChild(link); - list.appendChild(item); - }); - } - - function search() { - var query = input.value.trim().toLowerCase(); - - if (!query) { - hits = []; - list.innerHTML = ""; - status.textContent = strings.hint; - - return; - } - - load().then(function () { - var terms = query.split(/\s+/).filter(Boolean); - - hits = (index || []) - .map(function (entry) { - return { entry: entry, score: score(entry, terms) }; - }) - .filter(function (row) { - return row.score > 0; - }) - .sort(function (a, b) { - return b.score - a.score; - }) - .slice(0, 25) - .map(function (row) { - return row.entry; - }); - - cursor = 0; - status.textContent = hits.length - ? hits.length + " " + strings.matches - : strings.empty + " “" + query + "”"; - - render(terms); - }); - } - - function show() { - dialog.setAttribute("open", ""); - input.value = ""; - input.focus(); - status.textContent = strings.hint; - list.innerHTML = ""; - load(); - } - - function hide() { - dialog.removeAttribute("open"); - } - - function move(step) { - if (hits.length === 0) { - return; - } - - cursor = (cursor + step + hits.length) % hits.length; - - Array.prototype.forEach.call(list.children, function (item, position) { - item.setAttribute("aria-selected", position === cursor ? "true" : "false"); - }); - - var selected = list.children[cursor]; - - if (selected) { - selected.scrollIntoView({ block: "nearest" }); - } - } - - /** - * The header is drawn by the help application after the page loads, so the - * two controls wait for it and then sit beside the theme switcher, wearing - * its own classes. Until it appears — or if it never does — they stay the - * floating pair they were. - */ - var watcher = null; - - var poll = 0; - - var deadline = 0; - - function mountInHeader() { - var switchers = document.querySelector(".wh-header__switchers"); - - if (!switchers || switchers.contains(languageButton)) { - return Boolean(switchers); - } - - var theme = switchers.querySelector('[data-test="theme-switcher"]'); - - if (!theme) { - return false; - } - - [open, languageButton].forEach(function (button) { - button.className = theme.className; - button.classList.add("asu-in-header"); - }); - - switchers.insertBefore(open, theme); - switchers.insertBefore(languageButton, theme); - - return true; - } - - if (!mountInHeader()) { - // The header can finish rendering between the check above and the observer - // below, and then no mutation ever follows to react to — which is exactly - // what happened on the published site. Polling closes that gap; the - // observer keeps the common case instant. - watcher = new MutationObserver(check); - - poll = window.setInterval(check, 150); - - deadline = window.setTimeout(stop, 15000); - - watcher.observe(document.documentElement, { childList: true, subtree: true }); - - check(); - } - - function check() { - if (mountInHeader()) { - stop(); - } - } - - function stop() { - if (watcher) { - watcher.disconnect(); - } - - window.clearInterval(poll); - window.clearTimeout(deadline); - } - - /** - * The menu hangs under its button wherever the button ended up. - */ - function placeMenu() { - var rect = languageButton.getBoundingClientRect(); - - if (!languageButton.classList.contains("asu-in-header")) { - languageMenu.style.top = ""; - languageMenu.style.right = ""; - - return; - } - - languageMenu.style.top = rect.bottom + 8 + "px"; - languageMenu.style.right = Math.max(8, window.innerWidth - rect.right) + "px"; - } - - languageButton.addEventListener("click", function () { - var opened = languageMenu.hasAttribute("open"); - - if (opened) { - languageMenu.removeAttribute("open"); - } else { - placeMenu(); - languageMenu.setAttribute("open", ""); - } - - languageButton.setAttribute("aria-expanded", String(!opened)); - }); - - window.addEventListener("resize", function () { - if (languageMenu.hasAttribute("open")) { - placeMenu(); - } - }); - - document.addEventListener("click", function (event) { - if (!languageMenu.contains(event.target) && event.target !== languageButton) { - languageMenu.removeAttribute("open"); - languageButton.setAttribute("aria-expanded", "false"); - } - }); - - open.addEventListener("click", show); - input.addEventListener("input", search); - - dialog.addEventListener("click", function (event) { - if (!panel.contains(event.target)) { - hide(); - } - }); - - document.addEventListener("keydown", function (event) { - var typing = /^(INPUT|TEXTAREA|SELECT)$/.test(document.activeElement.tagName); - - if (!dialog.hasAttribute("open")) { - var shortcut = - (event.key === "/" && !typing) || ((event.metaKey || event.ctrlKey) && event.key === "k"); - - if (shortcut) { - event.preventDefault(); - show(); - } - - return; - } - - if (event.key === "Escape") { - hide(); - } else if (event.key === "ArrowDown") { - event.preventDefault(); - move(1); - } else if (event.key === "ArrowUp") { - event.preventDefault(); - move(-1); - } else if (event.key === "Enter" && hits[cursor]) { - event.preventDefault(); - window.location.href = base() + hits[cursor].url; - } - }); -})(); diff --git a/scripts/docs/finalize-site.mjs b/scripts/docs/finalize-site.mjs index e7ca2630..41da0608 100644 --- a/scripts/docs/finalize-site.mjs +++ b/scripts/docs/finalize-site.mjs @@ -75,15 +75,28 @@ function urlOf(language, page) { * or the language switcher — so the same files are put in here instead. */ function injections(language) { - const read = (name) => { - try { - return readFileSync(join(ROOT, language.root, name), "utf8").trim(); - } catch { - return ""; - } - }; + try { + return { head: readFileSync(join(ROOT, language.root, "head.html"), "utf8").trim() }; + } catch { + return { head: "" }; + } +} - return { head: read("head.html"), body: read("search.html") }; +/** + * The same page in the other languages, as a row of links. + * + * It goes at the top of the article, which puts it directly under the + * breadcrumbs, and it is plain HTML: a reader with no JavaScript, and a crawler + * that runs none, both still see every translation. + */ +function languageRow(language, page, present) { + const links = present.map((other) => + other === language + ? `${other.name}` + : `${other.name}` + ); + + return ``; } const pages = pagesOf(root); @@ -147,11 +160,14 @@ for (const page of pages) { `$1${SITE}/images/banner-1280x640.jpg$2` ); - if (injected.body && !html.includes("asu-fab")) { - const body = html.lastIndexOf(""); + // Directly under the breadcrumbs, which sit above the article. + if (!html.includes("asu-languages")) { + const article = html.match(/]*>/); + + if (article) { + const at = html.indexOf(article[0]) + article[0].length; - if (body !== -1) { - html = `${html.slice(0, body)}${injected.body}\n${html.slice(body)}`; + html = `${html.slice(0, at)}${languageRow(language, page, present)}${html.slice(at)}`; } } diff --git a/scripts/docs/generate-topics.mjs b/scripts/docs/generate-topics.mjs index 74c57700..4ef87e86 100644 --- a/scripts/docs/generate-topics.mjs +++ b/scripts/docs/generate-topics.mjs @@ -36,7 +36,7 @@ import prettier from "prettier"; import ts from "typescript"; import { LANGUAGES, SOURCE_LANGUAGE } from "./languages.mjs"; -import { buildProfiles, headHtml, searchHtml, writersideCfg } from "./site.mjs"; +import { buildProfiles, headHtml, writersideCfg } from "./site.mjs"; const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../.."); @@ -975,7 +975,6 @@ for (const language of LANGUAGES) { // 1. Project configuration, the search widget and the structured head. emit(join(root, "buildprofiles.xml"), buildProfiles(language)); emit(join(root, "head.html"), await pretty(headHtml(language), join(root, "head.html"))); - emit(join(root, "search.html"), await pretty(searchHtml(language), join(root, "search.html"))); // The configuration is the same everywhere but for the version, which comes // from the package, so even the English project is written rather than kept. diff --git a/scripts/docs/site.mjs b/scripts/docs/site.mjs index 0c1aeb37..9ae6d3a3 100644 --- a/scripts/docs/site.mjs +++ b/scripts/docs/site.mjs @@ -133,260 +133,3 @@ export function headHtml(language) { * page. Writerside publishes no search of its own, and has no notion of a * translated site, so both live here. */ -export function searchHtml(language) { - const strings = language.strings; - - const roots = LANGUAGES.map((other) => ({ - code: other.code, - name: other.name, - url: other.webRoot, - current: other.code === language.code - })); - - return ` - - - - - - - - - - -`; -}