feat(search): support `minisearch` customization (#2576)

Co-authored-by: Divyansh Singh <40380293+brc-dd@users.noreply.github.com>
pull/2588/head
烽宁 1 year ago committed by GitHub
parent e8074e60ec
commit 9fee5542cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,3 +1,7 @@
---
outline: deep
---
# Search
## Local Search
@ -58,6 +62,38 @@ export default defineConfig({
})
```
### miniSearch options
You can configure MiniSearch like this:
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
miniSearch: {
/**
* @type {Pick<import('minisearch').Options, 'extractField' | 'tokenize' | 'processTerm'>}
*/
options: { /* ... */ },
/**
* @type {import('minisearch').SearchOptions}
* @default
* { fuzzy: 0.2, prefix: true, boost: { title: 4, text: 2, titles: 1 } }
*/
searchOptions: { /* ... */ }
}
}
}
}
})
```
Learn more in [MiniSearch docs](https://lucaong.github.io/minisearch/classes/_minisearch_.minisearch.html).
## Algolia Search
VitePress supports searching your docs site using [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch). Refer their getting started guide. In your `.vitepress/config.ts` you'll need to provide at least the following to make it work:

@ -80,8 +80,12 @@ const searchIndex = computedAsync(async () =>
searchOptions: {
fuzzy: 0.2,
prefix: true,
boost: { title: 4, text: 2, titles: 1 }
}
boost: { title: 4, text: 2, titles: 1 },
...(theme.value.search?.provider === 'local' &&
theme.value.search.options?.miniSearch?.searchOptions)
},
...(theme.value.search?.provider === 'local' &&
theme.value.search.options?.miniSearch?.options)
}
)
)
@ -396,8 +400,16 @@ function formMarkRegex(terms: Set<string>) {
<div class="backdrop" @click="$emit('close')" />
<div class="shell">
<form class="search-bar" @pointerup="onSearchBarClick($event)" @submit.prevent="">
<label :title="placeholder" id="localsearch-label" for="localsearch-input">
<form
class="search-bar"
@pointerup="onSearchBarClick($event)"
@submit.prevent=""
>
<label
:title="placeholder"
id="localsearch-label"
for="localsearch-input"
>
<svg
class="search-icon"
width="18"
@ -454,7 +466,9 @@ function formMarkRegex(terms: Set<string>) {
class="toggle-layout-button"
:class="{ 'detailed-list': showDetailedList }"
:title="$t('modal.displayDetails')"
@click="selectedIndex > -1 && (showDetailedList = !showDetailedList)"
@click="
selectedIndex > -1 && (showDetailedList = !showDetailedList)
"
>
<svg
width="18"
@ -527,7 +541,11 @@ function formMarkRegex(terms: Set<string>) {
<div>
<div class="titles">
<span class="title-icon">#</span>
<span v-for="(t, index) in p.titles" :key="index" class="title">
<span
v-for="(t, index) in p.titles"
:key="index"
class="title"
>
<span class="text" v-html="t" />
<svg width="18" height="18" viewBox="0 0 24 24">
<path

@ -1,12 +1,12 @@
import path from 'node:path'
import type { Plugin, ViteDevServer } from 'vite'
import MiniSearch from 'minisearch'
import fs from 'fs-extra'
import _debug from 'debug'
import fs from 'fs-extra'
import MiniSearch from 'minisearch'
import path from 'path'
import type { Plugin, ViteDevServer } from 'vite'
import type { SiteConfig } from '../config'
import type { MarkdownEnv } from '../markdown'
import { createMarkdownRenderer } from '../markdown'
import { resolveSiteDataByRoute, slash } from '../shared'
import { resolveSiteDataByRoute, slash, type DefaultTheme } from '../shared'
const debug = _debug('vitepress:local-search')
@ -21,7 +21,7 @@ interface IndexObject {
}
export async function localSearchPlugin(
siteConfig: SiteConfig
siteConfig: SiteConfig<DefaultTheme.Config>
): Promise<Plugin> {
if (siteConfig.site.themeConfig?.search?.provider !== 'local') {
return {
@ -63,7 +63,9 @@ export async function localSearchPlugin(
if (!index) {
index = new MiniSearch<IndexObject>({
fields: ['title', 'titles', 'text'],
storeFields: ['title', 'titles']
storeFields: ['title', 'titles'],
...(siteConfig.site.themeConfig?.search?.provider === 'local' &&
siteConfig.site.themeConfig.search.options?.miniSearch?.options)
})
indexByLocales.set(locale, index)
}

@ -1,4 +1,5 @@
import { type ComputedRef, type Ref } from 'vue'
import type { Options as MiniSearchOptions } from 'minisearch'
import type { ComputedRef, Ref } from 'vue'
import type { DocSearchProps } from './docsearch.js'
import type { LocalSearchTranslations } from './local-search.js'
import type { PageData } from './shared.js'
@ -335,6 +336,20 @@ export namespace DefaultTheme {
translations?: LocalSearchTranslations
locales?: Record<string, Partial<Omit<LocalSearchOptions, 'locales'>>>
miniSearch?: {
/**
* @see https://lucaong.github.io/minisearch/modules/_minisearch_.html#options
*/
options?: Pick<
MiniSearchOptions,
'extractField' | 'tokenize' | 'processTerm'
>
/**
* @see https://lucaong.github.io/minisearch/modules/_minisearch_.html#searchoptions-1
*/
searchOptions?: MiniSearchOptions['searchOptions']
}
}
// algolia -------------------------------------------------------------------

Loading…
Cancel
Save