Use lunr.js to provide simple full-text search, using JavaScript in your browser, for your Jekyll static website.
Inspired by Pascal Widdershoven's Jekyll + indextank and Michael Levin's Sitemap.xml Generator plugins.
This Jekyll plugin handles the generation of a lunr.js compatible .json
index file. Runtime search configuration is provided by a simple jQuery plugin.
It allows full-text search of all your Jekyll pages and posts. Executed by the client without any server-side processing (outside of serving static files).
Choose to install as either a Ruby Gem, or by copying the pre-built plugin file to your Jekyll site.
Install the jekyll-lunr-js-search Ruby Gem.
gem install jekyll-lunr-js-search
Modify your Jekyll _config.yml
file to include the Gem.
gems: ['jekyll-lunr-js-search']
build/jekyll_lunr_js_search.rb
inside the _plugins
folder in the root of your Jekyll site.The content from all Jekyll posts and pages will be indexed to a js/index.json
file ready for lunr.js to consume. This happens each time the site is generated.
A jQuery plugin is provided in js/jquery.lunr.search.js
to handle the configuration of lunr.js with the search index JSON data generated by this plugin.
Dependencies for the jQuery plugin are as follows.
A pre-built version of the jQuery plugin, along with all of the above dependencies, concatenated and minified is available from at build/search.min.js.
The plugin will automatically add the minified JavaScript file js/search.min.js
to your _site
.
To use it, you must add a script reference to the bottom of your nominated search page.
<script src="https://github.com/slashdotdash/jekyll-lunr-js-search/raw/master/js/search.min.js" type="text/javascript" charset="utf-8"></script>
js/jquery.lunr.search.js
to your Jekyll site's JavaScript directory.Add a script reference to the bottom of your nominated search page for jquery.lunr.search.js
and each of the dependencies outlined above.
<script src="https://github.com/slashdotdash/jekyll-lunr-js-search/raw/master/js/jquery-1.9.1.min.js" type="text/javascript" charset="utf-8"></script>
<script src="https://github.com/slashdotdash/jekyll-lunr-js-search/raw/master/js/lunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="https://github.com/slashdotdash/jekyll-lunr-js-search/raw/master/js/mustache.js" type="text/javascript" charset="utf-8"></script>
<script src="https://github.com/slashdotdash/jekyll-lunr-js-search/raw/master/js/date.format.js" type="text/javascript" charset="utf-8"></script>
<script src="https://github.com/slashdotdash/jekyll-lunr-js-search/raw/master/js/URI.min.js" type="text/javascript" charset="utf-8"></script>
<script src="https://github.com/slashdotdash/jekyll-lunr-js-search/raw/master/js/jquery.lunr.search.js" type="text/javascript" charset="utf-8"></script>
Make sure you use the same version of lunr.js as the gem. The Jekyll log output includes the version used.
Ideally you would concatenate, minify and optimise these six .js
files using uglify/Google closure/etc to produce a single search.min.js
file to reference (or use the pre-built script as described in 2a above).
<script src="https://github.com/slashdotdash/jekyll-lunr-js-search/raw/master/js/search.min.js" type="text/javascript" charset="utf-8"></script>
<form action="/search" method="get">
<input type="text" id="search-query" name="q" placeholder="Search" autocomplete="off">
</form>
Search happens as you type, once at least three characters have been entered.
Providing the form action and specifying the get method allows the user to hit return/enter to also submit the search. Amend the form's action URL as necessary for the search page on your own site.
<section id="search-results" style="display: none;"> </section>
This may be initially hidden as the plugin will show the element when searching.
{% raw %}
<script id="search-results-template" type="text/mustache">
{{#entries}}
<article>
<h3>
{{#date}}<small><time datetime="{{pubdate}}" pubdate>{{displaydate}}</time></small>{{/date}}
<a href="https://github.com/slashdotdash/jekyll-lunr-js-search/blob/master/{{url}}">{{title}}</a>
</h3>
{{#is_post}}
<ul>
{{#tags}}<li>{{.}} </li>{{/tags}}
</ul>
{{/is_post}}
</article>
{{/entries}}
</script>
{% endraw %}
Note the use of {% raw %}
and {% endraw %}
to ensure the Mustache tags are not stripped out by Jekyll.
The fields available to display are as follows.
List of search result entries (mandatory).
Raw published date for posts, or null for pages. Can be used to toggle display of the following dates in the template {{#date}}has a date{{/date}} {{#!date}}no date{{/date}}
.
Post published date, formatted as 'yyyy-mm-dd', to be used in a html5 <time datetime="{{pubdate}}">
element (posts only).
Post published date, formatted as 'mmm dd, yyyy', such as Oct 12, 2012 (posts only)
Title of the Jekyll page or post.
URL of the Jekyll page or post that can be used to create a hyperlink <a href="https://github.com/slashdotdash/jekyll-lunr-js-search/blob/master/{{url}}">{{title}}</a>
.
Categories (array) of the Jekyll page or post, can be used in a loop {{#categories}}{{.}} {{/categories}}
to list them.
Tags (array) of the Jekyll page or post, can be used in a loop {{#tags}}{{.}} {{/tags}}
to list them.
Booelan value, true if current result element is a post. Can be used to toggle display of specific elements in the template {{#is_post}}is a post{{/is_post}}
<script type="text/javascript">
$(function() {
$('#search-query').lunrSearch({
indexUrl : '/js/index.json', // url for the .json file containing search index data
results : '#search-results', // selector for containing search results element
template : '#search-results-template', // selector for Mustache.js template
titleMsg : '<h1>Search results<h1>', // message attached in front of results (can be empty)
emptyMsg : '<p>Nothing found.</p>' // shown message if search returns no results
});
});
</script>
Add the following exclude_from_search
setting to any page's YAML config.
exclude_from_search: true
Or add an array of exclusions (as individual regular expressions) to the site's _config.yml
file.
lunr_search:
excludes: [rss.xml, atom.xml]
You can also configure a stopwords file, and a minimum length of word to be included in the index file. This can be done by adding a search block to _config.yml
. The default values are:
lunr_search:
stopwords: "stopwords.txt"
min_length: 3
The stopwords file must consist of one word per line, in lowercase, without punctuation.
You can choose to store index.json
, search.min.js
and lunr.min.js
in a different directory like this:
lunr_search:
js_dir: "javascript"
Search plugin is deployed to 10consulting.com/search. Some example search queries are /search/?q=git, /search/?q=cqrs.
It also features on-demand loading of the search plugin .js
when focusing into the search field on the homepage. Look at the browser network requests clicking into the search input.
To build the single jekyll_lunr_js_search.rb
plugin file.
Install Bundler and then run the following.
bundle install
Install Bower.
To build the plugin.
rake build
Then copy build/jekyll_lunr_js_search.rb
to your Jekyll site's _plugins
folder and the build/*.min.js
files to your site's js
folder.
If you include the .js
and .js.map
files your browser developer console will link to the unminified code.