Skip to main content

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 egen sidmall (en slot i taget)
klartex -d data.json --header-template sidhuvud.tex.jinja

# Lista mallar
klartex templates

# Visa JSON Schema för en mall
klartex schema protokoll

Som HTTP-tjänst (klartex serve)

Samma renderare bakom en liten HTTP-yta: POST /render (JSON in, PDF ut) och GET /health. Ligger bakom extran serve.

pip install 'klartex[serve]'
klartex serve --host 127.0.0.1 --port 8000

Mall, data och eventuella slot-källor går i samma JSON-objekt. Assets följer med som base64 och skrivs till en temporärkatalog som lever precis så länge anropet gör det.

{
  "template": "_block",
  "data": {"body": [{"type": "heading", "text": "Hej"}]},
  "header_source": "\\fancyhead[R]{\\includegraphics[height=1cm]{logo.png}}",
  "assets": {"logo.png": "<base64>"}
}

Svaret är application/pdf, eller ett fel vars detail.type är input_error, validation_error, payload_too_large, render_error eller overloaded. Schema- och blockfel bär dessutom detail.path — en lista som ["body", 1, "items", 0, "text"] som pekar ut noden som fallerade.

Miljövariabel Default Betydelse
KLARTEX_MAX_CONCURRENT 2 Samtidiga xelatex-körningar. Fler samtidiga anrop får 503 med Retry-After.
KLARTEX_MAX_BODY_MB 80 Största begäran som läses. Kontrollen sker på Content-Length innan kroppen läses, så gränsen gäller den storlek anroparen uppger.

Tjänsten har varken autentisering eller rate limiting — den är ett kompileringslager och ska stå bakom en anropare som äger båda. Därför binder den till 127.0.0.1 om inget annat anges. Ett latex-block i indata kör godtycklig LaTeX i renderingsprocessen; kör tjänsten avskild från allt som inte tål det.

Renderingstjänsten som image

Varje release publicerar också ghcr.io/swedev/klartex-render:X.Y.Z — samma pinnade bas som releasegrinden testar i, med releasens wheel-paket installerat. Taggen är alltid lika med klartex-versionen, och det finns ingen latest: pinna den version som motsvarar din klartex==-pin.

docker run --rm -p 127.0.0.1:8000:8000 \
  --read-only --tmpfs /tmp --tmpfs /home/render \
  ghcr.io/swedev/klartex-render:X.Y.Z

Imagen kör som icke-root och binder till 0.0.0.0 inuti containern — publicera porten bara på det nät anroparen finns på.

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 pagenumber Sidnummer centrerat, valfritt med dokumenttiteln före (title)
footer columns Flerkolumnsfot med företags-, kontakt- och betalningsuppgifter (fields)
footer null Tom sidfot

En del som utelämnas får ytans default: blockmotorn har tomt sidhuvud och sidnummerfoten, recepten letterhead-sidhuvudet och sidnummerfoten med dokumenttiteln före sidnumret (footer: {"variant": "pagenumber", "title": true}).

"page_template": {
  "header": {
    "variant": "letterhead",
    "fields": {
      "org_name": "Min Förening",
      "address": "Storgatan 1, 123 45 Stad",
      "web": "minforening.se",
      "email": "styrelsen@minforening.se",
      "logo": "logo.pdf"
    }
  },
  "footer": {
    "variant": "columns",
    "fields": {
      "company": "Min Förening",
      "org_number": "802000-0000",
      "bankgiro": "1234-5678"
    }
  }
}
"page_template": { "header": "logo", "footer": null }

Objektformen av letterhead kräver fields.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.

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 (--header-template, --footer-template): filer hittas relativt till slot-filernas egen katalog, med arbetsmappen som fallback. En mall och dess logotyper kan därmed ligga samlade i t.ex. en Branding/-mapp och användas från vilken arbetsmapp som helst. För en symlänkad fil gäller målets katalog.
  • API med header_source eller footer_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 skickar asset_dir=<katalog> till render(); 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 (eller asset_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:

  1. Dokumentnivåklartex-base.cls hanterar siduppställning och grundläggande sidhuvud/sidfot. Sidmallar (.tex.jinja) injiceras i preambeln och styr färger, logotyp och layout.
  2. Komponentnivå — Återanvändbara .sty-paket som ger strukturerade LaTeX-makron (t.ex. klartex-signatureblock.sty, klartex-klausuler.sty, klartex-agenda.sty)
  3. 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 komponerar body[] 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 }}"
  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.17.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for klartex 0.17.0
File Size Uploaded
klartex-0.17.0.tar.gz 101.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for klartex 0.17.0
File Interpreter ABI Platform
klartex-0.17.0-py3-none-any.whl Python 3 none any Details

Total release size:210.6 kB

Release files / klartex-0.17.0.tar.gz

Download URL klartex-0.17.0.tar.gz
Size 101.5 kB
Tags Source
SHA-256 checksum
How to use checksums
d6464cff792b5ff82eefca488394c4ed717bace470495a35e0066ab316c91e1e
BLAKE2b-256 checksum
How to use checksums
41391123c644b90df625b8039054534d2f36e0ac5ad3e12ef96d9b5d583cb046
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

Release files / klartex-0.17.0-py3-none-any.whl

Download URL klartex-0.17.0-py3-none-any.whl
Size 109.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
617bbb39a6485c30707936dbc3357cbd482ef7f653f989022723e31879a0979f
BLAKE2b-256 checksum
How to use checksums
42a3a8b0aab36d82f3fe3737e67f28773699f951535188bbb035e332c11d376d
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
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page