Render octave commemorations in getDayCollects on stacking days
getDayCollects previously dropped kind: 'octave' commemorations entirely, so on days where the temporal office keeps its own standing (the Christmas Octave's own Nativity/Stephen/John/Holy-Innocents stack, e.g. Dec 30) those octaves contributed nothing but a name in the day label. Add an octave branch, gated on temporalCategory !== 'ordinary- feria' -- the same condition resolveOfficeWinner uses -- so an ordinary octave day's already-substituted primary content never gets a redundant repeat.
This commit is contained in:
@@ -462,6 +462,22 @@ function sanctoralCommemorationPart(commemoration: Extract<Commemoration, { kind
|
|||||||
return { kind: 'preces', text: { text: {}, status: { la: 'missing', en: 'missing' } }, label };
|
return { kind: 'preces', text: { text: {}, status: { la: 'missing', en: 'missing' } }, label };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** An octave commemoration's own rendering — the fuller "Commemoratio
|
||||||
|
* Octavæ ..." Ant+V/R+collect bundle (`${id}-octave-commemoration`, e.g.
|
||||||
|
* christmas-day-octave-commemoration.yml), same shape and fallback
|
||||||
|
* pattern as sanctoralCommemorationPart. No per-saint `propers`
|
||||||
|
* indirection needed: an octave commemoration's id already is the base
|
||||||
|
* feast/saint id (`christmas-day`, `st-stephen-protomartyr`, ...),
|
||||||
|
* matching the proper file's own id 1:1. */
|
||||||
|
function octaveCommemorationPart(commemoration: Extract<Commemoration, { kind: 'octave' }>): ResolvedPart {
|
||||||
|
const label = `Commemoration of the Octave of ${commemoration.name}`;
|
||||||
|
const combined = resolveCommon(`${commemoration.id}-octave-commemoration`);
|
||||||
|
if (combined.status.la !== 'missing' || combined.status.en !== 'missing') {
|
||||||
|
return { kind: 'preces', text: combined, label };
|
||||||
|
}
|
||||||
|
return { kind: 'preces', text: { text: {}, status: { la: 'missing', en: 'missing' } }, label };
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The day's own collect, plus one more per commemoration (calendar/
|
* The day's own collect, plus one more per commemoration (calendar/
|
||||||
* types.ts's LiturgicalDay.commemorations) — Lauds/Vespers say all of
|
* types.ts's LiturgicalDay.commemorations) — Lauds/Vespers say all of
|
||||||
@@ -475,10 +491,22 @@ function sanctoralCommemorationPart(commemoration: Extract<Commemoration, { kind
|
|||||||
* Amen." for the single-collect case every other hour uses today, and
|
* Amen." for the single-collect case every other hour uses today, and
|
||||||
* stripping that back out per-collect to chain them properly would need
|
* stripping that back out per-collect to chain them properly would need
|
||||||
* text surgery this doesn't attempt — so on a commemorated day, each
|
* text surgery this doesn't attempt — so on a commemorated day, each
|
||||||
* collect here renders as its own complete, separate block instead. An
|
* collect here renders as its own complete, separate block instead.
|
||||||
* octave commemoration never contributes anything of its own here — once
|
*
|
||||||
* resolveOfficeWinner is in play, its content is already the primary
|
* An octave commemoration only renders its own block here when
|
||||||
* collect above, so a separate entry would just be a redundant repeat.
|
* `day.temporalCategory !== 'ordinary-feria'` — the same gate
|
||||||
|
* resolveOfficeWinner uses (see its own doc comment). On an *ordinary*
|
||||||
|
* octave day (e.g. an in-between day of St. Lawrence's own octave),
|
||||||
|
* resolveOfficeWinner has already substituted that octave's content as
|
||||||
|
* the primary collect above, so rendering it again here would be a
|
||||||
|
* redundant repeat (or worse, an honestly-"missing" duplicate for the
|
||||||
|
* many octaves without their own `-octave-commemoration.yml` authored).
|
||||||
|
* On a day the temporal identity itself keeps real standing (the
|
||||||
|
* Christmas Octave's own stacking days, e.g. Dec 26-31, where Christmas
|
||||||
|
* + Stephen + John + Holy Innocents are each merely commemorated
|
||||||
|
* alongside the day's own temporal office), resolveOfficeWinner does
|
||||||
|
* *not* touch the primary collect at all, so this is the only place
|
||||||
|
* these four octaves' real "Commemoratio Octavæ ..." content surfaces.
|
||||||
*/
|
*/
|
||||||
export function getDayCollects(day: LiturgicalDay): ResolvedPart[] {
|
export function getDayCollects(day: LiturgicalDay): ResolvedPart[] {
|
||||||
const parts: ResolvedPart[] = [{ kind: 'prayer', text: getDayCollect(day) }];
|
const parts: ResolvedPart[] = [{ kind: 'prayer', text: getDayCollect(day) }];
|
||||||
@@ -487,6 +515,8 @@ export function getDayCollects(day: LiturgicalDay): ResolvedPart[] {
|
|||||||
parts.push({ kind: 'prayer', text: toResolvedText(getTemporalProper(`${commemoration.id}-collect`)) });
|
parts.push({ kind: 'prayer', text: toResolvedText(getTemporalProper(`${commemoration.id}-collect`)) });
|
||||||
} else if (commemoration.kind === 'sanctoral') {
|
} else if (commemoration.kind === 'sanctoral') {
|
||||||
parts.push(sanctoralCommemorationPart(commemoration));
|
parts.push(sanctoralCommemorationPart(commemoration));
|
||||||
|
} else if (commemoration.kind === 'octave' && day.temporalCategory !== 'ordinary-feria') {
|
||||||
|
parts.push(octaveCommemorationPart(commemoration));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return parts;
|
return parts;
|
||||||
|
|||||||
@@ -157,6 +157,34 @@ describe('resolveOrdo("vespers", ...)', () => {
|
|||||||
expect(anne).toBeDefined();
|
expect(anne).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("renders each of the Christmas Octave's own stacked 'Commemoratio Octavæ' blocks on a day the temporal office itself keeps standing", () => {
|
||||||
|
// 2033-12-30 -- one day past the '2033-12-29' stacking fixture already
|
||||||
|
// used in tests/calendar/octaves.test.ts (St. Thomas of Canterbury's
|
||||||
|
// day, itself outside this app's calendar so the day stays plain
|
||||||
|
// temporal). All four of Christmas/Stephen/John/Holy Innocents' own
|
||||||
|
// octaves are active and none of them wins the day outright (the
|
||||||
|
// temporal day itself, "privileged-feria-minor", keeps the office) --
|
||||||
|
// see hours/resolve-common.ts's getDayCollects, kind === 'octave'
|
||||||
|
// branch, and its own doc comment for why this is the one case an
|
||||||
|
// octave commemoration renders its own Ant+V/R+collect block here.
|
||||||
|
const ordo = resolveOrdo('vespers', '2033-12-30');
|
||||||
|
const octaveParts = ordo.parts.filter(
|
||||||
|
(p): p is Extract<typeof p, { kind: 'preces' }> => p.kind === 'preces' && (p.label?.includes('Octave of') ?? false),
|
||||||
|
);
|
||||||
|
expect(octaveParts.map((p) => p.label).sort()).toEqual(
|
||||||
|
[
|
||||||
|
'Commemoration of the Octave of Christmas',
|
||||||
|
'Commemoration of the Octave of The Holy Innocents, Martyrs',
|
||||||
|
'Commemoration of the Octave of St. John, Apostle and Evangelist',
|
||||||
|
'Commemoration of the Octave of St. Stephen, Protomartyr',
|
||||||
|
].sort(),
|
||||||
|
);
|
||||||
|
for (const part of octaveParts) {
|
||||||
|
expect(part.text.status.la).toBe('verified');
|
||||||
|
expect(part.text.status.en).toBe('verified');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it("renders Advent's seasonal chapter/hymn/versicle instead of the plain weekday default", () => {
|
it("renders Advent's seasonal chapter/hymn/versicle instead of the plain weekday default", () => {
|
||||||
// 2025-12-02 is a Tuesday in Advent (St. Bibiana, Simplex, merely
|
// 2025-12-02 is a Tuesday in Advent (St. Bibiana, Simplex, merely
|
||||||
// commemorated — the day's own winner stays temporal either way).
|
// commemorated — the day's own winner stays temporal either way).
|
||||||
|
|||||||
Reference in New Issue
Block a user