To enable search for your site, you can use Lunr
, which will create a searchable index without the need for any server-side or external search service. The inspiration to integrate Lunr with Cryogen was the following site Lunr-Index-and-Search-for-Static-Sites
, where the source JavaScript files can be found, which are used with slightly modifications here.
A live demo of the result can be found at: https://blog.stderr.at/
Prerequisites
Before we start, Node.js and some modules must be installed on your system:
- Install
Node.js
- Install lunr:
npm install lunr
- Install cheerio:
npm install cheerio
Copy build-index.js
As the filename says, this script will create the index file, which will be used to search your pages.
NOTE: Everytime when a new post/page is published, the index should be recreated. Therefore, the best option would be to add this to your deployment routine.
Download: build-index.js
Most notable lines
The following lines might require attention:
Line 8: The output folder of the html files. In this example only posts-output will be indexed (no tags, no pages).
const HTML_FOLDER = "public/posts-output";
Line 11: Files to exclude from the index
const EXCLUDE_FILES = ["search.html"];
Line 13: The output path and filename for the index. This depends on your actual theme.
const OUTPUT_INDEX = "themes/nucleus/js/index/lunr_index.js";
Line 64: This adds "posts-output" to the link, which might be removed depending on you page
"link": "posts-output/"+file,
Create an index file
The index file should be created with any new post or page which is published using the following command:
node ./build-index.js
Download lunrclient.js
Download lunrclient.js and place it into the js/
folder of your theme.
This script will create the search result page.
Changes to HTML and CSS
Changes to the actual html/css highly depend on your theme. Therefor only a basic snippets of a possible change of the base.html are shown here.
In the head
tag the JavaScript files must be loaded. First lunr itself, then the indexfile and then the client file:
<script src="https://unpkg.com/lunr/lunr.js"></script>
<script src="/js/index/lunr_index.js"></script>
<script src="/js/lunrclient.js"></script>
The search form can look like this:
<!--- Search form -->
<form id="lunrSearchForm" name="lunrSearchForm" action="/">
<input class="search-input" name="q" placeholder="Enter search term" type="text">
<input class="button nopadding" type="submit" value="Search">
</form>
<div class="loading" id="loading-div">
<i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i>
<span class="sr-only">Loading...</span>
</div>
Last but not least the search result is rendered in the main page (right side, nucleus example theme was used here).
The script lunrclient.js
will replace the elements "resultCount" and "searchResults".
<div id="right" class="clearfix">
<div class="resultCount" id="resultCount"></div>
<hr />
<div id="searchResults">
{% block content %}
{% endblock %}
</div>
Tip: If you use the nucleus example template, or any javascript which does a window.onload, you may want to do the following changes too:
themes/nucleus/js/scripts.js
add
/* window.onload function */
function start()
{
externalLinks();
startlunr();
}
Remove window.onload = externalLinks
from the line
function externalLinks() { if (!document.getElementsByTagName) return; var anchors = document.getElementsByTagName("a"); for (var i=0; i<anchors.length; i++) { var anchor = anchors[i]; if (anchor.getAttribute("href") && anchor.getAttribute("rel") == "external") anchor.target = "_blank"; } } window.onload = externalLinks;
themes/nucleus/html/base.html
Below the line {% script "js/scripts.js" %}
add:
<script>window.onload = start;</script>