First attemts at using lunr search engine
This commit is contained in:
parent
3ad404cddb
commit
aeef23f4d6
4 changed files with 220 additions and 2 deletions
93
docs/pylib/build_search_index.py
Normal file
93
docs/pylib/build_search_index.py
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Builds a lunr static search index for optimized search
|
||||||
|
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import glob
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
from os.path import sep, abspath, dirname, join as joinpath
|
||||||
|
from lunr import lunr
|
||||||
|
|
||||||
|
_DOCS_PATH = dirname(dirname(abspath(__file__)))
|
||||||
|
|
||||||
|
_DEFAULT_BUILD_DIR = joinpath(_DOCS_PATH, "build", "html")
|
||||||
|
_DEFAULT_URL_BASE = f"file://{_DEFAULT_BUILD_DIR}"
|
||||||
|
_INDEX_PATH = joinpath("_static", "js", "lunr", "search_index.json")
|
||||||
|
|
||||||
|
DEFAULT_SOURCE_DIR = joinpath(_DOCS_PATH, "source")
|
||||||
|
DEFAULT_OUTFILE = joinpath(DEFAULT_SOURCE_DIR, _INDEX_PATH)
|
||||||
|
|
||||||
|
URL_BASE = os.environ.get("SEARCH_URL_BASE", _DEFAULT_URL_BASE)
|
||||||
|
|
||||||
|
|
||||||
|
def create_search_index(sourcedir, outfile):
|
||||||
|
"""
|
||||||
|
Create the index.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
sourcedir (str): Path to the source directory. This will be searched
|
||||||
|
for both .md and .rst files.
|
||||||
|
outfile (str): Path to the index file to create.
|
||||||
|
|
||||||
|
"""
|
||||||
|
markdown_files = glob.glob(f"{sourcedir}{sep}*.md")
|
||||||
|
markdown_files.extend(glob.glob(f"{sourcedir}{sep}*{sep}*.md"))
|
||||||
|
rest_files = glob.glob(f"{sourcedir}{sep}*.rst")
|
||||||
|
rest_files.extend(glob.glob(f"{sourcedir}{sep}*{sep}*.rst"))
|
||||||
|
filepaths = markdown_files + rest_files
|
||||||
|
|
||||||
|
outlist = []
|
||||||
|
|
||||||
|
print(f"Building Search index from {len(filepaths)} files ... ", end="")
|
||||||
|
|
||||||
|
for filepath in filepaths:
|
||||||
|
with open(filepath, 'r') as fil:
|
||||||
|
filename = filepath.rsplit(sep, 1)[1].split(".", 1)[0]
|
||||||
|
url = f"{URL_BASE}{sep}{filename}.html".strip()
|
||||||
|
title = filename.replace("-", " ").strip()
|
||||||
|
body = fil.read()
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"url": url,
|
||||||
|
"title": title,
|
||||||
|
"text": body,
|
||||||
|
}
|
||||||
|
outlist.append(data)
|
||||||
|
|
||||||
|
idx = lunr(
|
||||||
|
ref="url",
|
||||||
|
documents=outlist,
|
||||||
|
fields=[
|
||||||
|
{
|
||||||
|
"field_name": "title",
|
||||||
|
"boost": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field_name": "text",
|
||||||
|
"boost": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
with open(outfile, "w") as fil:
|
||||||
|
fil.write(json.dumps(idx.serialize()))
|
||||||
|
|
||||||
|
print(f"wrote to source{sep}{_INDEX_PATH}.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
parser = ArgumentParser(description="Build a static search index.")
|
||||||
|
|
||||||
|
parser.add_argument("-i", dest="sourcedir", default=DEFAULT_SOURCE_DIR,
|
||||||
|
help="Absolute path to the documentation source dir")
|
||||||
|
parser.add_argument("-o", dest="outfile", default=DEFAULT_OUTFILE,
|
||||||
|
help="Absolute path to the index file to output.")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
create_search_index(args.sourcedir, args.outfile)
|
||||||
|
|
@ -2,8 +2,7 @@
|
||||||
|
|
||||||
sphinx==2.4.4
|
sphinx==2.4.4
|
||||||
sphinx-multiversion==0.1.1
|
sphinx-multiversion==0.1.1
|
||||||
|
lunr==0.5.6
|
||||||
|
|
||||||
# recommonmark custom branch with evennia-specific fixes
|
# recommonmark custom branch with evennia-specific fixes
|
||||||
git+https://github.com/evennia/recommonmark.git@evennia-mods#egg=recommonmark
|
git+https://github.com/evennia/recommonmark.git@evennia-mods#egg=recommonmark
|
||||||
|
|
||||||
# theme
|
|
||||||
|
|
|
||||||
95
docs/source/_static/js/lunr/search.js
Normal file
95
docs/source/_static/js/lunr/search.js
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
//
|
||||||
|
// Using the pre-generated index file, set up a dynamic
|
||||||
|
// search mechanims that returns quick suggestions of the
|
||||||
|
// best matches you start to enter.
|
||||||
|
//
|
||||||
|
|
||||||
|
var lunrIndex,
|
||||||
|
$results,
|
||||||
|
documents;
|
||||||
|
|
||||||
|
function initLunr() {
|
||||||
|
// retrieve the index file
|
||||||
|
$.getJSON("_static/js/lunr/search_index.json")
|
||||||
|
.done(function(index) {
|
||||||
|
|
||||||
|
lunrIndex = lunr.Index.load(index)
|
||||||
|
|
||||||
|
// documents = index;
|
||||||
|
|
||||||
|
// lunrIndex = lunr(function(){
|
||||||
|
// this.ref('url')
|
||||||
|
// this.field('body')
|
||||||
|
|
||||||
|
// this.field("title", {
|
||||||
|
// boost: 10
|
||||||
|
// });
|
||||||
|
|
||||||
|
// documents.forEach(function(doc) {
|
||||||
|
// try {
|
||||||
|
// this.add(doc)
|
||||||
|
// } catch (e) {}
|
||||||
|
// }, this)
|
||||||
|
// })
|
||||||
|
})
|
||||||
|
.fail(function(jqxhr, textStatus, error) {
|
||||||
|
var err = textStatus + ", " + error;
|
||||||
|
console.error("Error getting Lunr index file:", err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function search(query) {
|
||||||
|
return lunrIndex.search(query).map(function(result) {
|
||||||
|
return documents.filter(function(page) {
|
||||||
|
try {
|
||||||
|
console.log(page)
|
||||||
|
return page.href === result.ref;
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Error in search. ' + e)
|
||||||
|
}
|
||||||
|
})[0];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderResults(results) {
|
||||||
|
if (!results.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// show first ten results
|
||||||
|
results.slice(0, 10).forEach(function(result) {
|
||||||
|
var $result = $("<li>");
|
||||||
|
|
||||||
|
$result.append($("<a>", {
|
||||||
|
href: result.url,
|
||||||
|
text: "» " + result.title
|
||||||
|
}));
|
||||||
|
|
||||||
|
$results.append($result);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function initUI() {
|
||||||
|
$results = $("#lunrsearchresults");
|
||||||
|
|
||||||
|
$("#lunrsearch").keyup(function(){
|
||||||
|
// empty previous results
|
||||||
|
$results.empty();
|
||||||
|
|
||||||
|
// trigger search when at least two chars provided.
|
||||||
|
var query = $(this).val();
|
||||||
|
if (query.length < 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var results = search(query);
|
||||||
|
|
||||||
|
renderResults(results);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initLunr();
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
initUI();
|
||||||
|
});
|
||||||
31
docs/source/_templates/searchbox.html
Normal file
31
docs/source/_templates/searchbox.html
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
{#
|
||||||
|
basic/searchbox.html
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Variant for lunrJS search
|
||||||
|
|
||||||
|
#}
|
||||||
|
{%- if pagename != "search" and builder != "singlehtml" %}
|
||||||
|
<div id="searchbox" style="display: none" role="search">
|
||||||
|
<h3 id="searchlabel">{{ _('Quick search') }}</h3>
|
||||||
|
<div class="searchformwrapper">
|
||||||
|
<form class="search" action="{{ pathto('search') }}" method="get">
|
||||||
|
<input type="text" name="q" aria-labelledby="searchlabel" />
|
||||||
|
<input type="submit" value="{{ _('Go') }}" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>$('#searchbox').show(0);</script>
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
{#
|
||||||
|
|
||||||
|
Lunr indexed quick search
|
||||||
|
|
||||||
|
#}
|
||||||
|
<p><input id="lunrsearch" type="text" placeholder="type something here"></p>
|
||||||
|
<ul id="lunrsearchresults"></ul>
|
||||||
|
|
||||||
|
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
|
||||||
|
<script src="https://unpkg.com/lunr/lunr.js"></script>
|
||||||
|
<script src="_static/js/lunr/search.js"></script>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue