How I Implemented lunr.js In My Blog
As you probably are aware, this blog is hosted on GitHub pages and is powered by Jekyll. It provides an interesting challenge when dealing with dynamic content, such as search. Luckily, there is lunr.js, a client-side full text search engine. Sadly there isn’t much good documentation on how to implement it, so I’ll just go over it quickly.
First go grab the JS or Minified JS from the GitHub project or use a CDN and include it in your HTML page. While you’re at it, go ahead and make a search.js
file
Now we need to create the lunr.js index.
Of course your setup will be different. As you can see, you can apply boosts to certain fields. Pay attention to the this.ref('id')
bit.
Now since I’m deploying to GitHub Pages, I can’t just add in plugins. Therefore I have to do indexing client side, which is fine as long as your blog isn’t Coding Horror. Jekyll has a nifty Liquid filter called jsonify
to turn anything into valid JSON. So let’s create a posts.json
and utilize that as well as some looping.
---
layout: null
---
[
{% for post in site.posts %}
{
"id": {{ post.id | jsonify }},
"title": {{ post.title | jsonify }},
"category": {{ post.category | jsonify}},
"tags": {{ post.tags | jsonify }},
"url": {{ post.url | jsonify }},
"date": {{ post.date | jsonify }},
"path": {{ post.path | jsonify }},
"excerpt": {{ post.excerpt | strip_html | strip_newlines | jsonify }},
"body": {{ post.content | strip_html | jsonify }},
"content": {{ post.content | jsonify }}
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
Now we can simply get them with a jQuery.get
call.
Remember how I said to pay attention to the this.ref('id')
bit? Well, Jekyll’s idea of an id is something like /2008/12/14/my-post
, and since posts are being stored in an array, it makes finding them a little tricky. Simple fix: use a post factory.
Now you have the basics for client-side search! Still need to work on the view part. For my site, I used Handlebars, but you can use whatever floats your boat.
If you chose to embed the template inside the search page, be sure to wrap it in a {% raw %} block so Jekyll doesn’t evaluate the brackets.
From here, it’s just wiring up the template to an event handler and you are good to go!
Congrats, you now have client side search on your Jekyll blog!
EDIT: (later that very same day):
I forgot to add in the comma in JSON. ,