From dc482cde94973a267da426e39447461366f4eb03 Mon Sep 17 00:00:00 2001 From: Server <10.9.8.250@reg.snw.su> Date: Wed, 19 Aug 2026 06:37:42 +0000 Subject: [PATCH] Support legacy compiled HTML shells --- README.md | 2 ++ docslib/_version.py | 2 +- docslib/templates/client.js | 19 +++++++++++-------- tests/test_server.py | 13 +++++++++---- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 5929728..ca3a114 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/docslib/_version.py b/docslib/_version.py index c3c006f..81b5cd7 100644 --- a/docslib/_version.py +++ b/docslib/_version.py @@ -1,3 +1,3 @@ """Single source of truth for the SharedDocsLib package version.""" -__version__ = "0.4.4" +__version__ = "0.4.5" diff --git a/docslib/templates/client.js b/docslib/templates/client.js index fe16c24..7548790 100644 --- a/docslib/templates/client.js +++ b/docslib/templates/client.js @@ -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")); diff --git a/tests/test_server.py b/tests/test_server.py index e0d0690..06386df 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -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():