jekyll_pages_api_search Plugin

The jekyll_pages_api_search Ruby
gem adds a
lunr.js search index to a
Jekyll-based web site.
The search index is generated and compressed automatically via jekyll build
or jekyll serve. The supporting JavaScript code is optimized, compressed,
and loads asynchronously. These features ensure that the preparation of the
search index does not introduce rendering latency in the browser.

Example of querying the search index and selecting from the search
results page. The `/` key moves focus to the search query box, and the first
result receives the tab index, making mouse-based navigation unnecessary.
How it works
On the server building the site, the plugin takes the corpus produced by the
jekyll_pages_api gem and feeds
it to a Node.js script that compiles it into a lunr.js
index, serialized as JSON. The plugin adds this output file to the Jekyll site
output. It generates a compressed copy as well, enabling web servers to take
advantage of sending the compressed output directly, e.g. using the Nginx
gzip_static on directive.
The gem also generates a (configurable, customizable) search results page that
will serve the search results.
On the client, the search interface box submits a query form that fetches the
search results page. The code on the search results page then fetches the
search index from the server (which will be cached by the browser until the
next site build). After loading the index, the page issues the query and
inserts the results into its search results interface element.
All of the client-side components are bundled together with
assets/js/search.js into assets/js/search-bundle.js using
Browserify.
Installation
-
Install Node.js on your system. This plugin requires
version 4.2 or greater or version 5 or greater. You may wish to first install a
version manager such as nvm to manage and install different Node.js versions.
-
Add this line to your Jekyll project's Gemfile:
group :jekyll_plugins do
gem 'jekyll_pages_api_search'
end
- Add the following to the project's
_config.yml file:
jekyll_pages_api_search:
index_fields:
title:
boost: 10
tags:
boost: 10
url:
boost: 5
body:
browserify:
source: js/my-search.js
target: js/my-search-bundle.js
-
Run jekyll build or jekyll serve to produce search-index.json and
search-index.json.gz files in the _site directory (or other output
directory, as configured).
If browserify: is defined, it will also produce the target: bundle file
and its gzipped version. See the browserify section
for more details.
-
If you're running Nginx, you may want to use the
gzip_static on
directive
to take advantage of the gzipped versions of the search index and supporting
JavaScript.
Usage
To add the index to your pages, insert the following tags in your _layouts
and _includes files as you see fit:
{% jekyll_pages_api_search_interface %}: inserts the HTML for the search
box and search results
{% jekyll_pages_api_search_load %}: inserts the <script> tags to load
the search code asynchronously; the search code will then load
search-index.json asynchronously
You can also add @import "jekyll_pages_api_search"; to one of your Sass
assets to use the default interface style.
Add skip_index: true to the front matter of any documents you would like to
exclude from the index (e.g. indexes that contain summaries of other documents).
Configuration
In addition to the fields listed above in the installation
instructions, the following properties of the
jekyll_pages_api_search configuration object are also available:
- results_page_title: Sets the title of the generated search results page.
- layout: The name of the layout file for the search results page, minus
the
.html suffix. By default this is search-results, and is provided by
the plugin. If you add a search-results.html to your site's layout_dir
(typically _layouts), the plugin will use that layout instead.
- endpoint: The name of the endpoint generated for the search results
page. Defaults to
search.
Results UI and search engine options
To customize elements of the search user interface and search engine, add the
following objects to your search result page's layout before the
{% jekyll_pages_api_search_load %} tag. Override only the properties
required for your installation (default values shown below).
<script>
var JEKYLL_PAGES_API_SEARCH_UI_OPTIONS = {
inputElementId: 'search-input',
searchResultsId: 'search-results',
emptyResultsMessagePrefix: 'No results found for',
emptyResultsElementType: 'p',
emptyResultsElementClass: 'search-empty'
};
var JEKYLL_PAGES_API_SEARCH_ENGINE_OPTIONS = {
queryParam: 'q'
};
</script>
To override the default search results rendering function, define a function
called renderJekyllPagesApiSearchResults that conforms to the following
interface. This is the default implementation, which creates new <li>
elements containing a link for each search result.
<script>
function renderJekyllPagesApiSearchResults(query, results, doc, resultsElem) {
results.forEach(function(result, index) {
var item = doc.createElement('li'),
link = doc.createElement('a'),
text = doc.createTextNode(result.title);
link.appendChild(text);
link.title = result.title;
link.href = result.url;
item.appendChild(link);
resultsElem.appendChild(item);
link.tabindex = index;
if (index === 0) {
link.focus();
}
});
}
</script>
Using browserify
The most modular means of defining renderJekyllPagesApiSearchResults may be
to create a Node.js implementation file and generate a browser-compatible
version using browserify. First create the
implementation as described above. Then perform the following steps:
# Create a package.json file
$ npm init
# Install browserify and uglifyify, a JavaScript minimizer
$ npm install browserify uglifyify --save-dev
Add the browserify: configuration as defined in the installation
instructions above, replacing js/my-search.js with the path
to your renderJekyllPagesApiSearchResults implementation script and
js/my-search-bundle.js with the path to your generated bundle.
Customizing tags and script loading
If you prefer to craft your own versions of these tags and styles, you can
capture the output of these tags and the Sass @import statement, then create
new tags or included files based on this output, careful not to change
anything that causes the interaction between these components to fail.
Alternately, you can inspect the code of this gem (all paths relative to
lib/jekyll_pages_api_search/):
{% jekyll_pages_api_search_interface %}: includes search.html
{% jekyll_pages_api_search_load %}: generated by the LoadSearchTag class
from tags.rb
{% jekyll_pages_api_search_results %}: generated by the SearchResultsTag
class from tags.rb
@import "jekyll_pages_api_search";: includes
sass/jekyll_pages_api_search.scss
Running standalone
If you wish to generate a search-index.json file (and optionaly a
pages.json file) when using a site generation tool other than Jekyll, you
can run the jekyll_pages_api_search executable as a post-generation step.
Run jekyll_pages_api -h for instructions.
Developing
Install Node.js per the installation instructions (step #1).
The Rakefile will prompt you to install Node.js and any packages
that are missing from your system when running bundle exec rake build.
After cloning this repository, do the following to ensure your installation is
in a good state:
$ cd jekyll_pages_api_search
$ npm install
$ bundle install
$ bundle exec rake test
Run bundle exec rake -T to get a list of build commands and descriptions.
Commit an update to bump the version number of
lib/jekyll_pages_api_search/version.rb before running bundle exec rake release.
While developing this gem, add this to the Gemfile of any project using the
gem to try out your changes (presuming the project's working directory is a
sibling of the gem's working directory):
group :jekyll_plugins do
gem 'jekyll_pages_api_search', :path => '../jekyll_pages_api_search'
end
Releasing
After following the steps from the Developing section to build
and test the gem:
-
Ensure all changes for the release have already been merged all into the
master branch.
-
Bump the version number by editing
lib/jekyll_pages_api_search/version.rb.
-
Commit the version number update directly to the master branch, replacing
X.X.X with the new version number:
$ git commit -m 'Bump to vX.X.X' lib/jekyll_pages_api_search/version.rb
-
Finally, run the following command. It will build the gem, tag the head
commit in git, push the branch and tag to GitHub, and ultimately push the
release to jekyll_pages_api_search on RubyGems.org.
$ bundle exec rake release
Open Source License
This software is made available as Open Source software under the
ISC License. For the text of the license, see the LICENSE
file.
Prior work
This is derived from the original 18F/jekyll_pages_api_search.