Collapse Terce/Sext/None's identical hymn resolution into one helper

Terce, Sext, and None each had a byte-identical 'hymn' case
(resolveCommon(part.textRef.id), no doxology mechanism, no override/
season tiering). Replace all three with a single shared
resolveSelfContainedHymn helper in resolve-common.ts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F25189JqjXddUhU9hM9nUS
This commit is contained in:
2026-08-24 07:14:19 -04:00
parent 449472d5aa
commit 72033221c3
4 changed files with 16 additions and 7 deletions
+2 -2
View File
@@ -13,6 +13,7 @@ import {
resolveOfficeWinner, resolveOfficeWinner,
resolveMinorHourAntiphon, resolveMinorHourAntiphon,
resolveMinorHourChapter, resolveMinorHourChapter,
resolveSelfContainedHymn,
} from './resolve-common'; } from './resolve-common';
import noneDefinitionData from '../data/hours/none.yml'; import noneDefinitionData from '../data/hours/none.yml';
import antiphonsData from '../data/hours/none-antiphons.yml'; import antiphonsData from '../data/hours/none-antiphons.yml';
@@ -25,8 +26,7 @@ function resolvePart(part: HourPart, day: LiturgicalDay): ResolvedPart[] {
case 'opening-versicle': case 'opening-versicle':
return [{ kind: 'versicle', text: resolveCommon(getOpeningVersicleId(day.season, day.winner)) }]; return [{ kind: 'versicle', text: resolveCommon(getOpeningVersicleId(day.season, day.winner)) }];
case 'hymn': case 'hymn':
// Self-contained, no appendDoxology — see none-hymn.yml. return resolveSelfContainedHymn(part);
return [{ kind: 'hymn', text: resolveCommon(part.textRef.id) }];
case 'chapter': case 'chapter':
return [{ kind: 'chapter', text: resolveMinorHourChapter('none', day, part.textRef.id) }]; return [{ kind: 'chapter', text: resolveMinorHourChapter('none', day, part.textRef.id) }];
case 'day-collect': case 'day-collect':
+10 -1
View File
@@ -1,4 +1,4 @@
import type { ResolvedPart, ResolvedText } from './types'; import type { PropersRef, ResolvedPart, ResolvedText } from './types';
import type { Commemoration, DayWinner, LiturgicalDay, Weekday } from '../calendar/types'; import type { Commemoration, DayWinner, LiturgicalDay, Weekday } from '../calendar/types';
import type { ProperText } from '../propers'; import type { ProperText } from '../propers';
import { getCommonProper, getTemporalProper } from '../propers'; import { getCommonProper, getTemporalProper } from '../propers';
@@ -31,6 +31,15 @@ export function resolveCommon(id: string): ResolvedText {
return toResolvedText(getCommonProper(id)); return toResolvedText(getCommonProper(id));
} }
/** Terce/Sext/None's own Matins-less hymn 'hymn' case — a plain, fixed,
* self-contained text with no doxology mechanism at all (the closing
* doxology is baked directly into each hour's own hymn text file; see
* {terce,sext,none}-hymn.yml) and no override/season tiering. Byte-
* identical across all three files before being centralized here. */
export function resolveSelfContainedHymn(part: { textRef: PropersRef }): ResolvedPart[] {
return [{ kind: 'hymn', text: resolveCommon(part.textRef.id) }];
}
// Named temporal winners with real standing of their own, unconditionally // Named temporal winners with real standing of their own, unconditionally
// override-eligible — see hours/lauds.ts's getPsalmodyOverrideFor, which // override-eligible — see hours/lauds.ts's getPsalmodyOverrideFor, which
// shares this set (imported from here, not duplicated) since it's the // shares this set (imported from here, not duplicated) since it's the
+2 -2
View File
@@ -13,6 +13,7 @@ import {
resolveOfficeWinner, resolveOfficeWinner,
resolveMinorHourAntiphon, resolveMinorHourAntiphon,
resolveMinorHourChapter, resolveMinorHourChapter,
resolveSelfContainedHymn,
} from './resolve-common'; } from './resolve-common';
import sextDefinitionData from '../data/hours/sext.yml'; import sextDefinitionData from '../data/hours/sext.yml';
import antiphonsData from '../data/hours/sext-antiphons.yml'; import antiphonsData from '../data/hours/sext-antiphons.yml';
@@ -25,8 +26,7 @@ function resolvePart(part: HourPart, day: LiturgicalDay): ResolvedPart[] {
case 'opening-versicle': case 'opening-versicle':
return [{ kind: 'versicle', text: resolveCommon(getOpeningVersicleId(day.season, day.winner)) }]; return [{ kind: 'versicle', text: resolveCommon(getOpeningVersicleId(day.season, day.winner)) }];
case 'hymn': case 'hymn':
// Self-contained, no appendDoxology — see sext-hymn.yml. return resolveSelfContainedHymn(part);
return [{ kind: 'hymn', text: resolveCommon(part.textRef.id) }];
case 'chapter': case 'chapter':
return [{ kind: 'chapter', text: resolveMinorHourChapter('sext', day, part.textRef.id) }]; return [{ kind: 'chapter', text: resolveMinorHourChapter('sext', day, part.textRef.id) }];
case 'day-collect': case 'day-collect':
+2 -2
View File
@@ -13,6 +13,7 @@ import {
resolveOfficeWinner, resolveOfficeWinner,
resolveMinorHourAntiphon, resolveMinorHourAntiphon,
resolveMinorHourChapter, resolveMinorHourChapter,
resolveSelfContainedHymn,
} from './resolve-common'; } from './resolve-common';
import terceDefinitionData from '../data/hours/terce.yml'; import terceDefinitionData from '../data/hours/terce.yml';
import antiphonsData from '../data/hours/terce-antiphons.yml'; import antiphonsData from '../data/hours/terce-antiphons.yml';
@@ -25,8 +26,7 @@ function resolvePart(part: HourPart, day: LiturgicalDay): ResolvedPart[] {
case 'opening-versicle': case 'opening-versicle':
return [{ kind: 'versicle', text: resolveCommon(getOpeningVersicleId(day.season, day.winner)) }]; return [{ kind: 'versicle', text: resolveCommon(getOpeningVersicleId(day.season, day.winner)) }];
case 'hymn': case 'hymn':
// Self-contained, no appendDoxology — see terce-hymn.yml. return resolveSelfContainedHymn(part);
return [{ kind: 'hymn', text: resolveCommon(part.textRef.id) }];
case 'chapter': case 'chapter':
return [{ kind: 'chapter', text: resolveMinorHourChapter('terce', day, part.textRef.id) }]; return [{ kind: 'chapter', text: resolveMinorHourChapter('terce', day, part.textRef.id) }];
case 'day-collect': case 'day-collect':