Skip to main content
Version: 0.6.0

Migrating from 0.5

v0.6.0 replaces the themes namespace with theme, draws the page frame itself instead of using letter-pro, renames payment-goal to payment-terms and checks the invoice data by default. Most documents of 0.5 (and 0.4) need two changes: drop the theme: argument (or replace it) and rename payment-goal.

Before and After​

// 0.5
#show: invoice.with(
theme: themes.DIN-5008(form: "B", font: "Inter", hole-mark: false),
// ..
)
#payment-goal(days: 14)
// 0.6
#show: invoice.with(
theme: theme.classic.with(
layout: theme.layout.din-5008-b,
theme.custom.fonts(body: ("Inter", "Liberation Sans", "Libertinus Serif")),
theme.custom.marks(punch: none),
),
// sender: .., recipient: .., invoice-nr: ..
)
#payment-terms(days: 14)

Mapping Table​

0.50.6
theme: themes.DIN-5008()Nothing: the default theme.classic picks its layout from the sender's country; a German sender gets DIN 5008 form A.
themes.DIN-5008(form: "B")theme.classic.with(layout: theme.layout.din-5008-b)
font: "Inter"theme.custom.fonts(body: ("Inter", "Libertinus Serif")) or theme.custom.brand(font: ..); end the chain in an embedded font.
hole-mark: falsetheme.custom.marks(punch: none)
folding-marks: falsetheme.custom.marks(fold: ()); no marks at all: theme.custom.marks(none)
color-row-odd: a, color-row-even: btheme.custom.items-table(zebra: (a, b))
margin: (..)theme.custom.page(margin: (..)). Partial dictionaries fold; the bottom margin is computed by default.
footer: [..] (page 1 only)theme.custom.area("footer", parts: ([..], "registration")): on every page, and info motifs work in it.
theme: themes.blanktheme: theme.plain: sender, title and recipient in the flow, the registration block in the footer.
a native set page(..) before invoiceNo longer applies: the theme owns set page. Use theme.custom.page(..), theme.custom.marks(..) or a layout.
themes.blank.with(document: ..) as a hook in teststheme.resolve(..) assertions, or a part(..) stub that inspects its view (Parts).
.with(line-items: ..) on a 0.5 themetheme.custom.wrap("totals", ..) over view.totals.rows, or theme.custom.part("items-table", ..).
payment-goal(days: 14)payment-terms(days: 14); the parameters are unchanged, discount included.
themes.DIN-5008().with(zugferd-report: (ctx, result) => ..)theme.custom.part("zugferd-report", (ctx, result) => ..), or wrap the default list with theme.custom.wrap("zugferd-report", ..) (Custom Report Layout).
zugferd-report: nonetheme.custom.part("zugferd-report", none): errors of the e-invoice then stop the build, as before.
prints: (..) of a theme of your ownNothing: what a theme prints is read from its layout (What the Theme Prints).
bank-details(qr-code: (size: ..))Unchanged, and it overrides the theme's theme.custom.bank-details(qr-size: ..). Sizes below 20 mm are raised to 20 mm. qr-code: (display: false) still hides the code.
a missing field printed a placeholder such as #recipient.nameA draft marks it inline (‹missing: recipient name›) and lists it on a report page; validation: "strict" stops the build (Validation).

A theme called with a 0.5 parameter fails with a pointer to this page:

theme `classic`: unexpected named argument(s) `form`. A theme takes patches (e.g. `.with(theme.custom.colors(primary: teal))`) and `layout:` (e.g. `layout: theme.layout.din-5008-b`). `form` is a 0.5 `themes.DIN-5008` parameter; see the migration table in the theme docs.

What Else Changes​

AreaChange
Default lookclassic evolves the 0.5 look: a legal footer on every page, a continuation header on following pages, "Page 1 of 2", a reference line in the bank details and a grouped IBAN. Reference images of your own documents change once.
Validationinvoice(validation: "draft") is the default. An incomplete invoice still renders, but with markers, a badge, a watermark and a report page, and without the ZUGFeRD XML; the rules of the e-invoice are checked once the data is complete and follow zugferd-errors as before. See Validation.
Page frameinvoice-pro no longer depends on letter-pro. The layout owns the page: native set page rules before invoice have no effect.
Unknown keysEvery patch is checked. A misspelt key stops the build with its path, a did-you-mean hint and the allowed keys.
Locale stringsNew strings: document.page, document.continued-on, sections.*, line-items.item-id, line-items.unit, signature.thanks and the validation group. See Locale API.