Support legacy compiled HTML shells

This commit is contained in:
Server 2026-08-19 06:37:42 +00:00
parent 7163d1e4fe
commit dc482cde94
4 changed files with 23 additions and 13 deletions

View file

@ -17,6 +17,8 @@ UI не содержит языко-зависимых служебных под
На десктопе компактный header содержит toggle боковой панели, полное название документации, поиск и переключатель темы. Sidebar по умолчанию открыт, его состояние не сохраняется между загрузками, а при сворачивании внутренняя раскладка остаётся неподвижной и обрезается границей панели без переноса текста. Поисковый placeholder медленно печатает первые слова случайного названия, добавляет троеточие только в конце и сохраняет готовый текст 5 секунд; при вводе поле раскрывает ранжированные результаты вниз. Проверка manifest выполняется автоматически в фоне без отдельной кнопки обновления.
Обновлённый runtime сохраняет совместимость со старыми скомпилированными HTML-оболочками: отсутствие desktop-toggle, мобильного переключателя темы или общего контейнера page-transition не останавливает запуск клиента.
На мобильных устройствах используется viewport `100dvh` и нижний dock. Кнопка `☰` заменяет содержимое страницы копией desktop-sidebar, которая выезжает с левой границы экрана; между header-кнопками и деревом доступен круглый переключатель темы. Выбор страницы в открытом мобильном меню закрывает его и показывает новый контент моментально, без page-transition. Ввод в нижний поиск заменяет содержимое результатами, расположенными снизу вверх по релевантности. При остальных переходах контент вместе с кнопками предыдущей и следующей страницы плавно смещается на 30 px по направлению навигации и меняет прозрачность.
## Установка из Git

View file

@ -1,3 +1,3 @@
"""Single source of truth for the SharedDocsLib package version."""
__version__ = "0.4.4"
__version__ = "0.4.5"

View file

@ -402,13 +402,14 @@
const currentIndex = manifest.pages.findIndex((candidate) => candidate.number === currentNumber);
const direction = currentIndex >= 0 && index < currentIndex ? -1 : 1;
const animate = currentIndex >= 0 && !skipAnimation && !reducedMotion.matches && typeof elements.pageTransition.animate === "function";
const transitionElement = elements.pageTransition || elements.content;
const animate = currentIndex >= 0 && !skipAnimation && !reducedMotion.matches && typeof transitionElement.animate === "function";
const transitionId = ++pageTransitionId;
pageAnimation?.cancel();
pageAnimation = null;
if (animate) {
const outgoing = elements.pageTransition.animate(
const outgoing = transitionElement.animate(
[
{ opacity: 1, transform: "translateX(0)" },
{ opacity: 0, transform: `translateX(${-30 * direction}px)` },
@ -423,7 +424,7 @@
applyPage(page, index);
if (!animate || transitionId !== pageTransitionId) return;
const incoming = elements.pageTransition.animate(
const incoming = transitionElement.animate(
[
{ opacity: 0, transform: `translateX(${30 * direction}px)` },
{ opacity: 1, transform: "translateX(0)" },
@ -576,7 +577,7 @@
document.documentElement.dataset.theme = theme;
const icon = theme === "dark" ? "☀" : "◐";
elements.themeIcon.textContent = icon;
elements.mobileThemeIcon.textContent = icon;
if (elements.mobileThemeIcon) elements.mobileThemeIcon.textContent = icon;
localStorage.setItem("docslib-theme", theme);
}
@ -725,11 +726,13 @@
elements.mobileSearchResults.replaceChildren();
setMobileMode(mobileMode === "menu" ? "content" : "menu");
});
elements.desktopSidebarToggle.addEventListener("click", () => {
setDesktopSidebar(document.body.classList.contains("desktop-sidebar-collapsed"));
});
try {
elements.desktopSidebarToggle.addEventListener("click", () => {
setDesktopSidebar(document.body.classList.contains("desktop-sidebar-collapsed"));
});
} catch (_) { /* older compiled HTML may not include the sidebar toggle */ }
document.getElementById("theme-button").addEventListener("click", toggleTheme);
elements.mobileThemeButton.addEventListener("click", toggleTheme);
if (elements.mobileThemeButton) elements.mobileThemeButton.addEventListener("click", toggleTheme);
elements.refresh.addEventListener("pointerenter", () => elements.toolbar.classList.add("refresh-expanded"));
elements.refresh.addEventListener("pointerleave", () => elements.toolbar.classList.remove("refresh-expanded"));
elements.refresh.addEventListener("focus", () => elements.toolbar.classList.add("refresh-expanded"));

View file

@ -97,7 +97,7 @@ def test_all_endpoints_and_self_contained_build(tmp_path):
assert html_response.status_code == 200
assert "http://127.0.0.1:9000/manifest.json" in html
assert "http://127.0.0.1:9000/version" in html
assert 'globalThis.COMPILED_FROM_VERSION = "0.4.4";' in html
assert 'globalThis.COMPILED_FROM_VERSION = "0.4.5";' in html
assert ".content { --custom-test: yes; }" in html
assert r'document.body.dataset.customTest = \"yes\";' in html
assert 'id="docslib-loading"' in html
@ -222,13 +222,18 @@ def test_all_endpoints_and_self_contained_build(tmp_path):
assert ".desktop-sidebar > * { width: calc(var(--desktop-sidebar-width) - 36px); min-width: calc(var(--desktop-sidebar-width) - 36px); }" in system_css
assert "body.desktop-sidebar-collapsed .desktop-sidebar { width: 0; flex-basis: 0;" in html
assert 'elements.desktopSidebarToggle.addEventListener("click"' in system_js
assert 'try {\n elements.desktopSidebarToggle.addEventListener("click"' in system_js
assert "older compiled HTML may not include the sidebar toggle" in system_js
assert "const transitionElement = elements.pageTransition || elements.content" in system_js
assert "if (elements.mobileThemeIcon) elements.mobileThemeIcon.textContent = icon" in system_js
assert "if (elements.mobileThemeButton) elements.mobileThemeButton.addEventListener" in system_js
assert 'document.body.classList.toggle("desktop-sidebar-collapsed", !open)' in system_js
assert "localStorage.setItem" not in system_js[system_js.index("function setDesktopSidebar"):system_js.index("function closeSearch")]
assert "animation: mobile-menu-enter .26s" in html
assert "transform: translateX(-100%)" in html
assert "const direction = currentIndex >= 0 && index < currentIndex ? -1 : 1" in system_js
assert 'const outgoing = elements.pageTransition.animate(' in system_js
assert 'const incoming = elements.pageTransition.animate(' in system_js
assert 'const outgoing = transitionElement.animate(' in system_js
assert 'const incoming = transitionElement.animate(' in system_js
assert 'transform: `translateX(${-30 * direction}px)`' in system_js
assert 'transform: `translateX(${30 * direction}px)`' in system_js
assert 'opacity: 0' in system_js
@ -248,7 +253,7 @@ def test_all_endpoints_and_self_contained_build(tmp_path):
def test_build_writes_static_bundle(tmp_path):
assert __version__ == "0.4.4"
assert __version__ == "0.4.5"
@Page("1", "Static page")
def static_page():