mirror of
https://github.com/kennethreitz/kjvstudy.org.git
synced 2026-06-05 23:00:16 +00:00
Add comprehensive Bible concordance feature
Concordance System: - Complete word occurrence index for entire KJV Bible - Shows all instances of any searched word with full context - Case-insensitive exact word matching with word boundaries - Results organized by biblical book for easy navigation - Each occurrence links directly to the verse Features: - Search any word to find all occurrences (e.g., "love" appears ~300 times) - Highlighted word in context for quick identification - Statistics showing total occurrences and books containing the word - Popular word suggestions (love, faith, LORD, God, Jesus, grace, etc.) - Grouped by book with occurrence counts per book - Full verse context provided for each occurrence - Mobile-responsive design UI Design: - Clean, Tufte CSS-styled interface - Popular concordance lookups grid - Usage tips for KJV-specific spellings - Search box prominently featured - Stats showing word frequency and distribution Implementation: - Route: /concordance with ?word= parameter - Word boundary regex matching for accuracy - Real-time highlighting of matched words - Complete Bible text scanning - Organized output by biblical book order Integration: - Added to homepage navigation under "Concordance and Search" - Standalone page with comprehensive instructions - Links from every occurrence to full verse pages Usage Notes: - Exact word matching (won't find inflected forms) - Case-insensitive search - Handles KJV archaic forms (loveth, cometh, etc.) - Proper nouns supported (Jesus, Moses, David) - Theological terms supported (justification, redemption) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -493,6 +493,81 @@ def search_api(q: str = Query(..., description="Search query"), limit: Optional[
|
||||
"is_direct_verse": is_direct_verse
|
||||
}
|
||||
|
||||
|
||||
@app.get("/concordance", response_class=HTMLResponse)
|
||||
def concordance_page(request: Request, word: str = Query(None, description="Word to look up")):
|
||||
"""Concordance page showing all occurrences of a word"""
|
||||
books = list(bible.iter_books())
|
||||
|
||||
if not word or len(word.strip()) < 2:
|
||||
return templates.TemplateResponse(
|
||||
"concordance.html",
|
||||
{
|
||||
"request": request,
|
||||
"books": books,
|
||||
"word": word or "",
|
||||
"total_occurrences": 0,
|
||||
"occurrences_by_book": {},
|
||||
"books_with_word": []
|
||||
}
|
||||
)
|
||||
|
||||
search_word = word.strip()
|
||||
occurrences = []
|
||||
occurrences_by_book = {}
|
||||
books_with_word = set()
|
||||
|
||||
# Search through all verses
|
||||
import re
|
||||
# Create a word boundary pattern for exact word matching
|
||||
# This handles punctuation and word boundaries properly
|
||||
pattern = re.compile(r'\b' + re.escape(search_word) + r'\b', re.IGNORECASE)
|
||||
|
||||
for book in bible.iter_books():
|
||||
book_name = book.name
|
||||
book_occurrences = []
|
||||
|
||||
for chapter_num in range(1, book.num_chapters + 1):
|
||||
chapter = book.chapter(chapter_num)
|
||||
|
||||
for verse in chapter.verses:
|
||||
# Check if the word appears in this verse
|
||||
if pattern.search(verse.text):
|
||||
# Highlight the word in the text
|
||||
highlighted_text = pattern.sub(
|
||||
lambda m: f'<span class="highlight">{m.group()}</span>',
|
||||
verse.text
|
||||
)
|
||||
|
||||
occurrence = {
|
||||
'book': book_name,
|
||||
'chapter': chapter_num,
|
||||
'verse': verse.verse,
|
||||
'text': verse.text,
|
||||
'highlighted_text': highlighted_text
|
||||
}
|
||||
|
||||
occurrences.append(occurrence)
|
||||
book_occurrences.append(occurrence)
|
||||
books_with_word.add(book_name)
|
||||
|
||||
# Only add to occurrences_by_book if there are occurrences in this book
|
||||
if book_occurrences:
|
||||
occurrences_by_book[book_name] = book_occurrences
|
||||
|
||||
return templates.TemplateResponse(
|
||||
"concordance.html",
|
||||
{
|
||||
"request": request,
|
||||
"books": books,
|
||||
"word": search_word,
|
||||
"total_occurrences": len(occurrences),
|
||||
"occurrences_by_book": occurrences_by_book,
|
||||
"books_with_word": sorted(books_with_word)
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def parse_verse_reference(reference: str):
|
||||
"""Parse a verse reference and return a URL for it.
|
||||
|
||||
|
||||
@@ -0,0 +1,306 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{% if word %}Concordance: "{{ word }}" - {{ total_occurrences }} occurrences{% else %}Bible Concordance{% endif %} - KJV Study{% endblock %}
|
||||
{% block description %}{% if word %}Complete concordance showing all {{ total_occurrences }} occurrences of "{{ word }}" in the King James Bible with context.{% else %}Search the complete KJV Bible concordance to find every occurrence of any word.{% endif %}{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<style>
|
||||
.concordance-search {
|
||||
max-width: 55%;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.concordance-input {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
font-size: 1.1rem;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.concordance-input:focus {
|
||||
outline: none;
|
||||
border-color: #111;
|
||||
}
|
||||
|
||||
.concordance-button {
|
||||
margin-top: 1rem;
|
||||
padding: 0.75rem 1.5rem;
|
||||
background: #111;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.concordance-button:hover {
|
||||
background: #333;
|
||||
}
|
||||
|
||||
.concordance-stats {
|
||||
max-width: 55%;
|
||||
margin: 2rem 0;
|
||||
padding: 1rem 0;
|
||||
border-top: 1px solid #ccc;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.concordance-stats .stat-number {
|
||||
font-family: et-book-roman-old-style;
|
||||
font-weight: 600;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.occurrence-list {
|
||||
max-width: 55%;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.occurrence {
|
||||
margin: 1.5rem 0;
|
||||
padding-bottom: 1.5rem;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.occurrence:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.occurrence-reference {
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.occurrence-reference a {
|
||||
text-decoration: none;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
.occurrence-reference a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.occurrence-text {
|
||||
line-height: 1.8;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.occurrence-text .highlight {
|
||||
background: #fffacd;
|
||||
padding: 0.1rem 0.2rem;
|
||||
font-weight: 600;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
.book-group {
|
||||
margin: 2.5rem 0;
|
||||
}
|
||||
|
||||
.book-group h3 {
|
||||
margin-bottom: 1rem;
|
||||
padding-bottom: 0.5rem;
|
||||
border-bottom: 2px solid #111;
|
||||
}
|
||||
|
||||
.book-count {
|
||||
color: #666;
|
||||
font-weight: normal;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.concordance-tips {
|
||||
max-width: 55%;
|
||||
margin: 2rem 0;
|
||||
padding: 1.5rem;
|
||||
background: #f9f9f9;
|
||||
border-left: 3px solid #111;
|
||||
}
|
||||
|
||||
.concordance-tips h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.concordance-tips ul {
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.popular-words {
|
||||
max-width: 55%;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.word-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
||||
gap: 1rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.word-link {
|
||||
padding: 0.5rem;
|
||||
background: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
.word-link:hover {
|
||||
background: #e5e5e5;
|
||||
}
|
||||
|
||||
.word-link-word {
|
||||
font-weight: 600;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.word-link-count {
|
||||
font-size: 0.85rem;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
.concordance-search,
|
||||
.concordance-stats,
|
||||
.occurrence-list,
|
||||
.concordance-tips,
|
||||
.popular-words {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.word-list {
|
||||
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Bible Concordance</h1>
|
||||
<p class="subtitle">Find every occurrence of any word in the King James Bible</p>
|
||||
|
||||
<section>
|
||||
<form class="concordance-search" method="get" action="/concordance">
|
||||
<input
|
||||
type="text"
|
||||
name="word"
|
||||
value="{{ word }}"
|
||||
placeholder="Enter a word to find all occurrences..."
|
||||
class="concordance-input"
|
||||
autofocus
|
||||
>
|
||||
<button type="submit" class="concordance-button">Search Concordance</button>
|
||||
</form>
|
||||
|
||||
{% if word %}
|
||||
{% if total_occurrences > 0 %}
|
||||
<div class="concordance-stats">
|
||||
<p>The word <strong>"{{ word }}"</strong> appears <span class="stat-number">{{ total_occurrences }}</span> time{{ 's' if total_occurrences != 1 else '' }} in the King James Bible</p>
|
||||
{% if books_with_word %}
|
||||
<p style="margin-top: 0.5rem; color: #666;">Found in {{ books_with_word|length }} book{{ 's' if books_with_word|length != 1 else '' }}: {{ books_with_word|join(', ') }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if occurrences_by_book %}
|
||||
{% for book_name, book_occurrences in occurrences_by_book.items() %}
|
||||
<div class="book-group">
|
||||
<h3>{{ book_name }} <span class="book-count">({{ book_occurrences|length }} occurrence{{ 's' if book_occurrences|length != 1 else '' }})</span></h3>
|
||||
|
||||
<div class="occurrence-list">
|
||||
{% for occurrence in book_occurrences %}
|
||||
<div class="occurrence">
|
||||
<div class="occurrence-reference">
|
||||
<a href="/book/{{ occurrence.book }}/chapter/{{ occurrence.chapter }}/verse/{{ occurrence.verse }}">
|
||||
{{ occurrence.book }} {{ occurrence.chapter }}:{{ occurrence.verse }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="occurrence-text">{{ occurrence.highlighted_text | safe }}</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<div class="concordance-stats">
|
||||
<p><strong>No occurrences found</strong> for "{{ word }}". Try a different word or check your spelling.</p>
|
||||
<p style="margin-top: 0.5rem; color: #666;">Note: The KJV uses older English spellings. Try words like "loveth" instead of "loves", "cometh" instead of "comes".</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if not word or total_occurrences == 0 %}
|
||||
<div class="popular-words">
|
||||
<h2>Popular Concordance Lookups</h2>
|
||||
<p>Browse frequently searched words:</p>
|
||||
|
||||
<div class="word-list">
|
||||
<a href="/concordance?word=love" class="word-link">
|
||||
<span class="word-link-word">love</span>
|
||||
<span class="word-link-count">~300 times</span>
|
||||
</a>
|
||||
<a href="/concordance?word=faith" class="word-link">
|
||||
<span class="word-link-word">faith</span>
|
||||
<span class="word-link-count">~250 times</span>
|
||||
</a>
|
||||
<a href="/concordance?word=LORD" class="word-link">
|
||||
<span class="word-link-word">LORD</span>
|
||||
<span class="word-link-count">~7000 times</span>
|
||||
</a>
|
||||
<a href="/concordance?word=God" class="word-link">
|
||||
<span class="word-link-word">God</span>
|
||||
<span class="word-link-count">~4000 times</span>
|
||||
</a>
|
||||
<a href="/concordance?word=Jesus" class="word-link">
|
||||
<span class="word-link-word">Jesus</span>
|
||||
<span class="word-link-count">~900 times</span>
|
||||
</a>
|
||||
<a href="/concordance?word=grace" class="word-link">
|
||||
<span class="word-link-word">grace</span>
|
||||
<span class="word-link-count">~170 times</span>
|
||||
</a>
|
||||
<a href="/concordance?word=peace" class="word-link">
|
||||
<span class="word-link-word">peace</span>
|
||||
<span class="word-link-count">~400 times</span>
|
||||
</a>
|
||||
<a href="/concordance?word=salvation" class="word-link">
|
||||
<span class="word-link-word">salvation</span>
|
||||
<span class="word-link-count">~160 times</span>
|
||||
</a>
|
||||
<a href="/concordance?word=righteousness" class="word-link">
|
||||
<span class="word-link-word">righteousness</span>
|
||||
<span class="word-link-count">~300 times</span>
|
||||
</a>
|
||||
<a href="/concordance?word=mercy" class="word-link">
|
||||
<span class="word-link-word">mercy</span>
|
||||
<span class="word-link-count">~340 times</span>
|
||||
</a>
|
||||
<a href="/concordance?word=truth" class="word-link">
|
||||
<span class="word-link-word">truth</span>
|
||||
<span class="word-link-count">~230 times</span>
|
||||
</a>
|
||||
<a href="/concordance?word=blessed" class="word-link">
|
||||
<span class="word-link-word">blessed</span>
|
||||
<span class="word-link-count">~300 times</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="concordance-tips">
|
||||
<h3>Using the Concordance</h3>
|
||||
<ul>
|
||||
<li><strong>Case-insensitive</strong> - Search for "Love", "love", or "LOVE" - all work the same</li>
|
||||
<li><strong>Exact matches only</strong> - Searches for the exact word form (e.g., "love" won't find "loved" or "loveth")</li>
|
||||
<li><strong>Old English forms</strong> - The KJV uses archaic verb forms like "cometh", "goeth", "loveth"</li>
|
||||
<li><strong>Proper nouns</strong> - Search for names like "Jesus", "Moses", "David" to track their appearances</li>
|
||||
<li><strong>Theological terms</strong> - Look up "justification", "sanctification", "redemption", etc.</li>
|
||||
<li><strong>Context provided</strong> - Each occurrence shows the full verse for context</li>
|
||||
<li><strong>Organized by book</strong> - Results grouped by biblical book for easy navigation</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -522,7 +522,7 @@ document.addEventListener('keydown', function(e) {
|
||||
|
||||
<p><span class="newthought">Reading Plans</span> — Structured <a href="/reading-plans">Bible reading schedules</a> for systematic Scripture study, including chronological, thematic, and testament-specific plans to guide sustained engagement with God's Word.</p>
|
||||
|
||||
<p><span class="newthought">Concordance and Search</span> — A comprehensive <a href="/search">search facility</a> allowing the reader to trace any word or phrase throughout the entire corpus of Scripture, after the manner of Cruden's Complete Concordance.</p>
|
||||
<p><span class="newthought">Concordance and Search</span> — A comprehensive <a href="/concordance">concordance</a> showing every occurrence of any word in Scripture, and a <a href="/search">search facility</a> allowing the reader to trace any word or phrase throughout the entire corpus of Scripture, after the manner of Cruden's Complete Concordance.</p>
|
||||
|
||||
<p><span class="newthought">Biblical Geography</span> — <a href="/biblical-maps">Maps and descriptions</a> of those places mentioned in Holy Writ, from the rivers of Babylon to the shores of Galilee, illuminating the geographical context of sacred history.</p>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user