feat: add compact dual-QR document frame
This commit is contained in:
+6
-4
@@ -23,9 +23,10 @@ Obiekt `card` identyfikuje serię, numer, wersję, UUID, autora i status.
|
|||||||
Obiekt `generated` wskazuje ścieżki wyjściowe TeX/HTML/CSS. Pole `template`
|
Obiekt `generated` wskazuje ścieżki wyjściowe TeX/HTML/CSS. Pole `template`
|
||||||
wybiera layout.
|
wybiera layout.
|
||||||
|
|
||||||
Opcjonalny obiekt `title_block` włącza tabliczkę zasobu o wysokości dokładnie
|
Opcjonalny obiekt `title_block` włącza tabliczkę zasobu o skonfigurowanej
|
||||||
3 cm na każdej stronie, także pierwszej, bibliografii, słownika i stronach
|
wysokości 2,6 lub 3 cm na każdej stronie, także pierwszej, bibliografii,
|
||||||
kontynuacji. Tabliczka zastępuje dużą tabelę metadanych strony tytułowej.
|
słownika i stronach kontynuacji. Tabliczka zastępuje dużą tabelę metadanych
|
||||||
|
strony tytułowej.
|
||||||
Zawiera kategorię, tytuł, metadane karty, numer strony oraz widoczny,
|
Zawiera kategorię, tytuł, metadane karty, numer strony oraz widoczny,
|
||||||
kanoniczny URL. Ten sam URL jest kodowany lokalnie w QR: jako SVG w HTML i
|
kanoniczny URL. Ten sam URL jest kodowany lokalnie w QR: jako SVG w HTML i
|
||||||
przez pakiet `qrcode` w TeX. Opcjonalny `repository_url` dodaje drugi QR do
|
przez pakiet `qrcode` w TeX. Opcjonalny `repository_url` dodaje drugi QR do
|
||||||
@@ -36,7 +37,8 @@ nagłówek na każdej logicznej karcie, a wydruk używa `@page { size: A4; }` or
|
|||||||
pól marginesu, dlatego nagłówek powtarza się również po automatycznym podziale
|
pól marginesu, dlatego nagłówek powtarza się również po automatycznym podziale
|
||||||
długiej sekcji.
|
długiej sekcji.
|
||||||
|
|
||||||
Pola `height_cm: 3`, `repeat_on_every_page: true` i
|
Pole `height_cm` przyjmuje `2.6` (kompaktowy nagłówek z QR 22 mm i równym
|
||||||
|
światłem) albo `3`; pola `repeat_on_every_page: true` i
|
||||||
`replace_front_matter: true` dokumentują ten kontrakt. `show_qr: true` wymaga
|
`replace_front_matter: true` dokumentują ten kontrakt. `show_qr: true` wymaga
|
||||||
kanonicznego adresu HTTP(S) w `url` albo pary `url_host_uuid`/`doc_uuid`, z
|
kanonicznego adresu HTTP(S) w `url` albo pary `url_host_uuid`/`doc_uuid`, z
|
||||||
której powstaje `https://<url_host_uuid>/<doc_uuid>`.
|
której powstaje `https://<url_host_uuid>/<doc_uuid>`.
|
||||||
|
|||||||
@@ -311,7 +311,7 @@
|
|||||||
},
|
},
|
||||||
"show_qr": { "type": "boolean" },
|
"show_qr": { "type": "boolean" },
|
||||||
"show_repository_qr": { "type": "boolean" },
|
"show_repository_qr": { "type": "boolean" },
|
||||||
"height_cm": { "const": 3 },
|
"height_cm": { "enum": [2.6, 3] },
|
||||||
"repeat_on_every_page": { "const": true },
|
"repeat_on_every_page": { "const": true },
|
||||||
"replace_front_matter": { "const": true }
|
"replace_front_matter": { "const": true }
|
||||||
},
|
},
|
||||||
|
|||||||
+211
-114
@@ -422,8 +422,8 @@ def validate_source(data: dict) -> None:
|
|||||||
errors.append(
|
errors.append(
|
||||||
"title_block.show_qr=true wymaga title_block.url albo pary url_host_uuid/doc_uuid"
|
"title_block.show_qr=true wymaga title_block.url albo pary url_host_uuid/doc_uuid"
|
||||||
)
|
)
|
||||||
if title_block.get("height_cm", 3) not in (3, 3.0):
|
if title_block.get("height_cm", 3) not in (2.6, 3, 3.0):
|
||||||
errors.append("title_block.height_cm musi wynosić dokładnie 3")
|
errors.append("title_block.height_cm musi wynosić 2.6 albo 3")
|
||||||
if title_block.get("repeat_on_every_page", True) is not True:
|
if title_block.get("repeat_on_every_page", True) is not True:
|
||||||
errors.append("title_block.repeat_on_every_page musi być true")
|
errors.append("title_block.repeat_on_every_page musi być true")
|
||||||
if title_block.get("replace_front_matter", True) is not True:
|
if title_block.get("replace_front_matter", True) is not True:
|
||||||
@@ -672,6 +672,10 @@ def macro(name: str, value: str) -> str:
|
|||||||
|
|
||||||
def render_preamble(data: dict) -> list[str]:
|
def render_preamble(data: dict) -> list[str]:
|
||||||
card = data["card"]
|
card = data["card"]
|
||||||
|
header_height_mm = resource_header_height_mm(data)
|
||||||
|
source_url = repository_url(data)
|
||||||
|
doc_uuid = str((data.get("title_block") or {}).get("doc_uuid", ""))
|
||||||
|
card_number = f"{card.get('number', '')}/{card.get('count', '')}"
|
||||||
return [
|
return [
|
||||||
r"\documentclass[12pt,a4paper]{article}",
|
r"\documentclass[12pt,a4paper]{article}",
|
||||||
"",
|
"",
|
||||||
@@ -683,7 +687,7 @@ def render_preamble(data: dict) -> list[str]:
|
|||||||
r"\usepackage{amsmath}",
|
r"\usepackage{amsmath}",
|
||||||
r"\usepackage{amssymb}",
|
r"\usepackage{amssymb}",
|
||||||
r"\usepackage{xcolor}",
|
r"\usepackage{xcolor}",
|
||||||
r"\usepackage[a4paper,left=2.15cm,right=2.15cm,top=3.75cm,bottom=2.2cm,includehead]{geometry}",
|
rf"\usepackage[a4paper,left=2.15cm,right=2.15cm,top=0.5cm,bottom=0.5cm,headheight={header_height_mm:g}mm,headsep=3mm,footskip=8mm,includehead,includefoot]{{geometry}}",
|
||||||
r"\usepackage{eso-pic}",
|
r"\usepackage{eso-pic}",
|
||||||
r"\usepackage{marginnote}",
|
r"\usepackage{marginnote}",
|
||||||
r"\usepackage{array}",
|
r"\usepackage{array}",
|
||||||
@@ -726,9 +730,9 @@ def render_preamble(data: dict) -> list[str]:
|
|||||||
r"\newcommand{\EscWriteRow}[1][2.8em]{\rule{0pt}{#1}}",
|
r"\newcommand{\EscWriteRow}[1][2.8em]{\rule{0pt}{#1}}",
|
||||||
r"\setlength{\parindent}{0pt}",
|
r"\setlength{\parindent}{0pt}",
|
||||||
r"\setlength{\parskip}{0.45em}",
|
r"\setlength{\parskip}{0.45em}",
|
||||||
r"\setlength{\headheight}{30mm}",
|
rf"\setlength{{\headheight}}{{{header_height_mm:g}mm}}",
|
||||||
r"\setlength{\headsep}{3mm}",
|
r"\setlength{\headsep}{3mm}",
|
||||||
r"\setlength{\footskip}{24pt}",
|
r"\setlength{\footskip}{8mm}",
|
||||||
r"\setlength{\marginparwidth}{1.5cm}",
|
r"\setlength{\marginparwidth}{1.5cm}",
|
||||||
r"\setlength{\marginparsep}{0.25cm}",
|
r"\setlength{\marginparsep}{0.25cm}",
|
||||||
r"\renewcommand{\arraystretch}{1.22}",
|
r"\renewcommand{\arraystretch}{1.22}",
|
||||||
@@ -738,10 +742,18 @@ def render_preamble(data: dict) -> list[str]:
|
|||||||
r"\pagestyle{fancy}",
|
r"\pagestyle{fancy}",
|
||||||
r"\fancyhf{}",
|
r"\fancyhf{}",
|
||||||
r"\fancyhead[C]{\ESCPageResourceHeader}",
|
r"\fancyhead[C]{\ESCPageResourceHeader}",
|
||||||
r"\lfoot{\scriptsize rewizja \BuildCommit}",
|
r"\fancyfoot[C]{%",
|
||||||
r"\cfoot{\scriptsize \thepage/\pageref{LastPage}}",
|
r" \begin{minipage}{\textwidth}%",
|
||||||
r"\rfoot{\scriptsize \DocumentUUID}",
|
r" \hrule height0.35pt\vspace{0.5mm}%",
|
||||||
|
r" \fontsize{4.2}{4.8}\selectfont\ttfamily%",
|
||||||
|
r" \begin{tabularx}{\textwidth}{@{}p{27mm}p{49mm}Xr@{}}%",
|
||||||
|
rf" \textbf{{KARTA}} {tex_escape(card_number)} & \textbf{{UUID}} {tex_escape(card.get('uuid', ''))} & \textbf{{DOKUMENT}} {tex_escape(doc_uuid)} & \textbf{{ARKUSZ}} \thepage/\pageref{{LastPage}} \\%",
|
||||||
|
rf" \textbf{{WERSJA}} {tex_escape(card.get('version', ''))} · {tex_escape(card.get('revision_date', ''))} & \multicolumn{{2}}{{l}}{{\fontsize{{3.6}}{{4.1}}\selectfont\textbf{{GITEA}} \href{{{source_url}}}{{\nolinkurl{{{source_url}}}}}}} & \textbf{{AUTOR}} {tex_escape(card.get('author', ''))}%",
|
||||||
|
r" \end{tabularx}%",
|
||||||
|
r" \end{minipage}%",
|
||||||
|
r"}",
|
||||||
r"\renewcommand{\headrulewidth}{0pt}",
|
r"\renewcommand{\headrulewidth}{0pt}",
|
||||||
|
r"\renewcommand{\footrulewidth}{0pt}",
|
||||||
"",
|
"",
|
||||||
r"\newcommand{\ESCMarginTag}[4]{%",
|
r"\newcommand{\ESCMarginTag}[4]{%",
|
||||||
r" \hspace*{#1}\textcolor{#2}{#3~#4}%",
|
r" \hspace*{#1}\textcolor{#2}{#3~#4}%",
|
||||||
@@ -2849,7 +2861,8 @@ def render_main_html(data: dict) -> str:
|
|||||||
f'<section class="pdf-main card-section">{render_running_header_html(card) if not use_resource_header else ""}'
|
f'<section class="pdf-main card-section">{render_running_header_html(card) if not use_resource_header else ""}'
|
||||||
f'{heading}'
|
f'{heading}'
|
||||||
f'{render_step_map_html(section, data)}{content}</section>'
|
f'{render_step_map_html(section, data)}{content}</section>'
|
||||||
f'<aside class="pdf-margin right">{right_margin}</aside></article>'
|
f'<aside class="pdf-margin right">{right_margin}</aside>'
|
||||||
|
f'{render_page_footer_html(data, page_number, total_pages) if use_resource_header else ""}</article>'
|
||||||
)
|
)
|
||||||
if bibliography_html:
|
if bibliography_html:
|
||||||
bibliography_page = len(data.get("sections", [])) + 2
|
bibliography_page = len(data.get("sections", [])) + 2
|
||||||
@@ -2859,7 +2872,8 @@ def render_main_html(data: dict) -> str:
|
|||||||
f'<aside class="pdf-margin left"></aside>'
|
f'<aside class="pdf-margin left"></aside>'
|
||||||
f'<section class="pdf-main card-section">{render_running_header_html(card) if not use_resource_header else ""}'
|
f'<section class="pdf-main card-section">{render_running_header_html(card) if not use_resource_header else ""}'
|
||||||
f'<h2>Bibliografia i źródła</h2>{bibliography_html}</section>'
|
f'<h2>Bibliografia i źródła</h2>{bibliography_html}</section>'
|
||||||
f'<aside class="pdf-margin right"></aside></article>'
|
f'<aside class="pdf-margin right"></aside>'
|
||||||
|
f'{render_page_footer_html(data, bibliography_page, total_pages) if use_resource_header else ""}</article>'
|
||||||
)
|
)
|
||||||
|
|
||||||
scope = data.get("front_page_scope", {})
|
scope = data.get("front_page_scope", {})
|
||||||
@@ -2882,17 +2896,17 @@ def render_main_html(data: dict) -> str:
|
|||||||
|
|
||||||
css = r"""
|
css = r"""
|
||||||
:root{--ink:#111;--muted:#666;--line:#b9b9b9;--line-soft:#dddddd;--paper:#fff;--desk:#eeeeee;--og:#008000;--tech:#d36b00;--kw:#0018c8;--we:#e00000}
|
:root{--ink:#111;--muted:#666;--line:#b9b9b9;--line-soft:#dddddd;--paper:#fff;--desk:#eeeeee;--og:#008000;--tech:#d36b00;--kw:#0018c8;--we:#e00000}
|
||||||
*{box-sizing:border-box} html{scroll-behavior:smooth} body{margin:0;background:var(--desk);color:var(--ink);font-family:Georgia,"Times New Roman",serif;line-height:1.42}
|
*{box-sizing:border-box} html{scroll-behavior:smooth} body{margin:0;background:var(--desk);color:var(--ink);font-family:"Latin Modern Roman","LM Roman 12",Georgia,"Times New Roman",serif;line-height:1.25}
|
||||||
.topbar{position:sticky;top:0;z-index:20;background:rgba(245,245,245,.94);border-bottom:1px solid #d0d0d0;padding:8px 14px;font-family:system-ui,-apple-system,Segoe UI,sans-serif}
|
.topbar{position:sticky;top:0;z-index:20;background:rgba(245,245,245,.94);border-bottom:1px solid #d0d0d0;padding:8px 14px;font-family:system-ui,-apple-system,Segoe UI,sans-serif}
|
||||||
.topbar details{max-width:1120px;margin:0 auto}.topbar summary{cursor:pointer;font-weight:650}.toc-links{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}.toc-links a{font-size:13px;color:#333;text-decoration:none;border:1px solid #ccc;background:white;border-radius:4px;padding:3px 7px}
|
.topbar details{max-width:1120px;margin:0 auto}.topbar summary{cursor:pointer;font-weight:650}.toc-links{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}.toc-links a{font-size:13px;color:#333;text-decoration:none;border:1px solid #ccc;background:white;border-radius:4px;padding:3px 7px}
|
||||||
.paper{padding:18px 12px 44px;overflow-x:auto}.sheet{width:210mm;min-height:297mm;margin:0 auto 18px;background:var(--paper);box-shadow:0 2px 12px rgba(0,0,0,.13);display:grid;grid-template-columns:22mm minmax(0,1fr) 22mm;column-gap:4mm;align-content:start;padding:13mm 21.5mm 11mm}.resource-header-enabled .sheet{padding-top:5mm;row-gap:0}
|
.paper{padding:18px 12px 44px;overflow-x:auto}.sheet{position:relative;width:210mm;min-height:297mm;margin:0 auto 18px;background:var(--paper);box-shadow:0 2px 12px rgba(0,0,0,.13);display:block;padding:13mm 21.5mm 15mm}.resource-header-enabled .sheet{padding-top:5mm}.sheet>.page-resource-header{margin-bottom:3mm}
|
||||||
.pdf-main{min-width:0}.running-header{display:flex;justify-content:space-between;gap:18px;align-items:flex-end;border-bottom:1px solid #111;padding-bottom:3px;margin-bottom:26px;font-size:15px}.running-header span{white-space:nowrap}
|
.pdf-main{min-width:0;width:100%}.running-header{display:flex;justify-content:space-between;gap:18px;align-items:flex-end;border-bottom:1px solid #111;padding-bottom:3px;margin-bottom:26px;font-size:15px}.running-header span{white-space:nowrap}
|
||||||
.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}
|
.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}
|
.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}
|
.front-scope{padding:0 0 3mm;border-bottom:1px solid var(--line-soft)}.front-scope h2{font-size:24px;line-height:1.15;margin:0 0 3mm}.front-scope p{font-size:16px}
|
||||||
.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}
|
.card-section h2{font-size:24px;line-height:1.15;margin:0 0 4mm}.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:23px;margin-right:12mm;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}
|
p{font-size:16px;margin:0 0 3mm}.pdf-main ul{font-size:16px;margin:2mm 0 3mm 7mm;padding:0}.pdf-main li{margin:1.2mm 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}
|
.pdf-margin{position:absolute;top:34mm;width:18mm;font-family:"Latin Modern Mono",ui-monospace,SFMono-Regular,Consolas,monospace;font-size:5px;line-height:1.12;color:#333;max-height:245mm;overflow:hidden}.pdf-margin.left{left:2mm;text-align:left}.pdf-margin.right{right:2mm;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}
|
.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}
|
||||||
.step-map{font-family:"Latin Modern Mono",ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px;line-height:1.3;color:#5c5c5c;background:transparent;border:0;border-top:1px solid #cfcfcf;border-bottom:1px solid #e0e0e0;border-radius:0;padding:8px 0;margin:0 0 16px}.step-map summary{cursor:pointer;font-weight:400;color:#555}
|
.step-map{font-family:"Latin Modern Mono",ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px;line-height:1.3;color:#5c5c5c;background:transparent;border:0;border-top:1px solid #cfcfcf;border-bottom:1px solid #e0e0e0;border-radius:0;padding:8px 0;margin:0 0 16px}.step-map summary{cursor:pointer;font-weight:400;color:#555}
|
||||||
.tree-legend{display:flex;flex-wrap:wrap;gap:4px;margin:7px 0}.steps{display:grid;gap:6px}.step-row{border-top:1px dashed #c9c9c9;padding-top:6px}.step-row:first-child{border-top:0}.step-title span{font-weight:700;margin-right:7px}.step-trees{display:flex;flex-wrap:wrap;gap:4px;margin-top:3px}.step-refs{display:flex;flex-wrap:wrap;gap:6px;margin-top:3px}.step-refs a{font-size:10px;color:#666}
|
.tree-legend{display:flex;flex-wrap:wrap;gap:4px;margin:7px 0}.steps{display:grid;gap:6px}.step-row{border-top:1px dashed #c9c9c9;padding-top:6px}.step-row:first-child{border-top:0}.step-title span{font-weight:700;margin-right:7px}.step-trees{display:flex;flex-wrap:wrap;gap:4px;margin-top:3px}.step-refs{display:flex;flex-wrap:wrap;gap:6px;margin-top:3px}.step-refs a{font-size:10px;color:#666}
|
||||||
@@ -2901,12 +2915,12 @@ p{font-size:17px;margin:0 0 12px}.pdf-main ul{font-size:17px;margin:8px 0 14px 2
|
|||||||
figure{margin:24px 0;text-align:center}figure img{max-width:100%;display:block;margin:0 auto;border:0;border-radius:0}figcaption{font-size:14px;color:#444;margin-top:8px;text-align:left}.card-asset.asset-screenshot img{border:1px solid #aaa}.card-asset a{display:block;cursor:zoom-in}
|
figure{margin:24px 0;text-align:center}figure img{max-width:100%;display:block;margin:0 auto;border:0;border-radius:0}figcaption{font-size:14px;color:#444;margin-top:8px;text-align:left}.card-asset.asset-screenshot img{border:1px solid #aaa}.card-asset a{display:block;cursor:zoom-in}
|
||||||
.table-wrap{overflow:auto;margin:14px 0}table{border-collapse:collapse;width:100%;font-size:16px}th,td{border:1px solid #111;padding:5px 8px;text-align:left;vertical-align:top}th{font-weight:400;background:white}
|
.table-wrap{overflow:auto;margin:14px 0}table{border-collapse:collapse;width:100%;font-size:16px}th,td{border:1px solid #111;padding:5px 8px;text-align:left;vertical-align:top}th{font-weight:400;background:white}
|
||||||
.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}
|
.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}.task-legacy{margin:10px 0}.task-legacy>strong{display:block;font:700 11px/1.2 "Latin Modern Mono",ui-monospace,monospace;color:#555}.task-flow{border:1px solid #aaa;margin:8px 0 18px}.task-flow-header{display:grid;grid-template-columns:auto 1fr auto;align-items:baseline;gap:10px;padding:8px 11px;background:#f3f3f3;border-bottom:1px solid #aaa}.task-flow-header span{font:700 10px/1.2 "Latin Modern Mono",ui-monospace,monospace;color:#555}.task-flow-header h3{font-size:18px;margin:0}.task-flow-header code{font-size:8px;color:#777}.task-block,.task-exercise{margin:10px 12px;padding:0 0 10px;border-bottom:1px solid #ddd}.task-block header,.task-exercise header{display:flex;align-items:baseline;gap:8px;margin-bottom:6px}.task-block header span,.task-exercise header span{font:700 9px/1.2 "Latin Modern Mono",ui-monospace,monospace;text-transform:uppercase;color:#666}.task-block h4,.task-exercise h4{font-size:16px;margin:0}.block-steps{counter-reset:block-step;margin:5px 0 0 24px!important}.block-steps li{margin:7px 0}.block-steps li::marker{font-family:"Latin Modern Mono",ui-monospace,monospace}.task-exercise{border:1px solid #777;border-left:4px solid #111;padding:9px 11px;background:#fafafa}.task-exercise header{flex-wrap:wrap}.exercise-based-on{margin-left:auto;font-size:8px;color:#777}.exercise-evidence{border-top:1px dashed #bbb;margin-top:8px;padding-top:6px}.exercise-evidence>strong{font-size:11px;text-transform:uppercase}.exercise-criterion{font-size:13px;margin:7px 0 0}.task-flow>footer{padding:8px 11px;border-top:1px solid #aaa;font-size:12px}.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}
|
code{font-family:"Latin Modern Mono",ui-monospace,SFMono-Regular,Consolas,monospace}.tasks{font-size:16px}.task-legacy{margin:2.5mm 0}.task-legacy>strong{display:block;font:700 10px/1.2 "Latin Modern Mono",ui-monospace,monospace;color:#555}.task-flow{border:1px solid #aaa;margin:2mm 0 4mm}.task-flow-header{display:grid;grid-template-columns:auto 1fr auto;align-items:baseline;gap:10px;padding:8px 11px;background:#f3f3f3;border-bottom:1px solid #aaa}.task-flow-header span{font:700 10px/1.2 "Latin Modern Mono",ui-monospace,monospace;color:#555}.task-flow-header h3{font-size:18px;margin:0}.task-flow-header code{font-size:8px;color:#777}.task-block,.task-exercise{margin:10px 12px;padding:0 0 10px;border-bottom:1px solid #ddd}.task-block header,.task-exercise header{display:flex;align-items:baseline;gap:8px;margin-bottom:6px}.task-block header span,.task-exercise header span{font:700 9px/1.2 "Latin Modern Mono",ui-monospace,monospace;text-transform:uppercase;color:#666}.task-block h4,.task-exercise h4{font-size:16px;margin:0}.block-steps{counter-reset:block-step;margin:5px 0 0 24px!important}.block-steps li{margin:7px 0}.block-steps li::marker{font-family:"Latin Modern Mono",ui-monospace,monospace}.task-exercise{border:1px solid #777;border-left:4px solid #111;padding:9px 11px;background:#fafafa}.task-exercise header{flex-wrap:wrap}.exercise-based-on{margin-left:auto;font-size:8px;color:#777}.exercise-evidence{border-top:1px dashed #bbb;margin-top:8px;padding-top:6px}.exercise-evidence>strong{font-size:11px;text-transform:uppercase}.exercise-criterion{font-size:13px;margin:7px 0 0}.task-flow>footer{padding:8px 11px;border-top:1px solid #aaa;font-size:12px}.we-block{border-top:1px solid #ddd;padding:8px 0}.we-block summary{cursor:pointer}.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)}
|
.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}.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(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{html,body{background:white}.topbar,.inspector{display:none}.paper{padding:0}.sheet{display:grid;grid-template-columns:22mm minmax(0,1fr) 22mm;column-gap:4mm;width:auto;min-height:0;margin:0;box-shadow:none;break-after:page;padding:0;row-gap:6mm}.sheet:last-child{break-after:auto}.resource-header-enabled .sheet{padding:0;row-gap:6mm}.sheet>.page-resource-header{display:none!important}.pdf-margin{position:static;max-height:none;overflow:hidden;margin:0;padding:0;border:0}.task-block,.task-exercise,figure{break-inside:avoid}}
|
@media print{html,body{background:white}.topbar,.inspector{display:none}.paper{padding:0}.sheet{position:relative;display:block;width:auto;min-height:0;margin:0;box-shadow:none;break-after:page;padding:0}.sheet:last-child{break-after:auto}.resource-header-enabled .sheet{padding:0}.sheet>.page-resource-header,.sheet>.page-resource-footer{display:none!important}.pdf-margin{position:absolute;top:0;width:18mm;max-height:none;overflow:hidden;margin:0;padding:0;border:0}.pdf-margin.left{left:-19.5mm}.pdf-margin.right{right:-19.5mm}.task-block,.task-exercise,figure{break-inside:avoid}}
|
||||||
"""
|
"""
|
||||||
css += page_resource_header_css()
|
css += page_resource_header_css(data)
|
||||||
if use_resource_header:
|
if use_resource_header:
|
||||||
css += page_resource_print_css(data)
|
css += page_resource_print_css(data)
|
||||||
js = r"""
|
js = r"""
|
||||||
@@ -2974,9 +2988,10 @@ document.addEventListener('click', event => {
|
|||||||
{front_intro_html}
|
{front_intro_html}
|
||||||
</section>
|
</section>
|
||||||
<aside class="pdf-margin right">{front_right}</aside>
|
<aside class="pdf-margin right">{front_right}</aside>
|
||||||
|
{render_page_footer_html(data, 1, total_pages) if use_resource_header else ''}
|
||||||
</article>
|
</article>
|
||||||
{''.join(sections_html)}
|
{''.join(sections_html)}
|
||||||
<article class="sheet dictionary-sheet">{render_page_header_html(data, dictionary_page, total_pages) if use_resource_header else ''}<aside class="pdf-margin left"></aside><section class="pdf-main card-section">{render_running_header_html(card) if not use_resource_header else ''}<h2>Słownik WE/EN/EK/KW</h2>{render_learning_tree_overview_html(data)}</section><aside class="pdf-margin right"></aside></article>
|
<article class="sheet dictionary-sheet">{render_page_header_html(data, dictionary_page, total_pages) if use_resource_header else ''}<aside class="pdf-margin left"></aside><section class="pdf-main card-section">{render_running_header_html(card) if not use_resource_header else ''}<h2>Słownik WE/EN/EK/KW</h2>{render_learning_tree_overview_html(data)}</section><aside class="pdf-margin right"></aside>{render_page_footer_html(data, dictionary_page, total_pages) if use_resource_header else ''}</article>
|
||||||
</main>
|
</main>
|
||||||
{inspector_html}
|
{inspector_html}
|
||||||
<script>{js}</script>
|
<script>{js}</script>
|
||||||
@@ -3084,6 +3099,12 @@ def title_block_fields(data: dict) -> dict[str, str | bool]:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def resource_header_height_mm(data: dict) -> float:
|
||||||
|
"""Return the configured repeated-header height in millimetres."""
|
||||||
|
configured = data.get("title_block") or {}
|
||||||
|
return float(configured.get("height_cm", 3)) * 10
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=32)
|
@lru_cache(maxsize=32)
|
||||||
def qr_svg(value: str) -> str:
|
def qr_svg(value: str) -> str:
|
||||||
"""Generate a self-contained QR SVG without a network dependency.
|
"""Generate a self-contained QR SVG without a network dependency.
|
||||||
@@ -3181,7 +3202,7 @@ def qr_svg_from_tex(value: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def render_page_header_html(data: dict, page: int, total: int) -> str:
|
def render_page_header_html(data: dict, page: int, total: int) -> str:
|
||||||
"""Render the canonical 30 mm resource header used by every page wrapper."""
|
"""Render the configured resource header used by every page wrapper."""
|
||||||
card = data["card"]
|
card = data["card"]
|
||||||
fields = title_block_fields(data)
|
fields = title_block_fields(data)
|
||||||
url = str(fields["url"])
|
url = str(fields["url"])
|
||||||
@@ -3212,62 +3233,104 @@ def render_page_header_html(data: dict, page: int, total: int) -> str:
|
|||||||
else ""
|
else ""
|
||||||
)
|
)
|
||||||
|
|
||||||
def datum(label: str, value: object, class_name: str = "") -> str:
|
|
||||||
suffix = f" {class_name}" if class_name else ""
|
|
||||||
return (
|
|
||||||
f'<div class="resource-datum{suffix}"><span>{html_escape(label)}</span>'
|
|
||||||
f'<strong>{html_escape(value or "—")}</strong></div>'
|
|
||||||
)
|
|
||||||
|
|
||||||
card_number = f"{card.get('number', '')}/{card.get('count', '')}"
|
card_number = f"{card.get('number', '')}/{card.get('count', '')}"
|
||||||
sheet_number = f"{page}/{total}"
|
sheet_number = f"{page}/{total}"
|
||||||
header_class = "page-resource-header page-resource-header--dual" if repository_qr_html else "page-resource-header"
|
header_class = "page-resource-header page-resource-header--dual" if repository_qr_html else "page-resource-header"
|
||||||
source_link = (
|
|
||||||
f'<a class="resource-url resource-repository-url" href="{html_escape(source_url)}">'
|
def inline_fields(items: list[tuple[str, object]], strong_first: bool = False) -> str:
|
||||||
f'<span>GITEA</span>{html_escape(source_url)}</a>'
|
rendered: list[str] = []
|
||||||
if source_url
|
for index, (label, value) in enumerate(items):
|
||||||
else ""
|
if index:
|
||||||
|
rendered.append('<span class="resource-separator">|</span>')
|
||||||
|
rendered.append(f'<span class="resource-label">{html_escape(label)}</span>')
|
||||||
|
tag = "strong" if strong_first and index == 0 else "span"
|
||||||
|
rendered.append(f'<{tag} class="resource-value">{html_escape(value or "—")}</{tag}>')
|
||||||
|
return '<div class="resource-inline">' + "".join(rendered) + "</div>"
|
||||||
|
|
||||||
|
primary_rows = [
|
||||||
|
inline_fields(
|
||||||
|
[
|
||||||
|
(fields["category"], f"{card_prefix(card)}: {card.get('title', '')}"),
|
||||||
|
],
|
||||||
|
strong_first=True,
|
||||||
|
),
|
||||||
|
inline_fields(
|
||||||
|
[
|
||||||
|
("Projekt", card.get("project", "")),
|
||||||
|
("Seria", card.get("series_title", card.get("series", ""))),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
inline_fields(
|
||||||
|
[
|
||||||
|
("Przedmiot", card.get("subject", "")),
|
||||||
|
("Poziom", card.get("level", "")),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
inline_fields([("HTML", url or "brak URL")]),
|
||||||
|
]
|
||||||
|
meta_rows = [
|
||||||
|
inline_fields(
|
||||||
|
[("Data", card.get("revision_date", "")), ("Status", card.get("status", ""))]
|
||||||
|
),
|
||||||
|
inline_fields([("Karta", card_number), ("Wersja", card.get("version", ""))]),
|
||||||
|
inline_fields([("Autor", card.get("author", "")), ("Arkusz", sheet_number)]),
|
||||||
|
inline_fields([("UUID", card.get("uuid", ""))]),
|
||||||
|
]
|
||||||
|
column_group = (
|
||||||
|
'<col style="width:24mm"><col><col style="width:39mm"><col style="width:24mm">'
|
||||||
|
if repository_qr_html
|
||||||
|
else '<col><col style="width:47mm"><col style="width:24mm">'
|
||||||
)
|
)
|
||||||
|
rows: list[str] = []
|
||||||
|
for index, (primary, meta) in enumerate(zip(primary_rows, meta_rows)):
|
||||||
|
cells: list[str] = []
|
||||||
|
if index == 0 and repository_qr_html:
|
||||||
|
cells.append(f'<td rowspan="4" class="resource-qr-cell resource-qr-cell--left">{repository_qr_html}</td>')
|
||||||
|
cells.append(f'<td class="resource-header-cell resource-header-cell--primary">{primary}</td>')
|
||||||
|
cells.append(f'<td class="resource-header-cell resource-header-cell--meta">{meta}</td>')
|
||||||
|
if index == 0:
|
||||||
|
cells.append(f'<td rowspan="4" class="resource-qr-cell resource-qr-cell--right">{page_qr_html}</td>')
|
||||||
|
rows.append("<tr>" + "".join(cells) + "</tr>")
|
||||||
|
|
||||||
return (
|
return (
|
||||||
f'<header class="{header_class}" data-resource-url="{html_escape(url)}" '
|
f'<header class="{header_class}" data-resource-url="{html_escape(url)}" '
|
||||||
f'data-repository-url="{html_escape(source_url)}" '
|
f'data-repository-url="{html_escape(source_url)}" '
|
||||||
f'data-page="{page}" data-page-total="{total}">'
|
f'data-page="{page}" data-page-total="{total}">'
|
||||||
f'{repository_qr_html}'
|
f'<table class="resource-header-table"><colgroup>{column_group}</colgroup>'
|
||||||
'<div class="resource-primary">'
|
f'<tbody>{"".join(rows)}</tbody></table>'
|
||||||
f'<div class="resource-title"><span>{html_escape(fields["category"])}</span>'
|
|
||||||
f'<strong>{html_escape(card_prefix(card))}: {html_escape(card.get("title", ""))}</strong></div>'
|
|
||||||
'<div class="resource-details">'
|
|
||||||
f'{datum("Projekt", card.get("project", ""))}'
|
|
||||||
f'{datum("Seria", card.get("series_title", card.get("series", "")))}'
|
|
||||||
f'{datum("Przedmiot", card.get("subject", ""))}'
|
|
||||||
f'{datum("Poziom", card.get("level", ""), "resource-level")}'
|
|
||||||
'</div>'
|
|
||||||
'<div class="resource-urls">'
|
|
||||||
f'{source_link}'
|
|
||||||
f'<a class="resource-url" href="{html_escape(url)}"><span>HTML</span>{html_escape(url or "brak URL")}</a>'
|
|
||||||
'</div>'
|
|
||||||
'</div>'
|
|
||||||
'<div class="resource-meta">'
|
|
||||||
f'{datum("Data", card.get("revision_date", ""))}'
|
|
||||||
f'{datum("Status", card.get("status", ""))}'
|
|
||||||
f'{datum("Karta", card_number)}'
|
|
||||||
f'{datum("Wersja", card.get("version", ""))}'
|
|
||||||
f'{datum("Autor", card.get("author", ""))}'
|
|
||||||
f'{datum("Arkusz", sheet_number)}'
|
|
||||||
f'{datum("UUID", card.get("uuid", ""), "resource-uuid")}'
|
|
||||||
'</div>'
|
|
||||||
f'{page_qr_html}'
|
|
||||||
'</header>'
|
'</header>'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def page_resource_header_css() -> str:
|
def render_page_footer_html(data: dict, page: int, total: int) -> str:
|
||||||
|
"""Render the compact per-sheet footer used by the HTML A4 preview."""
|
||||||
|
card = data["card"]
|
||||||
|
title_block = data.get("title_block") or {}
|
||||||
|
doc_uuid = str(title_block.get("doc_uuid", ""))
|
||||||
|
source_url = repository_url(data)
|
||||||
|
card_number = f"{card.get('number', '')}/{card.get('count', '')}"
|
||||||
|
return (
|
||||||
|
'<footer class="page-resource-footer" role="contentinfo"><table><tbody>'
|
||||||
|
'<tr>'
|
||||||
|
f'<td><b>KARTA</b> {html_escape(card_number)}</td>'
|
||||||
|
f'<td><b>UUID</b> {html_escape(card.get("uuid", ""))}</td>'
|
||||||
|
f'<td><b>DOKUMENT</b> {html_escape(doc_uuid)}</td>'
|
||||||
|
f'<td class="footer-right"><b>ARKUSZ</b> {page}/{total}</td>'
|
||||||
|
'</tr><tr>'
|
||||||
|
f'<td><b>WERSJA</b> {html_escape(card.get("version", ""))} · {html_escape(card.get("revision_date", ""))}</td>'
|
||||||
|
f'<td colspan="2"><b>GITEA</b> {html_escape(source_url)}</td>'
|
||||||
|
f'<td class="footer-right"><b>AUTOR</b> {html_escape(card.get("author", ""))}</td>'
|
||||||
|
'</tr></tbody></table></footer>'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def page_resource_header_css(data: dict) -> str:
|
||||||
return r"""
|
return r"""
|
||||||
.page-resource-header{grid-column:1/-1;width:100%;height:30mm;min-height:30mm;max-height:30mm;border:1px solid #1c1c1a;display:grid;grid-template-columns:minmax(0,1fr) 47mm 24mm;background:#fff;color:#111;overflow:hidden;font-family:system-ui,-apple-system,"Segoe UI",sans-serif;line-height:1.12}.page-resource-header--dual{grid-template-columns:24mm minmax(0,1fr) 39mm 24mm}
|
.page-resource-header{width:100%;height:__RESOURCE_HEADER_HEIGHT__;min-height:__RESOURCE_HEADER_HEIGHT__;max-height:__RESOURCE_HEADER_HEIGHT__;background:#fff;color:#111;overflow:hidden;font-family:ui-monospace,SFMono-Regular,"Latin Modern Mono",Consolas,monospace;line-height:1.08}
|
||||||
.resource-qr{box-sizing:border-box;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.35mm;border-right:1px solid #aaa;padding:.65mm .8mm;color:#555;text-decoration:none;font-size:7px}.resource-qr-page{border-right:0}.resource-qr .title-qr{display:block;width:22mm;height:22mm;max-width:22mm;max-height:22mm;flex:none}.resource-qr-label{font:700 5px/1 ui-monospace,SFMono-Regular,Consolas,monospace;letter-spacing:.08em;color:#444}.resource-qr-empty{text-align:center}.resource-qr-empty span,.resource-qr-empty strong{display:block;font:600 5.5px/1.15 ui-monospace,SFMono-Regular,Consolas,monospace}
|
.resource-header-table{width:100%;height:100%;border-collapse:collapse;table-layout:fixed;border:1px solid #111;font:600 5pt/1.05 ui-monospace,SFMono-Regular,"Latin Modern Mono",Consolas,monospace}.resource-header-table tr{height:25%}.resource-header-cell{padding:.25mm .65mm;border-right:1px solid #777;border-bottom:1px solid #aaa;vertical-align:middle;overflow:hidden}.resource-header-table tr:last-child .resource-header-cell{border-bottom:0}.resource-header-cell--meta{border-right:1px solid #777}.resource-inline{display:flex;align-items:baseline;gap:.55mm;min-width:0;white-space:nowrap;overflow:hidden}.resource-label{font-weight:700;text-transform:uppercase;flex:none}.resource-value{font:inherit;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.resource-header-table tr:first-child .resource-header-cell--primary .resource-value{font-weight:800;font-size:6pt}.resource-separator{color:#999;flex:none}
|
||||||
.resource-primary{min-width:0;display:flex;flex-direction:column;justify-content:center;padding:1mm;border-right:1px solid #aaa;font:600 5.3px/1.2 ui-monospace,SFMono-Regular,Consolas,monospace}.resource-title{display:flex;flex-direction:column;min-width:0}.resource-title span,.resource-title strong{font:inherit;color:#111;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.resource-details{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.72fr);column-gap:1mm;min-width:0}.resource-datum{display:flex;gap:.7mm;align-items:baseline;min-width:0}.resource-datum span,.resource-datum strong{font:inherit;color:#111;white-space:nowrap}.resource-datum span{text-transform:uppercase}.resource-datum strong{overflow:hidden;text-overflow:ellipsis}.resource-details .resource-datum:nth-child(2)::before,.resource-meta .resource-datum:nth-child(2)::before,.resource-meta .resource-datum:nth-child(4)::before{content:"·"}.resource-details .resource-datum:nth-child(3),.resource-level{grid-column:1/-1}.resource-urls{min-width:0}.resource-url{display:block;font:inherit;color:#111;text-decoration:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.resource-url span{display:inline-block;width:8mm;font-weight:inherit}.resource-meta{padding:1mm;border-right:1px solid #aaa;display:grid;grid-template-columns:auto minmax(0,1fr);column-gap:.7mm;align-content:center;min-width:0;font:600 5.3px/1.2 ui-monospace,SFMono-Regular,Consolas,monospace}.resource-meta .resource-datum{font:inherit}.resource-meta .resource-datum:nth-child(n+5){grid-column:1/-1}.resource-meta .resource-uuid strong{font:inherit;overflow:visible;text-overflow:clip}.resource-repository-url{min-width:0}
|
.resource-qr-cell{padding:0;vertical-align:middle;overflow:hidden}.resource-qr-cell--left{border-right:1px solid #777}.resource-qr-cell--right{border-left:1px solid #777}.resource-qr{box-sizing:border-box;width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.25mm;padding:.45mm;color:#333;text-decoration:none}.resource-qr .title-qr{display:block;width:22mm;height:22mm;max-width:22mm;max-height:22mm;flex:none}.resource-qr-label{font:700 4.5pt/1 ui-monospace,SFMono-Regular,"Latin Modern Mono",Consolas,monospace;letter-spacing:.08em;color:#333}.resource-qr-empty{text-align:center}.resource-qr-empty span,.resource-qr-empty strong{display:block;font:600 5pt/1.15 ui-monospace,SFMono-Regular,Consolas,monospace}
|
||||||
"""
|
.page-resource-footer{position:absolute;left:21.5mm;right:21.5mm;bottom:5mm;border-top:1px solid #111;padding-top:.6mm;font:500 5pt/1.1 ui-monospace,SFMono-Regular,"Latin Modern Mono",Consolas,monospace;color:#222;overflow:hidden}.page-resource-footer table{width:100%;border-collapse:collapse;table-layout:fixed;font:inherit}.page-resource-footer td{width:25%;padding:.25mm .6mm;border:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.page-resource-footer td+td{border-left:1px solid #ddd}.page-resource-footer .footer-right{text-align:right}
|
||||||
|
""".replace("__RESOURCE_HEADER_HEIGHT__", f"{resource_header_height_mm(data):g}mm")
|
||||||
|
|
||||||
|
|
||||||
def css_paged_string(value: object) -> str:
|
def css_paged_string(value: object) -> str:
|
||||||
@@ -3281,9 +3344,11 @@ def css_paged_string(value: object) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def page_resource_print_css(data: dict) -> str:
|
def page_resource_print_css(data: dict) -> str:
|
||||||
"""Render a real 30 mm repeated header in CSS paged-media margin boxes."""
|
"""Render the repeated header in CSS paged-media margin boxes."""
|
||||||
card = data["card"]
|
card = data["card"]
|
||||||
fields = title_block_fields(data)
|
fields = title_block_fields(data)
|
||||||
|
header_height_mm = resource_header_height_mm(data)
|
||||||
|
page_top_margin_mm = header_height_mm + 5
|
||||||
url = str(fields["url"])
|
url = str(fields["url"])
|
||||||
source_url = str(fields["repository_url"])
|
source_url = str(fields["repository_url"])
|
||||||
|
|
||||||
@@ -3297,6 +3362,16 @@ def page_resource_print_css(data: dict) -> str:
|
|||||||
page_qr_background = qr_background(url, bool(fields["show_qr"]))
|
page_qr_background = qr_background(url, bool(fields["show_qr"]))
|
||||||
repository_qr_enabled = bool(fields["show_repository_qr"])
|
repository_qr_enabled = bool(fields["show_repository_qr"])
|
||||||
repository_qr_background = qr_background(source_url, repository_qr_enabled)
|
repository_qr_background = qr_background(source_url, repository_qr_enabled)
|
||||||
|
center_grid_svg = (
|
||||||
|
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 119 26" '
|
||||||
|
'preserveAspectRatio="none">'
|
||||||
|
'<rect width="119" height="26" fill="white"/>'
|
||||||
|
'<path d="M80 0V26 M0 6.5H119 M0 13H119 M0 19.5H119" '
|
||||||
|
'fill="none" stroke="#888" stroke-width="0.14"/>'
|
||||||
|
'</svg>'
|
||||||
|
)
|
||||||
|
center_grid_data = base64.b64encode(center_grid_svg.encode("utf-8")).decode("ascii")
|
||||||
|
center_grid_background = f'url("data:image/svg+xml;base64,{center_grid_data}")'
|
||||||
middle = "\n".join(
|
middle = "\n".join(
|
||||||
[
|
[
|
||||||
f"{fields['category']} | {card_prefix(card)}: {card.get('title', '')}",
|
f"{fields['category']} | {card_prefix(card)}: {card.get('title', '')}",
|
||||||
@@ -3320,7 +3395,7 @@ def page_resource_print_css(data: dict) -> str:
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
qr_box = (
|
qr_box = (
|
||||||
"height:30mm;box-sizing:border-box;padding:24mm .8mm .5mm;"
|
f"height:{header_height_mm:g}mm;box-sizing:border-box;padding:24mm .8mm .5mm;"
|
||||||
"border:1px solid #111;background-color:#fff;background-repeat:no-repeat;"
|
"border:1px solid #111;background-color:#fff;background-repeat:no-repeat;"
|
||||||
"background-position:center 1mm;background-size:22mm 22mm;"
|
"background-position:center 1mm;background-size:22mm 22mm;"
|
||||||
"vertical-align:middle;text-align:center;"
|
"vertical-align:middle;text-align:center;"
|
||||||
@@ -3336,55 +3411,60 @@ def page_resource_print_css(data: dict) -> str:
|
|||||||
center_before_page = "\n".join(
|
center_before_page = "\n".join(
|
||||||
[
|
[
|
||||||
header_row(
|
header_row(
|
||||||
fields["category"],
|
f"{fields['category']} | {card_prefix(card)}: {card.get('title', '')}",
|
||||||
f"DATA {card.get('revision_date', '')} · STATUS {card.get('status', '')}",
|
f"DATA {card.get('revision_date', '')} | STATUS {card.get('status', '')}",
|
||||||
),
|
),
|
||||||
header_row(
|
header_row(
|
||||||
f"{card_prefix(card)}: {card.get('title', '')}",
|
f"PROJEKT {card.get('project', '')} | SERIA {card.get('series_title', card.get('series', ''))}",
|
||||||
f"KARTA {card.get('number', '')}/{card.get('count', '')} · WERSJA {card.get('version', '')}",
|
f"KARTA {card.get('number', '')}/{card.get('count', '')} | WERSJA {card.get('version', '')}",
|
||||||
),
|
),
|
||||||
header_row(
|
header_row(
|
||||||
f"PROJEKT {card.get('project', '')} · SERIA {card.get('series_title', card.get('series', ''))}",
|
f"PRZEDMIOT {card.get('subject', '')} | POZIOM {card.get('level', '')}",
|
||||||
f"AUTOR {card.get('author', '')}",
|
f"AUTOR {card.get('author', '')} | ARKUSZ ",
|
||||||
),
|
),
|
||||||
header_row(f"PRZEDMIOT {card.get('subject', '')}", "ARKUSZ "),
|
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
center_after_page = "\n" + "\n".join(
|
center_after_page = "\n" + header_row(
|
||||||
[
|
f"HTML {url}",
|
||||||
header_row(
|
|
||||||
f"POZIOM {card.get('level', '')}",
|
|
||||||
f"UUID {card.get('uuid', '')}",
|
f"UUID {card.get('uuid', '')}",
|
||||||
),
|
|
||||||
header_row(f"GITEA {source_url}"),
|
|
||||||
header_row(f"HTML {url}"),
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
|
footer_left = (
|
||||||
|
f"KARTA {card.get('number', '')}/{card.get('count', '')}\n"
|
||||||
|
f"WERSJA {card.get('version', '')} · {card.get('revision_date', '')}"
|
||||||
|
)
|
||||||
|
footer_center = f"UUID {card.get('uuid', '')}\nGITEA {source_url}"
|
||||||
|
footer_right_before_page = "ARKUSZ "
|
||||||
return f"""
|
return f"""
|
||||||
@page{{
|
@page{{
|
||||||
size:A4;
|
size:A4;
|
||||||
margin:35mm 21.5mm 15mm;
|
margin:{page_top_margin_mm:g}mm 21.5mm 15mm;
|
||||||
@top-left{{content:"GITEA";width:24mm;{qr_box};background-image:{repository_qr_background}}}
|
@top-left{{content:"GITEA";width:24mm;{qr_box};background-image:{repository_qr_background}}}
|
||||||
@top-center{{content:"{css_paged_string(center_before_page)}" counter(page) "/" counter(pages) "{css_paged_string(center_after_page)}";width:119mm;height:30mm;box-sizing:border-box;padding:1mm;border-block:1px solid #111;background-color:#fff;background-image:linear-gradient(#aaa,#aaa);background-repeat:no-repeat;background-position:80mm 0;background-size:1px 100%;white-space:pre;vertical-align:middle;text-align:left;font:600 5.3px/1.2 ui-monospace,SFMono-Regular,Consolas,monospace;color:#111;overflow:hidden}}
|
@top-center{{content:"{css_paged_string(center_before_page)}" counter(page) "/" counter(pages) "{css_paged_string(center_after_page)}";width:119mm;height:{header_height_mm:g}mm;box-sizing:border-box;padding:1mm;border-block:1px solid #111;background-color:#fff;background-image:{center_grid_background};background-repeat:no-repeat;background-position:center;background-size:100% 100%;white-space:pre;vertical-align:middle;text-align:left;font:600 5.3px/1.2 ui-monospace,SFMono-Regular,Consolas,monospace;color:#111;overflow:hidden}}
|
||||||
@top-right{{content:"HTML";width:24mm;{qr_box};background-image:{page_qr_background}}}
|
@top-right{{content:"HTML";width:24mm;{qr_box};background-image:{page_qr_background}}}
|
||||||
|
@bottom-left{{content:"{css_paged_string(footer_left)}";width:45mm;height:7mm;box-sizing:border-box;padding:.7mm 1mm 0;border-top:1px solid #111;white-space:pre;text-align:left;font:500 4.8px/1.2 ui-monospace,SFMono-Regular,Consolas,monospace}}
|
||||||
|
@bottom-center{{content:"{css_paged_string(footer_center)}";width:90mm;height:7mm;box-sizing:border-box;padding:.7mm 1mm 0;border-top:1px solid #111;white-space:pre;text-align:left;font:500 4.8px/1.2 ui-monospace,SFMono-Regular,Consolas,monospace;overflow:hidden}}
|
||||||
|
@bottom-right{{content:"{css_paged_string(footer_right_before_page)}" counter(page) "/" counter(pages) "{css_paged_string(chr(10) + 'AUTOR ' + str(card.get('author', '')))}";width:32mm;height:7mm;box-sizing:border-box;padding:.7mm 1mm 0;border-top:1px solid #111;white-space:pre;text-align:right;font:500 4.8px/1.2 ui-monospace,SFMono-Regular,Consolas,monospace}}
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return f"""
|
return f"""
|
||||||
@page{{
|
@page{{
|
||||||
size:A4;
|
size:A4;
|
||||||
margin:35mm 21.5mm 15mm;
|
margin:{page_top_margin_mm:g}mm 21.5mm 15mm;
|
||||||
@top-left{{content:"{css_paged_string(meta_before_page)}" counter(page) "/" counter(pages) "{css_paged_string(meta_after_page)}";width:47mm;height:30mm;box-sizing:border-box;padding:1.5mm 1.7mm;border:1px solid #111;white-space:pre-wrap;vertical-align:middle;text-align:left;font:600 5.7px/1.3 ui-monospace,SFMono-Regular,Consolas,monospace;color:#111}}
|
@top-left{{content:"{css_paged_string(meta_before_page)}" counter(page) "/" counter(pages) "{css_paged_string(meta_after_page)}";width:47mm;height:{header_height_mm:g}mm;box-sizing:border-box;padding:1.5mm 1.7mm;border:1px solid #111;white-space:pre-wrap;vertical-align:middle;text-align:left;font:600 5.7px/1.3 ui-monospace,SFMono-Regular,Consolas,monospace;color:#111}}
|
||||||
@top-center{{content:"{css_paged_string(middle)}";width:96mm;height:30mm;box-sizing:border-box;padding:1.5mm 2mm;border-block:1px solid #111;white-space:pre-wrap;vertical-align:middle;text-align:left;font:600 6.2px/1.25 ui-monospace,SFMono-Regular,Consolas,monospace;color:#111}}
|
@top-center{{content:"{css_paged_string(middle)}";width:96mm;height:{header_height_mm:g}mm;box-sizing:border-box;padding:1.5mm 2mm;border-block:1px solid #111;white-space:pre-wrap;vertical-align:middle;text-align:left;font:600 6.2px/1.25 ui-monospace,SFMono-Regular,Consolas,monospace;color:#111}}
|
||||||
@top-right{{content:"HTML";width:24mm;{qr_box};background-image:{page_qr_background}}}
|
@top-right{{content:"HTML";width:24mm;{qr_box};background-image:{page_qr_background}}}
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def render_page_header_tex_macro(data: dict) -> list[str]:
|
def render_page_header_tex_macro(data: dict) -> list[str]:
|
||||||
"""Define the repeated 30 mm TeX header for the classic emitter."""
|
"""Define the repeated TeX header for the classic emitter."""
|
||||||
card = data["card"]
|
card = data["card"]
|
||||||
fields = title_block_fields(data)
|
fields = title_block_fields(data)
|
||||||
|
header_height_mm = resource_header_height_mm(data)
|
||||||
|
outer_height_mm = header_height_mm - 0.5
|
||||||
|
inner_height_mm = header_height_mm - 1
|
||||||
url = str(fields["url"])
|
url = str(fields["url"])
|
||||||
source_url = str(fields["repository_url"])
|
source_url = str(fields["repository_url"])
|
||||||
dual_qr = bool(fields["show_repository_qr"])
|
dual_qr = bool(fields["show_repository_qr"])
|
||||||
@@ -3407,14 +3487,43 @@ def render_page_header_tex_macro(data: dict) -> list[str]:
|
|||||||
card_number = f"{card.get('number', '')}/{card.get('count', '')}"
|
card_number = f"{card.get('number', '')}/{card.get('count', '')}"
|
||||||
primary_width = "76mm" if dual_qr else "89mm"
|
primary_width = "76mm" if dual_qr else "89mm"
|
||||||
meta_width = "39mm" if dual_qr else "47mm"
|
meta_width = "39mm" if dual_qr else "47mm"
|
||||||
repository_meta_line = (
|
row_height_mm = (inner_height_mm - 0.5) / 4
|
||||||
rf" {{\fontsize{{3.8}}{{4.3}}\selectfont\ttfamily GITEA: \href{{{source_url}}}{{\nolinkurl{{{source_url}}}}}}}%"
|
|
||||||
if source_url
|
def header_rows_tex(rows: list[str]) -> list[str]:
|
||||||
else ""
|
output: list[str] = []
|
||||||
|
for index, row in enumerate(rows):
|
||||||
|
output.append(
|
||||||
|
" \\parbox[c]["
|
||||||
|
+ f"{row_height_mm:g}mm"
|
||||||
|
+ "][c]{\\linewidth}{\\hspace{0.65mm}"
|
||||||
|
+ row
|
||||||
|
+ "\\hspace{0.65mm}}%"
|
||||||
)
|
)
|
||||||
|
if index != len(rows) - 1:
|
||||||
|
output.extend(
|
||||||
|
[
|
||||||
|
r" \par\nointerlineskip%",
|
||||||
|
r" \hrule height0.35pt%",
|
||||||
|
r" \nointerlineskip%",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return output
|
||||||
|
|
||||||
|
primary_rows = [
|
||||||
|
rf"{{\fontsize{{5.0}}{{5.4}}\selectfont\ttfamily {tex_escape(fields['category'])} | \textbf{{{tex_escape(title)}}}}}",
|
||||||
|
rf"{{\fontsize{{4.8}}{{5.2}}\selectfont\ttfamily \textbf{{PROJEKT}} {tex_escape(card.get('project', ''))} | \textbf{{SERIA}} {tex_escape(card.get('series_title', card.get('series', '')))}}}",
|
||||||
|
rf"{{\fontsize{{4.5}}{{5.0}}\selectfont\ttfamily \textbf{{PRZEDMIOT}} {tex_escape(card.get('subject', ''))} | \textbf{{POZIOM}} {tex_escape(card.get('level', ''))}}}",
|
||||||
|
rf"{{\fontsize{{3.8}}{{4.2}}\selectfont\ttfamily \textbf{{HTML}} \href{{{url}}}{{\nolinkurl{{{url}}}}}}}",
|
||||||
|
]
|
||||||
|
meta_rows = [
|
||||||
|
rf"{{\fontsize{{4.6}}{{5.0}}\selectfont\ttfamily \textbf{{DATA}} {tex_escape(card.get('revision_date', ''))} | \textbf{{STATUS}} {tex_escape(card.get('status', ''))}}}",
|
||||||
|
rf"{{\fontsize{{4.6}}{{5.0}}\selectfont\ttfamily \textbf{{KARTA}} {tex_escape(card_number)} | \textbf{{WERSJA}} {tex_escape(card.get('version', ''))}}}",
|
||||||
|
rf"{{\fontsize{{4.6}}{{5.0}}\selectfont\ttfamily \textbf{{AUTOR}} {tex_escape(card.get('author', ''))} | \textbf{{ARKUSZ}} \thepage/\pageref{{LastPage}}}}",
|
||||||
|
rf"{{\fontsize{{3.8}}{{4.2}}\selectfont\ttfamily \textbf{{UUID}} {tex_escape(card.get('uuid', ''))}}}",
|
||||||
|
]
|
||||||
source_cell = (
|
source_cell = (
|
||||||
[
|
[
|
||||||
r" \begin{minipage}[c][29mm][c]{24mm}\centering%",
|
rf" \begin{{minipage}}[c][{inner_height_mm:g}mm][c]{{24mm}}\centering%",
|
||||||
" " + source_qr + r"\par%",
|
" " + source_qr + r"\par%",
|
||||||
r" \vspace{0.2mm}{\fontsize{4.5}{4.8}\selectfont\bfseries\ttfamily GITEA}%",
|
r" \vspace{0.2mm}{\fontsize{4.5}{4.8}\selectfont\bfseries\ttfamily GITEA}%",
|
||||||
r" \end{minipage}%",
|
r" \end{minipage}%",
|
||||||
@@ -3430,29 +3539,17 @@ def render_page_header_tex_macro(data: dict) -> list[str]:
|
|||||||
r" \setlength{\fboxsep}{0pt}%",
|
r" \setlength{\fboxsep}{0pt}%",
|
||||||
r" \setlength{\fboxrule}{0.35pt}%",
|
r" \setlength{\fboxrule}{0.35pt}%",
|
||||||
r" \noindent\fbox{%",
|
r" \noindent\fbox{%",
|
||||||
r" \begin{minipage}[c][29.5mm][c]{\dimexpr\textwidth-2\fboxrule\relax}%",
|
rf" \begin{{minipage}}[c][{outer_height_mm:g}mm][c]{{\dimexpr\textwidth-2\fboxrule\relax}}%",
|
||||||
*source_cell,
|
*source_cell,
|
||||||
rf" \begin{{minipage}}[c][29mm][c]{{{primary_width}}}%",
|
rf" \begin{{minipage}}[c][{inner_height_mm:g}mm][c]{{{primary_width}}}%",
|
||||||
rf" {{\fontsize{{5.5}}{{6.2}}\selectfont\ttfamily\textcolor{{black!58}}{{{tex_escape(fields['category'])}}}}}\par%",
|
*header_rows_tex(primary_rows),
|
||||||
rf" {{\fontsize{{9.2}}{{10.1}}\selectfont\bfseries {tex_escape(title)}}}\par%",
|
|
||||||
r" \vspace{0.1mm}%",
|
|
||||||
rf" {{\fontsize{{5.6}}{{6.3}}\selectfont Projekt: \texttt{{{tex_escape(card.get('project', ''))}}}\quad Seria: \texttt{{{tex_escape(card.get('series_title', card.get('series', '')))}}}}}\par%",
|
|
||||||
rf" {{\fontsize{{5.6}}{{6.3}}\selectfont Przedmiot: \texttt{{{tex_escape(card.get('subject', ''))}}}}}\par%",
|
|
||||||
rf" {{\fontsize{{5.0}}{{5.7}}\selectfont Poziom: \texttt{{{tex_escape(card.get('level', ''))}}}}}\par%",
|
|
||||||
rf" {{\fontsize{{4.2}}{{4.8}}\selectfont\ttfamily HTML: \href{{{url}}}{{\nolinkurl{{{url}}}}}}}%",
|
|
||||||
r" \end{minipage}%",
|
r" \end{minipage}%",
|
||||||
r" \hfill\vrule width0.35pt\hspace{1mm}%",
|
r" \hfill\vrule width0.35pt\hspace{1mm}%",
|
||||||
rf" \begin{{minipage}}[c][29mm][c]{{{meta_width}}}%",
|
rf" \begin{{minipage}}[c][{inner_height_mm:g}mm][c]{{{meta_width}}}%",
|
||||||
rf" {{\fontsize{{5.7}}{{6.5}}\selectfont Data: \texttt{{{tex_escape(card.get('revision_date', ''))}}}\hfill Status: \texttt{{{tex_escape(card.get('status', ''))}}}}}\par%",
|
*header_rows_tex(meta_rows),
|
||||||
rf" {{\fontsize{{5.7}}{{6.5}}\selectfont Karta: \texttt{{{tex_escape(card_number)}}}\hfill Wersja: \texttt{{{tex_escape(card.get('version', ''))}}}}}\par%",
|
|
||||||
rf" {{\fontsize{{5.7}}{{6.5}}\selectfont Autor: \texttt{{{tex_escape(card.get('author', ''))}}}}}\par%",
|
|
||||||
r" {\fontsize{5.7}{6.5}\selectfont Arkusz: \texttt{\thepage/\pageref{LastPage}}}\par%",
|
|
||||||
r" \vspace{0.5mm}\hrule\vspace{0.5mm}%",
|
|
||||||
rf" {{\fontsize{{4.7}}{{5.3}}\selectfont\ttfamily UUID: {tex_escape(card.get('uuid', ''))}}}\par%",
|
|
||||||
repository_meta_line,
|
|
||||||
r" \end{minipage}%",
|
r" \end{minipage}%",
|
||||||
r" \hfill\vrule width0.35pt\hspace{1mm}%",
|
r" \hfill\vrule width0.35pt\hspace{1mm}%",
|
||||||
r" \begin{minipage}[c][29mm][c]{24mm}\centering%",
|
rf" \begin{{minipage}}[c][{inner_height_mm:g}mm][c]{{24mm}}\centering%",
|
||||||
" " + page_qr + r"\par%",
|
" " + page_qr + r"\par%",
|
||||||
r" \vspace{0.2mm}{\fontsize{4.5}{4.8}\selectfont\bfseries\ttfamily HTML}%",
|
r" \vspace{0.2mm}{\fontsize{4.5}{4.8}\selectfont\bfseries\ttfamily HTML}%",
|
||||||
r" \end{minipage}%",
|
r" \end{minipage}%",
|
||||||
@@ -4333,7 +4430,7 @@ body{margin:0;background:#eceae4;display:flex;flex-direction:column;align-items:
|
|||||||
.page-footer{display:flex;justify-content:space-between;border-top:1.5px solid #1c1c1a;padding-top:8px;margin-top:14px;font:400 9.5px 'JetBrains Mono',monospace;color:#8a887f;gap:16px}
|
.page-footer{display:flex;justify-content:space-between;border-top:1.5px solid #1c1c1a;padding-top:8px;margin-top:14px;font:400 9.5px 'JetBrains Mono',monospace;color:#8a887f;gap:16px}
|
||||||
@media print{@page{size:A4 landscape;margin:0}body{background:#fff;padding:0;gap:0}.page{box-shadow:none!important;border:none!important;break-after:page}}
|
@media print{@page{size:A4 landscape;margin:0}body{background:#fff;padding:0;gap:0}.page{box-shadow:none!important;border:none!important;break-after:page}}
|
||||||
"""
|
"""
|
||||||
css += page_resource_header_css()
|
css += page_resource_header_css(data)
|
||||||
card = data["card"]
|
card = data["card"]
|
||||||
return f"""<!DOCTYPE html>
|
return f"""<!DOCTYPE html>
|
||||||
<html lang="pl">
|
<html lang="pl">
|
||||||
@@ -4514,7 +4611,7 @@ def render_5b_document_page_html(data: dict, page_data: dict, page: int, total:
|
|||||||
return render_5b_page_html(data, center, page, total)
|
return render_5b_page_html(data, center, page, total)
|
||||||
|
|
||||||
|
|
||||||
def render_main_html_5b_css(template: dict | None = None) -> str:
|
def render_main_html_5b_css(data: dict, template: dict | None = None) -> str:
|
||||||
css = r"""
|
css = r"""
|
||||||
*{-webkit-print-color-adjust:exact;print-color-adjust:exact;box-sizing:border-box}
|
*{-webkit-print-color-adjust:exact;print-color-adjust:exact;box-sizing:border-box}
|
||||||
body{margin:0;background:#eceae4;display:flex;flex-direction:column;align-items:center;gap:24px;padding:24px}
|
body{margin:0;background:#eceae4;display:flex;flex-direction:column;align-items:center;gap:24px;padding:24px}
|
||||||
@@ -4547,7 +4644,7 @@ body{margin:0;background:#eceae4;display:flex;flex-direction:column;align-items:
|
|||||||
.page-footer{position:absolute;left:var(--page-rule-left);bottom:95px;width:var(--page-rule-width);display:flex;justify-content:space-between;border-top:0;padding-top:6px;margin-top:0;font:400 8.2px 'JetBrains Mono',monospace;color:#8a887f;gap:10px}.page-footer::before{content:"";position:absolute;left:0;right:0;top:0;border-top:1.4px solid #1c1c1a}
|
.page-footer{position:absolute;left:var(--page-rule-left);bottom:95px;width:var(--page-rule-width);display:flex;justify-content:space-between;border-top:0;padding-top:6px;margin-top:0;font:400 8.2px 'JetBrains Mono',monospace;color:#8a887f;gap:10px}.page-footer::before{content:"";position:absolute;left:0;right:0;top:0;border-top:1.4px solid #1c1c1a}
|
||||||
@media print{@page{size:A4 portrait;margin:0}body{background:#fff;padding:0;gap:0}.page{box-shadow:none!important;border:none!important;break-after:page}}
|
@media print{@page{size:A4 portrait;margin:0}body{background:#fff;padding:0;gap:0}.page{box-shadow:none!important;border:none!important;break-after:page}}
|
||||||
"""
|
"""
|
||||||
return css + page_resource_header_css()
|
return css + page_resource_header_css(data)
|
||||||
|
|
||||||
|
|
||||||
def render_main_html_5b(data: dict, template: dict) -> str:
|
def render_main_html_5b(data: dict, template: dict) -> str:
|
||||||
@@ -5740,7 +5837,7 @@ def render_html_output(data: dict, template: dict) -> str:
|
|||||||
|
|
||||||
def render_html_css_output(data: dict, template: dict) -> str:
|
def render_html_css_output(data: dict, template: dict) -> str:
|
||||||
if template_emitter(template, "html") == "5b":
|
if template_emitter(template, "html") == "5b":
|
||||||
return render_main_html_5b_css(template)
|
return render_main_html_5b_css(data, template)
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user