feat: refine optional card HTML controls

This commit is contained in:
user
2026-07-15 16:47:22 +02:00
parent c66f72f73e
commit 35a609d860
2 changed files with 39 additions and 7 deletions
+3
View File
@@ -213,6 +213,9 @@
"html_css": {
"type": "string"
},
"html_tree_inspector": {
"type": "boolean"
},
"bibliography": {
"type": "string"
},
+36 -7
View File
@@ -2111,6 +2111,8 @@ def render_tree_button(alias: str, tree_ref: str, tree_index: dict[str, dict]) -
def render_step_map_html(section: dict, data: dict) -> str:
if section.get("render_step_map") is False:
return ""
steps = section.get("steps", []) or []
if not steps:
return ""
@@ -2118,7 +2120,6 @@ def render_step_map_html(section: dict, data: dict) -> str:
tree_refs = section_tree_refs(section)
aliases = {tree_ref: f"D{index + 1}" for index, tree_ref in enumerate(tree_refs)}
area = " ".join(section.get("area_refs", []) or [])
open_attr = "" if section.get("render_step_map") is False else " open"
legend = " ".join(render_tree_button(aliases[tree_ref], tree_ref, tree_index) for tree_ref in tree_refs)
rows = []
for index, step in enumerate(steps, start=1):
@@ -2132,7 +2133,7 @@ def render_step_map_html(section: dict, data: dict) -> str:
f'{html_escape(step.get("title", ""))}</div><div class="step-trees">{tokens}</div>{refs_html}</div>'
)
return (
f'<details class="step-map"{open_attr}><summary>Drzewka obszaru {html_escape(area)}</summary>'
f'<details class="step-map" open><summary>Drzewka obszaru {html_escape(area)}</summary>'
f'<div class="tree-legend">{legend}</div><div class="steps">{"".join(rows)}</div></details>'
)
@@ -2279,7 +2280,12 @@ def render_bibliography_section_html(data: dict) -> str:
def render_main_html(data: dict) -> str:
equation_numbers, figure_numbers = collect_numbered_labels(data)
card = data["card"]
tree_data = json.dumps(tree_html_data(data), ensure_ascii=False).replace("</", "<\\/")
show_tree_inspector = data.get("generated", {}).get("html_tree_inspector", True)
tree_data = (
json.dumps(tree_html_data(data), ensure_ascii=False).replace("</", "<\\/")
if show_tree_inspector
else "{}"
)
toc = "".join(
f'<a href="#{html_escape(html_id("section-" + str(index)))}">{index}. {html_escape(section.get("title", ""))}</a>'
for index, section in enumerate(data.get("sections", []), start=1)
@@ -2310,11 +2316,25 @@ def render_main_html(data: dict) -> str:
else render_latex_fragment_html(section.get("content_tex", ""), equation_numbers, figure_numbers)
)
left_margin, right_margin = render_section_margins_html(section, data)
task_identity = section.get("task_identity", {}) or {}
identity_html = ""
if task_identity:
identity_html = (
'<span class="task-identity">'
f'<strong>{html_escape(task_identity.get("label", ""))}</strong>'
f'<span class="task-identity-name">{html_escape(task_identity.get("name", ""))}</span>'
f'<code>{html_escape(task_identity.get("uuid", ""))}</code>'
"</span>"
)
heading = (
f'<h2 class="section-heading"><span class="section-index">{index}</span>'
f'<span class="section-title">{html_escape(section.get("title", ""))}</span>{identity_html}</h2>'
)
sections_html.append(
f'<article class="sheet section-sheet" id="{html_escape(html_id("section-" + str(index)))}">'
f'<aside class="pdf-margin left">{left_margin}</aside>'
f'<section class="pdf-main card-section">{render_running_header_html(card)}'
f'<h2><span>{index}</span>{html_escape(section.get("title", ""))}</h2>'
f'{heading}'
f'{render_step_map_html(section, data)}{content}</section>'
f'<aside class="pdf-margin right">{right_margin}</aside></article>'
)
@@ -2346,7 +2366,7 @@ def render_main_html(data: dict) -> str:
.hero h1{font-size:24px;line-height:1.15;margin:0 0 4px;border-bottom:1px solid #111;padding-bottom:4px}.hero .byline{float:right;margin-top:-31px;font-size:15px}
.meta{clear:both;display:grid;grid-template-columns:148px minmax(0,1fr);gap:4px 18px;padding:34px 0 24px;border-bottom:1px solid #111;font-size:17px}.meta dt{color:#333}.meta dd{margin:0;font-family:"Latin Modern Mono",ui-monospace,SFMono-Regular,Consolas,monospace}
.front-scope{padding:26px 0 10px;border-bottom:1px solid var(--line-soft)}.front-scope h2{font-size:28px;margin:0 0 12px}.front-scope p{font-size:18px}
.card-section h2{font-size:28px;line-height:1.2;margin:0 0 18px}.card-section h2 span{font-family:"Latin Modern Mono",ui-monospace,SFMono-Regular,Consolas,monospace;font-size:26px;margin-right:20px;font-weight:400}
.card-section h2{font-size:28px;line-height:1.2;margin:0 0 18px}.section-heading{display:flex;align-items:flex-start;gap:0}.section-heading .section-index{font-family:"Latin Modern Mono",ui-monospace,SFMono-Regular,Consolas,monospace;font-size:26px;margin-right:20px;font-weight:400}.section-heading .section-title{min-width:0}.task-identity{margin-left:auto;padding-left:22px;text-align:right;font-family:"Latin Modern Mono",ui-monospace,SFMono-Regular,Consolas,monospace;font-size:10px;line-height:1.25;color:#555;white-space:nowrap}.task-identity strong,.task-identity-name,.task-identity code{display:block}.task-identity strong{font-size:12px;color:#111}.task-identity-name{max-width:240px;overflow:hidden;text-overflow:ellipsis}.task-identity code{font-size:9px;color:#777}
p{font-size:17px;margin:0 0 12px}.pdf-main ul{font-size:17px;margin:8px 0 14px 24px;padding:0}.pdf-main li{margin:5px 0}
.pdf-margin{font-family:"Latin Modern Mono",ui-monospace,SFMono-Regular,Consolas,monospace;font-size:7px;line-height:1.14;color:#333;align-self:start;position:sticky;top:48px;max-height:calc(100vh - 80px);overflow:hidden}.pdf-margin.left{text-align:left}.pdf-margin.right{text-align:left}
.margin-title{font-weight:700;color:#666;margin-bottom:3px;letter-spacing:.02em}.margin-list{display:flex;flex-direction:column;align-items:flex-start}.margin-tag{display:block;margin:0 0 1px;padding:0;border:0;background:transparent;font:inherit;line-height:inherit;text-align:left;cursor:pointer;margin-left:var(--indent)}.margin-tag.we{color:var(--we)}.margin-tag.og,.margin-tag.tech{color:var(--og)}.margin-tag.kw{color:var(--kw)}.margin-tag .local{color:#777}.margin-tag:hover{text-decoration:underline}.margin-empty{color:#aaa}
@@ -2359,7 +2379,7 @@ figure{margin:24px 0;text-align:center}figure img{max-width:100%;display:block;m
.empty-check{display:inline-block;width:1em;height:1em;border:1px solid #111;vertical-align:-.12em}.answer-line,.dotfill{display:block;border-bottom:1px dotted #111;height:1.45em;min-width:10em}.write-row{display:block;min-height:2.8em}
code{font-family:"Latin Modern Mono",ui-monospace,SFMono-Regular,Consolas,monospace}.tasks{font-size:17px}.tasks li{margin:10px 0}.we-block{border-top:1px solid #ddd;padding:8px 0}.we-block summary{cursor:pointer}.dictionary-sheet .pdf-main{grid-column:2}.dictionary-sheet .pdf-margin{display:none}
.inspector{position:fixed;right:14px;bottom:14px;width:min(360px,calc(100vw - 28px));max-height:46vh;overflow:auto;background:white;border:1px solid #cfcfcf;box-shadow:0 4px 18px rgba(0,0,0,.18);border-radius:6px;padding:12px;font-family:system-ui,-apple-system,Segoe UI,sans-serif;font-size:13px;z-index:30}.inspector h2{font-size:14px;margin:0 0 8px}.inspector .empty{color:#777}.tree-card h3{font-size:15px;margin:6px 0}.tree-card code{display:inline-block;margin:4px 0}.tree-card .line{font-weight:700}.tree-card .line.OG{color:var(--og)}.tree-card .line.TECH{color:var(--tech)}.kw-list{padding-left:18px}.kw-list code{color:var(--kw)}
@media(max-width:900px){.sheet{display:block;min-height:0;padding:26px 18px}.pdf-margin{position:static;max-height:none;overflow:visible;margin:10px 0;padding:8px;border:1px solid #ddd}.pdf-margin.left{border-left:3px solid var(--tech)}.pdf-margin.right{border-left:3px solid var(--og)}.hero .byline{float:none;margin:0 0 14px}.meta{grid-template-columns:1fr}.inspector{position:static;width:auto;max-height:none;margin:0 12px 18px}.topbar{position:static}}
@media(max-width:900px){.sheet{display:block;min-height:0;padding:26px 18px}.pdf-margin{position:static;max-height:none;overflow:visible;margin:10px 0;padding:8px;border:1px solid #ddd}.pdf-margin.left{border-left:3px solid var(--tech)}.pdf-margin.right{border-left:3px solid var(--og)}.hero .byline{float:none;margin:0 0 14px}.meta{grid-template-columns:1fr}.section-heading{flex-wrap:wrap}.task-identity{width:100%;padding:6px 0 0}.inspector{position:static;width:auto;max-height:none;margin:0 12px 18px}.topbar{position:static}}
@media print{body{background:white}.topbar,.inspector{display:none}.paper{padding:0}.sheet{width:210mm;min-height:297mm;margin:0;box-shadow:none;break-after:page;padding:18mm 9mm 15mm}.pdf-margin{position:static;max-height:none;overflow:hidden}}
"""
js = r"""
@@ -2395,6 +2415,15 @@ document.addEventListener('click', event => {
}
});
"""
inspector_html = (
'<aside class="inspector"><h2>Opis kodu</h2><div id="tree-inspector">'
'<p class="empty">Kliknij kod z marginesu albo D1, D2 itd., żeby zobaczyć opis.</p>'
"</div></aside>"
if show_tree_inspector
else ""
)
if not show_tree_inspector:
js = ""
return f"""<!doctype html>
<html lang="pl">
<head>
@@ -2422,7 +2451,7 @@ document.addEventListener('click', event => {
{''.join(sections_html)}
<article class="sheet dictionary-sheet"><aside class="pdf-margin left"></aside><section class="pdf-main card-section">{render_running_header_html(card)}<h2>Słownik WE/EN/EK/KW</h2>{render_learning_tree_overview_html(data)}</section><aside class="pdf-margin right"></aside></article>
</main>
<aside class="inspector"><h2>Opis kodu</h2><div id="tree-inspector"><p class="empty">Kliknij kod z marginesu albo D1, D2 itd., żeby zobaczyć opis.</p></div></aside>
{inspector_html}
<script>{js}</script>
</body>
</html>