Unified search bar, initial styling

This commit is contained in:
2023-01-17 03:36:40 -08:00
parent 85b0283791
commit 77a3ba1311
10 changed files with 204 additions and 68 deletions
+72 -19
View File
@@ -6,25 +6,31 @@ import sqlite3
import string # for literals
import json # for dictionary
import hunspell # for spell checking
DEBUG = 2
DEBUG = 0
"""
To-do:
Separate dictionary-dictionary for hunsepll
Search phrase alias
Response Bible book reading
Search highlighting
Styles
Bible Reading Plan
Bible Viewer
Bible Reader
"""
def dbg(message):
# if DEBUG is at or above a value of one, a call from debug level one will print red
if DEBUG >= 1:
print(f'\033[91m{message}\033[0m')
def dbg2(message):
# if DEBUG is at or above a value of two, a call from debug level one will print green
if DEBUG >= 2:
print(f'\033[32m{message}\033[0m')
print(f' \033[32m{message}\033[0m')
def dbg3(message):
if DEBUG >= 3:
print(f' \033[35m{message}\033[0m')
dbg("Debug Level 1 Enabled")
dbg2("Debug Level 2 Enabled")
dbg3("Debug Level 3 Enabled")
dictionary_json = "data/1828_Webster_KJV.json"
kjv_cur = sqlite3.connect("data/kjv.db").cursor()
@@ -40,31 +46,32 @@ idx_verse = 3
idx_text = 4
def lookup_one_verse(verse_id):
dbg("lookup_one_verse({})".format(verse_id))
dbg2("lookup_one_verse({})".format(verse_id))
return(kjv_cur.execute("SELECT * FROM fts_kjv WHERE id = {};".format(verse_id)).fetchone())
def lookup_bookname(book_id):
dbg2("lookup_bookname({})".format(book_id))
dbg3("lookup_bookname({})".format(book_id))
result = kjv_cur.execute("SELECT n FROM key_english WHERE b = {};".format(book_id)).fetchone()
if result:
result = result[0]
dbg("lookup_bookname.result = '{}'".format(result))
dbg2("lookup_bookname.result = '{}'".format(result))
return result
def lookup_book_id(bookname):
dbg2("lookup_book_id({})".format(bookname))
dbg3("lookup_book_id({})".format(bookname))
result = kjv_cur.execute("SELECT b FROM key_english WHERE n = '{}';".format(bookname)).fetchone()
if result:
result = result[0]
dbg2("lookup_book_id.result = '{}'".format(result))
dbg3("lookup_book_id.result = '{}'".format(result))
return result
def lookup_fts(kwds):
dbg3("lookup_fts.kwds = '{}'".format(kwds))
return kjv_cur.execute("SELECT * FROM fts_kjv('{}')".format(kwds)).fetchall()
def lookup_contains(kw):
results = kjv_cur.execute("SELECT * FROM fts_kjv WHERE t LIKE '%{}%';".format(kw)).fetchall()
dbg("lookup_contains({}) {} results".format(kw,len(results)))
dbg2("lookup_contains({}) {} results".format(kw,len(results)))
return results
def lookup_by_verse_id(start_verse, end_verse = None):
@@ -110,16 +117,18 @@ def lookup_contains_exact(kw):
def ref_input_cleaning(ref, valid_chars=(string.ascii_letters + string.digits + ":-,")):
dbg2("ref_input_cleaning({})".format(ref))
ref = list(ref.replace(" ",""))
ref = ref.replace(" ","")
if ref.count(':') != 1:
dbg2("ref_input_cleaning.if ref.count(:): TRUE")
return False
dbg2(" -> Assuming user wanted entire chapter")
ref += ":-"
if ref.count("-") > 1:
dbg2("ref_input_cleaning.if ref.count(-): TRUE")
return False
if not ref[-1].isdigit() and ref[-1] != '-':
dbg2("ref_input_cleaning.if ref[-1] TRUE")
return False
ref = list(ref)
# preserve book number if we can guess the first
# character is a number and 3nd is a letter
if ref[0].isdigit() and ref[1].isalpha():
@@ -149,6 +158,30 @@ def ref_parse_book(ref):
return book
return False
@app.get("/find")
def parse_query():
query = request.args.get("kw", None)
if not query:
return send_file("html/find.html")
result = show()
if not hasattr(result, '__len__'):
dbg3("parse_query.show = '{}'".format(result))
return result
if len(result) > 17:
return result
result = ''
if len(query.split()) == 1:
result += "<!DOCTYPE html><style>"
result += open("styles/collapsible.css", 'r').read()
result += "</style><button type='button' class='collapsible'>See Definition</button><div class='content'>"
result += define() + "</div><script>"
result += open("js/collapsible.js", 'r').read() + "</script>"
dbg3("parse_query.define = '{}'".format(result))
result += search()
dbg3("parse_query.search = '{}'".format(result))
return result
@app.get("/define")
def define():
ref = request.args.get("kw", None)
@@ -175,7 +208,7 @@ def return_dict_plain(ref, defs):
response = ''
for e in defs:
response += e + "<br><br>"
return ref.capitalize() + "<br><br>" + response
return ref.capitalize() + "<br><br>" + response + "\n"
def return_dict_rich(ref, defs):
header = open('html/header.html', 'r')
@@ -184,7 +217,8 @@ def return_dict_rich(ref, defs):
response = ''
for e in defs:
response += e + "<br><br>"
return (header.read() + response_html.read().format(passage = ref.capitalize(), text = response) + css.read())
# return (header.read() + response_html.read().format(passage = ref.capitalize(), text = response) + css.read())
return (response_html.read().format(passage = ref.capitalize(), text = response) + css.read())
@app.get("/show")
def show():
@@ -197,7 +231,7 @@ def show():
r_ = ref_input_cleaning(r.strip())
if r_:
refs.append(r_)
if not ref:
if not refs:
return("Invalid Query")
verse_results = []
#check if the search is for multiple refs
@@ -223,14 +257,14 @@ def show():
ref_bookname = ref_parse_book(book_str)
ref_book_id = lookup_book_id(ref_bookname)
if not ref_book_id:
return("Book reference invalid. Ex: 1John3:16")
return("Invalid Query")
start_verse_id = get_verse_id(ref_book_id, ref_chapter, start_verse)
if end_verse:
end_verse_id = get_verse_id(ref_book_id, ref_chapter, end_verse)
dbg2("show.start_verse_id({})".format(start_verse_id))
dbg2("show.end_verse_id({})".format(end_verse_id))
results = lookup_by_verse_id(start_verse_id, end_verse_id)
dbg2("show.results({})".format(results))
dbg3("show.results({})".format(results))
for result in results:
verse_results.append(result)
response_list = response_multi(verse_results)
@@ -257,7 +291,7 @@ def response_text(scripture):
chapter = str(scripture[idx_chapter])
verse = str(scripture[idx_verse])
text = str(scripture[idx_text])
return (bookname + " " + chapter + ":" + verse + " " + text)
return (bookname + " " + chapter + ":" + verse + " " + text + "\n")
def response_rich(scripture):
css = open('styles/human_readable.css', 'r')
@@ -353,3 +387,22 @@ def search():
response = jsonify(response_list)
dbg2("Search Response: {}".format(response))
return response
@app.get("/reader")
def bible_reader():
return send_file("html/reader.html")
# We should return an index of all books with
# drop down menus of each chapter, and a search
# bar at the top for quick seeking, which can use
# show(). Each page should return a header and footer.
# header should have a navigation bar and "next/previous chapter"
# Footer should have next/previous as well.
# Maybe preliminary theming support
@app.get("/plan")
def reading_plan():
return send_file("html/reading_plan.html")
# needs 2 sets of data, books and time frame.
# should default to the entire Bible in 1 year.
# should start today() and end today()+1year
# Should return a calender with date and verse range.
+13
View File
@@ -0,0 +1,13 @@
<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>Quick Search</h2>
<form action="/find">
<label for='kw'>Query</label><br>
<input type="text" name="kw"><br><br>
<input type="hidden" name="view" value="rich"">Rich<br>
<input type="submit">
<form>
+3 -8
View File
@@ -1,9 +1,4 @@
<DOCTYPE html>
<header>
<a href="/">Home</a>
<a href="/search">Bible Search</a>
<a href="/show">Bible Verses</a>
<a href="/define">Bible Define</a>
<a href="/random?view=rich">Random Verse</a>
<a href="/votd?view=rich">Verse of the Day</a>
</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>
+48 -39
View File
@@ -13,43 +13,36 @@ html{
<h1>KJV API</h1>
<p>KJV accessible via web calls</p>
<h3>Usage</h3>
<p>URL Root: <a href="https://api.1611.social/">https://api.1611.social/<a> (you are here)</p>
<ul>
<li><a href="/salvation">/salvation</a> - Learn what you have to do to go to heaven.</li>
<li><a href="/random">/random</a> - A random verse from the KJV</li>
<li><a href="/votd">/votd</a> - A random verse that changes from day-to-day.</li>
<li><a href="/search">/search</a> - Search keywords. No arguments = landing page.</li>
<li><a href="/show">/show</a> - Show a set of verses. No arguments = landing page.</li>
<li><a href="/define">/define</a> - Search the Dictionary. No arguments = landing page.</li>
</ul>
<h2>Quick Search</h2>
<form action="/find">
<label for='kw'>Query</label><br>
<input type="text" name="kw"><br><br>
<h3>Verse searching</h3>
<p>'/show?kw=' will try to match single verses and verse ranges. (not sets) For example:</p>
<pre>
<code>
/show?kw=john3:16
/show?kw=1 John 3:3- (gets the whole rest of the chapter)
</code>
</pre>
<label for='view'>View<label><br>
<input type="radio" name="view" value="rich" checked="checked">Rich<br>
<input type="radio" name="view" value="plain">Plain<br>
<input type="radio" name="view" value="json">JSON<br>
<h3>Keyword searching</h3>
<p>'/search?kw=keyword' accepts a search word, and will return any verses matching the query. For example:</p>
<input type="submit">
<form>
<h3>Integration</h3>
<p>If you want to put the verse of the day into your website, you can use the following example php:</p>
<p>echo curl_exec(curl_init('https://api.1611.social/votd?view=plain'));</p>
<pre>
<code>
API ENDPOINT SPECIFICATION v 0.2
API ENDPOINT SPECIFICATION v 0.3
================================
/random - outputs a random verse
/votd - returns verse of the day
/search - returns a keyword search result set
/show - returns a verse or set of verses by name/location
/define - 1828 Noah Webster dictionary
<a href="/find">
/find</a> - Tries to show a verse, if it's not a verse
it will try to search your query. If it's a
single query it will try to find a definition
for the word as well. Only avaliable in "Rich"
and meant for interactive use/browsing
<a href="/random">/random</a> - outputs a random verse
<a href="/votd">/votd</a> - returns verse of the day
<a href="/search">/search</a> - returns a keyword search result set
<a href="/show">/show</a> - returns a verse or set of verses by name/location
<a href="/define">/define</a> - 1828 Noah Webster dictionary search
URL PARAMETERS
==============
@@ -60,14 +53,26 @@ URL PARAMETERS
default: json
?kw=
- comma-delimited keyword search for /search
- The keyword(s) of your query.
FEATURES
========
- King James Only. (No heretical commentaries or false Bibles)
- High quality source documents
- Free
-
- Developer hates the sodomites
INTERACTIVE ENDPOINTS
=====================
/search and /define will show you a landing page where you can
use HTML forms to complete your search. Both of these will
offer you spelling suggestions if it can't find the right word.
This will only offer words that are actually in the Bible.
The following endpoints will present you with a query box and
radio selector for choosing your output format.
- / (same function as /find)
- /search
- /define
- /show
EXAMPLES
========
@@ -77,11 +82,15 @@ api.tld/show?kw=john3:16,1john5:7&view=plain
api.tld/search?kw=faith
api.tld/search?kw=nimrod&view=rich
api.tld/define?kw=faith&view=rich
INTEGRATION
===========
If you want to put the verse of the day into your website, you can use the following example php:
echo curl_exec(curl_init('https://api.1611.social/votd?view=plain'));
BUGS
====
Suggestions, bug reports or improvements can be reported to <a href="https://1611.social/@tyler">@tyler@1611.social</a>
</code>
</pre>
<h3>Bugs</h3>
<p>Suggestions, bug reports or improvements can be reported to <a href="https://1611.social/@tyler">@tyler@1611.social</a></p>
</html>
View File
View File
+1 -2
View File
@@ -1,3 +1,2 @@
<!DOCTYPE html>
<h1>{passage}</h1>
<h3>{passage}</h3>
<p>{text}</p>
+14
View File
@@ -0,0 +1,14 @@
var coll = document.getElementsByClassName("collapsible");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
});
}
+25
View File
@@ -0,0 +1,25 @@
/* Style the button that is used to open and close the collapsible content */
.collapsible {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
/* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */
.active, .collapsible:hover {
background-color: #ccc;
}
/* Style the collapsible content. Note: hidden by default */
.content {
padding: 0 18px;
display: none;
overflow: hidden;
background-color: #f1f1f1;
}
+28
View File
@@ -0,0 +1,28 @@
* {
text-align: left;
background-color: rgb(35, 35, 36);
}
@font-face {
font-family: Arizona-Regular;
src: url(./fonts/Arizonia-Regular.ttf);
}
@font-face {
font-family: Parisienne;
src: url(./fonts/Parisienne-Regular.ttf);
}
h1 {
background-color: aqua;
font-size: 50px;
text-align: center;
margin: auto;
font-family: Parisienne;
}
p {
color: bisque;
margin-top: 20px;
font-size: 20px;
}