Print complete documentation with light output

This commit is contained in:
Server 2026-08-12 09:18:19 +00:00
parent f189c37282
commit c489209610
5 changed files with 75 additions and 7 deletions

View file

@ -254,6 +254,14 @@ console.log(globalThis.COMPILED_FROM_VERSION); // например, "0.3.7"
Присваивание добавляется в bootstrap-скрипт самой HTML-ки. Автообновление manifest не меняет `COMPILED_FROM_VERSION`: значение обновится только после новой компиляции и замены `index.html`.
Для печати всей документации из `custom_js` или консоли доступна глобальная функция:
```javascript
PrintFullDocumentation();
```
Она формирует единый документ из всех страниц в порядке manifest и открывает системный диалог печати. Каждая страница документации начинается с нового печатного листа. Печатная тема всегда использует белый фон и чёрный текст независимо от выбранной экранной темы.
## Live-preview
В live-режиме браузер опрашивает только `/live`. Сервер следит за файлами, в которых объявлены страницы, а также за системными и пользовательскими CSS/JS. При изменении он пересобирает manifest; клиент сохраняет его и перезагружается с новым runtime. В запускаемом файле вызов `run()` обязательно помещать под `if __name__ == "__main__"`, чтобы watcher не запускал второй сервер.

View file

@ -1,4 +1,3 @@
"""Single source of truth for the SharedDocsLib package version."""
__version__ = "0.3.7"
__version__ = "0.3.8"

View file

@ -134,6 +134,7 @@ button { color: inherit; }
:root[data-theme="dark"] #next-page { color: #000; background: #eee; }
.mobile-view, .mobile-dock { display: none; }
.full-print-document { display: none; }
@media (max-width: 820px) {
.app-shell { display: block; }
@ -179,9 +180,20 @@ button { color: inherit; }
}
@media print {
html, body { height: auto; max-height: none; overflow: visible; }
:root, :root[data-theme="dark"] { color-scheme: light; }
html, body { height: auto; max-height: none; overflow: visible; color: #000 !important; background: #fff !important; }
.app-shell, .workspace, .page-surface, .content, .full-print-document, .print-page { color: #000 !important; background: #fff !important; }
.content a, .content figcaption, .content blockquote { color: #000 !important; }
.content pre, .content code, .content details, .content th, .callout { color: #000 !important; background: #fff !important; border-color: #777 !important; }
.app-shell { display: block; }
.desktop-header, .desktop-sidebar, .mobile-dock, .page-navigation { display: none; }
.workspace, .page-surface { display: block; height: auto; overflow: visible; }
.content { width: 100%; padding: 0; }
body.docslib-print-all > .app-shell { display: none; }
body.docslib-print-all > .full-print-document { display: block; }
.print-page { break-after: page; page-break-after: always; }
.print-page:last-child { break-after: auto; page-break-after: auto; }
.print-page-heading { margin: 0 0 2rem; padding-bottom: 1rem; border-bottom: 1px solid #777; }
.print-page-heading h1 { margin: 0; color: #000 !important; }
.print-page-number { display: block; margin-bottom: .3rem; color: #555 !important; }
}

View file

@ -226,8 +226,8 @@
return asset ? `data:${asset.mime};base64,${asset.data}` : "";
}
function hydrateAssets() {
elements.content.querySelectorAll("[data-docslib-asset]").forEach((element) => {
function hydrateAssets(root = elements.content) {
root.querySelectorAll("[data-docslib-asset]").forEach((element) => {
const name = element.dataset.docslibAsset;
const uri = assetDataUri(name);
if (uri && element.tagName === "IMG") element.src = uri;
@ -235,6 +235,47 @@
});
}
function removeFullPrintDocument() {
document.body.classList.remove("docslib-print-all");
document.getElementById("docslib-full-print")?.remove();
}
function PrintFullDocumentation() {
removeFullPrintDocument();
const printable = document.createElement("div");
printable.id = "docslib-full-print";
printable.className = "full-print-document";
manifest.pages.forEach((page) => {
const article = document.createElement("article");
article.className = "content print-page";
article.dataset.page = page.number;
const heading = document.createElement("header");
heading.className = "print-page-heading";
const number = document.createElement("span");
number.className = "print-page-number";
number.textContent = page.number;
const title = document.createElement("h1");
title.textContent = page.title;
heading.append(number, title);
const body = document.createElement("div");
body.className = "print-page-content";
body.innerHTML = page.content || "";
article.append(heading, body);
hydrateAssets(article);
printable.append(article);
});
document.body.append(printable);
document.body.classList.add("docslib-print-all");
requestAnimationFrame(() => requestAnimationFrame(() => window.print()));
}
globalThis.PrintFullDocumentation = PrintFullDocumentation;
window.addEventListener("afterprint", removeFullPrintDocument);
function updateActiveNavigation(number) {
document.querySelectorAll(".tree-link[data-page]").forEach((button) => {
button.classList.toggle("active", button.dataset.page === number);

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.3.7";' in html
assert 'globalThis.COMPILED_FROM_VERSION = "0.3.8";' in html
assert ".content { --custom-test: yes; }" in html
assert r'document.body.dataset.customTest = \"yes\";' in html
assert 'id="docslib-loading"' in html
@ -156,6 +156,14 @@ def test_all_endpoints_and_self_contained_build(tmp_path):
assert ".nav-arrow-previous { border-bottom-width: 2px; border-left-width: 2px; }" in html
assert ".nav-arrow-next { border-top-width: 2px; border-right-width: 2px; }" in html
assert 'arrow.textContent = direction' not in html
assert "globalThis.PrintFullDocumentation = PrintFullDocumentation" in system_js
assert 'printable.id = "docslib-full-print"' in system_js
assert "manifest.pages.forEach((page) =>" in system_js
assert 'window.addEventListener("afterprint", removeFullPrintDocument)' in system_js
system_css = manifest["client"]["css"]["system"]
assert 'body.docslib-print-all > .full-print-document { display: block; }' in system_css
assert 'color: #000 !important; background: #fff !important;' in system_css
assert ".print-page { break-after: page; page-break-after: always; }" in system_css
assert "--shell: #000000" in html
assert 'id="desktop-search-input"' in html
assert '<header class="desktop-header">' in html
@ -200,7 +208,7 @@ def test_all_endpoints_and_self_contained_build(tmp_path):
def test_build_writes_static_bundle(tmp_path):
assert __version__ == "0.3.7"
assert __version__ == "0.3.8"
@Page("1", "Static page")
def static_page():