Support legacy compiled HTML shells
This commit is contained in:
parent
7163d1e4fe
commit
dc482cde94
4 changed files with 23 additions and 13 deletions
|
|
@ -17,6 +17,8 @@ UI не содержит языко-зависимых служебных под
|
||||||
|
|
||||||
На десктопе компактный header содержит toggle боковой панели, полное название документации, поиск и переключатель темы. Sidebar по умолчанию открыт, его состояние не сохраняется между загрузками, а при сворачивании внутренняя раскладка остаётся неподвижной и обрезается границей панели без переноса текста. Поисковый placeholder медленно печатает первые слова случайного названия, добавляет троеточие только в конце и сохраняет готовый текст 5 секунд; при вводе поле раскрывает ранжированные результаты вниз. Проверка manifest выполняется автоматически в фоне без отдельной кнопки обновления.
|
На десктопе компактный header содержит toggle боковой панели, полное название документации, поиск и переключатель темы. Sidebar по умолчанию открыт, его состояние не сохраняется между загрузками, а при сворачивании внутренняя раскладка остаётся неподвижной и обрезается границей панели без переноса текста. Поисковый placeholder медленно печатает первые слова случайного названия, добавляет троеточие только в конце и сохраняет готовый текст 5 секунд; при вводе поле раскрывает ранжированные результаты вниз. Проверка manifest выполняется автоматически в фоне без отдельной кнопки обновления.
|
||||||
|
|
||||||
|
Обновлённый runtime сохраняет совместимость со старыми скомпилированными HTML-оболочками: отсутствие desktop-toggle, мобильного переключателя темы или общего контейнера page-transition не останавливает запуск клиента.
|
||||||
|
|
||||||
На мобильных устройствах используется viewport `100dvh` и нижний dock. Кнопка `☰` заменяет содержимое страницы копией desktop-sidebar, которая выезжает с левой границы экрана; между header-кнопками и деревом доступен круглый переключатель темы. Выбор страницы в открытом мобильном меню закрывает его и показывает новый контент моментально, без page-transition. Ввод в нижний поиск заменяет содержимое результатами, расположенными снизу вверх по релевантности. При остальных переходах контент вместе с кнопками предыдущей и следующей страницы плавно смещается на 30 px по направлению навигации и меняет прозрачность.
|
На мобильных устройствах используется viewport `100dvh` и нижний dock. Кнопка `☰` заменяет содержимое страницы копией desktop-sidebar, которая выезжает с левой границы экрана; между header-кнопками и деревом доступен круглый переключатель темы. Выбор страницы в открытом мобильном меню закрывает его и показывает новый контент моментально, без page-transition. Ввод в нижний поиск заменяет содержимое результатами, расположенными снизу вверх по релевантности. При остальных переходах контент вместе с кнопками предыдущей и следующей страницы плавно смещается на 30 px по направлению навигации и меняет прозрачность.
|
||||||
|
|
||||||
## Установка из Git
|
## Установка из Git
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
"""Single source of truth for the SharedDocsLib package version."""
|
"""Single source of truth for the SharedDocsLib package version."""
|
||||||
|
|
||||||
__version__ = "0.4.4"
|
__version__ = "0.4.5"
|
||||||
|
|
|
||||||
|
|
@ -402,13 +402,14 @@
|
||||||
|
|
||||||
const currentIndex = manifest.pages.findIndex((candidate) => candidate.number === currentNumber);
|
const currentIndex = manifest.pages.findIndex((candidate) => candidate.number === currentNumber);
|
||||||
const direction = currentIndex >= 0 && index < currentIndex ? -1 : 1;
|
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;
|
const transitionId = ++pageTransitionId;
|
||||||
|
|
||||||
pageAnimation?.cancel();
|
pageAnimation?.cancel();
|
||||||
pageAnimation = null;
|
pageAnimation = null;
|
||||||
if (animate) {
|
if (animate) {
|
||||||
const outgoing = elements.pageTransition.animate(
|
const outgoing = transitionElement.animate(
|
||||||
[
|
[
|
||||||
{ opacity: 1, transform: "translateX(0)" },
|
{ opacity: 1, transform: "translateX(0)" },
|
||||||
{ opacity: 0, transform: `translateX(${-30 * direction}px)` },
|
{ opacity: 0, transform: `translateX(${-30 * direction}px)` },
|
||||||
|
|
@ -423,7 +424,7 @@
|
||||||
|
|
||||||
applyPage(page, index);
|
applyPage(page, index);
|
||||||
if (!animate || transitionId !== pageTransitionId) return;
|
if (!animate || transitionId !== pageTransitionId) return;
|
||||||
const incoming = elements.pageTransition.animate(
|
const incoming = transitionElement.animate(
|
||||||
[
|
[
|
||||||
{ opacity: 0, transform: `translateX(${30 * direction}px)` },
|
{ opacity: 0, transform: `translateX(${30 * direction}px)` },
|
||||||
{ opacity: 1, transform: "translateX(0)" },
|
{ opacity: 1, transform: "translateX(0)" },
|
||||||
|
|
@ -576,7 +577,7 @@
|
||||||
document.documentElement.dataset.theme = theme;
|
document.documentElement.dataset.theme = theme;
|
||||||
const icon = theme === "dark" ? "☀" : "◐";
|
const icon = theme === "dark" ? "☀" : "◐";
|
||||||
elements.themeIcon.textContent = icon;
|
elements.themeIcon.textContent = icon;
|
||||||
elements.mobileThemeIcon.textContent = icon;
|
if (elements.mobileThemeIcon) elements.mobileThemeIcon.textContent = icon;
|
||||||
localStorage.setItem("docslib-theme", theme);
|
localStorage.setItem("docslib-theme", theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -725,11 +726,13 @@
|
||||||
elements.mobileSearchResults.replaceChildren();
|
elements.mobileSearchResults.replaceChildren();
|
||||||
setMobileMode(mobileMode === "menu" ? "content" : "menu");
|
setMobileMode(mobileMode === "menu" ? "content" : "menu");
|
||||||
});
|
});
|
||||||
|
try {
|
||||||
elements.desktopSidebarToggle.addEventListener("click", () => {
|
elements.desktopSidebarToggle.addEventListener("click", () => {
|
||||||
setDesktopSidebar(document.body.classList.contains("desktop-sidebar-collapsed"));
|
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);
|
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("pointerenter", () => elements.toolbar.classList.add("refresh-expanded"));
|
||||||
elements.refresh.addEventListener("pointerleave", () => elements.toolbar.classList.remove("refresh-expanded"));
|
elements.refresh.addEventListener("pointerleave", () => elements.toolbar.classList.remove("refresh-expanded"));
|
||||||
elements.refresh.addEventListener("focus", () => elements.toolbar.classList.add("refresh-expanded"));
|
elements.refresh.addEventListener("focus", () => elements.toolbar.classList.add("refresh-expanded"));
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ def test_all_endpoints_and_self_contained_build(tmp_path):
|
||||||
assert html_response.status_code == 200
|
assert html_response.status_code == 200
|
||||||
assert "http://127.0.0.1:9000/manifest.json" in html
|
assert "http://127.0.0.1:9000/manifest.json" in html
|
||||||
assert "http://127.0.0.1:9000/version" 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 ".content { --custom-test: yes; }" in html
|
||||||
assert r'document.body.dataset.customTest = \"yes\";' in html
|
assert r'document.body.dataset.customTest = \"yes\";' in html
|
||||||
assert 'id="docslib-loading"' 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 ".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 "body.desktop-sidebar-collapsed .desktop-sidebar { width: 0; flex-basis: 0;" in html
|
||||||
assert 'elements.desktopSidebarToggle.addEventListener("click"' in system_js
|
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 '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 "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 "animation: mobile-menu-enter .26s" in html
|
||||||
assert "transform: translateX(-100%)" in html
|
assert "transform: translateX(-100%)" in html
|
||||||
assert "const direction = currentIndex >= 0 && index < currentIndex ? -1 : 1" in system_js
|
assert "const direction = currentIndex >= 0 && index < currentIndex ? -1 : 1" in system_js
|
||||||
assert 'const outgoing = elements.pageTransition.animate(' in system_js
|
assert 'const outgoing = transitionElement.animate(' in system_js
|
||||||
assert 'const incoming = elements.pageTransition.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 'transform: `translateX(${30 * direction}px)`' in system_js
|
assert 'transform: `translateX(${30 * direction}px)`' in system_js
|
||||||
assert 'opacity: 0' 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):
|
def test_build_writes_static_bundle(tmp_path):
|
||||||
assert __version__ == "0.4.4"
|
assert __version__ == "0.4.5"
|
||||||
|
|
||||||
@Page("1", "Static page")
|
@Page("1", "Static page")
|
||||||
def static_page():
|
def static_page():
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue