diff options
Diffstat (limited to 'templates')
| -rw-r--r-- | templates/ef/grid.typ | 113 |
1 files changed, 81 insertions, 32 deletions
diff --git a/templates/ef/grid.typ b/templates/ef/grid.typ index c197ad2..8c41705 100644 --- a/templates/ef/grid.typ +++ b/templates/ef/grid.typ @@ -6,20 +6,27 @@ // 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. +// The grid must FILL the page, not sit in its top quarter -- AND every +// month must fit on exactly ONE page, never spill onto a second (Defect 3; +// this file used to read `rows: (auto, 1fr)`, described below as filling +// the page "completely regardless of 5 or 6 rows"). That description was +// true for row COUNT but silently assumed a fixed CONTENT height per row +// too: adding the sigla line grew each cell's natural content past what a +// 1/6-of-remaining-space `1fr` row allows, and a Typst `fr` track's size is +// the LARGER of its fair share and its content's own minimum -- it grows +// PAST 1fr rather than shrinking content to fit, which is exactly how a +// 6-row month (`I classis` sliced mid-cell, the next month's own heading +// printed underneath it) spilled onto a second page. Fixed now the same +// way grid.tex's own \cellh already was: an EXPLICIT row height +// ([cellh] below, computed from the page's own text height divided by six +// -- every month in the 1583-9999 domain has 5 or 6 Sunday-started weeks, +// never more), with each cell's own content wrapped in a height-clipped +// block sized to match. A 5-week month still leaves a blank sixth row (the +// same trade-off grid.tex's own header already discloses and defends); +// the disclosed DIVERGENCE this comment used to describe -- Typst +// stretching every month to fill the page regardless of row count -- is +// GONE: overflow safety now matters more than that cosmetic fill, and a +// fixed height is what makes the fit provable rather than hoped for. // // 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 @@ -64,35 +71,76 @@ ) #let cpad = luma(248) +// a4 landscape text area is 277x190mm at this page's own 10mm margin. +// [titleh] is the measured height of the month title line + its own +// #v below (16pt bold, one line, verified against real rendered output, +// not assumed); [headerh] the weekday-name row. What is left +// (190 - titleh - headerh) is divided by SIX, never five, so a 6-row +// month is what this budget is proven against -- a 5-row month then has +// one row's worth of genuine spare room, not a tight fit. [cellinset] is +// subtracted back out per side when sizing each cell's own clipped inner +// block below. +// Budgeted against 184mm, not the full 190mm text height: a first attempt +// at exactly 190mm (zero slack) measurably split the table BETWEEN rows +// on real output -- Typst's own table breaks across a page boundary by +// default when the sum of explicit row heights doesn't quite clear the +// remaining space, stranding the 6th row alone on its own page with no +// heading -- so 6mm of genuine slack is deliberate, not rounded for +// looks. `breakable: false` below is the second, independent guard: even +// if this budget is ever wrong again, the WHOLE table jumps to a fresh +// page rather than splitting a row across two -- loudly wrong (an odd +// blank page) rather than silently wrong (a sliced row). It is a #block +// property, not a #table one (Typst rejects `table(breakable: ...)` +// outright as an unexpected argument -- verified live), so the table +// below is wrapped in a block rather than passed the flag directly. +// +// Each cell's own content sits in a SECOND, height-clipped block, exactly +// [cellh] minus its own top/bottom inset: the table row height is +// EXPLICIT ([cellh], not `auto` or `1fr`), so nothing inside can grow the +// row past it -- content that still does not fit is clipped rather than +// spilling into the next cell or the next page, the "truncate +// gracefully" option Defect 3's own brief names. Never actually hit on +// real 1583-9999 data (checked against the full 2027 fixture, every +// month, both row counts -- see the task report), but the box is +// provably safe either way, which a content-driven row never was. Inside +// that block, one Typst paragraph throughout, 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. +#let titleh = 9mm +#let headerh = 6mm +#let cellh = (184mm - titleh - headerh) / 6 +#let cellinset = 1.2mm + {{#months}} -#text(size: 20pt, weight: "bold")[{{name}} {{year}}] -#v(2mm) +#text(size: 16pt, weight: "bold")[{{name}} {{year}}] +#v(1.5mm) +#block(breakable: false)[ #table( columns: (1fr,) * 7, - rows: (auto, 1fr), + rows: (headerh, cellh), stroke: 0.4pt + luma(150), - inset: 1.6mm, + inset: cellinset, align: left + top, {{#weekday_headings}} - table.cell(align: center + horizon)[#text(weight: "bold")[{{name}}]], + table.cell(align: center + horizon)[#text(size: 7pt, 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}}] + #block(height: cellh - 2 * cellinset, clip: true)[ + #set par(leading: 0.3em) + #text(weight: "bold")[{{dom}}] #text(size: 6.5pt)[{{name}}] + #v(1fr) + #text(size: 6pt)[{{rank_name}}] \ + #text(size: 6pt)[{{#first}}{{first}}{{/first}}{{#gospel}}{{#first}} #sym.dot.c {{/first}}{{gospel}}{{/gospel}}] + ] ], {{/in_month}} {{^in_month}} @@ -101,5 +149,6 @@ {{/days}} {{/weeks}} ) +] #pagebreak(weak: true) {{/months}} |
