English version: README.en.md
Klartex
PDF-generering via LaTeX — strukturerad data in, professionella dokument ut.
klartex.se · PyPI · GitHub
Klartex tar JSON-data + mallnamn och producerar PDF via XeLaTeX. Kan användas som Python-bibliotek eller CLI-verktyg.
Mallar
| Mall | Beskrivning |
|---|---|
_block |
Universell blockmotor — agenten komponerar dokumentet fritt |
protokoll |
Mötesprotokoll med dagordning, beslut och justerare |
faktura |
Faktura med rader, moms och betalningsinformation |
kvitto |
Kvitto med enkel radlista, betalsätt och totalbelopp |
resultatrakning |
Resultaträkning med jämförelseår och noter |
balansrakning |
Balansräkning med tillgångar och skulder/eget kapital |
budgetrapport |
Budgetrapport med kontokoder, budget och utfall |
sie-exportrapport |
Läsbar PDF av SIE4-bokföringsdata |
Installation
# Som globalt CLI-verktyg
pipx install klartex
# Eller i ett projekt
pip install klartex
Kräver Python ≥ 3.12 och XeLaTeX.
# macOS
brew install --cask mactex
# Debian/Ubuntu
sudo apt install texlive-xetex texlive-fonts-recommended \
texlive-latex-extra texlive-latex-recommended texlive-science texlive-plain-generic
Paketuppsättningen för Debian/Ubuntu är en snabb approximation av renderingsmiljön. Den exakta listan över TeX Live-paket som behövs finns i .github/tl_packages — det är vad CI installerar, och med BasicTeX eller en minimal TeX Live räcker tlmgr install $(grep -v '^#' .github/tl_packages). texlive-xetex ensamt räcker inte — bland annat ulem (i texlive-plain-generic), tcolorbox och siunitx behövs för att rendera.
Färdig renderingsmiljö (containerimage)
Den miljö klartex släpps mot publiceras som ghcr.io/swedev/klartex-base: full TeX Live plus Microsoft core fonts (Georgia, Arial, Times New Roman …) och den Python-runtime som behövs för att installera paketet. Tjänster som renderar med klartex bygger vidare på den i stället för att återskapa apt-listan.
FROM ghcr.io/swedev/klartex-base:<tagg>@sha256:<digest>
Pinna alltid tagg och manifest-digest — det finns ingen latest-tagg. Imagen byggs av .github/workflows/base-image.yml från docker/Dockerfile.base, och hela testsviten körs inuti den färdigbyggda amd64-imagen innan något publiceras — en image som klartex inte renderar i når aldrig registret.
Samma image är också releasegrind: .github/workflows/publish.yml kör hela testsviten inuti den pinnade imagen innan paketet byggs, så varje version som publiceras på PyPI har passerat i renderingsmiljön.
Användning
Som Python-bibliotek
from klartex import render
pdf_bytes = render("protokoll", data)
Som CLI
# Rendera (block engine är default)
klartex -d data.json
# Pipe JSON via stdin
cat data.json | klartex
# Med explicit mall
klartex -d data.json -t protokoll
# Med extern sidmall (hela sidan, eller en slot i taget)
klartex -d data.json --page-template minforening.tex.jinja
klartex -d data.json --header-template sidhuvud.tex.jinja
# Lista mallar
klartex templates
# Visa JSON Schema för en mall
klartex schema protokoll
Sidmallar (Page Templates)
En sidmall består av två oberoende delar: header (sidhuvud) och footer (sidfot). Varje del väljs för sig — en färdig variant, ett objekt med uppgifterna som ska stå där, eller null för tomt. Strukturerade inställningar fortsätter gälla för den del som är fördefinierad, även när den andra delen har egen LaTeX.
| Slot | Variant | Innehåll |
|---|---|---|
header |
letterhead |
Organisationsuppgifter till vänster, logotyp till höger |
header |
logo |
Enbart logotyp till höger |
header |
null |
Tomt sidhuvud — sidhuvudets utrymme återtas |
footer |
standard |
Sidnummer centrerat; med kontaktuppgifter en flerkolumnsfot |
footer |
null |
Tom sidfot |
De tre namnen formal, clean och none är alias för färdiga kombinationer:
| Alias | Motsvarar |
|---|---|
formal |
header: "letterhead" + footer: {"title": true} |
clean |
header: "logo" + footer: "standard" |
none |
header: null + footer: "standard" |
"page_template": "formal"
"page_template": {
"header": {
"variant": "letterhead",
"org_name": "Min Förening",
"address": "Storgatan 1, 123 45 Stad",
"web": "minforening.se",
"email": "styrelsen@minforening.se",
"logo": "logo.pdf"
},
"footer": {
"company": "Min Förening",
"org_number": "802000-0000",
"bankgiro": "1234-5678"
}
}
"page_template": { "header": "logo", "footer": null }
Ett alias kan kombineras med en slot som ersätter den sidan av kombinationen: {"name": "clean", "footer": null} ger logotypsidhuvudet utan sidfot.
Objektformen av letterhead kräver org_name — namnet är det som sidhuvudet byggs runt, och utan det skulle övriga uppgifter inte skrivas ut. Ett sidhuvud helt utan uppgifter anges som variantnamnet självt ("header": "letterhead"). logo är ett filnamn utan LaTeX-specialtecken (\ # $ % & _ { } ~ ^).
Utöver sloten finns inställningar på dokumentnivå — font, header_font och diff_style — som gäller oavsett om en slot har egen LaTeX, plus page_numbers och first_page_header.
Egen sidmall
Rå LaTeX skickas per slot, inte i JSON:
klartex -d data.json --header-template sidhuvud.tex.jinja
klartex -d data.json --header-template sidhuvud.tex.jinja --footer-template sidfot.tex.jinja
render("_block", data, header_source=Path("sidhuvud.tex.jinja").read_text())
Båda filerna måste ligga i samma katalog — den katalogen blir mallkatalogen som filer hittas relativt till. --page-template (och "page_template_source" i API-anrop) tar i stället över båda sloten med en enda fil, och kan inte kombineras med slot-flaggorna.
En slot-fil definierar sin egen del av chromet:
\definecolor{brandprimary}{HTML}{2E5A1C}
\definecolor{brandsecondary}{HTML}{555555}
\renewcommand{\orgname}{Min Förening}
\fancyhead[L]{\fontsize{6pt}{9pt}\selectfont\textbf{\orgname}}
\fancyhead[R]{\includegraphics[height=0.855cm]{logo.pdf}}
\makeatletter
\fancyfoot[C]{%
\kx@setlang%
\fontsize{6pt}{9pt}\selectfont\color{brandsecondary}%
\doctitle\ \textbullet\ \kx@page\ \thepage\ \kx@of\ \pageref{LastPage}%
}
\makeatother
Dessa makron är kontraktet mellan sidmallen och dokumentklassen och kan skrivas om i preamblens toppnivå: \orgname, \orgaddress, \orgwebsite, \orgemail, \orgphone, \brandlogo. Klassen definierar dem tomma, så använd \renewcommand. Sidhuvudets utrymme återtas i slutet av preamblen om \orgname och \brandlogo båda är tomma — ett värde som sätts senare (t.ex. i \AtBeginDocument) hinner inte med det testet.
Delarna skrivs ut i fast ordning: inställningar på dokumentnivå, sidhuvud, sidfot, återtaget utrymme. En egen slot bör därför inte röra den andra slotens \fancyhead/\fancyfoot-celler.
Var logotyper och andra filer hittas skiljer sig mellan de två ytorna:
- CLI med filbaserad sidmall (
--page-template,--header-template,--footer-template, eller autodetekterad<data-stem>.tex.jinja/page_template.tex.jinja): filer hittas relativt till sidmallens egen katalog, med arbetsmappen som fallback. En mall och dess logotyper kan därmed ligga samlade i t.ex. enBranding/-mapp och användas från vilken arbetsmapp som helst. För en symlänkad mall gäller målets katalog. Autodetektering hoppas över när en slot-flagga anges. - API med
page_template_source,header_sourceellerfooter_source: parametrarna tar rå text utan sökväg, så det finns ingen mallkatalog att utgå från. Anropare som vill hitta filer utanför arbetsmappen skickarasset_dir=<katalog>tillrender(); annars gäller arbetsmappen.
Både
\includegraphics{logo.pdf}och\includegraphics{./logo.pdf}fungerar, liksom\input{../delat/farger.tex}— relativa referenser utgår från mallens katalog (ellerasset_dir, i annat fall arbetsmappen). En skillnad finns dock: namn med./eller../faller inte tillbaka på arbetsmappen. TeX:s filsökning (Kpathsea) söker aldrig upp sådana namn, utan provar dem rakt av mot xelatex arbetskatalog — och den katalogen är just mallens katalog. Namn utan prefix söks däremot i hela kedjan och hittas även om filen bara ligger i arbetsmappen.
Arkitektur
Klartex har en trelagers-arkitektur:
- Dokumentnivå —
klartex-base.clshanterar siduppställning och grundläggande sidhuvud/sidfot. Sidmallar (.tex.jinja) injiceras i preambeln och styr färger, logotyp och layout. - Komponentnivå — Återanvändbara
.sty-paket som ger strukturerade LaTeX-makron (t.ex.klartex-signatureblock.sty,klartex-klausuler.sty,klartex-agenda.sty) - Receptnivå — YAML-filer som deklarerar vilka komponenter och innehållsfält som ska kombineras
Renderingsvägar
- Recipe-mallar (
protokoll,faktura,kvitto) — YAML-recept som deklarerar komponenter och mappningar - Block engine (
_block) — Agenten komponerarbody[]fritt från typade block
Skapa en YAML-receptmall
Skapa en recipe.yaml i mallens katalog (t.ex. klartex/templates/min-mall/recipe.yaml):
template:
name: min-mall
description: "Beskrivning av mallen"
lang: sv
document:
title: "{{ data.title }}"
page_template: formal
metadata:
- label: "Datum:"
field: date
components:
- type: klausuler
data_map:
items: agenda_items
options:
item_title_field: title
item_body_field: body
schema: schema.json
Tillgängliga recept-komponenter: heading, description_list, agenda, text, resultatrakning, budgettabell, notapparat, invoice_header, invoice_recipient, invoice_table, payment_info, invoice_note, receipt_header, receipt_table. Block-motsvarigheterna (agenda, description_list, heading, resultatrakning, budgettabell, notapparat, text) renderas via samma delade makron som block-engine-vägen.
Block engine-block: heading, text, list, table, callout, quote, title_page, parties, clause, signatures, description_list, form, columns, agenda, name_roster, resultatrakning, budgettabell, notapparat, page_break, latex.
Årsmötespaket
Blockmotorn kan komponera alla dokument som behövs för ett föreningsårsmöte:
| Dokument | Blocktyper |
|---|---|
| Kallelse + dagordning | heading, description_list, agenda |
| Verksamhetsberättelse | heading, name_roster, text, signatures |
| Ekonomisk årsredovisning | heading, text, resultatrakning, notapparat, signatures |
| Revisionsberättelse | heading, text, signatures |
| Budget | heading, budgettabell |
| Valberedningens förslag | heading, name_roster, signatures |
| Motion | heading, text, clause, signatures |
| Styrelsens yttrande | heading, text, signatures |
Agenten väljer och ordnar block för varje dokument — inga separata mallar behövs. Se tests/fixtures/block_kallelse.json m.fl. för fullständiga exempel.
Licens
MIT
Release files for klartex 0.16.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| klartex-0.16.0.tar.gz | 92.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| klartex-0.16.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size:205.5 kB
Release files / klartex-0.16.0.tar.gz
| Download URL | klartex-0.16.0.tar.gz |
|---|---|
| Size | 92.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ecfab11d6267ef771796499f72e36816c713be95659d680d8242353210a11f0e
|
|
BLAKE2b-256 checksum How to use checksums |
e7a0a740891e87049ae1398ac8f854d7e892b2b22f48c7d37ccd9ffad8dffa03
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 30, 2026.
Transparency logRelease files / klartex-0.16.0-py3-none-any.whl
| Download URL | klartex-0.16.0-py3-none-any.whl |
|---|---|
| Size | 112.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0b5b0624bd80f519367314a35e35e68733497677556c6d30c0efd976d730c32f
|
|
BLAKE2b-256 checksum How to use checksums |
85d62fc2f42323e654994b846eb15295bbe1b628296ce9758b422601f30e7dcd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 30, 2026.
Transparency log