@vuepress-plume/plugin-search 1.0.0-rc.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,188 @@
1
+ <script lang="ts" setup>
2
+ import { toRef } from 'vue'
3
+ import type { SearchBoxLocales } from '../../shared/index.js'
4
+ import { useLocale } from '../composables/locale.js'
5
+
6
+ const props = defineProps<{
7
+ locales: SearchBoxLocales
8
+ }>()
9
+
10
+ const locale = useLocale(toRef(props.locales))
11
+ </script>
12
+
13
+ <template>
14
+ <button type="button" class="mini-search mini-search-button" :aria-label="locale.placeholder">
15
+ <span class="mini-search-button-container">
16
+ <svg class="mini-search-search-icon" width="20" height="20" viewBox="0 0 20 20" aria-label="search icon">
17
+ <path
18
+ d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z"
19
+ stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"
20
+ />
21
+ </svg>
22
+ <span class="mini-search-button-placeholder">{{ locale.placeholder }}</span>
23
+ </span>
24
+ <span class="mini-search-button-keys">
25
+ <kbd class="mini-search-button-key" />
26
+ <kbd class="mini-search-button-key">K</kbd>
27
+ </span>
28
+ </button>
29
+ </template>
30
+
31
+ <style>
32
+ .mini-search-button {
33
+ display: flex;
34
+ align-items: center;
35
+ justify-content: center;
36
+ width: 48px;
37
+ height: 55px;
38
+ padding: 0;
39
+ margin: 0;
40
+ background: transparent;
41
+ transition: border-color 0.25s, background-color 0.25s;
42
+ }
43
+
44
+ .mini-search-button:hover {
45
+ background: transparent;
46
+ }
47
+
48
+ .mini-search-button:focus {
49
+ outline: 1px dotted;
50
+ outline: 5px auto -webkit-focus-ring-color;
51
+ }
52
+
53
+ .mini-search-button:focus:not(:focus-visible) {
54
+ outline: none !important;
55
+ }
56
+
57
+ @media (min-width: 768px) {
58
+ .mini-search-button {
59
+ justify-content: flex-start;
60
+ width: 100%;
61
+ height: 40px;
62
+ padding: 0 10px 0 12px;
63
+ background-color: var(--vp-c-bg-alt);
64
+ border: 1px solid transparent;
65
+ border-radius: 8px;
66
+ }
67
+
68
+ .mini-search-button:hover {
69
+ background: var(--vp-c-bg-alt);
70
+ border-color: var(--vp-c-brand-1);
71
+ }
72
+ }
73
+
74
+ .mini-search-button .mini-search-button-container {
75
+ display: flex;
76
+ align-items: center;
77
+ }
78
+
79
+ .mini-search-button .mini-search-search-icon {
80
+ position: relative;
81
+ width: 16px;
82
+ height: 16px;
83
+ color: var(--vp-c-text-1);
84
+ fill: currentcolor;
85
+ transition: color 0.3s;
86
+ }
87
+
88
+ .mini-search-button:hover .mini-search-search-icon {
89
+ color: var(--vp-c-text-1);
90
+ }
91
+
92
+ @media (min-width: 768px) {
93
+ .mini-search-button .mini-search-search-icon {
94
+ top: 1px;
95
+ width: 14px;
96
+ height: 14px;
97
+ margin-right: 8px;
98
+ color: var(--vp-c-text-2);
99
+ }
100
+ }
101
+
102
+ .mini-search-button .mini-search-button-placeholder {
103
+ display: none;
104
+ padding: 0 16px 0 0;
105
+ margin-top: 2px;
106
+ font-size: 13px;
107
+ font-weight: 500;
108
+ color: var(--vp-c-text-2);
109
+ transition: color 0.3s;
110
+ }
111
+
112
+ .mini-search-button:hover .mini-search-button-placeholder {
113
+ color: var(--vp-c-text-1);
114
+ }
115
+
116
+ @media (min-width: 768px) {
117
+ .mini-search-button .mini-search-button-placeholder {
118
+ display: inline-block;
119
+ }
120
+ }
121
+
122
+ .mini-search-button .mini-search-button-keys {
123
+ display: none;
124
+ min-width: auto;
125
+
126
+ /* rtl:ignore */
127
+ direction: ltr;
128
+ }
129
+
130
+ @media (min-width: 768px) {
131
+ .mini-search-button .mini-search-button-keys {
132
+ display: flex;
133
+ align-items: center;
134
+ }
135
+ }
136
+
137
+ .mini-search-button .mini-search-button-key {
138
+ display: block;
139
+ width: auto;
140
+
141
+ /* rtl:end:ignore */
142
+ min-width: 0;
143
+ height: 22px;
144
+ padding-left: 6px;
145
+ margin: 2px 0 0;
146
+ font-family: var(--vp-font-family-base);
147
+ font-size: 12px;
148
+ font-weight: 500;
149
+ line-height: 22px;
150
+ border: 1px solid var(--vp-c-divider);
151
+
152
+ /* rtl:begin:ignore */
153
+ border-right: none;
154
+ border-radius: 4px 0 0 4px;
155
+ transition: color 0.3s, border-color 0.3s;
156
+ }
157
+
158
+ .mini-search-button .mini-search-button-key + .mini-search-button-key {
159
+ padding-right: 6px;
160
+ padding-left: 2px;
161
+
162
+ /* rtl:begin:ignore */
163
+ border-right: 1px solid var(--vp-c-divider);
164
+ border-left: none;
165
+ border-radius: 0 4px 4px 0;
166
+
167
+ /* rtl:end:ignore */
168
+ }
169
+
170
+ .mini-search-button .mini-search-button-key:first-child {
171
+ font-size: 0 !important;
172
+ }
173
+
174
+ .mini-search-button .mini-search-button-key:first-child::after {
175
+ font-size: 12px;
176
+ color: var(--mini-search-muted-color);
177
+ letter-spacing: normal;
178
+ content: "Ctrl";
179
+ }
180
+
181
+ .mac .mini-search-button .mini-search-button-key:first-child::after {
182
+ content: "\2318";
183
+ }
184
+
185
+ .mini-search-button .mini-search-button-key:first-child > * {
186
+ display: none;
187
+ }
188
+ </style>
@@ -0,0 +1,17 @@
1
+ <template>
2
+ <svg
3
+ width="18"
4
+ height="18"
5
+ viewBox="0 0 24 24"
6
+ aria-hidden="true"
7
+ >
8
+ <path
9
+ fill="none"
10
+ stroke="currentColor"
11
+ stroke-linecap="round"
12
+ stroke-linejoin="round"
13
+ stroke-width="2"
14
+ d="M19 12H5m7 7l-7-7l7-7"
15
+ />
16
+ </svg>
17
+ </template>
@@ -0,0 +1,17 @@
1
+ <template>
2
+ <svg
3
+ width="18"
4
+ height="18"
5
+ viewBox="0 0 24 24"
6
+ aria-hidden="true"
7
+ >
8
+ <path
9
+ fill="none"
10
+ stroke="currentColor"
11
+ stroke-linecap="round"
12
+ stroke-linejoin="round"
13
+ stroke-width="2"
14
+ d="M20 5H9l-7 7l7 7h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2Zm-2 4l-6 6m0-6l6 6"
15
+ />
16
+ </svg>
17
+ </template>
@@ -0,0 +1,19 @@
1
+ <template>
2
+ <svg
3
+ width="18"
4
+ height="18"
5
+ viewBox="0 0 24 24"
6
+ aria-hidden="true"
7
+ >
8
+ <g
9
+ fill="none"
10
+ stroke="currentColor"
11
+ stroke-linecap="round"
12
+ stroke-linejoin="round"
13
+ stroke-width="2"
14
+ >
15
+ <circle cx="11" cy="11" r="8" />
16
+ <path d="m21 21l-4.35-4.35" />
17
+ </g>
18
+ </svg>
19
+ </template>
@@ -0,0 +1 @@
1
+ export * from './searchIndex.js';
@@ -0,0 +1 @@
1
+ export * from './searchIndex.js';
@@ -0,0 +1,18 @@
1
+ import type { MaybeRef } from 'vue';
2
+ import type { SearchBoxLocales } from '../../shared/index.js';
3
+ export declare function useLocale(locales: MaybeRef<SearchBoxLocales>): import("vue").ComputedRef<Partial<{
4
+ placeholder: string;
5
+ buttonText: string;
6
+ resetButtonTitle: string;
7
+ backButtonTitle: string;
8
+ noResultsText: string;
9
+ footer: {
10
+ selectText: string;
11
+ selectKeyAriaLabel: string;
12
+ navigateText: string;
13
+ navigateUpKeyAriaLabel: string;
14
+ navigateDownKeyAriaLabel: string;
15
+ closeText: string;
16
+ closeKeyAriaLabel: string;
17
+ };
18
+ }>>;
@@ -0,0 +1,25 @@
1
+ import { useRouteLocale } from 'vuepress/client';
2
+ import { computed, toRef } from 'vue';
3
+ const defaultLocales = {
4
+ '/': {
5
+ placeholder: 'Search',
6
+ resetButtonTitle: 'Reset search',
7
+ backButtonTitle: 'Close search',
8
+ noResultsText: 'No results for',
9
+ footer: {
10
+ selectText: 'to select',
11
+ selectKeyAriaLabel: 'enter',
12
+ navigateText: 'to navigate',
13
+ navigateUpKeyAriaLabel: 'up arrow',
14
+ navigateDownKeyAriaLabel: 'down arrow',
15
+ closeText: 'to close',
16
+ closeKeyAriaLabel: 'escape',
17
+ },
18
+ },
19
+ };
20
+ export function useLocale(locales) {
21
+ const localesRef = toRef(locales);
22
+ const routeLocale = useRouteLocale();
23
+ const locale = computed(() => localesRef.value[routeLocale.value] ?? defaultLocales[routeLocale.value] ?? defaultLocales['/']);
24
+ return locale;
25
+ }
@@ -0,0 +1,3 @@
1
+ export declare function useSearchIndex(): import("vue").ShallowRef<Record<string, () => Promise<{
2
+ default: string;
3
+ }>>>;
@@ -0,0 +1,14 @@
1
+ import { searchIndex } from '@internal/minisearchIndex';
2
+ import { shallowRef } from 'vue';
3
+ const searchIndexData = shallowRef(searchIndex);
4
+ export function useSearchIndex() {
5
+ return searchIndexData;
6
+ }
7
+ if (__VUEPRESS_DEV__ && (import.meta.webpackHot || import.meta.hot)) {
8
+ __VUE_HMR_RUNTIME__.updateSearchIndex = (data) => {
9
+ searchIndexData.value = data;
10
+ };
11
+ __VUE_HMR_RUNTIME__.updateSearchIndex = (data) => {
12
+ searchIndexData.value = data;
13
+ };
14
+ }
@@ -0,0 +1,3 @@
1
+ import type { ClientConfig } from 'vuepress/client';
2
+ declare const _default: ClientConfig;
3
+ export default _default;
@@ -0,0 +1,14 @@
1
+ import { defineClientConfig } from 'vuepress/client';
2
+ import { h } from 'vue';
3
+ import Search from './components/Search.vue';
4
+ const locales = __SEARCH_LOCALES__;
5
+ const searchOptions = __SEARCH_OPTIONS__;
6
+ export default defineClientConfig({
7
+ enhance({ app }) {
8
+ app.component('SearchBox', props => h(Search, {
9
+ locales,
10
+ options: searchOptions,
11
+ ...props,
12
+ }));
13
+ },
14
+ });
@@ -0,0 +1,3 @@
1
+ import SearchBox from './components/Search.vue';
2
+ import { useSearchIndex } from './composables/index.js';
3
+ export { SearchBox, useSearchIndex, };
@@ -0,0 +1,3 @@
1
+ import SearchBox from './components/Search.vue';
2
+ import { useSearchIndex } from './composables/index.js';
3
+ export { SearchBox, useSearchIndex, };
@@ -0,0 +1,20 @@
1
+ declare module '*.vue' {
2
+ import type { ComponentOptions } from 'vue'
3
+
4
+ const comp: ComponentOptions
5
+ export default comp
6
+ }
7
+
8
+ declare module '@internal/minisearchIndex' {
9
+ const searchIndex: Record<string, () => Promise<{ default: string }>>
10
+ export {
11
+ searchIndex,
12
+ }
13
+ }
14
+
15
+ declare module 'mark.js/src/vanilla.js' {
16
+ import type Mark from 'mark.js'
17
+
18
+ const mark: typeof Mark
19
+ export default mark
20
+ }
@@ -0,0 +1,9 @@
1
+ export declare class LRUCache<K, V> {
2
+ private max;
3
+ private cache;
4
+ constructor(max?: number);
5
+ get(key: K): V | undefined;
6
+ set(key: K, val: V): void;
7
+ first(): K | undefined;
8
+ clear(): void;
9
+ }
@@ -0,0 +1,33 @@
1
+ // adapted from https://stackoverflow.com/a/46432113/11613622
2
+ export class LRUCache {
3
+ max;
4
+ cache;
5
+ constructor(max = 10) {
6
+ this.max = max;
7
+ this.cache = new Map();
8
+ }
9
+ get(key) {
10
+ const item = this.cache.get(key);
11
+ if (item !== undefined) {
12
+ // refresh key
13
+ this.cache.delete(key);
14
+ this.cache.set(key, item);
15
+ }
16
+ return item;
17
+ }
18
+ set(key, val) {
19
+ // refresh key
20
+ if (this.cache.has(key))
21
+ this.cache.delete(key);
22
+ // evict oldest
23
+ else if (this.cache.size === this.max)
24
+ this.cache.delete(this.first());
25
+ this.cache.set(key, val);
26
+ }
27
+ first() {
28
+ return this.cache.keys().next().value;
29
+ }
30
+ clear() {
31
+ this.cache.clear();
32
+ }
33
+ }
@@ -0,0 +1,4 @@
1
+ import { searchPlugin } from './searchPlugin.js';
2
+ export { prepareSearchIndex } from './prepareSearchIndex.js';
3
+ export * from '../shared/index.js';
4
+ export { searchPlugin, };
@@ -0,0 +1,4 @@
1
+ import { searchPlugin } from './searchPlugin.js';
2
+ export { prepareSearchIndex } from './prepareSearchIndex.js';
3
+ export * from '../shared/index.js';
4
+ export { searchPlugin, };
@@ -0,0 +1,10 @@
1
+ import type { App } from 'vuepress/core';
2
+ import type { SearchOptions, SearchPluginOptions } from '../shared/index.js';
3
+ export interface SearchIndexOptions {
4
+ app: App;
5
+ searchOptions: SearchOptions;
6
+ isSearchable: SearchPluginOptions['isSearchable'];
7
+ }
8
+ export declare function prepareSearchIndex({ app, isSearchable, searchOptions, }: SearchIndexOptions): Promise<void>;
9
+ export declare function onSearchIndexUpdated(filepath: string, { app, isSearchable, searchOptions, }: SearchIndexOptions): Promise<void>;
10
+ export declare function onSearchIndexRemoved(filepath: string, { app, isSearchable, searchOptions, }: SearchIndexOptions): Promise<void>;
@@ -0,0 +1,140 @@
1
+ import MiniSearch from 'minisearch';
2
+ import pMap from 'p-map';
3
+ const SEARCH_INDEX_DIR = 'internal/minisearchIndex/';
4
+ const indexByLocales = new Map();
5
+ const indexCache = new Map();
6
+ function getIndexByLocale(locale, options) {
7
+ let index = indexByLocales.get(locale);
8
+ if (!index) {
9
+ index = new MiniSearch({
10
+ fields: ['title', 'titles', 'text'],
11
+ storeFields: ['title', 'titles'],
12
+ ...options.miniSearch?.options,
13
+ });
14
+ indexByLocales.set(locale, index);
15
+ }
16
+ return index;
17
+ }
18
+ function getIndexCache(filepath) {
19
+ let index = indexCache.get(filepath);
20
+ if (!index) {
21
+ index = [];
22
+ indexCache.set(filepath, index);
23
+ }
24
+ return index;
25
+ }
26
+ export async function prepareSearchIndex({ app, isSearchable, searchOptions, }) {
27
+ const pages = isSearchable ? app.pages.filter(isSearchable) : app.pages;
28
+ await pMap(pages, p => indexFile(p, searchOptions), {
29
+ concurrency: 64,
30
+ });
31
+ await writeTemp(app);
32
+ }
33
+ export async function onSearchIndexUpdated(filepath, { app, isSearchable, searchOptions, }) {
34
+ const pages = isSearchable ? app.pages.filter(isSearchable) : app.pages;
35
+ if (pages.some(p => p.filePathRelative?.endsWith(filepath))) {
36
+ await indexFile(app.pages.find(p => p.filePathRelative?.endsWith(filepath)), searchOptions);
37
+ await writeTemp(app);
38
+ }
39
+ }
40
+ export async function onSearchIndexRemoved(filepath, { app, isSearchable, searchOptions, }) {
41
+ const pages = isSearchable ? app.pages.filter(isSearchable) : app.pages;
42
+ if (pages.some(p => p.filePathRelative?.endsWith(filepath))) {
43
+ const page = app.pages.find(p => p.filePathRelative?.endsWith(filepath));
44
+ const fileId = page.path;
45
+ const locale = page.pathLocale;
46
+ const index = getIndexByLocale(locale, searchOptions);
47
+ const cache = getIndexCache(fileId);
48
+ index.removeAll(cache);
49
+ await writeTemp(app);
50
+ }
51
+ }
52
+ async function writeTemp(app) {
53
+ const records = [];
54
+ for (const [locale] of indexByLocales) {
55
+ const index = indexByLocales.get(locale);
56
+ const localeName = locale.replace(/^\/|\/$/g, '').replace(/\//g, '_') || 'default';
57
+ const filename = `searchBox-${localeName}.js`;
58
+ records.push(`${JSON.stringify(locale)}: () => import('@${SEARCH_INDEX_DIR}${filename}')`);
59
+ await app.writeTemp(`${SEARCH_INDEX_DIR}${filename}`, `export default ${JSON.stringify(JSON.stringify(index) ?? {})}`);
60
+ }
61
+ await app.writeTemp(`${SEARCH_INDEX_DIR}index.js`, `export const searchIndex = {${records.join(',')}}${app.env.isDev ? `\n${genHmrCode('searchIndex')}` : ''}`);
62
+ }
63
+ async function indexFile(page, options) {
64
+ // get file metadata
65
+ const fileId = page.path;
66
+ const locale = page.pathLocale;
67
+ const index = getIndexByLocale(locale, options);
68
+ const cache = getIndexCache(fileId);
69
+ // retrieve file and split into "sections"
70
+ const html = page.contentRendered;
71
+ const sections = splitPageIntoSections(html);
72
+ if (cache && cache.length)
73
+ index.removeAll(cache);
74
+ // add sections to the locale index
75
+ for await (const section of sections) {
76
+ if (!section || !(section.text || section.titles))
77
+ break;
78
+ const { anchor, text, titles } = section;
79
+ const id = anchor ? [fileId, anchor].join('#') : fileId;
80
+ const item = {
81
+ id,
82
+ text,
83
+ title: titles.at(-1),
84
+ titles: titles.slice(0, -1),
85
+ };
86
+ index.add(item);
87
+ cache.push(item);
88
+ }
89
+ }
90
+ const headingRegex = /<h(\d*).*?>(<a.*? href="#.*?".*?>.*?<\/a>)<\/h\1>/gi;
91
+ const headingContentRegex = /<a.*? href="#(.*?)".*?>(.*?)<\/a>/i;
92
+ /**
93
+ * Splits HTML into sections based on headings
94
+ */
95
+ function* splitPageIntoSections(html) {
96
+ const result = html.split(headingRegex);
97
+ result.shift();
98
+ let parentTitles = [];
99
+ for (let i = 0; i < result.length; i += 3) {
100
+ const level = Number.parseInt(result[i]) - 1;
101
+ const heading = result[i + 1];
102
+ const headingResult = headingContentRegex.exec(heading);
103
+ const title = clearHtmlTags(headingResult?.[2] ?? '').trim();
104
+ const anchor = headingResult?.[1] ?? '';
105
+ const content = result[i + 2];
106
+ if (!title || !content)
107
+ continue;
108
+ const titles = parentTitles.slice(0, level);
109
+ titles[level] = title;
110
+ yield { anchor, titles, text: getSearchableText(content) };
111
+ if (level === 0)
112
+ parentTitles = [title];
113
+ else
114
+ parentTitles[level] = title;
115
+ }
116
+ }
117
+ function getSearchableText(content) {
118
+ content = clearHtmlTags(content);
119
+ return content;
120
+ }
121
+ function clearHtmlTags(str) {
122
+ return str.replace(/<[^>]*>/g, '');
123
+ }
124
+ function genHmrCode(m) {
125
+ const func = `update${m[0].toUpperCase()}${m.slice(1)}`;
126
+ return `
127
+ if (import.meta.webpackHot) {
128
+ import.meta.webpackHot.accept()
129
+ if (__VUE_HMR_RUNTIME__.${m}) {
130
+ __VUE_HMR_RUNTIME__.${func}(${m})
131
+ }
132
+ }
133
+
134
+ if (import.meta.hot) {
135
+ import.meta.hot.accept(({ ${m} }) => {
136
+ __VUE_HMR_RUNTIME__.${func}(${m})
137
+ })
138
+ }
139
+ `;
140
+ }
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from 'vuepress/core';
2
+ import type { SearchPluginOptions } from '../shared/index.js';
3
+ export declare function searchPlugin({ locales, isSearchable, ...searchOptions }?: SearchPluginOptions): Plugin;
@@ -0,0 +1,37 @@
1
+ import chokidar from 'chokidar';
2
+ import { getDirname, path } from 'vuepress/utils';
3
+ import { addViteOptimizeDepsInclude } from '@vuepress/helper';
4
+ import { onSearchIndexRemoved, onSearchIndexUpdated, prepareSearchIndex } from './prepareSearchIndex.js';
5
+ const __dirname = getDirname(import.meta.url);
6
+ export function searchPlugin({ locales = {}, isSearchable, ...searchOptions } = {}) {
7
+ return app => ({
8
+ name: '@vuepress-plume/plugin-search',
9
+ clientConfigFile: path.resolve(__dirname, '../client/config.js'),
10
+ define: {
11
+ __SEARCH_LOCALES__: locales,
12
+ __SEARCH_OPTIONS__: searchOptions,
13
+ },
14
+ extendsBundlerOptions(bundlerOptions) {
15
+ addViteOptimizeDepsInclude(bundlerOptions, app, ['mark.js/src/vanilla.js', '@vueuse/integrations/useFocusTrap', 'minisearch']);
16
+ },
17
+ onPrepared: async (app) => {
18
+ await prepareSearchIndex({ app, isSearchable, searchOptions });
19
+ },
20
+ onWatched: async (app, watchers) => {
21
+ const searchIndexWatcher = chokidar.watch('pages/**/*.js', {
22
+ cwd: app.dir.temp(),
23
+ ignoreInitial: true,
24
+ });
25
+ searchIndexWatcher.on('add', (filepath) => {
26
+ onSearchIndexUpdated(filepath, { app, isSearchable, searchOptions });
27
+ });
28
+ searchIndexWatcher.on('change', (filepath) => {
29
+ onSearchIndexUpdated(filepath, { app, isSearchable, searchOptions });
30
+ });
31
+ searchIndexWatcher.on('unlink', (filepath) => {
32
+ onSearchIndexRemoved(filepath, { app, isSearchable, searchOptions });
33
+ });
34
+ watchers.push(searchIndexWatcher);
35
+ },
36
+ });
37
+ }
@@ -0,0 +1,38 @@
1
+ import type { LocaleConfig, Page } from 'vuepress/core';
2
+ import type { Options as MiniSearchOptions } from 'minisearch';
3
+ export type SearchBoxLocales = LocaleConfig<{
4
+ placeholder: string;
5
+ buttonText: string;
6
+ resetButtonTitle: string;
7
+ backButtonTitle: string;
8
+ noResultsText: string;
9
+ footer: {
10
+ selectText: string;
11
+ selectKeyAriaLabel: string;
12
+ navigateText: string;
13
+ navigateUpKeyAriaLabel: string;
14
+ navigateDownKeyAriaLabel: string;
15
+ closeText: string;
16
+ closeKeyAriaLabel: string;
17
+ };
18
+ }>;
19
+ export interface SearchPluginOptions extends SearchOptions {
20
+ locales?: SearchBoxLocales;
21
+ isSearchable?: (page: Page) => boolean;
22
+ }
23
+ export interface SearchOptions {
24
+ /**
25
+ * @default false
26
+ */
27
+ disableQueryPersistence?: boolean;
28
+ miniSearch?: {
29
+ /**
30
+ * @see https://lucaong.github.io/minisearch/modules/_minisearch_.html#options
31
+ */
32
+ options?: Pick<MiniSearchOptions, 'extractField' | 'tokenize' | 'processTerm'>;
33
+ /**
34
+ * @see https://lucaong.github.io/minisearch/modules/_minisearch_.html#searchoptions-1
35
+ */
36
+ searchOptions?: MiniSearchOptions['searchOptions'];
37
+ };
38
+ }
@@ -0,0 +1 @@
1
+ export {};