Collapse consecutive bible-plan chapters into a citation range
Deploy / deploy (push) Successful in 1m51s

Multi-chapter readings (e.g. Job 34-37, authored as one YAML entry per
chapter) were rendering as "Job 34; Job 35; Job 36; Job 37" instead of
the compact "Job 34-37". Verse-qualified and non-consecutive citations
are unaffected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
This commit is contained in:
2026-09-03 11:46:34 -04:00
parent d660f9e531
commit 64a5634557
3 changed files with 54 additions and 4 deletions
+32 -1
View File
@@ -66,6 +66,37 @@ function citationLabel(citation: ScriptureCitation): string {
return citation.verses ? `${book} ${citation.chapter}:${citation.verses}` : `${book} ${citation.chapter}`;
}
/** Collapses consecutive same-book, whole-chapter passages (e.g. Job 34, 35,
* 36, 37 — the source data authors one entry per chapter) into a compact
* "Book start-end" range, since `citationLabel` alone would otherwise
* produce a separate "Book N" for each chapter. Verse-qualified citations
* never merge into a range. */
function formatCitationLabel(passages: ScriptureCitation[]): string {
const segments: string[] = [];
let i = 0;
while (i < passages.length) {
const start = passages[i]!;
if (start.verses) {
segments.push(citationLabel(start));
i++;
continue;
}
let j = i;
while (
j + 1 < passages.length &&
passages[j + 1]!.book === start.book &&
!passages[j + 1]!.verses &&
passages[j + 1]!.chapter === passages[j]!.chapter + 1
) {
j++;
}
const book = start.book.charAt(0).toUpperCase() + start.book.slice(1);
segments.push(j > i ? `${book} ${start.chapter}-${passages[j]!.chapter}` : `${book} ${start.chapter}`);
i = j + 1;
}
return segments.join('; ');
}
function isGospelReading(passages: ScriptureCitation[]): boolean {
return passages.every((p) => GOSPEL_BOOKS.has(p.book));
}
@@ -76,7 +107,7 @@ function resolveReading(record: BiblePlanReadingRecord, bookIndex: number): Bibl
la: text.la ? 'verified' : 'missing',
en: text.en ? 'verified' : 'missing',
};
const label = record.passages.map(citationLabel).join('; ');
const label = formatCitationLabel(record.passages);
const firstBook = record.passages[0]?.book;
const responsory = firstBook ? getResponsoryForBook(firstBook, bookIndex)?.text : undefined;
return {