diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-20 10:07:15 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-20 10:07:37 +0200 |
| commit | 6aebb3ec513c0177a39c2eb8d4b741e90d6f53f4 (patch) | |
| tree | 3fb327d0b3fa9ffd67d493c7393cdf9a963bf8b9 /templates/ef/grid.typ | |
| parent | 66543815ae6cbf6e576a889c9291678744243953 (diff) | |
| download | colitur-6aebb3ec513c0177a39c2eb8d4b741e90d6f53f4.tar.gz colitur-6aebb3ec513c0177a39c2eb8d4b741e90d6f53f4.zip | |
feat(templates): ordo booklet and wall calendar in Typst
Adds templates/ef/ordo.typ (A5, one week per page, each day framed with
a colour swatch, real names, every fixed string through term.*) and
templates/ef/grid.typ (A4 landscape, one month per page, 7 columns,
colour-filled cells, Epistle/Gospel sigla), matching what ordo.tex and
grid.tex already do.
Typst resolves its own table of contents inside a single compile: no
pageref/aux-file dance, unlike pdflatex's own two-pass need for
ordo.tex. ordo.typ's TOC is one flat heading per week (Month . Week N)
rather than ordo.tex's own month-once/weeks-nested layout, since the
view model has no first-of-month flag for a template to test and
inventing one would be new engine state for a cosmetic grouping.
grid.typ deliberately diverges from grid.tex's own partial-fill
behaviour for a 5-week month: Typst's row-size list repeats its own
last entry for every remaining row, so a two-entry rows spec fills the
page completely regardless of week count, where LaTeX's fixed cellh
leaves a 5-week month's bottom sixth blank on purpose. Both divergences
are documented in the templates' own headers.
Two bugs found and fixed while building these against the real typst
0.14.2 binary: two stray hash characters in grid.typ's header comment
that were not actually inside a line-comment (would have been parsed
as Typst code, not prose); and two lines merging into one wherever they
were separated only by a bare newline (still the same soft-wrapped
paragraph in Typst, unlike LaTeX's own explicit paragraph break) --
fixed with a trailing backslash to force a real line break without
adding inter-paragraph spacing, verified against a full-year render
(zero typst warnings across all 365 days of 2027, in both templates).
Goldens (test/golden/ordo-2027.typ, test/golden/grid-2027.typ) were
generated through the harness's own View.of_days/Template.render_string
path, via a throwaway generator, NOT through the CLI: the CLI's default
language table differs from the harness's own English-chained-to-Latin
table, confirmed live (diffing CLI output against the harness's own
render showed exactly the expected language divergence and nothing
else) -- the same trap this project has hit before.
make check-templates now typesets both templates with the typst binary,
using the same SKIPPED-and-exit-0 shape the pdflatex/groff blocks
already use when their own tool is absent, verified in both directions:
absent (PATH without typst) skips loudly and exits 0, and a
deliberately corrupted template fails the target with a non-zero exit
and typst's own error text.
Diffstat (limited to 'templates/ef/grid.typ')
| -rw-r--r-- | templates/ef/grid.typ | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/templates/ef/grid.typ b/templates/ef/grid.typ new file mode 100644 index 0000000..c197ad2 --- /dev/null +++ b/templates/ef/grid.typ @@ -0,0 +1,105 @@ +// colitur wall calendar -- A4 landscape, one month per page. Typst. flavour: typst +// Build: colitur table --year 2027 --template grid.typ > grid.typ && typst compile grid.typ +// ONE compile pass: this template has no table of contents and no +// cross-references (unlike ordo.typ), so there is nothing for a second pass +// to resolve even in principle -- unlike pdflatex's own two-pass need for +// grid.tex's sibling ordo.tex, though grid.tex itself already needed only +// one pass too. +// +// The grid must FILL the page, not sit in its top quarter. grid.tex's own +// header explains why it computes an explicit fixed row height by hand +// (\cellh) and why that leaves a 5-week month only 5/6 full rather than +// 6/6 -- LaTeX's tabular has no notion of "share out whatever is left". +// Typst's table/grid DOES: a row-size list shorter than the actual row +// count repeats its OWN LAST entry for every remaining row (verified live: +// a 5-row table given `rows: (auto, 1fr)` renders five equal 1fr rows, not +// one), so `rows: (auto, 1fr)` below fills the page COMPLETELY regardless +// of whether the month has 5 or 6 Sunday-started weeks, with no week count +// arithmetic in this file at all. This is a genuine, disclosed DIVERGENCE +// from grid.tex's own behaviour, not an oversight: LaTeX leaves a 5-week +// month's bottom sixth blank on purpose (documented there); this template +// instead stretches every month to fill the whole page every time, because +// Typst makes that the simpler option, not the harder one. +// +// Real names, not slugs: the observed day's own display name is a PLAIN +// resolved string (View.of_days), interpolated directly as a plain var +// below -- there is no dotted-la-with-slug-fallback idiom left to write +// (see ordo.typ's own header for the full reasoning; it applies here +// unchanged). +// +// The weekday header row comes from the view's top-level weekday_headings +// list (name/last objects), not a hard-coded Dom/Lun/Mar row: the engine +// rejects an EMPTY tag path -- a bare dot inside a section, on its own -- +// as a parse error, so the loop below names a field on each heading object +// rather than interpolating the section's own value directly, and a +// hard-coded row would not be localised anyway. +// +// No separator flag needed: grid.tex's own `last` field exists because a +// LaTeX tabular row needs its ampersand BETWEEN cells, never after the +// final one, and the engine has no "unless last" construct to lean on +// instead -- so that template renders the flag as data. Typst's own +// #table() takes a flat, comma-separated argument list and wraps it into +// rows itself, by column count, so the SAME rule applies to every cell, +// header row included, with no special case for the last one -- verified +// live that a trailing comma before a function call's closing parenthesis +// is accepted, not a syntax error. `last` is therefore simply unused here; +// left in the view model for grid.tex's own sake, not removed for this one. +// +// Sigla, compactly: each cell also carries the day's Epistle and Gospel +// references (view fields first/gospel), joined by a centred dot rather +// than repeating Ep./Ev. labels -- the same choice grid.tex and grid.ms +// already made, kept consistent rather than invented a second way. A +// #v(1fr) inside each cell's own content -- verified live to work the same +// way inside a table cell as inside any other block -- pushes the rank +// line and the sigla to the bottom of the cell, leaving the day number and +// name at the top, so the two short lines never collide with a long entry +// above them the way a single crammed line would. +#set page(paper: "a4", flipped: true, margin: 10mm, numbering: none) +#set text(size: 8pt) +#set par(justify: false) + +#let cgrid = ( + white: rgb("#FFFFFF"), red: rgb("#F8DCDC"), green: rgb("#DDEEDD"), + violet: rgb("#E6DAF0"), rose: rgb("#FADCE8"), black: rgb("#DCDCDC"), +) +#let cpad = luma(248) + +{{#months}} +#text(size: 20pt, weight: "bold")[{{name}} {{year}}] +#v(2mm) +#table( + columns: (1fr,) * 7, + rows: (auto, 1fr), + stroke: 0.4pt + luma(150), + inset: 1.6mm, + align: left + top, + {{#weekday_headings}} + table.cell(align: center + horizon)[#text(weight: "bold")[{{name}}]], + {{/weekday_headings}} + {{#weeks}} + {{#days}} + {{#in_month}} + table.cell(fill: cgrid.at("{{colour}}"))[ + // One paragraph, a trailing backslash between the rank line and the + // sigla line rather than a bare newline: two markup lines joined only + // by a bare newline stay on ONE rendered line (still the same soft- + // wrapped paragraph) -- verified live, the first draft of this cell + // merged "III classis" straight into the citation. grid.tex's own + // header explains why the rank line and the sigla get their own line + // EACH rather than being crammed onto one -- the same reasoning + // applies here, so this keeps the two-line shape it settled on. + #set par(leading: 0.35em) + #text(weight: "bold")[{{dom}}] #text(size: 7pt)[{{name}}] + #v(1fr) + #text(size: 6.5pt)[{{rank_name}}] \ + #text(size: 6.5pt)[{{#first}}{{first}}{{/first}}{{#gospel}}{{#first}} #sym.dot.c {{/first}}{{gospel}}{{/gospel}}] + ], + {{/in_month}} + {{^in_month}} + table.cell(fill: cpad)[], + {{/in_month}} + {{/days}} + {{/weeks}} +) +#pagebreak(weak: true) +{{/months}} |
