Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
@antora/lunr-extension
Advanced tools
An Antora extension that adds offline, full-text search powered by Lunr to your Antora documentation site.
Lunr provides a great search experience for readers without having to rely on external search services. With this extension, you can add offline, full-text search powered by Lunr to your Antora documentation site.
📌 NOTE: The Antora Lunr Extension is designed for and compatible with Antora 3.0 and newer. If you're using an earlier version of Antora, you must use antora-lunr instead.
To add search functionality powered by Lunr to your Antora documentation site, you need to install this extension package, register the extension in your Antora playbook file, and add the search interface to the pages in your site. Let's get started.
In order to use this extension, you must be using at least Node.js 16 and Antora 3. We assume you've already set up an Antora playbook file (i.e., antora-playbook.yml) to build your site.
Begin by installing the extension package into your playbook project:
$ npm i @antora/lunr-extension
You also have the option of installing the extension globally by adding the -g
flag to the npm i
command:
$ npm i -g @antora/lunr-extension
We strongly recommend installing dependencies into your playbook project. This strategy makes it easier to manage the dependencies, clearly documents those dependencies, and ensures the build is portable and isolated from other sites.
Both of the previous two commands download and install the latest release of this software from the npm registry. If you want to use the development version, please refer to the <<contributing, contributing section>>.
Although the software in the git repository is regularly and rigorously tested, the behavior of the development version may not always match the documentation.
This section explains how to activate the Lunr integration and how to use the search interface it provides.
Now that you have the Lunr extension installed, you need to register the extension with Antora.
To register the extension, you'll add an entry that cites the name of the package to the antora.extensions
key in your Antora playbook file.
Open the Antora playbook file and add the extension as follows:
antora-playbook.yml
antora:
extensions:
- '@antora/lunr-extension'
If you don't need to specify any configuration keys, the entry in antora.extensions
can be the name of the package.
In this case, quotes are required around the package name since @
is a special character in YAML.
💡 TIP: Alternately, you can register the extension when you run the antora
command using the --extension
option.
In order to specify configuration keys for the extension, you must change the entry to a map syntax.
When using the map syntax, the package name must be preceded by the require
key, as shown here:
antora-playbook.yml
antora:
extensions:
- require: '@antora/lunr-extension'
You may want to start with this syntax so you don't have to remember to switch to it later when you want to specify configuration.
The next time you build your documentation site, the extension will automatically generate a search index and write it to a file named search-index.js at the root of the site.
The location of this file depends on the value of output.dir
key in your playbook.
When using the default output dir, that location is build/site/search-index.js.
The search is not coupled to the value of the site URL. That means you can set the site URL in the playbook to any allowable value and the search will work regardless. (See the docs for the site.url key for a list of allowable values). In fact, you don't have to set the site URL at all. This works because the URLs in the search results are always computed relative to the current page. They are not absolute URLs.
💡 TIP: If you're using the http-server module to provide an HTTP server to view your site locally, you can set the site.url
key to http://localhost:8080
to emulate the conditions of a production environment.
Thanks to the use of relative URLs in the search results, the browser is able to resolve URLs in the results regardless of where the site is deployed or on what page the search is used. You can even use the search when viewing the site offline through a file URI.
If you registered the extension in your playbook file, you can generate your site using the antora
command without having to pass any additional options or environment variables.
$ antora antora-playbook.yml
If you have not registered the extension in your playbook file, you can register it using the --extension
CLI option of the antora
command:
$ antora --extension @antora/lunr-extension antora-playbook.yml
Using the --extension
option also allows you to enable the extension that's registered in the playbook file, but marked as not enabled using the enabled
key.
See Enable an Extension for details about how that works.
Once you have incorporated the Lunr-based search into your site, the next step is to perform a search.
To search, start typing a query (i.e., a word or phrase) into the search box at the top of the page. For example:
install
The search results will be shown under the search box in real time as you type.
The search client will first attempt to find an exact match.
If that query doesn't return any results, the search client will try a begins with search (e.g., install*
).
If that query doesn't return any results, the search client will try a contains search (e.g., *install*
).
If no results are found, the search results will report “No results found for query”.
📌 NOTE: The search engine applies stemming to terms, so it may also find matches for different forms of the word that have the same meaning (i.e., root words).
Lunr supports searches for multiple terms. However, the default behavior may not match your experience using other search engines. By default, multiple search terms are combined with an OR operator (i.e., either term). Consider the following query:
install antora
If a document matches at least one of the search terms, the document will show up in the results. Documents that contain both terms will score higher and thus show up first.
If you want to search for documents that have all of the terms entered (i.e., required term presence), you must add a modifier to the terms.
To indicate that a term must be present in a matching documents, prefix the term with +
(e.g., +install
).
For example, to find a document that contains both “install” and “antora”, use the following query:
+install +antora
🔥 CAUTION: Unlike other search engines, Lunr does not support queries that are enclosed in quotes. In the future, this extension may automatically translate a query with that syntax into a query that uses required term presence.
If you only want to search for a term in page titles and section titles, prefix the term with title:
.
For example:
title:install
When searching for titles, only titles will show in the results. You will not see text snippets from other areas of the page.
You can search for titles that have all of the specified terms by combining the title:
prefix with the +
modifier.
For example:
+title:install +title:antora
This extension will likely support more advanced searches in the future, so watch this space to learn about new searching capabilities.
To learn more about how Lunr searches work, see Searching with Lunr.
Depending on the index size, it can take a few seconds to download and load a pre-built index. While loading the pre-built index, the search input will be disabled. Once the index is loaded, the search input will become active and the user will be able to perform a search.
In addition, an event will be published on the search input element. You can add an event listener if you want to be notified when the index is loaded:
const searchInput = document.getElementById('search-input')
searchInput.addEventListener('loadedindex', (event) => {
console.log(`Index loaded in: ${event.detail.took}ms`) // <1>
})
<1> The event contains the time spent loading the index in milliseconds
This section explains how to control the behavior of this integration using configuration keys and other settings.
In order to specify configuration keys, the entry in the antora.extensions
key must use the map syntax.
When using this form, you specify the package name using the require
key.
The configuration keys should be siblings of the require
key.
Only the require
key should be prefixed with the entry marker, -
.
📌 NOTE: In antora-lunr (the predecessor of this extension), configuration was performed using environment variables. In this extension, configuration is now done using configuration keys in the playbook.
To index only the latest (i.e., released) version, set the index_latest_only
configuration key:
antora-playbook.yml
antora:
extensions:
- require: '@antora/lunr-extension'
index_latest_only: true
By default the extension indexes all the versions of your documentation components.
You can instruct the indexer to exclude certain pages by defining the noindex
document attribute in the AsciiDoc header:
# Do Not Index Me
This content will not show up in the search results.
You can exclude the pages for an entire component version by defining the noindex
AsciiDoc attribute in the component descriptor for that version:
antora.yml
asciidoc:
attributes:
noindex: '@'
The indexer will also look for the robots
meta tag in HTML document and exclude the page if the value of the content attribute is noindex
.
That allows you to exclude pages that were either not created from AsciiDoc or that contain a meta robots tag that was added by the UI template based on another condition.
By default, the maximum length of a snippet in a search result is 100 characters.
To change this length, set the snippet_length
configuration key:
antora-playbook.yml
antora:
extensions:
- require: '@antora/lunr-extension'
snippet_length: 250
The value of this option is an upper limit. The length of the snippet will not exceed the length of the matched text.
By default, Lunr only supports English as an indexing language. You can add support for the following other languages:
📌 NOTE: To use Chinese as your language, you must install the nodejieba
dependency (i.e., npm i nodejieba
).
To use one or more languages, set the languages
configuration key with all the desired language codes as a list:
antora-playbook.yml
antora:
extensions:
- require: '@antora/lunr-extension'
languages: [en, fr]
By default, the search client will silence the error thrown by Lunr if a query is invalid. The client assumes that if the query is invalid, there are no results to present.
If you're trying to debug a query, and you want to see the message of the error Lunr throws, you can put the search client into debug mode.
To do so, add ?lunr-debug=1
to the end of the URL of the current page and reload the page.
💡 TIP: If the page URL already has a query string, then append &lunr-debug=1
instead.
When debug mode is enabled, messages about invalid queries will show up in the browser console at the Debug level. For example:
Invalid search query: invalid:term (unrecognised field 'invalid', possible fields: 'title', 'name', 'text', 'component')
The user is not currently notified about an invalid query, though that could change in the future.
This section is intended for anyone designing and creating a custom UI. This extension relies on a contract with the UI in order to minimize the configuration the user must perform to get the extension working. Antora's default UI fulfills this contract. For custom UIs, the assumptions of this contract are documented here.
The extension provides the lunr.js script. Your UI should not include it. If it does, you will get a duplicate file error.
When this extension is enabled, it sets the SITE_SEARCH_PROVIDER
environment variable to the value lunr
.
This variable is available to the UI templates as env.SITE_SEARCH_PROVIDER
.
The existence of this variable informs the UI template which search integration is active (in this case, Lunr).
When this variable is set, the UI is expected to add certain elements to support the extension.
📌 NOTE: If the UI you're using does not fulfill this contract, you'll need to use the supplemental UI to complete the contract.
This extension assumes that the UI will add an input field for search somewhere in the page. Currently, the provided styles assume it's located in the navbar. The template snippet should look something like this:
{{#if env.SITE_SEARCH_PROVIDER}}
<input id="search-input" type="text" placeholder="Search the docs">
{{/if}}
The UI may enclose the input in other elements in order to position it properly. In Antora's default UI, it looks like this:
{{#if env.SITE_SEARCH_PROVIDER}}
<div class="navbar-item search hide-for-print">
<div id="search-field" class="field">
<input id="search-input" type="text" placeholder="Search the docs"{{#if page.home}} autofocus{{/if}}>
</div>
</div>
{{/if}}
The only requirement is that the input be of type text
and have the ID search-input
.
You can use the following snippet if you want to add a checkbox in order to restrict searches to the current component:
{{#if env.SITE_SEARCH_PROVIDER}}
<div class="navbar-item search hide-for-print">
<div id="search-field" class="field has-filter">
<input id="search-input" type="text" placeholder="Search the docs"{{#if page.home}} autofocus{{/if}}>
<label class="filter checkbox">
<input type="checkbox" data-facet-filter="component:{{page.component.name}}"> In this project
</label>
</div>
</div>
{{/if}}
If you want to filter on the current component by default, you can add the checked
attribute on the checkbox:
<input type="checkbox" data-facet-filter="component:{{page.component.name}}" checked> In this project
If you always want to filter on the current component (without giving an option), you can hide the checkbox using an inline style:
<label class="filter checkbox" style="display: none">
<input type="checkbox" data-facet-filter="component:{{page.component.name}}" checked> In this project
</label>
This extension assumes that the UI will include the search-scripts partial somewhere in the footer. This partial loads the lunr script, search UI script, and search index into the page. The template snippet that includes this partial should look something like this:
{{#if env.SITE_SEARCH_PROVIDER}}
{{> search-scripts}}
{{/if}}
This extension will automatically add the partial search-scripts to the UI catalog if it does not already exist.
This package provides additional CSS to style the search results (data/css/search.css). This stylesheet is loaded by the search UI script also provided from this package. This extension will automatically add the stylesheet search.css to the UI catalog if it does not already exist.
If a custom UI depends on additional styles, the creator of the UI can either bundle those styles or ask the user to place an alternate stylesheet in the supplemental UI.
If you are interested in contributing to this project, please refer to the <<contributing.adoc#,contributing guide>>. In this guide, you'll learn how to:
Thanks in advance for helping to make this project a success!
Here's a list of projects using the Antora Lunr extension.
To add your project to this list, please edit this file!
AsciiDoc(R) is a trademark of the Eclipse Foundation, Inc.
FAQs
An Antora extension that adds offline, full-text search powered by Lunr to your Antora documentation site.
The npm package @antora/lunr-extension receives a total of 15,340 weekly downloads. As such, @antora/lunr-extension popularity was classified as popular.
We found that @antora/lunr-extension demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.