Frontend Features and refactor

This commit is contained in:
2026-10-19 15:10:59 -07:00
parent 7a0dbe19ea
commit 317f5bf746
28 changed files with 3915 additions and 530 deletions
+5
View File
@@ -0,0 +1,5 @@
<nav class="chapter-nav" aria-label="Chapter">
<a class="chapter-prev" href="{prev_chapter_link}" rel="prev" aria-label="Previous chapter: {prev_chapter_name}"><span aria-hidden="true">&lsaquo;</span><span class="nav-name">{prev_chapter_name}</span></a>
<a class="chapter-current" href="{current_chapter_link}" title="Read the whole chapter">{current_chapter_name}</a>
<a class="chapter-next" href="{next_chapter_link}" rel="next" aria-label="Next chapter: {next_chapter_name}"><span class="nav-name">{next_chapter_name}</span><span aria-hidden="true">&rsaquo;</span></a>
</nav>
+10 -10
View File
@@ -4,22 +4,22 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bible Dictionary - KJV API</title>
<link rel="stylesheet" href="/styles/page.css">
<style>body{background-color:#1a1a1a}</style>
<link rel="stylesheet" href="/styles/page.css?v=__V__">
</head>
<body>
<header>
<a href="/">Home</a> | <a href="/define">Dictionary</a> |
<a href="/random?view=rich">Random Verse</a> | <a href="/votd?view=rich">Verse of the Day</a>
<a href="/">Home</a> <a href="/define">Dictionary</a>
<a href="/random?view=rich">Random Verse</a> <a href="/votd?view=rich">Verse of the Day</a>
</header>
<h2>Bible Dictionary</h2>
<form action="/define">
<label for='kw'>Word lookup</label>
<input type="text" name="kw" placeholder="Enter a word to define...">
<label for='view'>View</label>
<input type="radio" name="view" value="rich" checked="checked"> Rich
<input type="radio" name="view" value="plain"> Plain
<input type="radio" name="view" value="json"> JSON
<label for="kw">Word lookup</label>
<input type="text" name="kw" id="kw" autocapitalize="off" autocomplete="off" enterkeyhint="search" placeholder="Enter a word to define...">
<div class="form-row"><b>View</b><br>
<label class="choice"><input type="radio" name="view" value="rich" checked="checked"> Rich</label>
<label class="choice"><input type="radio" name="view" value="plain"> Plain</label>
<label class="choice"><input type="radio" name="view" value="json"> JSON</label>
</div>
<input type="submit" value="Define">
</form>
<p>This tool uses an abridged 1828 Noah Webster dictionary.</p>
+6 -6
View File
@@ -4,19 +4,19 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Quick Search - KJV API</title>
<link rel="stylesheet" href="/styles/page.css">
<style>body{background-color:#1a1a1a}</style>
<link rel="stylesheet" href="/styles/page.css?v=__V__">
<script src="/js/book_suggest.js?v=__V__" defer></script>
</head>
<body>
<header>
<a href="/">Home</a> | <a href="/find">Quick Search</a> |
<a href="/random?view=rich">Random Verse</a> |
<a href="/">Home</a> <a href="/find">Quick Search</a>
<a href="/random?view=rich">Random Verse</a>
<a href="/votd?view=rich">Verse of the Day</a>
</header>
<h2>Quick Search</h2>
<form action="/find">
<label for='kw'>Query</label>
<input type="text" name="kw" placeholder="Enter verse reference or keywords...">
<label for="kw">Query</label>
<input type="text" name="kw" id="kw" data-book-suggest autocapitalize="off" autocomplete="off" enterkeyhint="search" placeholder="Enter verse reference or keywords...">
<input type="hidden" name="view" value="rich">
<input type="submit" value="Search">
</form>
+16
View File
@@ -1,3 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>How to Be Saved - KJV API</title>
<link rel="stylesheet" href="/styles/page.css?v=__V__">
</head>
<body>
<header>
<a href="/">Home</a> <a href="/find">Quick Search</a>
<a href="/random?view=rich">Random Verse</a> <a href="/votd?view=rich">Verse of the Day</a>
</header>
<h2>How to Be Saved</h2>
<h3>1. Understand you are a sinner:</h3>
<p>No one is good enough to go to Heaven on their own merit. No matter how much good we do, we still come short.</p>
<p><b>Romans 3:23</b>(a) For all have sinned, and come short of the glory of God;</p>
@@ -28,3 +42,5 @@
<p>Let us help you word a prayer. Realize it is not mere words that save, but your faith in Jesus Christ.</p>
<p><i>Dear Jesus, I know that I am a sinner, and I know I deserve to go to Hell. But I believe that you died on the cross, was buried, and rose from the grave to pay for my sins. Please save me and take me to Heaven when I die. Amen.</i></p>
</body>
</html>
+212 -111
View File
@@ -5,114 +5,77 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>KJV API - Legacy Edition</title>
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="stylesheet" href="/styles/page.css">
<script src="/js/collapsible.js" defer></script>
<link rel="stylesheet" href="/styles/page.css?v=__V__">
<script src="/js/collapsible.js?v=__V__" defer></script>
<style>
/* Bible Book Styles */
.book-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
gap: 0.5rem;
padding: 0.5rem 0;
/* Home page layout */
.site-title {
margin: var(--space-md) 0 0.25rem;
}
.book-button {
background-color: var(--color-bg-tertiary);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-sm);
padding: 0.75rem 1rem;
text-align: left;
color: var(--color-text-primary);
transition: all var(--transition-fast);
cursor: pointer;
font-family: var(--font-ui);
font-weight: 600;
font-size: 0.95rem;
width: 100%;
}
.book-button:hover {
background-color: var(--color-accent-primary);
color: var(--color-bg-primary);
border-color: var(--color-accent-primary);
transform: translateY(-1px);
}
.book-button.active {
background-color: var(--color-accent-primary);
color: var(--color-bg-primary);
border-color: var(--color-accent-primary);
}
.chapter-grid {
display: none;
grid-template-columns: repeat(auto-fill, minmax(45px, 1fr));
gap: 0.4rem;
padding: 1rem;
background-color: var(--color-bg-secondary);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-sm);
margin-top: 0.5rem;
margin-bottom: 0.5rem;
}
.chapter-link {
background-color: var(--color-bg-tertiary);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-sm);
padding: 0.5rem;
text-align: center;
color: var(--color-text-primary);
font-size: 0.85rem;
transition: all var(--transition-fast);
display: block;
}
.chapter-link:hover {
background-color: var(--color-accent-primary);
color: var(--color-bg-primary);
text-decoration: none;
transform: translateY(-1px);
}
.quick-actions {
display: flex;
gap: 0.75rem;
justify-content: center;
flex-wrap: wrap;
margin: 1.5rem 0;
}
.quick-btn {
background-color: var(--color-accent-primary);
color: var(--color-bg-primary);
padding: 0.75rem 1.5rem;
border-radius: var(--border-radius-sm);
font-weight: 600;
transition: all var(--transition-fast);
display: inline-block;
}
.quick-btn:hover {
background-color: var(--color-accent-hover);
transform: translateY(-1px);
text-decoration: none;
.tagline {
margin: 0 0 var(--space-lg);
color: var(--color-text-muted);
}
.search-section {
background-color: var(--color-bg-secondary);
padding: var(--space-xl);
padding: var(--space-lg);
border-radius: var(--border-radius);
border: 1px solid var(--color-border);
margin-bottom: var(--space-xl);
box-shadow: 0 2px 8px var(--color-shadow);
}
.search-section form {
background: none;
border: none;
padding: 0;
margin: 0;
}
.search-row {
display: flex;
gap: var(--space-sm);
}
.search-row input[type=text] {
margin: 0;
flex: 1;
min-width: 0;
}
.quick-actions {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--space-sm);
margin-top: var(--space-md);
}
.quick-btn {
background-color: var(--color-bg-tertiary);
color: var(--color-text-primary);
border: 1px solid var(--color-border);
padding: 0.7rem 1rem;
min-height: 44px;
border-radius: var(--border-radius-sm);
font-weight: 600;
text-align: center;
transition: background-color var(--transition-fast), border-color var(--transition-fast);
}
.quick-btn:hover {
background-color: var(--color-accent-primary);
border-color: var(--color-accent-primary);
color: var(--color-on-accent);
text-decoration: none;
}
.testament-header {
color: var(--color-accent-primary);
font-size: 1.8rem;
margin-top: 2rem;
margin-bottom: 1rem;
font-size: 1.6rem;
margin-top: var(--space-2xl);
margin-bottom: var(--space-sm);
font-weight: 700;
border-bottom: 2px solid var(--color-accent-primary);
padding-bottom: 0.5rem;
@@ -120,43 +83,169 @@
.category-header {
color: var(--color-text-secondary);
font-size: 1.1rem;
margin-top: 1.5rem;
margin-bottom: 0.75rem;
font-size: 1.05rem;
margin-top: var(--space-lg);
margin-bottom: var(--space-sm);
font-weight: 600;
}
@media (max-width: 768px) {
/* Books: each book is a button; its chapter grid opens full-width underneath
the row it sits in (display: contents lets the chapter grid span the
book grid, and "dense" back-fills the gap with the following books). */
.book-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
grid-auto-flow: row dense;
gap: var(--space-sm);
}
.book-grid > div {
display: contents;
}
.book-button {
background-color: var(--color-bg-secondary);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-sm);
padding: 0.7rem 0.9rem;
min-height: 44px;
text-align: left;
color: var(--color-text-primary);
cursor: pointer;
font-family: var(--font-ui);
font-weight: 600;
font-size: 0.95rem;
width: 100%;
margin: 0;
transition: background-color var(--transition-fast), border-color var(--transition-fast);
}
.book-button:hover,
.book-button.active {
background-color: var(--color-accent-primary);
color: var(--color-on-accent);
border-color: var(--color-accent-primary);
transform: none;
}
.chapter-grid {
display: none;
grid-column: 1 / -1;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 0.4rem;
padding: var(--space-md);
background-color: var(--color-bg-secondary);
border: 1px solid var(--color-accent-primary);
border-radius: var(--border-radius-sm);
}
.book-about {
grid-column: 1 / -1;
margin: 0 0 var(--space-xs);
font-size: 0.95rem;
line-height: 1.5;
color: var(--color-text-secondary);
}
.chapter-link {
background-color: var(--color-bg-tertiary);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-sm);
min-height: 44px;
padding: 0.35rem 0.75rem 0.35rem 0.4rem;
display: flex;
align-items: center;
gap: 0.75rem;
color: var(--color-text-primary);
font-size: 0.95rem;
line-height: 1.35;
transition: background-color var(--transition-fast);
}
.chapter-num {
flex: 0 0 2.4rem;
text-align: center;
font-weight: 700;
color: var(--color-accent-primary);
}
.chapter-sum {
color: var(--color-text-secondary);
}
.chapter-link:hover {
background-color: var(--color-accent-primary);
color: var(--color-on-accent);
text-decoration: none;
}
.chapter-link:hover .chapter-num,
.chapter-link:hover .chapter-sum {
color: var(--color-on-accent);
}
.api-docs {
margin-top: var(--space-2xl);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-sm);
background-color: var(--color-bg-secondary);
}
.api-docs summary {
padding: 0.9rem 1.1rem;
font-weight: 600;
cursor: pointer;
}
.api-docs pre {
margin: 0;
border: none;
border-top: 1px solid var(--color-border);
border-radius: 0 0 var(--border-radius-sm) var(--border-radius-sm);
}
@media (max-width: 480px) {
.book-grid {
grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
grid-template-columns: repeat(2, 1fr);
}
.quick-actions {
.chapter-grid {
grid-template-columns: 1fr;
}
.search-row {
flex-direction: column;
}
.quick-btn {
.search-row input[type=submit] {
width: 100%;
}
}
</style>
<script src="/js/book_suggest.js?v=__V__" defer></script>
</head>
<body>
<div class="container">
<h1>KJV API (Legacy edition)</h1>
<h1 class="site-title">KJV API <small>(Legacy edition)</small></h1>
<p class="tagline">King James Bible: search, read, and query by reference.</p>
<div class="search-section">
<form action="/find">
<label for='kw'>Search Scripture</label><br>
<input type="text" name="kw" id="kw" placeholder="Enter verse reference or search keywords..."><br><br>
<input type="hidden" name="view" value="rich">
<input type="submit" value="Search">
<form action="/find" role="search">
<label for="kw">Search Scripture</label>
<div class="search-row">
<input type="text" name="kw" id="kw" data-book-suggest autocapitalize="off" autocomplete="off" enterkeyhint="search" placeholder="Verse reference or keywords...">
<input type="hidden" name="view" value="rich">
<input type="submit" value="Search">
</div>
</form>
<div class="quick-actions">
<a href="/random?view=rich" class="quick-btn">Random Verse</a>
<a href="/votd?view=rich" class="quick-btn">Verse of the Day</a>
<a href="/plan" class="quick-btn">Make a Bible Reading Plan</a>
<a href="/saved" class="quick-btn">Saved Verses &amp; Notes</a>
<a href="#" class="quick-btn" id="continue-plan" hidden>Continue My Reading Plan</a>
</div>
</div>
@@ -171,8 +260,9 @@
{{ book.title }}
</button>
<div class="chapter-grid content">
{% if book.about %}<p class="book-about">{{ book.about }}</p>{% endif %}
{% for chapter in range(1, book.chapters + 1) %}
<a href="/show?kw={{ book.title }} {{ chapter }}&view=rich" class="chapter-link">{{ chapter }}</a>
<a href="/show?kw={{ book.title }} {{ chapter }}&view=rich" class="chapter-link"><span class="chapter-num">{{ chapter }}</span>{% if book.summaries|length >= chapter %}<span class="chapter-sum">{{ book.summaries[chapter - 1] }}</span>{% endif %}</a>
{% endfor %}
</div>
</div>
@@ -191,8 +281,9 @@
{{ book.title }}
</button>
<div class="chapter-grid content">
{% if book.about %}<p class="book-about">{{ book.about }}</p>{% endif %}
{% for chapter in range(1, book.chapters + 1) %}
<a href="/show?kw={{ book.title }} {{ chapter }}&view=rich" class="chapter-link">{{ chapter }}</a>
<a href="/show?kw={{ book.title }} {{ chapter }}&view=rich" class="chapter-link"><span class="chapter-num">{{ chapter }}</span>{% if book.summaries|length >= chapter %}<span class="chapter-sum">{{ book.summaries[chapter - 1] }}</span>{% endif %}</a>
{% endfor %}
</div>
</div>
@@ -201,8 +292,8 @@
{% endfor %}
<!-- API DOCUMENTATION -->
<button class="collapsible" style="margin-top: 2rem;">API Documentation</button>
<div class="content">
<details class="api-docs">
<summary>API Documentation</summary>
<pre><code>API ENDPOINT SPECIFICATION v 0.3
================================
@@ -275,9 +366,19 @@ api.tld/show?kw=john3:16,1john5:7&view=plain
BUGS
====
Suggestions, bug reports or improvements can be reported to <a href="https://nicecrew.digital/@tyler">@tyler@nicecrew.digital</a></code></pre>
</div>
</details>
</div>
<script>
try {
var plan = JSON.parse(localStorage.getItem('kjv.plan'));
if (plan && /^[0-9A-Z]+$/.test(plan.uid)) {
var link = document.getElementById('continue-plan');
link.href = '/plan/' + plan.uid + '?n=' + (parseInt(plan.n, 10) || 25);
link.hidden = false;
}
} catch (e) {}
</script>
</body>
</html>
+32 -25
View File
@@ -1,28 +1,35 @@
<div class="topbar" align="center">
</div>
<header>
<div class="header" id="NavHeader" align="center">
<a href="/">Home</a> |
<a href="/random?view=rich">Random Verse</a> |
<a href="/votd?view=rich">Verse of the Day</a>
<form action="/find">
<input type="text" name="kw" value="{query}" id="searchBar">
<input type="submit" value="Search">
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="dark light">
<title>{title} - KJV API</title>
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
{css}
<script src="/js/verse_menu.js?v=__V__" defer></script>
<script src="/js/book_suggest.js?v=__V__" defer></script>
</head>
<body>
<header class="site-header">
<div class="site-bar">
<a class="brand" href="/">KJV API</a>
<nav class="site-links" aria-label="Site">
<a href="/random?view=rich">Random Verse</a>
<a href="/votd?view=rich">Verse of the Day</a>
<a href="/plan">Reading Plan</a>
<a href="/saved">Saved</a>
</nav>
</div>
<form class="search-form" action="/find" role="search">
<input type="text" name="kw" value="{query}" id="searchBar" data-book-suggest aria-label="Search scripture" placeholder="Verse reference or keywords..." autocapitalize="off" autocomplete="off" enterkeyhint="search">
<input type="hidden" name="view" value="rich">
<input type="submit" value="Search">
</form>
<button onclick="make_shortcode()">Get Shortcode: </button>
<a id="context_href" href=''></a>
<br>
&leftarrow;
<a href="{prev_chapter_link}">{prev_chapter_name}</a> |
{current_chapter_name} |
<a href="{next_chapter_link}">{next_chapter_name}</a>
&rightarrow;
</div>
<script src="js/shortcode.js">
make_shortcode();
</script>
<div class="shortcode">
<button type="button" class="btn-small" onclick="make_shortcode()">Get shortcode</button>
<a id="context_href" href=""></a>
</div>
</header>
{chapter_nav}
<script src="/js/shortcode.js?v=__V__"></script>
+98
View File
@@ -0,0 +1,98 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Make a Bible Reading Plan - KJV API</title>
<link rel="stylesheet" href="/styles/page.css?v=__V__">
<style>
.fieldset { border: none; padding: 0; margin: 0 0 var(--space-lg); }
.fieldset legend { font-weight: 600; padding: 0; margin-bottom: 0.25rem; }
.inline-field { display: inline-block; width: 6rem; margin: 0 0.4rem; }
.inline-field input[type=text], input[type=number] {
min-height: 44px; padding: 0.4rem 0.6rem; font-size: 1rem; font-family: var(--font-ui);
background-color: var(--color-bg-primary); color: var(--color-text-primary);
border: 2px solid var(--color-border); border-radius: var(--border-radius-sm);
}
select {
min-height: 44px; font-size: 1rem; font-family: var(--font-ui); margin-left: 0.4rem;
background-color: var(--color-bg-primary); color: var(--color-text-primary);
border: 2px solid var(--color-border); border-radius: var(--border-radius-sm); padding: 0 0.5rem;
}
input[type=number] { width: 6rem; margin: 0 0.4rem; }
.quick-start { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 0.5rem; }
.quick-start button {
min-height: 40px; padding: 0.3rem 1rem; background-color: var(--color-bg-tertiary);
color: var(--color-text-primary); border: 1px solid var(--color-border);
}
.continue-box { display: none; background-color: var(--color-bg-secondary); border: 1px solid var(--color-accent-primary);
border-radius: var(--border-radius); padding: var(--space-md) var(--space-lg); margin: var(--space-md) 0; }
.continue-box a { font-weight: 600; }
</style>
<script src="/js/book_suggest.js?v=__V__" defer></script>
</head>
<body>
<header>
<a href="/">Home</a> <a href="/find">Quick Search</a>
<a href="/random?view=rich">Random Verse</a> <a href="/votd?view=rich">Verse of the Day</a>
<a href="/saved">Saved</a>
</header>
<h2>Make a Bible Reading Plan</h2>
<div class="continue-box" id="continue-box">
You already have a plan in this browser: <a id="continue-link" href="#">continue reading</a>.
</div>
<p>Pick where to start and how much to read each day. You'll get a page to bookmark; open it
each day to see today's reading, press <b>Done</b> when you've read it, and the plan moves on.
You can always go back to the previous reading or jump to any verse.</p>
<form action="/plan/new" method="post">
<div class="fieldset">
<label for="start">Start at</label>
<div class="quick-start">
<button type="button" data-start="Genesis 1:1">Genesis (whole Bible)</button>
<button type="button" data-start="Matthew 1:1">Matthew (New Testament)</button>
<button type="button" data-start="Psalms 1:1">Psalms</button>
<button type="button" data-start="John 1:1">John</button>
</div>
<input type="text" name="start" id="start" data-book-suggest placeholder="Genesis 1:1" autocapitalize="off" autocomplete="off">
</div>
<fieldset class="fieldset">
<legend>How much each day</legend>
<label class="choice"><input type="radio" name="pace" value="days" checked>
Finish the Bible in
<select name="days" aria-label="Finish in">
<option value="365" selected>1 year</option>
<option value="180">6 months</option>
<option value="90">90 days</option>
<option value="30">30 days</option>
</select>
</label><br>
<label class="choice"><input type="radio" name="pace" value="verses">
Read <input type="number" name="verses" value="30" min="1" max="500" aria-label="Verses per day"> verses a day
</label>
</fieldset>
<input type="submit" value="Create my plan">
</form>
<p>Your plan is saved on this server under a short code in the page address, so the bookmark
is all you need. Plans unused for 90 days are removed.</p>
<script>
var startInput = document.getElementById('start');
document.querySelectorAll('[data-start]').forEach(function (b) {
b.addEventListener('click', function () { startInput.value = b.getAttribute('data-start'); });
});
try {
var plan = JSON.parse(localStorage.getItem('kjv.plan'));
if (plan && /^[0-9A-Z]+$/.test(plan.uid)) {
document.getElementById('continue-link').href = '/plan/' + plan.uid + '?n=' + (parseInt(plan.n, 10) || 25);
document.getElementById('continue-box').style.display = 'block';
}
} catch (e) {}
</script>
</body>
</html>
+18 -1
View File
@@ -1,7 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Books - KJV API</title>
<link rel="stylesheet" href="/styles/page.css?v={{ v }}">
</head>
<body>
<header>
<a href="/">Home</a> <a href="/find">Quick Search</a>
</header>
<h2>Books</h2>
<div class="table-wrap">
<table id="Books">
{% for book in books %}
<tr>
<td><a href="/find?kw={{ book[0] }}&view=rich">{{ book[0] }}</a></td>
</tr>
{% endfor %}
</table>
</table>
</div>
</body>
</html>
-5
View File
@@ -1,5 +0,0 @@
<form action="/plan">
<input type="text" name="kw" value="{query}" id="searchBar">
<input type="submit" value="Search">
<input type="hidden" name="view" value="rich">
</form>
+1 -1
View File
@@ -1,4 +1,4 @@
<div class="verse-container">
<div class="verse-container" data-verse-id="{verse_id}">
<div class="verse-reference"><a href="/find?kw={chapter}&view=rich">{passage}</a></div>
<div class="verse-text">{text}</div>
</div>
+97
View File
@@ -0,0 +1,97 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Saved - KJV API</title>
<link rel="stylesheet" href="/styles/page.css?v=__V__">
<style>
.item { background-color: var(--color-bg-secondary); border: 1px solid var(--color-border);
border-left: 3px solid var(--color-accent-primary); border-radius: var(--border-radius-sm);
padding: var(--space-sm) var(--space-md); margin-bottom: var(--space-sm); }
.item .ref { font-weight: 700; }
.item .text { font-family: var(--font-scripture); margin: 0.25rem 0 0.5rem; color: var(--color-text-primary); }
.item p { margin: 0.25rem 0; }
.item button { min-height: 36px; padding: 0.2rem 0.9rem; font-size: 0.85rem;
background-color: var(--color-bg-tertiary); color: var(--color-text-primary); border: 1px solid var(--color-border); }
.empty { color: var(--color-text-muted); }
.note { font-size: 0.9rem; color: var(--color-text-muted); }
</style>
</head>
<body>
<header>
<a href="/">Home</a> <a href="/find">Quick Search</a> <a href="/plan">Reading Plan</a>
<a href="/random?view=rich">Random Verse</a> <a href="/votd?view=rich">Verse of the Day</a>
</header>
<h2>Saved</h2>
<p class="note">Saved in this browser only. Clearing site data or using another device starts fresh.</p>
<h3>Favorite verses</h3>
<div id="fav"></div>
<h3>Definitions</h3>
<div id="defs"></div>
<h3>Cross references</h3>
<div id="xrefs"></div>
<script>
var KEYS = { fav: 'kjv.favorites', defs: 'kjv.definitions', xrefs: 'kjv.crossrefs' };
function load(key) {
try { var v = JSON.parse(localStorage.getItem(key)); return Array.isArray(v) ? v : []; }
catch (e) { return []; }
}
function el(tag, cls, text) {
var n = document.createElement(tag);
if (cls) n.className = cls;
if (text !== undefined) n.textContent = text;
return n;
}
function findUrl(ref) { return '/find?kw=' + encodeURIComponent(ref) + '&view=rich'; }
function render(key, targetId, emptyText, build) {
var target = document.getElementById(targetId);
target.textContent = '';
var list = load(key);
if (!list.length) { target.appendChild(el('p', 'empty', emptyText)); return; }
list.forEach(function (item, i) {
var box = el('div', 'item');
build(box, item);
var remove = el('button', '', 'Remove');
remove.type = 'button';
remove.addEventListener('click', function () {
var current = load(key);
current.splice(i, 1);
try { localStorage.setItem(key, JSON.stringify(current)); } catch (e) {}
render(key, targetId, emptyText, build);
});
box.appendChild(remove);
target.appendChild(box);
});
}
function refLink(ref) {
var a = el('a', 'ref', ref);
a.href = findUrl(ref);
return a;
}
function draw() {
render(KEYS.fav, 'fav', 'No favorites yet. Tap a verse and choose Favorite.', function (box, f) {
box.appendChild(refLink(f.ref));
box.appendChild(el('div', 'text', f.text));
});
render(KEYS.defs, 'defs', 'No saved definitions. Tap a verse, choose Define words, and save one.', function (box, d) {
box.appendChild(el('strong', '', d.word));
if (d.ref) { box.appendChild(document.createTextNode(' from ')); box.appendChild(refLink(d.ref)); }
(d.defs || []).forEach(function (t) { box.appendChild(el('p', '', t)); });
});
render(KEYS.xrefs, 'xrefs', 'No saved cross references. Tap a verse, choose Cross references, and save one.', function (box, x) {
box.appendChild(refLink(x.ref));
box.appendChild(el('span', 'note', ' (cross reference of ' + x.from + ')'));
box.appendChild(el('div', 'text', x.text));
});
}
draw();
</script>
</body>
</html>
+10 -10
View File
@@ -4,22 +4,22 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bible Search - KJV API</title>
<link rel="stylesheet" href="/styles/page.css">
<style>body{background-color:#1a1a1a}</style>
<link rel="stylesheet" href="/styles/page.css?v=__V__">
</head>
<body>
<header>
<a href="/">Home</a> | <a href="/find">Quick Search</a> | <a href="/search">Bible Search</a> |
<a href="/random?view=rich">Random Verse</a> | <a href="/votd?view=rich">Verse of the Day</a>
<a href="/">Home</a> <a href="/find">Quick Search</a> <a href="/search">Bible Search</a>
<a href="/random?view=rich">Random Verse</a> <a href="/votd?view=rich">Verse of the Day</a>
</header>
<h2>Bible Search</h2>
<form action="/search">
<label for='kw'>Key Words</label>
<input type="text" name="kw" placeholder="Enter search keywords...">
<label for='view'>View</label>
<input type="radio" name="view" value="rich" checked="checked"> Rich
<input type="radio" name="view" value="plain"> Plain
<input type="radio" name="view" value="json"> JSON
<label for="kw">Key Words</label>
<input type="text" name="kw" id="kw" autocapitalize="off" autocomplete="off" enterkeyhint="search" placeholder="Enter search keywords...">
<div class="form-row"><b>View</b><br>
<label class="choice"><input type="radio" name="view" value="rich" checked="checked"> Rich</label>
<label class="choice"><input type="radio" name="view" value="plain"> Plain</label>
<label class="choice"><input type="radio" name="view" value="json"> JSON</label>
</div>
<input type="submit" value="Search">
</form>
<hr>
+4 -5
View File
@@ -4,13 +4,12 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sequential Bible Viewer - KJV API</title>
<link rel="stylesheet" href="/styles/page.css">
<style>body{background-color:#1a1a1a}</style>
<link rel="stylesheet" href="/styles/page.css?v=__V__">
</head>
<body>
<header>
<a href="/">Home</a> | <a href="/find">Quick Search</a> | <a href="/seq">Sequential Viewer</a> |
<a href="/random?view=rich">Random Verse</a> | <a href="/votd?view=rich">Verse of the Day</a>
<a href="/">Home</a> <a href="/find">Quick Search</a> <a href="/seq">Sequential Viewer</a>
<a href="/random?view=rich">Random Verse</a> <a href="/votd?view=rich">Verse of the Day</a>
</header>
<h2>Sequential Bible Viewer</h2>
<p>In order to use this, you first need a UID, which you can get by querying <code>/seq?getuid=true</code> and optionally include <code>&start=BIBLEREF</code> (where BIBLEREF is like 1Cor2:1) to set a start position other than Genesis 1:1.</p>
@@ -18,7 +17,7 @@
<p>The <code>&view=</code> argument works with this.</p>
<h4>Example Pleroma Bot shell script</h4>
<pre><code>#!/bin/sh
verse=$(curl -XGET https://api.1611.social/seq?uid=MYUID?view=plain);
verse=$(curl -XGET https://bible.nicecrew.digital/seq?uid=MYUID?view=plain);
curl -XPOST -u biblebot:MYPASSWORD \
-H "Content-Type: application/json" \
-d '{"status": "'"${verse}"'"}' \
+18 -1
View File
@@ -1,3 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sequence Report - KJV API</title>
<link rel="stylesheet" href="/styles/page.css?v={{ v }}">
</head>
<body>
<header>
<a href="/">Home</a> <a href="/find">Quick Search</a>
</header>
<h2>Sequence Report</h2>
<div class="table-wrap">
<table id="seq_report">
{% for uid in uids %}
<tr>
@@ -6,4 +20,7 @@
<td>{{ uid[2] }}</td>
</tr>
{% endfor %}
</table>
</table>
</div>
</body>
</html>
+22 -5
View File
@@ -1,14 +1,31 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Shortcode Report - KJV API</title>
<link rel="stylesheet" href="/styles/page.css?v={{ v }}">
</head>
<body>
<header>
<a href="/">Home</a> <a href="/find">Quick Search</a>
</header>
<h2>Shortcode Report</h2>
<div class="table-wrap">
<table id="shortcode_report">
<tr>
<td>shortcode |</td>
<td>query |</td>
<td>shortcode</td>
<td>query</td>
<td>creation_date</td>
</tr>
{% for code in shortcodes %}
<tr>
<td>{{ code[0] }} |</td>
<td>{{ code[1] }} |</td>
<td>{{ code[0] }}</td>
<td>{{ code[1] }}</td>
<td>{{ code[2] }}</td>
</tr>
{% endfor %}
</table>
</table>
</div>
</body>
</html>
+11 -10
View File
@@ -4,22 +4,23 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Show Verse - KJV API</title>
<link rel="stylesheet" href="/styles/page.css">
<style>body{background-color:#1a1a1a}</style>
<link rel="stylesheet" href="/styles/page.css?v=__V__">
<script src="/js/book_suggest.js?v=__V__" defer></script>
</head>
<body>
<header>
<a href="/">Home</a> | <a href="/find">Quick Search</a> | <a href="/show">Show Verse</a> |
<a href="/random?view=rich">Random Verse</a> | <a href="/votd?view=rich">Verse of the Day</a>
<a href="/">Home</a> <a href="/find">Quick Search</a> <a href="/show">Show Verse</a>
<a href="/random?view=rich">Random Verse</a> <a href="/votd?view=rich">Verse of the Day</a>
</header>
<h2>Show Verse</h2>
<form action="/show">
<label for='kw'>Verse References</label>
<input type="text" name="kw" placeholder="e.g., 1 John 5:7 or John3:16,2Peter2:1">
<label for='view'>View</label>
<input type="radio" name="view" value="rich" checked="checked"> Rich
<input type="radio" name="view" value="plain"> Plain
<input type="radio" name="view" value="json"> JSON
<label for="kw">Verse References</label>
<input type="text" name="kw" id="kw" data-book-suggest autocapitalize="off" autocomplete="off" enterkeyhint="search" placeholder="e.g., 1 John 5:7 or John3:16,2Peter2:1">
<div class="form-row"><b>View</b><br>
<label class="choice"><input type="radio" name="view" value="rich" checked="checked"> Rich</label>
<label class="choice"><input type="radio" name="view" value="plain"> Plain</label>
<label class="choice"><input type="radio" name="view" value="json"> JSON</label>
</div>
<input type="submit" value="Show">
</form>
<hr>