From 2f1d192d7e55535a0d7f9f786af09f29eedef750 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Fri, 28 Nov 2025 16:27:36 -0500 Subject: [PATCH] Add complete Bible PDF export feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New endpoint /bible/pdf generates a comprehensive PDF of the entire King James Bible with all cross-references and word studies. Features: - Title page with edition information - Table of contents (Old Testament & New Testament) - All 66 books with proper page breaks - All 31,102 verses with footnotes - Cross-references grouped by description - Word studies with Greek/Hebrew terms - Running headers with book names - Page numbers - Professional typography PDF structure: - Title page - Table of contents (2 columns) - Genesis through Malachi (Old Testament) - Matthew through Revelation (New Testament) - Footer page This will generate a substantial PDF (likely 1000+ pages) with complete study content suitable for printing or offline study. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- kjvstudy_org/server.py | 92 ++++++++++ kjvstudy_org/templates/bible_pdf.html | 251 ++++++++++++++++++++++++++ 2 files changed, 343 insertions(+) create mode 100644 kjvstudy_org/templates/bible_pdf.html diff --git a/kjvstudy_org/server.py b/kjvstudy_org/server.py index 25fac55..ba5884e 100644 --- a/kjvstudy_org/server.py +++ b/kjvstudy_org/server.py @@ -1142,7 +1142,11 @@ def format_numbered_lists(text): templates.env.filters['format_lists'] = format_numbered_lists +def number_format(value): + """Format a number with commas (e.g., 31102 -> 31,102)""" + return f"{value:,}" +templates.env.filters['number_format'] = number_format def get_biblical_timeline_context(): @@ -2269,6 +2273,94 @@ async def chapter_pdf(request: Request, book: str, chapter: int): ) +@app.get("/bible/pdf") +async def bible_pdf(request: Request): + """Generate a PDF export of the complete Bible with cross-references and word studies.""" + if not WEASYPRINT_AVAILABLE: + raise HTTPException( + status_code=503, + detail="PDF generation is not available. WeasyPrint system libraries are not installed." + ) + + from .data import bible_metadata + + books = bible.get_books() + old_testament = bible_metadata.old_testament_books + new_testament = bible_metadata.new_testament_books + + # Prepare data for all books + books_data = [] + total_verses = 0 + + for book_name in books: + chapters_dict = {} + commentaries_dict = {} + shown_words = set() # Track word studies per book + + # Get all chapters for this book + chapters = bible.get_chapters_for_book(book_name) + + for chapter_num in chapters: + verses = bible.get_verses_by_book_chapter(book_name, chapter_num) + chapters_dict[chapter_num] = verses + total_verses += len(verses) + + # Generate commentaries for this chapter + chapter_commentaries = {} + for verse in verses: + commentary = generate_commentary(book_name, chapter_num, verse) + + # Add word study sidenotes (avoiding repetition within book) + word_studies = generate_word_study_sidenotes( + verse.text, book_name, chapter_num, verse.verse, shown_words + ) + commentary['word_studies'] = word_studies + for study in word_studies: + shown_words.add(study['word'].lower()) + + # Add cross-references grouped by description + from collections import defaultdict + cross_refs = get_cross_references(book_name, chapter_num, verse.verse) + grouped_refs = defaultdict(list) + for ref in cross_refs: + description = ref['note'] if ref['note'] else 'Related' + grouped_refs[description].append(ref['ref']) + + commentary['cross_reference_groups'] = [ + {'description': desc, 'refs': refs} + for desc, refs in grouped_refs.items() + ] + + chapter_commentaries[verse.verse] = commentary + + commentaries_dict[chapter_num] = chapter_commentaries + + books_data.append({ + 'name': book_name, + 'chapter_count': len(chapters), + 'chapters': chapters_dict, + 'commentaries': commentaries_dict + }) + + # Render HTML + html_content = templates.get_template("bible_pdf.html").render( + books=books_data, + old_testament=old_testament, + new_testament=new_testament, + total_verses=total_verses, + ) + + # Generate PDF (this will take a while for the full Bible!) + pdf_buffer = await render_html_to_pdf_async(html_content) + filename = "kjv-complete-bible.pdf" + + return StreamingResponse( + pdf_buffer, + media_type="application/pdf", + headers={"Content-Disposition": f"attachment; filename={filename}"} + ) + + @app.get("/book/{book}/chapter/{chapter}/verse/{verse_num}", response_class=HTMLResponse) def read_verse(request: Request, book: str, chapter: int, verse_num: int): """Display a single verse with detailed commentary""" diff --git a/kjvstudy_org/templates/bible_pdf.html b/kjvstudy_org/templates/bible_pdf.html new file mode 100644 index 0000000..c8acfe6 --- /dev/null +++ b/kjvstudy_org/templates/bible_pdf.html @@ -0,0 +1,251 @@ + + + + + King James Version Bible (Complete) + + + + +
+

HOLY BIBLE

+

Authorized King James Version

+

+ 1769 Cambridge Edition
+ Complete with Cross-References and Word Studies
+ {{ total_verses|number_format }} verses across 66 books +

+
+ + +
+

Table of Contents

+ +
+

Old Testament (39 books)

+
+ {% for book in old_testament %} +
{{ book }}
+ {% endfor %} +
+
+ +
+

New Testament (27 books)

+
+ {% for book in new_testament %} +
{{ book }}
+ {% endfor %} +
+
+
+ + + {% for book_data in books %} +
+

{{ book_data.name }}

+

{{ book_data.chapter_count }} {% if book_data.chapter_count == 1 %}chapter{% else %}chapters{% endif %}

+ + {% for chapter_num, verses in book_data.chapters.items() %} +
+

Chapter {{ chapter_num }}

+
+ {% for verse in verses %} + {% set commentary = book_data.commentaries.get(chapter_num, {}).get(verse.verse) %} + + {{ verse.verse }}{{ verse.text }}{% if commentary %}{% if commentary.cross_reference_groups %}*{% for group in commentary.cross_reference_groups %}{{ group.description }}: {% for ref in group.refs %}{{ ref }}{% if not loop.last %}; {% endif %}{% endfor %}.{% endfor %}{% endif %}{% if commentary.word_studies %}{% for study in commentary.word_studies %}†{{ study.word }}: {{ study.term }} ({{ study.translit }}) — {{ study.meaning }}.{% endfor %}{% endif %}{% endif %} + + {% endfor %} +
+
+ {% endfor %} +
+ {% endfor %} + + + + +