Setting up site search¶
Material for MkDocs provides an excellent, client-side search implementation, omitting the need for the integration of third-party services, which might be tricky to integrate to be compliant with data privacy regulations. Moreover, with some effort, search can be made available offline.
Configuration¶
Built-in search¶
The built-in search plugin integrates seamlessly with Material for MkDocs,
adding multilingual client-side search with lunr and lunr-languages.
It's enabled by default, but must be re-added to mkdocs.yml
when other plugins
are used:
plugins:
- search
The following options are supported:
lang
-
Default: automatically set – This option allows to include the language-specific stemmers provided by lunr-languages. Note that Material for MkDocs will set this automatically based on the site language, but it may be overridden, e.g. to support multiple languages:
plugins: - search: lang: ru
plugins: - search: lang: - en - ru
The following languages are supported:
ar
– Arabicda
– Danishdu
– Dutchen
– Englishfi
– Finnishfr
– Frenchde
– Germanhu
– Hungarianit
– Italianja
– Japaneseno
– Norwegianpt
– Portuguesero
– Romanianru
– Russianes
– Spanishsv
– Swedishth
– Thaitr
– Turkishvi
– Vietnamese
Material for MkDocs also tries to support languages that are not part of this list by choosing the stemmer yielding the best result automatically.
Only specify the languages you really need
Be aware that including support for other languages increases the general JavaScript payload by around 20kb (before
gzip
) and by another 15-30kb per language. separator
-
Default: automatically set – The separator for indexing and query tokenization can be customized, making it possible to index parts of words separated by other characters than whitespace and
-
, e.g. by including.
:plugins: - search: separator: '[\s\-\.]+'
prebuild_index
-
Default:
false
· Experimental – MkDocs can generate a prebuilt index of all pages during build time, which provides performance improvements at the cost of more bandwidth, as it reduces the build time of the search index:plugins: - search: prebuild_index: true
This may be beneficial for large documentation projects served with appropriate headers, i.e.
Content-Encoding: gzip
, but benchmarking before deployment is recommended.
Material for MkDocs doesn't provide official support for the other options of this plugin, so they may be supported but can also yield weird results. Use them at your own risk.
Search suggestions¶
Source · Feature flag · Experimental · Insiders only
When search suggestions are enabled, the search will display the likeliest completion for the last word, saving the user many key strokes by accepting the suggestion with Right
It can be enabled via mkdocs.yml
with:
theme:
features:
- search.suggest
Searching for code high yields code highlighting as a suggestion:
Search highlighting¶
Source · Feature flag · Experimental · Insiders only
When search highlighting is enabled and a user clicks on a search result,
Material for MkDocs will highlight all occurrences after following the link.
It can be enabled via mkdocs.yml
with:
theme:
features:
- search.highlight
Searching for code blocks yields:
Offline search¶
Source · Plugin · Experimental
If you distribute your documentation as *.html
files, the built-in search
will not work out-of-the-box due to the restrictions modern browsers impose for
security reasons. This can be mitigated with the localsearch plugin in
combination with @squidfunk's iframe-worker polyfill.
For setup instructions, refer to the official documentation.
Customization¶
The search implementation of Material for MkDocs is probably its most sophisticated feature, as it tries to balance a great typeahead experience, good performance, accessibility, and a result list that is easy to scan. This is where Material for MkDocs deviates from other themes.
The following section explains how search can be customized to tailor it to your needs.
Query transformation¶
Source · Difficulty: easy
When a user enters a query into the search box, the query is pre-processed before it is submitted to the search index. Material for MkDocs will apply the following transformations, which can be customized by extending the theme:
/**
* Default transformation function
*
* 1. Search for terms in quotation marks and prepend a `+` modifier to denote
* that the resulting document must contain all terms, converting the query
* to an `AND` query (as opposed to the default `OR` behavior). While users
* may expect terms enclosed in quotation marks to map to span queries, i.e.
* for which order is important, `lunr` doesn't support them, so the best
* we can do is to convert the terms to an `AND` query.
*
* 2. Replace control characters which are not located at the beginning of the
* query or preceded by white space, or are not followed by a non-whitespace
* character or are at the end of the query string. Furthermore, filter
* unmatched quotation marks.
*
* 3. Trim excess whitespace from left and right.
*
* @param query - Query value
*
* @return Transformed query value
*/
export function defaultTransform(query: string): string {
return query
.split(/"([^"]+)"/g) /* => 1 */
.map((terms, index) => index & 1
? terms.replace(/^\b|^(?![^\x00-\x7F]|$)|\s+/g, " +")
: terms
)
.join("")
.replace(/"|(?:^|\s+)[*+\-:^~]+(?=\s+|$)/g, "") /* => 2 */
.trim() /* => 3 */
}
If you want to switch to the default behavior of the mkdocs
or readthedocs
template, both of which don't transform the query prior to submission, or
customize the transform
function, you can do this by overriding the
config
block:
{% block config %}
<script>
var search = {
transform: function(query) {
return query
}
}
</script>
{% endblock %}
The transform
function will receive the query string as entered by the user
and must return the processed query string to be submitted to the search index.
Custom search¶
Source · Difficulty: challenging
Material for MkDocs implements search as part of a web worker. If you
want to switch the web worker with your own implementation, e.g. to submit
search to an external service, you can add a custom JavaScript file to the docs
directory and override the config
block:
{% block config %}
<script>
var search = {
worker: "<url>"
}
</script>
{% endblock %}
Communication with the search worker is implemented using a standardized
message format using discriminated unions, i.e. through the type
property
of the message. See the following interface definitions to learn about the
message formats:
The sequence and direction of messages is rather intuitive:
-
SearchSetupMessage
-
SearchReadyMessage
-
SearchQueryMessage
-
SearchResultMessage