just-the-docs/docs/search.md
Dale Phurrough 7a01ef1a59
add options for custom lunr Liquid and JS code (#1068)
This is a prototype for review and discussion. My use and testing of this PR is on top of 6d9d41359c46882d9b64a446d5a83fac5b3e20a7. The changes are trival to rebase to `main` and I'm happy to do so if this prototype moves forward.


* Feature request details in linked issue, fixes just-the-docs/just-the-docs#1067
* I welcome feedback and all discussion
* A draft doc site of mine using this PR is at https://docs.hidale.com/

To use the prototype, the two include files need to be customized. Here are mine from the draft website 9c0d836408

Co-authored-by: Matt Wang <matt@matthewwang.me>
2023-01-13 19:08:33 -08:00

5.4 KiB

layout title nav_order
default Search 7

Search

{: .no_toc }

Table of contents

{: .no_toc .text-delta }

  1. TOC {:toc}

Just the Docs uses lunr.js to add a client-side search interface powered by a JSON index that Jekyll generates. All search results are shown in an auto-complete style interface (there is no search results page). By default, all generated HTML pages are indexed using the following data points:

  • Page title
  • Page content
  • Page URL

Enable search in configuration

In your site's _config.yml, enable search:

# Enable or disable the site search
# Supports true (default) or false
search_enabled: true

Search granularity

Pages are split into sections that can be searched individually. The sections are defined by the headings on the page. Each section is displayed in a separate search result.

# Split pages into sections that can be searched individually
# Supports 1 - 6, default: 2
search.heading_level: 2

Search previews

A search result can contain previews that show where the search words are found in the specific section.

# Maximum amount of previews per search result
# Default: 3
search.previews: 3

# Maximum amount of words to display before a matched word in the preview
# Default: 5
search.preview_words_before: 5

# Maximum amount of words to display after a matched word in the preview
# Default: 10
search.preview_words_after: 10

Search tokenizer

The default is for hyphens to separate tokens in search terms: gem-based is equivalent to gem based, matching either word. To allow search for hyphenated words:

# Set the search token separator
# Default: /[\s\-/]+/
# Example: enable support for hyphenated search words
search.tokenizer_separator: /[\s/]+/

Display URL in search results

# Display the relative url in search results
# Supports true (default) or false
search.rel_url: false

Display search button

The search button displays in the bottom right corner of the screen and triggers the search input when clicked.

# Enable or disable the search button that appears in the bottom right corner of every page
# Supports true or false (default)
search.button: true

Sometimes you might have a page that you don't want to be indexed for the search nor to show up in search results, e.g, a 404 page. To exclude a page from search, add the search_exclude: true parameter to the page's YAML front matter:

Example

{: .no_toc }

---
layout: default
title: Page not found
nav_exclude: true
search_exclude: true
---

Generate search index when used as a gem

If you use Just the Docs as a remote theme, you do not need the following steps.

If you use the theme as a gem, you must initialize the search by running this rake command that comes with just-the-docs:

$ bundle exec just-the-docs rake search:init

This command creates the assets/js/zzzz-search-data.json file that Jekyll uses to create your search index. Alternatively, you can create the file manually with [this content]({{ site.github.repository_url }}/blob/main/assets/js/zzzz-search-data.json).

Custom content for search index

By default, the search feature indexes a page's .content, .title, and some headers within the .content. Other data (ex front matter, files in _data, assets) is not indexed. To index additional data, users can customize what lunr indexes.

{: .warning }

Customizing search indices is an advanced feature that requires Javascript and Liquid knowledge.

  1. First, ensure that assets/js/zzzz-search-data.json is up-to-date; it can be regenerated with rake or manually (see: "Generate search index when used as a gem").
  2. To add Liquid/Jekyll-based data: create a new include at the path _includes/lunr/custom-data.json. Insert custom Liquid code that reads various data (ex: include.page, site.data, site.static_files) that then generates valid JSON to add to the index. Verify the fields in the generated assets/js/search-data.json.
  3. For all custom data (Liquid, JavaScript, or external): create a new include at the path _includes/lunr/custom-index.js to your site. Add valid JavaScript that creates relevant fields to add to the index. You may want to inspect assets/js/just-the-docs.js to better understand the code structure. This is necessary to render any relevant custom index code.

Example

_includes/lunr/custom-data.json: this example adds each page's usage and examples front matter fields, normalizes the text, and writes the text to custom Javascript myusage and myexamples fields.

{% raw %}

{%- capture newline %}
{% endcapture -%}
"myusage": {{ include.page.usage | markdownify | replace:newline,' ' | strip_html | normalize_whitespace | strip | jsonify }},
"myexamples": {{ include.page.examples | markdownify | replace:newline,' ' | strip_html | normalize_whitespace | strip | jsonify }},

{% endraw %}

_includes/lunr/custom-index.js custom code is within a Javascript loop. All custom Javascript fields are accessed as fields of docs[i] such as docs[i].myusage. Finally, append your custom fields on to the already existing docs[i].content.

const content_to_merge = [docs[i].content, docs[i].myusage, docs[i].myexamples];
docs[i].content = content_to_merge.join(' ');