diff options
| -rw-r--r-- | man/colitur-templates.5 | 109 |
1 files changed, 96 insertions, 13 deletions
diff --git a/man/colitur-templates.5 b/man/colitur-templates.5 index ec883cb..a7e4992 100644 --- a/man/colitur-templates.5 +++ b/man/colitur-templates.5 @@ -149,8 +149,10 @@ carry a .I name field (each an object keyed by language, e.g. .BR la " and " en ). -Written naively, inside -.BR {{#days}} , +Written naively, when +.B {{#days}} +is nested inside +.BR {{#months}} , a bare .B {{name.la}} does @@ -166,8 +168,36 @@ falls back to the outer scope, which does have one. This is not a corner case: on an ordinary month, most days carry no Latin name at all (only named sanctoral days do), so the naive form renders the .I month's -name on nearly every day \(em in a flat booklet, dozens of wrong lines; in a -month grid, EVERY cell reads the month's own name. +name on nearly every day \(em in a per\-month booklet, dozens of wrong +lines; in a month grid (whose +.B {{#weeks}} +is itself only ever reachable through +.BR {{#months}} , +since +.I weeks +is a field of +.IR month , +never a top\-level list) EVERY cell reads the month's own name. +.PP +.B The collision needs a month actually on the scope stack to fire. +Iterating the TOP\-LEVEL, flat +.B days +list directly ( +.B {{#days}}...{{/days}} +at the outermost level, never passing through +.B {{#months}} +first) puts no month object anywhere on the stack, so the naive form does +.I not +silently substitute the wrong answer there \(em it silently resolves to +nothing, exactly as any other absent key would, because there is no +outer scope left to climb to. This is precisely what makes the hazard easy +to miss: an author who tries the naive form against the flat list first +sees the unnamed days come out empty, reasonably concludes the form is +safe, and then hits the real collision the moment the identical fields are +read from inside +.BR {{#months}} , +which is what every shipped template that produces a grid or a per\-month +booklet actually does. .TP .B num Both a @@ -630,15 +660,17 @@ an eighth, empty column and .B pdflatex would reject the file outright. .SH A WORKED MINIMAL TEMPLATE -A plain\-text booklet, one line per day, using the safe name idiom from -.BR "SCOPE AND LOOKUP" : +A plain\-text booklet, days nested inside months \(em the shape every +shipped template actually uses, and the shape the +.B SCOPE AND LOOKUP +hazard needs to fire \(em using the safe name idiom from that section: .RS .nf {{rite}} {{year}} -{{#days}} +{{#months}}{{#days}} {{iso}} {{#name}}{{la}}{{^la}}{{slug}}{{/la}}{{/name}} {{colour}}{{#comms}} +{{slug}}{{/comms}} -{{/days}} +{{/days}}{{/months}} .fi .RE .PP @@ -672,14 +704,65 @@ supplies instead. The third shows the non\-fallback case: 3 January .I does carry a Latin name (the votive Office of the Blessed Virgin Mary on -Saturday), and the idiom prints it correctly. A template using the unsafe, -bare +Saturday), and the idiom prints it correctly. +.PP +Now swap only the interpolation \(em the safe idiom above becomes the +naive, unsafe +.B {{name.la}} , +nesting left exactly as it was: +.RS +.nf + +{{rite}} {{year}} +{{#months}}{{#days}} +{{iso}} {{name.la}} {{colour}} +{{/days}}{{/months}} +.fi +.RE +.PP +Rendered against the identical year, same extension and flavour: +.RS +.nf + +.B colitur table \-\-year 2026 \-\-template minimal\-unsafe.txt | head \-7 +ef 2026 + +2026\-01\-01 Ianuarius white + +2026\-01\-02 Ianuarius white + +2026\-01\-03 Officium sanctae Mariae in sabbato white +.fi +.RE +.PP +The collision fires for real on the first two lines: with a month on the +scope stack, the day's own missing +.B la +key falls back all the way out to the ENCLOSING MONTH's own +.RB \(lq Ianuarius \(rq +rather than failing. The third line is untouched, because 3 January's own +.I name +object genuinely has a +.B la +key, so the dotted path resolves without ever needing to fall back. +.PP +.B This is specific to nesting, and that is the point. +The identical naive .B {{name.la}} -form would instead have printed +written against the TOP\-LEVEL, flat +.B days +list (no +.B {{#months}} +wrapping it) does +.I not +print .RB \(lq Ianuarius \(rq -on BOTH of those lines \(em the enclosing month's own name \(em see +anywhere \(em there is no month on the stack to fall back to, so it prints +nothing on an unnamed day instead, silently but not wrongly. See .B SCOPE AND LOOKUP -above. +above for why testing the naive form only against a flat list is exactly +how this hazard goes unnoticed until a template is later nested under +.BR {{#months}} . .SH SEE ALSO .BR colitur (1) for |
