Add section headings for all 66 books of the Bible

Adds 2,543 section headings (e.g., "The Sermon on the Mount",
"The Suffering Servant") that display before verses in chapter
pages. Headings are loaded from JSON and rendered as styled h3
elements in the Tufte typography style.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-12-05 09:37:46 -05:00
parent 3bbe683a60
commit d303d70f02
3 changed files with 5108 additions and 1 deletions
File diff suppressed because it is too large Load Diff
+29 -1
View File
@@ -1,5 +1,8 @@
"""Bible routes - book, chapter, verse, and interlinear views."""
import json
from collections import defaultdict
from functools import lru_cache
from pathlib import Path
from fastapi import APIRouter, HTTPException, Request
from fastapi.responses import HTMLResponse, RedirectResponse, StreamingResponse
@@ -13,6 +16,27 @@ from ..utils.books import normalize_book_name, OT_BOOKS
from ..utils.helpers import create_slug, get_related_content, get_chapter_popularity_score, get_chapter_popularity_explanation
from ..utils.pdf import WEASYPRINT_AVAILABLE, render_html_to_pdf_async
@lru_cache(maxsize=1)
def _load_section_headings():
"""Load section headings data from JSON file."""
data_path = Path(__file__).parent.parent / "data" / "section_headings.json"
if data_path.exists():
with open(data_path) as f:
return json.load(f)
return {}
def get_section_headings(book: str, chapter: int) -> dict:
"""Get section headings for a specific chapter.
Returns dict mapping verse number (int) to heading text.
"""
headings_data = _load_section_headings()
chapter_headings = headings_data.get(book, {}).get(str(chapter), {})
# Convert string keys to int for easier template use
return {int(k): v for k, v in chapter_headings.items()}
router = APIRouter()
templates = None
@@ -287,6 +311,9 @@ async def read_chapter(request: Request, book: str, chapter: int):
# Get related content for internal linking
related_content = get_related_content(book, chapter)
# Get section headings for this chapter
section_headings = get_section_headings(book, chapter)
# Build breadcrumbs
breadcrumbs = [
{"text": "Home", "url": "/"},
@@ -310,7 +337,8 @@ async def read_chapter(request: Request, book: str, chapter: int):
"current_book": book,
"current_chapter": chapter,
"pdf_available": WEASYPRINT_AVAILABLE,
"related_content": related_content
"related_content": related_content,
"section_headings": section_headings
}
)
+24
View File
@@ -181,6 +181,27 @@ hr::before {
color: var(--text-color);
}
/* Section headings - like study Bible pericopes */
.section-heading {
font-family: et-book, Palatino, "Palatino Linotype", "Palatino LT STD", "Book Antiqua", Georgia, serif;
font-size: 1.1rem;
font-weight: normal;
font-style: italic;
color: var(--text-secondary, #666);
margin: 1.8rem 0 0.6rem 0;
padding: 0;
border: none;
letter-spacing: 0.02em;
}
.section-heading:first-child {
margin-top: 0;
}
[data-theme="dark"] .section-heading {
color: #a0a0a0;
}
.verse-number-link {
font-family: et-book-roman-old-style;
font-size: 1rem;
@@ -460,6 +481,9 @@ document.body.dataset.resourceReader = 'false';
{% for verse in verses %}
{% set commentary = commentaries[verse.verse] if commentaries and verse.verse in commentaries else none %}
{% set has_commentary = commentary and (commentary.get('is_enhanced') or commentary.get('analysis')) %}
{% if section_headings and verse.verse in section_headings %}
<h3 class="section-heading">{{ section_headings[verse.verse] }}</h3>
{% endif %}
<p id="verse-{{ verse.verse }}">
<a href="/book/{{ book }}/chapter/{{ chapter }}/verse/{{ verse.verse }}" class="verse-number-link{% if has_commentary %} has-commentary{% endif %}">{{ verse.verse }}</a> {{ verse.text | red_letter(book, chapter, verse.verse) | inject_word_markers(commentary.word_studies if commentary else [], verse.verse, commentary.word_study_auto_expand if commentary else false) | link_names | safe }}
{% if commentary %}