First attemts at using lunr search engine

This commit is contained in:
Griatch 2020-04-10 16:23:31 +02:00
parent 3ad404cddb
commit aeef23f4d6
4 changed files with 220 additions and 2 deletions

View 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)

View file

@ -2,8 +2,7 @@
sphinx==2.4.4
sphinx-multiversion==0.1.1
lunr==0.5.6
# recommonmark custom branch with evennia-specific fixes
git+https://github.com/evennia/recommonmark.git@evennia-mods#egg=recommonmark
# theme

View 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();
});

View 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>