mirror of
https://github.com/kennethreitz/kjvstudy.org.git
synced 2026-06-20 14:30:57 +00:00
192 lines
6.2 KiB
Python
192 lines
6.2 KiB
Python
"""Strong's Concordance routes - Hebrew and Greek word study."""
|
|
import re
|
|
|
|
from fastapi import APIRouter, HTTPException, Request
|
|
from fastapi.responses import HTMLResponse, RedirectResponse
|
|
from fastapi.templating import Jinja2Templates
|
|
|
|
from ..kjv import bible
|
|
from ..strongs import format_strongs_entry, search_strongs, get_all_strongs
|
|
from ..interlinear_loader import find_verses_by_strongs
|
|
|
|
router = APIRouter()
|
|
templates = None
|
|
|
|
|
|
def init_templates(t: Jinja2Templates):
|
|
"""Initialize templates for Strong's routes."""
|
|
global templates
|
|
templates = t
|
|
|
|
|
|
# =============================================================================
|
|
# Routes
|
|
# =============================================================================
|
|
|
|
@router.get("/concordance")
|
|
async def concordance_redirect():
|
|
"""Redirect /concordance to /strongs."""
|
|
return RedirectResponse(url="/strongs", status_code=301)
|
|
|
|
|
|
@router.get("/strongs", response_class=HTMLResponse)
|
|
async def strongs_index(request: Request, q: str = None):
|
|
"""Strong's Concordance search and lookup page."""
|
|
from fastapi.responses import RedirectResponse
|
|
|
|
results = []
|
|
if q:
|
|
# Check if query looks like a Strong's number (H123, G456, etc.)
|
|
q_stripped = q.strip().upper()
|
|
if re.match(r'^[HG]\d+$', q_stripped):
|
|
# Normalize leading zeros (H0001 -> H1)
|
|
prefix = q_stripped[0]
|
|
num = str(int(q_stripped[1:]))
|
|
normalized = f"{prefix}{num}"
|
|
# Check if entry exists before redirecting
|
|
entry = format_strongs_entry(normalized)
|
|
if entry:
|
|
return RedirectResponse(url=f"/strongs/{normalized}", status_code=302)
|
|
|
|
results = search_strongs(q, language="both", limit=100)
|
|
|
|
books = bible.get_books()
|
|
breadcrumbs = [
|
|
{"text": "Home", "url": "/"},
|
|
{"text": "Strong's Concordance", "url": None}
|
|
]
|
|
|
|
return templates.TemplateResponse(
|
|
request,
|
|
"strongs_index.html",
|
|
{
|
|
"query": q or "",
|
|
"results": results,
|
|
"books": books,
|
|
"breadcrumbs": breadcrumbs
|
|
}
|
|
)
|
|
|
|
|
|
@router.get("/strongs/hebrew", response_class=HTMLResponse)
|
|
async def strongs_hebrew_index(request: Request, page: int = 1):
|
|
"""Paginated index of all Hebrew Strong's entries."""
|
|
data = get_all_strongs("hebrew", page=page, per_page=100)
|
|
|
|
books = bible.get_books()
|
|
breadcrumbs = [
|
|
{"text": "Home", "url": "/"},
|
|
{"text": "Strong's Concordance", "url": "/strongs"},
|
|
{"text": "Hebrew", "url": None}
|
|
]
|
|
|
|
return templates.TemplateResponse(
|
|
request,
|
|
"strongs_language_index.html",
|
|
{
|
|
"language": "Hebrew",
|
|
"language_code": "hebrew",
|
|
"entries": data["entries"],
|
|
"page": data["page"],
|
|
"total_pages": data["total_pages"],
|
|
"total": data["total"],
|
|
"books": books,
|
|
"breadcrumbs": breadcrumbs
|
|
}
|
|
)
|
|
|
|
|
|
@router.get("/strongs/greek", response_class=HTMLResponse)
|
|
async def strongs_greek_index(request: Request, page: int = 1):
|
|
"""Paginated index of all Greek Strong's entries."""
|
|
data = get_all_strongs("greek", page=page, per_page=100)
|
|
|
|
books = bible.get_books()
|
|
breadcrumbs = [
|
|
{"text": "Home", "url": "/"},
|
|
{"text": "Strong's Concordance", "url": "/strongs"},
|
|
{"text": "Greek", "url": None}
|
|
]
|
|
|
|
return templates.TemplateResponse(
|
|
request,
|
|
"strongs_language_index.html",
|
|
{
|
|
"language": "Greek",
|
|
"language_code": "greek",
|
|
"entries": data["entries"],
|
|
"page": data["page"],
|
|
"total_pages": data["total_pages"],
|
|
"total": data["total"],
|
|
"books": books,
|
|
"breadcrumbs": breadcrumbs
|
|
}
|
|
)
|
|
|
|
|
|
@router.get("/strongs/{strongs_number}", response_class=HTMLResponse)
|
|
async def strongs_entry(request: Request, strongs_number: str):
|
|
"""View a single Strong's concordance entry."""
|
|
entry = format_strongs_entry(strongs_number)
|
|
|
|
if not entry:
|
|
raise HTTPException(
|
|
status_code=404,
|
|
detail=f"Strong's number '{strongs_number}' not found"
|
|
)
|
|
|
|
# Find all verses containing this Strong's number
|
|
verse_occurrences = find_verses_by_strongs(strongs_number, limit=10000)
|
|
total_occurrences = len(verse_occurrences)
|
|
|
|
# Fetch full verse text for each occurrence and highlight the word
|
|
for occ in verse_occurrences:
|
|
verse_text = bible.get_verse_text(occ["book"], occ["chapter"], occ["verse"])
|
|
if verse_text:
|
|
# Highlight the English word in the verse text
|
|
english_word = occ.get("english", "")
|
|
if english_word and english_word in verse_text:
|
|
occ["verse_text"] = verse_text.replace(
|
|
english_word,
|
|
f'<mark>{english_word}</mark>',
|
|
1 # Only highlight first occurrence
|
|
)
|
|
else:
|
|
occ["verse_text"] = verse_text
|
|
else:
|
|
occ["verse_text"] = ""
|
|
|
|
# Extract and fetch related Strong's entries from derivation
|
|
related_entries = []
|
|
if entry.get("derivation"):
|
|
# Find all Strong's references like H1234 or G5678
|
|
strongs_refs = re.findall(r'([HG])(\d+)', entry["derivation"])
|
|
seen = set()
|
|
for prefix, num in strongs_refs:
|
|
ref = f"{prefix}{num}"
|
|
if ref.upper() != strongs_number.upper() and ref not in seen:
|
|
seen.add(ref)
|
|
related = format_strongs_entry(ref)
|
|
if related:
|
|
related_entries.append(related)
|
|
|
|
books = bible.get_books()
|
|
breadcrumbs = [
|
|
{"text": "Home", "url": "/"},
|
|
{"text": "Strong's Concordance", "url": "/strongs"},
|
|
{"text": strongs_number.upper(), "url": None}
|
|
]
|
|
|
|
return templates.TemplateResponse(
|
|
request,
|
|
"strongs_entry.html",
|
|
{
|
|
"entry": entry,
|
|
"books": books,
|
|
"breadcrumbs": breadcrumbs,
|
|
"verse_occurrences": verse_occurrences,
|
|
"total_occurrences": total_occurrences,
|
|
"related_entries": related_entries
|
|
}
|
|
)
|