'
f'
Projekt{html_escape(card["project"])}
'
f'
Przedmiot{html_escape(card["subject"])}
'
@@ -2813,12 +2954,12 @@ def render_code_subblock_5a_html(block: dict) -> str:
if block.get("pass_condition"):
pass_line = f'
PASS: {html_escape(text_5a(block.get("pass_condition", "")))}
'
return (
- '
'
+ f'
'
f'{html_escape(text_5a(block.get("title", "")))}
'
f'{html_escape(text_5a(block.get("context", "")))}
'
f'{render_code_columns_5a_html(block)}'
f'{pass_line}'
- ''
+ ''
)
@@ -3288,7 +3429,7 @@ body{margin:0;background:#eceae4;display:flex;flex-direction:column;align-items:
.kw-common{border-top:1px solid #e4e2dc;margin-top:2px;padding-top:3px;font:400 7px/1.6 'JetBrains Mono',monospace;color:#8a887f}.kw-common span{color:#1c1c1a}
.margin-panel-foot{padding:4px 8px;border-top:1px solid #d8d6d0;font:400 7px 'JetBrains Mono',monospace;color:#8a887f}
.page-main{display:flex;flex-direction:column;min-height:0}
-.metric-box{border:1.5px solid #1c1c1a}.metric-title{display:flex;justify-content:space-between;align-items:baseline;gap:12px;padding:9px 14px;border-bottom:1px solid #1c1c1a}.metric-title div{font-size:15px;font-weight:700}.metric-title span{font:500 9.5px 'JetBrains Mono',monospace;color:#4a4944;white-space:nowrap}
+.metric-box{border:1.5px solid #1c1c1a}.title-block{display:grid;grid-template-columns:1.08fr 2.55fr 1.25fr 66px;min-height:96px;border-bottom:1px solid #1c1c1a}.title-signers,.title-document{display:grid;grid-template-rows:repeat(3,minmax(0,1fr));min-width:0}.title-signers{border-right:1px solid #1c1c1a}.title-document{border-right:1px solid #1c1c1a}.title-meta{display:grid;grid-template-columns:1fr 1fr;grid-template-rows:repeat(3,minmax(0,1fr));min-width:0}.title-cell,.title-name,.title-url{display:flex;flex-direction:column;justify-content:center;min-width:0;padding:3px 6px;border-bottom:1px solid #d8d6d0}.title-signers .title-cell:last-child,.title-document>div:last-child,.title-meta .title-cell:nth-last-child(-n+2){border-bottom:0}.title-meta .title-cell:nth-child(odd){border-right:1px solid #d8d6d0}.title-cell span,.title-name span,.title-url span{font:600 6.7px/1.15 'JetBrains Mono',monospace;letter-spacing:.08em;text-transform:uppercase;color:#8a887f}.title-cell strong,.title-name strong{font-size:8.3px;line-height:1.13;font-weight:500;overflow-wrap:anywhere}.title-cell em{font:400 6.4px/1.1 'JetBrains Mono',monospace;color:#8a887f;font-style:normal}.title-category{display:flex;align-items:center;justify-content:space-between;gap:6px;padding:2px 6px;background:#3b5a8f;color:#fefefc;font-size:7.1px;letter-spacing:.06em;overflow:hidden}.title-category strong{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.title-category span{font:400 6.1px 'JetBrains Mono',monospace;white-space:nowrap;color:#fefefc}.title-name strong{font-size:9.2px;font-weight:700}.title-url code{font:400 6.4px/1.15 'JetBrains Mono',monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#4a4944}.title-qr-cell{display:flex;align-items:center;justify-content:center;padding:5px;border-left:1px solid #1c1c1a;background:#fefefc}.title-qr{width:100%;height:100%;display:block}.title-qr-empty{flex-direction:column;text-align:center;color:#8a887f}.title-qr-empty span{font:600 7px 'JetBrains Mono',monospace}.title-qr-empty strong{font:400 6px 'JetBrains Mono',monospace}.metric-title{display:flex;justify-content:space-between;align-items:baseline;gap:12px;padding:9px 14px;border-bottom:1px solid #1c1c1a}.metric-title div{font-size:15px;font-weight:700}.metric-title span{font:500 9.5px 'JetBrains Mono',monospace;color:#4a4944;white-space:nowrap}
.metric-grid{display:grid;grid-template-columns:1fr 1fr;font-size:11px}.metric-grid div{display:flex;gap:8px;padding:4px 14px;border-bottom:1px solid #d8d6d0}.metric-grid div:nth-child(odd){border-right:1px solid #d8d6d0}.metric-grid div:nth-last-child(-n+2){border-bottom:0}.metric-grid span{font:500 8.5px/1.9 'JetBrains Mono',monospace;color:#8a887f;text-transform:uppercase;flex:none}.metric-grid strong{font-weight:400}.metric-grid i{flex:1;border-bottom:1px dotted #9a988f}
.plain-box{border:1px solid #1c1c1a;padding:8px 14px;margin-top:11px}.plain-title{font-weight:700;font-size:11.5px;letter-spacing:.12em;text-transform:uppercase;margin-bottom:2px}.plain-box p{margin:0;text-align:justify}
.section-box{border:1px solid #1c1c1a;margin-top:10px}.section-box:first-child{margin-top:0}.section-box.dense{margin-top:8px}.section-head{display:flex;align-items:baseline;gap:8px;padding:5px 14px;background:#f4f3ef;border-bottom:1px solid #1c1c1a}.section-head span{font:600 9px 'JetBrains Mono',monospace;color:#8a887f}.section-head strong{font-weight:700;font-size:11.5px;letter-spacing:.12em;text-transform:uppercase}.section-body{padding:7px 14px}.dense .section-body{padding:6px 12px}
@@ -3300,7 +3441,7 @@ body{margin:0;background:#eceae4;display:flex;flex-direction:column;align-items:
.theory-table{width:100%;border-collapse:collapse;font-size:11px}.theory-table th{text-align:left;padding:3px 10px;border:1px solid #1c1c1a;background:#f4f3ef}.theory-table th:first-child{width:26%}.theory-table td{padding:3px 10px;vertical-align:top;border:1px solid #d8d6d0}.theory-table code{font:400 10px 'JetBrains Mono',monospace}
.tech-stack{display:grid;grid-template-columns:1fr 1fr;column-gap:18px;align-items:start}.stack-column h3{font:600 8.5px 'JetBrains Mono',monospace;letter-spacing:.08em;color:#4a4944;text-transform:uppercase;padding-bottom:3px;border-bottom:1px solid #1c1c1a;margin:0}.stack-grid{display:grid;grid-template-columns:88px 1fr;font-size:10px;line-height:1.35}.stack-grid div{padding:3px 0;border-bottom:1px solid #e4e2dc}.stack-grid div:nth-last-child(-n+2){border-bottom:0}.stack-grid code{font:400 9.5px/1.45 'JetBrains Mono',monospace}
.part-banner{border:1.5px solid #1c1c1a;background:#f4f3ef;padding:7px 14px;display:grid;grid-template-columns:190px 1fr;column-gap:12px;align-items:baseline}.part-banner strong{font:700 12px 'JetBrains Mono',monospace;letter-spacing:.08em}.part-banner span{font-size:12px;text-align:justify}
-.compact-list{margin:3px 0 0 15px;padding:0;font-size:10.5px;line-height:1.32}.compact-list li{margin:1px 0}.three-col{display:grid;grid-template-columns:1fr 1fr 1fr;column-gap:12px}.three-col h3,.model-grid h3{font:600 8.5px 'JetBrains Mono',monospace;text-transform:uppercase;color:#4a4944;margin:0 0 3px}.three-col p,.model-grid p{margin:0 0 4px;font-size:10.5px}.pass-line{margin:5px 0 0;padding-top:4px;border-top:1px solid #e4e2dc;font-size:10.5px}
+.compact-list{margin:3px 0 0 15px;padding:0;font-size:10.5px;line-height:1.32}.compact-list li{margin:1px 0}.code-subblock{border:1px solid #d8d6d0;border-left:3px solid #3b5a8f;padding:5px 7px;margin-top:5px}.code-subblock:first-child{margin-top:0}.code-subblock h3{margin:0 0 2px}.code-subblock>p{margin:0 0 4px}.three-col{display:grid;grid-template-columns:1fr 1fr 1fr;column-gap:12px}.three-col h3,.model-grid h3{font:600 8.5px 'JetBrains Mono',monospace;text-transform:uppercase;color:#4a4944;margin:0 0 3px}.three-col p,.model-grid p{margin:0 0 4px;font-size:10.5px}.pass-line{margin:5px 0 0;padding-top:4px;border-top:1px solid #e4e2dc;font-size:10.5px}
.math-task{display:grid;grid-template-columns:1fr 190px;column-gap:12px;align-items:start;border-bottom:1px solid #f0efe9;padding:3px 0;font-size:10.5px}.math-task:last-child{border-bottom:0}.math-task code{font:400 9px 'JetBrains Mono',monospace;color:#3b5a8f}.math-task em{grid-column:1 / -1;color:#8a887f;font-size:9.5px}.answer-line{display:block;border-bottom:1px dotted #9a988f;height:12px;margin-top:2px}
.model-grid{display:grid;grid-template-columns:1.5fr 1fr;column-gap:16px}.compact-table{width:100%;border-collapse:collapse;font-size:10px;line-height:1.25}.compact-table th{background:#f4f3ef;border:1px solid #1c1c1a;padding:3px 6px;text-align:left}.compact-table td{border:1px solid #d8d6d0;padding:3px 6px;vertical-align:top}.compact-table code{font:400 9px 'JetBrains Mono',monospace}.constants td:first-child{width:68%}.check-table td:first-child,.procedure-table td:first-child,.git-gate td:first-child{width:24px;text-align:center}.check-table td:nth-child(2){width:95px}
.command-list{margin:0 0 0 22px;padding:0;font-size:10.5px;line-height:1.45}.command-list code{font:400 9px 'JetBrains Mono',monospace}.safety-grid{display:grid;grid-template-columns:1fr 1fr;gap:6px}.safety-card{border:1px solid #d8d6d0;padding:5px 7px}.safety-card strong{display:block;font:600 9px 'JetBrains Mono',monospace;color:#3b5a8f;margin-bottom:2px}.safety-card span{font-size:10.5px;line-height:1.32;text-align:justify}
@@ -3351,11 +3492,8 @@ def build_5b_pages_html(data: dict) -> list[dict]:
"center": "".join(
[
render_metric_header_5a_html(data),
- render_mission_5a_html(data),
render_objectives_5a_html(data),
render_agenda_5a_html(data),
- render_hw_gate_5a_html(data),
- render_tech_stack_5a_html(data),
]
),
},
@@ -3364,7 +3502,10 @@ def build_5b_pages_html(data: dict) -> list[dict]:
"center": "".join(
[
render_running_card_header_5a_html(data),
+ render_mission_5a_html(data),
render_theory_5a_html(data),
+ render_tech_stack_5a_html(data),
+ render_hw_gate_5a_html(data),
render_math_5a_html(data),
]
),
@@ -3499,7 +3640,7 @@ body{margin:0;background:#eceae4;display:flex;flex-direction:column;align-items:
.tree-gap-left,.tree-gap-right{min-width:0}.tree-we{font-weight:600;color:#3b5a8f;margin-top:2px}.tree-we:first-child{margin-top:0}.tree-line.level-1{padding-left:5px}.tree-line.level-2{padding-left:10px;color:#4a4944}
.page-main{display:flex;flex-direction:column;min-height:0;justify-content:space-between}
.page.page-technical{--page-rule-left:104px;--page-rule-width:915px;width:1123px;height:794px}.page-technical .technical-page-grid{grid-template-columns:77px 21px minmax(0,1fr) 21px 77px}.technical-main{display:flex;min-height:0}.technical-section{flex:1;display:flex;flex-direction:column;margin-top:0}.technical-section .section-body{flex:1;min-height:0;padding:6px 8px}.technical-sheet-figure{height:100%;min-height:0;margin:0;display:flex;flex-direction:column;gap:4px}.technical-sheet-link{flex:1;min-height:0;display:flex;align-items:center;justify-content:center}.technical-sheet-figure img{width:100%;height:100%;object-fit:contain;border:1px solid #d8d6d0;background:white}.technical-sheet-figure figcaption{display:flex;justify-content:space-between;align-items:baseline;gap:10px;font-size:7.2px;line-height:1.18;color:#4a4944}.technical-sheet-figure figcaption span{min-width:0}.technical-sheet-missing{flex:1;display:flex;align-items:center;justify-content:center;border:1px solid #d8d6d0;color:#8a887f;font:600 8px 'JetBrains Mono',monospace;text-transform:uppercase}
-.metric-box{border:1.4px solid #1c1c1a}.metric-title{display:flex;justify-content:space-between;align-items:baseline;gap:8px;padding:7px 10px;border-bottom:1px solid #1c1c1a}.metric-title div{font-size:12.5px;font-weight:700}.metric-title span{font:500 8px 'JetBrains Mono',monospace;color:#4a4944;white-space:nowrap}
+.metric-box{border:1.4px solid #1c1c1a}.title-block{display:grid;grid-template-columns:1.0fr 2.35fr 1.24fr 52px;min-height:82px;border-bottom:1px solid #1c1c1a}.title-signers,.title-document{display:grid;grid-template-rows:repeat(3,minmax(0,1fr));min-width:0}.title-signers{border-right:1px solid #1c1c1a}.title-document{border-right:1px solid #1c1c1a}.title-meta{display:grid;grid-template-columns:1fr 1fr;grid-template-rows:repeat(3,minmax(0,1fr));min-width:0}.title-cell,.title-name,.title-url{display:flex;flex-direction:column;justify-content:center;min-width:0;padding:2px 4px;border-bottom:1px solid #d8d6d0}.title-signers .title-cell:last-child,.title-document>div:last-child,.title-meta .title-cell:nth-last-child(-n+2){border-bottom:0}.title-meta .title-cell:nth-child(odd){border-right:1px solid #d8d6d0}.title-cell span,.title-name span,.title-url span{font:600 5.4px/1.12 'JetBrains Mono',monospace;letter-spacing:.07em;text-transform:uppercase;color:#8a887f}.title-cell strong,.title-name strong{font-size:6.9px;line-height:1.1;font-weight:500;overflow-wrap:anywhere}.title-cell em{font:400 5.2px/1.05 'JetBrains Mono',monospace;color:#8a887f;font-style:normal}.title-category{display:flex;align-items:center;justify-content:space-between;gap:4px;padding:2px 4px;background:#3b5a8f;color:#fefefc;font-size:5.9px;letter-spacing:.04em;overflow:hidden}.title-category strong{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.title-category span{font:400 5.1px 'JetBrains Mono',monospace;white-space:nowrap;color:#fefefc}.title-name strong{font-size:7.6px;font-weight:700}.title-url code{font:400 5.4px/1.12 'JetBrains Mono',monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#4a4944}.title-qr-cell{display:flex;align-items:center;justify-content:center;padding:4px;border-left:1px solid #1c1c1a;background:#fefefc}.title-qr{width:100%;height:100%;display:block}.title-qr-empty{flex-direction:column;text-align:center;color:#8a887f}.title-qr-empty span{font:600 6px 'JetBrains Mono',monospace}.title-qr-empty strong{font:400 5px 'JetBrains Mono',monospace}.metric-title{display:flex;justify-content:space-between;align-items:baseline;gap:8px;padding:7px 10px;border-bottom:1px solid #1c1c1a}.metric-title div{font-size:12.5px;font-weight:700}.metric-title span{font:500 8px 'JetBrains Mono',monospace;color:#4a4944;white-space:nowrap}
.metric-grid{display:grid;grid-template-columns:1fr 1fr;font-size:9.4px}.metric-grid div{display:flex;gap:6px;padding:3px 10px;border-bottom:1px solid #d8d6d0}.metric-grid div:nth-child(odd){border-right:1px solid #d8d6d0}.metric-grid div:nth-last-child(-n+2){border-bottom:0}.metric-grid span{font:500 7.2px/1.7 'JetBrains Mono',monospace;color:#8a887f;text-transform:uppercase;flex:none}.metric-grid strong{font-weight:400}.metric-grid i{flex:1;border-bottom:1px dotted #9a988f}
.plain-box{border:1px solid #1c1c1a;padding:6px 10px;margin-top:7px}.plain-title{font-weight:700;font-size:9.8px;letter-spacing:.12em;text-transform:uppercase;margin-bottom:1px}.plain-box p{margin:0;text-align:justify}
.section-box{border:1px solid #1c1c1a;margin-top:7px}.section-box:first-child{margin-top:0}.section-box.dense{margin-top:6px}.section-head{display:flex;align-items:baseline;gap:6px;padding:4px 10px;background:#f4f3ef;border-bottom:1px solid #1c1c1a}.section-head span{font:600 7.8px 'JetBrains Mono',monospace;color:#8a887f}.section-head strong{font-weight:700;font-size:9.6px;letter-spacing:.12em;text-transform:uppercase}.section-body{padding:6px 10px}.dense .section-body{padding:5px 9px}
@@ -3511,7 +3652,7 @@ body{margin:0;background:#eceae4;display:flex;flex-direction:column;align-items:
.theory-table{width:100%;border-collapse:collapse;font-size:9.4px}.theory-table th{text-align:left;padding:2px 7px;border:1px solid #1c1c1a;background:#f4f3ef}.theory-table th:first-child{width:31%}.theory-table td{padding:2px 7px;vertical-align:top;border:1px solid #d8d6d0}.theory-table code{font:400 8px 'JetBrains Mono',monospace}
.tech-stack{display:grid;grid-template-columns:1fr 1fr;column-gap:10px;align-items:start}.stack-column h3{font:600 7.2px 'JetBrains Mono',monospace;letter-spacing:.08em;color:#4a4944;text-transform:uppercase;padding-bottom:2px;border-bottom:1px solid #1c1c1a;margin:0}.stack-grid{display:grid;grid-template-columns:70px 1fr;font-size:8.6px;line-height:1.25}.stack-grid div{padding:2px 0;border-bottom:1px solid #e4e2dc}.stack-grid div:nth-last-child(-n+2){border-bottom:0}.stack-grid code{font:400 7.7px/1.35 'JetBrains Mono',monospace}
.part-banner{border:1.4px solid #1c1c1a;background:#f4f3ef;padding:5px 10px;display:grid;grid-template-columns:126px 1fr;column-gap:9px;align-items:baseline}.part-banner strong{font:700 9px 'JetBrains Mono',monospace;letter-spacing:.08em}.part-banner span{font-size:9.4px;text-align:justify}
-.compact-list{margin:2px 0 0 13px;padding:0;font-size:8.7px;line-height:1.25}.compact-list li{margin:1px 0}.three-col,.connection-notes{display:grid;grid-template-columns:1fr 1fr 1fr;column-gap:8px}.connection-notes{grid-template-columns:1fr 1fr;margin-top:4px}.three-col h3,.model-grid h3,.connection-notes h3{font:600 7.2px 'JetBrains Mono',monospace;text-transform:uppercase;color:#4a4944;margin:0 0 2px}.three-col p,.model-grid p{margin:0 0 3px;font-size:8.8px}.pass-line{margin:4px 0 0;padding-top:3px;border-top:1px solid #e4e2dc;font-size:8.6px}
+.compact-list{margin:2px 0 0 13px;padding:0;font-size:8.7px;line-height:1.25}.compact-list li{margin:1px 0}.code-subblock{border:1px solid #d8d6d0;border-left:3px solid #3b5a8f;padding:4px 5px;margin-top:4px}.code-subblock:first-child{margin-top:0}.code-subblock h3{margin:0 0 2px}.code-subblock>p{margin:0 0 3px}.three-col,.connection-notes{display:grid;grid-template-columns:1fr 1fr 1fr;column-gap:8px}.connection-notes{grid-template-columns:1fr 1fr;margin-top:4px}.three-col h3,.model-grid h3,.connection-notes h3{font:600 7.2px 'JetBrains Mono',monospace;text-transform:uppercase;color:#4a4944;margin:0 0 2px}.three-col p,.model-grid p{margin:0 0 3px;font-size:8.8px}.pass-line{margin:4px 0 0;padding-top:3px;border-top:1px solid #e4e2dc;font-size:8.6px}
.math-task{display:grid;grid-template-columns:1fr 126px;column-gap:8px;align-items:start;border-bottom:1px solid #f0efe9;padding:3px 0;font-size:9px}.math-task:last-child{border-bottom:0}.math-task code{font:400 7.5px 'JetBrains Mono',monospace;color:#3b5a8f}.math-task em{grid-column:1 / -1;color:#8a887f;font-size:7.8px}.answer-line{display:block;border-bottom:1px dotted #9a988f;height:12px;margin-top:2px}
.model-grid{display:grid;grid-template-columns:1.25fr 1fr;column-gap:10px}.compact-table{width:100%;border-collapse:collapse;font-size:8.4px;line-height:1.18}.compact-table th{background:#f4f3ef;border:1px solid #1c1c1a;padding:2px 4px;text-align:left}.compact-table td{border:1px solid #d8d6d0;padding:2px 4px;vertical-align:top}.compact-table code{font:400 7.5px 'JetBrains Mono',monospace}.constants td:first-child{width:66%}.check-table td:first-child,.procedure-table td:first-child,.git-gate td:first-child{width:20px;text-align:center}.check-table td:nth-child(2){width:70px}.procedure-table td{height:25px}
.command-list{margin:0 0 0 18px;padding:0;font-size:8.8px;line-height:1.32}.command-list code{font:400 7.5px 'JetBrains Mono',monospace}.safety-grid{display:grid;grid-template-columns:1fr 1fr;gap:5px}.safety-card{border:1px solid #d8d6d0;padding:4px 5px}.safety-card strong{display:block;font:600 7.5px 'JetBrains Mono',monospace;color:#3b5a8f;margin-bottom:1px}.safety-card span{font-size:8.4px;line-height:1.22;text-align:justify}
@@ -3560,6 +3701,7 @@ def render_preamble_5a(card: dict) -> list[str]:
r"\usepackage[polish]{babel}",
r"\usepackage{array}",
r"\usepackage{tabularx}",
+ r"\usepackage{multirow}",
r"\usepackage{xcolor}",
r"\usepackage{amssymb}",
r"\usepackage{graphicx}",
@@ -3568,6 +3710,7 @@ def render_preamble_5a(card: dict) -> list[str]:
r"\IfFileExists{stix2.sty}{\usepackage{stix2}}{\usepackage{lmodern}}",
r"\IfFileExists{inconsolata.sty}{\usepackage{inconsolata}}{\usepackage{lmodern}}",
r"\usepackage[most]{tcolorbox}",
+ r"\usepackage{qrcode}",
r"\usepackage{hyperref}",
r"\hypersetup{hidelinks}",
r"\IfFileExists{build-meta.tex}{\input{build-meta.tex}}{\newcommand{\BuildCommit}{local}}",
@@ -3596,6 +3739,7 @@ def render_preamble_5a(card: dict) -> list[str]:
r"\newcommand{\FiveAWriteLine}{\par\noindent\dotfill}",
r"\newtcolorbox{FiveASection}[2]{enhanced,arc=0pt,boxrule=0.35pt,colback=ESCPaper,colframe=ESCInk,boxsep=0pt,left=2.8mm,right=2.8mm,top=1.2mm,bottom=1.2mm,colbacktitle=ESCHeader,coltitle=ESCInk,fonttitle=\bfseries\footnotesize,title={\ttfamily\textcolor{ESCMuted}{\S#1}\quad #2}}",
r"\newtcolorbox{FiveAPart}{enhanced,arc=0pt,boxrule=0.6pt,colback=ESCHeader,colframe=ESCInk,boxsep=0pt,left=2.8mm,right=2.8mm,top=1.2mm,bottom=1.2mm}",
+ r"\newtcolorbox{CardContentBlock}{enhanced,arc=0pt,boxrule=0.28pt,colback=ESCPaper,colframe=ESCLine,boxsep=0pt,left=1.4mm,right=1.4mm,top=0.8mm,bottom=0.8mm}",
"",
]
@@ -3637,18 +3781,45 @@ def render_margin_tree_panel_5a_tex(data: dict, column: str) -> list[str]:
def render_metric_header_5a_tex(data: dict) -> list[str]:
card = data["card"]
+ title_fields = title_block_fields(data)
fields = data.get("metric_fill_fields") or [{"label": "Uczeń"}, {"label": "Klasa · data"}]
first_label = fields[0].get("label", "Uczeń") if fields else "Uczeń"
second_label = fields[1].get("label", "Klasa · data") if len(fields) > 1 else "Klasa · data"
+
+ def title_cell(label: str, value: object, mono: bool = False) -> str:
+ content = tex_escape(str(value)) if mono else tex_5a(value)
+ face = r"\ttfamily" if mono else ""
+ return rf"{{\tiny\ttfamily\textcolor{{ESCMuted}}{{{tex_escape(label.upper())}}}}}\par{{\scriptsize {face} {content}}}"
+
+ url = str(title_fields["url"])
+ safe_qr_url = re.fullmatch(r"https?://[A-Za-z0-9._~:/?&=+\-]+", url)
+ qr = (
+ rf"\qrcode[height=15.5mm,level=L]{{{url}}}"
+ if title_fields["show_qr"] and safe_qr_url
+ else r"{\tiny\ttfamily\textcolor{ESCMuted}{QR: brak URL}}"
+ )
return [
- r"\begin{tcolorbox}[enhanced,arc=0pt,boxrule=0.6pt,colback=ESCPaper,colframe=ESCInk,boxsep=0pt,left=2.8mm,right=2.8mm,top=1.8mm,bottom=1.8mm]",
- rf"{{\bfseries {tex_5a(card_title_line_5a(card))}}}\hfill{{\scriptsize\ttfamily KARTA {tex_escape(card['number'])}/{tex_escape(card['count'])}}}\par",
- r"\vspace{0.2em}\hrule\vspace{0.2em}",
- r"\scriptsize",
- r"\begin{tabularx}{\linewidth}{@{}>{\ttfamily\textcolor{ESCMuted}}p{2.2cm}X>{\ttfamily\textcolor{ESCMuted}}p{2.5cm}X@{}}",
- rf"Projekt & {tex_5a(card['project'])} & Przedmiot & {tex_5a(card['subject'])} \\",
- rf"{tex_5a(first_label)} & \FiveAFill & {tex_5a(second_label)} & \FiveAFill \\",
+ r"\begin{tcolorbox}[enhanced,arc=0pt,boxrule=0.6pt,colback=ESCPaper,colframe=ESCInk,boxsep=0pt,left=0pt,right=0pt,top=0pt,bottom=0pt]",
+ r"\renewcommand{\arraystretch}{1.08}\scriptsize",
+ r"\noindent\begin{minipage}[t]{12.40cm}",
+ r"\begin{tabularx}{\linewidth}{|p{2.55cm}|Y|p{1.55cm}|p{1.75cm}|}",
+ r"\hline",
+ rf"{title_cell('Opracował', title_fields['prepared_by'])}\newline{{\tiny\ttfamily\textcolor{{ESCMuted}}{{{tex_escape(str(title_fields['prepared_on']))}}}}} & "
+ rf"{{\scriptsize\bfseries {tex_5a(title_fields['category'])}}}\hfill{{\tiny\ttfamily {tex_escape(str(title_fields['standard']))}}} & "
+ rf"{title_cell('Rewizja', title_fields['revision'], True)} & {title_cell('Data wydania', title_fields['issued_on'], True)} \\\hline",
+ rf"{title_cell('Sprawdził', title_fields['checked_by'])} & "
+ rf"{title_cell('Tytuł', title_fields['title'])} & "
+ rf"{title_cell('Seria', title_fields['series'], True)} & {title_cell('Typ', title_fields['document_type'])} \\\hline",
+ rf"{title_cell('Zatwierdził', title_fields['approved_by'])} & "
+ rf"{title_cell('URL', url or '—', True)} & "
+ rf"{title_cell('Narzędzie', title_fields['tool'])} & {title_cell('Arkusz', title_fields['sheet'], True)} \\\hline",
r"\end{tabularx}",
+ r"\end{minipage}\hfill",
+ r"\begin{minipage}[t][15.5mm][c]{1.95cm}\centering",
+ qr,
+ r"\end{minipage}",
+ r"\hspace{2.0mm}{\tiny\ttfamily\textcolor{ESCMuted}{PROJEKT}}\hspace{0.8mm}{\scriptsize " + tex_5a(card["project"]) + r"}\hfill{\tiny\ttfamily\textcolor{ESCMuted}{PRZEDMIOT}}\hspace{0.8mm}{\scriptsize " + tex_5a(card["subject"]) + r"}\hspace{2.0mm}\par",
+ rf"\hspace{{2.0mm}}{{\tiny\ttfamily\textcolor{{ESCMuted}}{{{tex_escape(first_label.upper())}}}}}\hspace{{0.8mm}}\FiveAFill\hfill{{\tiny\ttfamily\textcolor{{ESCMuted}}{{{tex_escape(second_label.upper())}}}}}\hspace{{0.8mm}}\FiveAFill\hspace{{2.0mm}}\par",
r"\end{tcolorbox}",
]
@@ -3805,14 +3976,15 @@ def render_code_columns_5a_tex(block: dict) -> list[str]:
def render_code_subblock_5a_tex(block: dict) -> list[str]:
body = [
- rf"\par\textbf{{{tex_5a(block.get('title', ''))}}}\par",
+ r"\begin{CardContentBlock}",
+ rf"\textbf{{{tex_5a(block.get('title', ''))}}}\par",
tex_5a(block.get("context", "")),
r"\par\vspace{0.15em}",
*render_code_columns_5a_tex(block),
]
if block.get("pass_condition"):
body.append(rf"\par{{\tiny\ttfamily\textcolor{{ESCAccent}}{{PASS: {tex_5a(block.get('pass_condition', ''))}}}}}")
- body.append(r"\vspace{0.25em}")
+ body.extend([r"\end{CardContentBlock}", r"\vspace{0.25em}"])
return body
@@ -4215,6 +4387,7 @@ def render_preamble_5b(card: dict) -> list[str]:
r"\usepackage[polish]{babel}",
r"\usepackage{array}",
r"\usepackage{tabularx}",
+ r"\usepackage{multirow}",
r"\usepackage{xcolor}",
r"\usepackage{amssymb}",
r"\usepackage{graphicx}",
@@ -4224,6 +4397,7 @@ def render_preamble_5b(card: dict) -> list[str]:
r"\IfFileExists{stix2.sty}{\usepackage{stix2}}{\usepackage{lmodern}}",
r"\IfFileExists{inconsolata.sty}{\usepackage{inconsolata}}{\usepackage{lmodern}}",
r"\usepackage[most]{tcolorbox}",
+ r"\usepackage{qrcode}",
r"\usepackage{hyperref}",
r"\hypersetup{hidelinks}",
r"\IfFileExists{build-meta.tex}{\input{build-meta.tex}}{\newcommand{\BuildCommit}{local}}",
@@ -4252,6 +4426,7 @@ def render_preamble_5b(card: dict) -> list[str]:
r"\newcommand{\FiveAWriteLine}{\par\noindent\dotfill}",
r"\newtcolorbox{FiveASection}[2]{enhanced,arc=0pt,boxrule=0.35pt,colback=ESCPaper,colframe=ESCInk,boxsep=0pt,left=2.0mm,right=2.0mm,top=1.0mm,bottom=1.0mm,colbacktitle=ESCHeader,coltitle=ESCInk,fonttitle=\bfseries\scriptsize,title={\ttfamily\textcolor{ESCMuted}{#1.}\quad #2}}",
r"\newtcolorbox{FiveAPart}{enhanced,arc=0pt,boxrule=0.55pt,colback=ESCHeader,colframe=ESCInk,boxsep=0pt,left=2.0mm,right=2.0mm,top=1.0mm,bottom=1.0mm}",
+ r"\newtcolorbox{CardContentBlock}{enhanced,arc=0pt,boxrule=0.28pt,colback=ESCPaper,colframe=ESCLine,boxsep=0pt,left=1.1mm,right=1.1mm,top=0.7mm,bottom=0.7mm}",
"",
]
@@ -4476,15 +4651,9 @@ def build_5b_pages_tex(data: dict) -> list[list[str]]:
"center": [
*render_metric_header_5a_tex(data),
r"\vfill",
- *render_mission_5a_tex(data),
- r"\vfill",
*render_objectives_5a_tex(data),
r"\vfill",
*render_agenda_5a_tex(data),
- r"\vfill",
- *render_hw_gate_5a_tex(data),
- r"\vfill",
- *render_tech_stack_5a_tex(data),
],
},
{
@@ -4492,8 +4661,14 @@ def build_5b_pages_tex(data: dict) -> list[list[str]]:
"center": [
*running_card_header_5b_tex(data),
r"\vfill",
+ *render_mission_5a_tex(data),
+ r"\vfill",
*render_theory_5a_tex(data),
r"\vfill",
+ *render_tech_stack_5a_tex(data),
+ r"\vfill",
+ *render_hw_gate_5a_tex(data),
+ r"\vfill",
*render_math_5a_tex(data),
],
},