13 KiB
outline |
---|
deep |
Поиск
Локальный поиск
VitePress поддерживает нечёткий полнотекстовый поиск с использованием внутрибраузерного индекса благодаря MiniSearch. Чтобы включить эту функцию, просто установите значение 'local'
для опции themeConfig.search.provider
в файле .vitepress/config.ts
:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local'
}
}
})
Пример результата:
В качестве альтернативы можно использовать Algolia DocSearch или некоторые плагины сообщества, например https://www.npmjs.com/package/vitepress-plugin-search или https://www.npmjs.com/package/vitepress-plugin-pagefind.
i18n
Пример конфигурации для использования многоязычного поиска:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
locales: {
ru: { // используйте ключ `root`, если хотите перевести локаль по умолчанию
translations: {
button: {
buttonText: 'Поиск',
buttonAriaLabel: 'Поиск'
},
modal: {
displayDetails: 'Отобразить подробный список',
resetButtonTitle: 'Сбросить поиск',
backButtonTitle: 'Закрыть поиск',
noResultsText: 'Нет результатов по запросу',
footer: {
selectText: 'выбрать',
selectKeyAriaLabel: 'выбрать',
navigateText: 'перейти',
navigateUpKeyAriaLabel: 'стрелка вверх',
navigateDownKeyAriaLabel: 'стрелка вниз',
closeText: 'закрыть',
closeKeyAriaLabel: 'esc'
}
}
}
}
}
}
}
}
})
Параметры MiniSearch
Вы можете настроить MiniSearch следующим образом:
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: {
/* ... */
}
}
}
}
}
})
Подробнее в документации MiniSearch.
Пользовательский рендерер содержимого
Вы можете настроить функцию, используемую для отображения содержимого в формате Markdown перед его индексацией:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
/**
* @param {string} src
* @param {import('vitepress').MarkdownEnv} env
* @param {import('markdown-it')} md
*/
_render(src, env, md) {
// возвращаем html
}
}
}
}
})
Эта функция будет очищена от данных сайта на стороне клиента, поэтому вы можете использовать в ней API Node.js.
Пример: Исключение страниц из поиска
Вы можете исключить страницы из поиска, добавив search: false
в блок метаданных страницы. Альтернативный вариант:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
_render(src, env, md) {
const html = md.render(src, env)
if (env.frontmatter?.search === false) return ''
if (env.relativePath.startsWith('some/path')) return ''
return html
}
}
}
}
})
::: warning ПРИМЕЧАНИЕ
В случае, если предоставляется пользовательская функция _render
, вам нужно самостоятельно обработать заголовок search: false
. Кроме того, объект env
не будет полностью заполнен до вызова md.render
, поэтому любые проверки необязательных свойств env
, таких как frontmatter
, должны быть выполнены после этого.
:::
Пример: Преобразование содержимого - добавление якорей
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
_render(src, env, md) {
const html = md.render(src, env)
if (env.frontmatter?.title)
return md.render(`# ${env.frontmatter.title}`) + html
return html
}
}
}
}
})
Поиск Algolia
VitePress поддерживает поиск в вашей документации с помощью Algolia DocSearch. Обратитесь к руководству по началу работы. В файле .vitepress/config.ts
вам нужно будет указать, по крайней мере, следующее, чтобы всё работало:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...'
}
}
}
})
i18n
Пример конфигурации для использования многоязычного поиска:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...',
locales: {
ru: {
placeholder: 'Поиск в документации',
translations: {
button: {
buttonText: 'Поиск',
buttonAriaLabel: 'Поиск'
},
modal: {
searchBox: {
resetButtonTitle: 'Сбросить поиск',
resetButtonAriaLabel: 'Сбросить поиск',
cancelButtonText: 'Отменить поиск',
cancelButtonAriaLabel: 'Отменить поиск'
},
startScreen: {
recentSearchesTitle: 'История поиска',
noRecentSearchesText: 'Нет истории поиска',
saveRecentSearchButtonTitle: 'Сохранить в истории поиска',
removeRecentSearchButtonTitle: 'Удалить из истории поиска',
favoriteSearchesTitle: 'Избранное',
removeFavoriteSearchButtonTitle: 'Удалить из избранного'
},
errorScreen: {
titleText: 'Невозможно получить результаты',
helpText:
'Вам может потребоваться проверить подключение к Интернету'
},
footer: {
selectText: 'выбрать',
navigateText: 'перейти',
closeText: 'закрыть',
searchByText: 'поставщик поиска'
},
noResultsScreen: {
noResultsText: 'Нет результатов для',
suggestedQueryText: 'Вы можете попытаться узнать',
reportMissingResultsText:
'Считаете, что поиск даёт ложные результаты?',
reportMissingResultsLinkText:
'Нажмите на кнопку «Обратная связь»'
}
}
}
}
}
}
}
}
})
Эти параметры можно переопределить. Чтобы узнать о них больше, обратитесь к официальной документации Algolia.
Конфигурация поискового робота
Вот пример конфигурации, основанной на той, что используется на этом сайте:
new Crawler({
appId: '...',
apiKey: '...',
rateLimit: 8,
startUrls: ['https://vitepress.dev/'],
renderJavaScript: false,
sitemaps: [],
exclusionPatterns: [],
ignoreCanonicalTo: false,
discoveryPatterns: ['https://vitepress.dev/**'],
schedule: 'at 05:10 on Saturday',
actions: [
{
indexName: 'vitepress',
pathsToMatch: ['https://vitepress.dev/**'],
recordExtractor: ({ $, helpers }) => {
return helpers.docsearch({
recordProps: {
lvl1: '.content h1',
content: '.content p, .content li',
lvl0: {
selectors: '',
defaultValue: 'Documentation'
},
lvl2: '.content h2',
lvl3: '.content h3',
lvl4: '.content h4',
lvl5: '.content h5'
},
indexHeadings: true
})
}
}
],
initialIndexSettings: {
vitepress: {
attributesForFaceting: ['type', 'lang'],
attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'],
attributesToSnippet: ['content:10'],
camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'],
searchableAttributes: [
'unordered(hierarchy_radio_camel.lvl0)',
'unordered(hierarchy_radio.lvl0)',
'unordered(hierarchy_radio_camel.lvl1)',
'unordered(hierarchy_radio.lvl1)',
'unordered(hierarchy_radio_camel.lvl2)',
'unordered(hierarchy_radio.lvl2)',
'unordered(hierarchy_radio_camel.lvl3)',
'unordered(hierarchy_radio.lvl3)',
'unordered(hierarchy_radio_camel.lvl4)',
'unordered(hierarchy_radio.lvl4)',
'unordered(hierarchy_radio_camel.lvl5)',
'unordered(hierarchy_radio.lvl5)',
'unordered(hierarchy_radio_camel.lvl6)',
'unordered(hierarchy_radio.lvl6)',
'unordered(hierarchy_camel.lvl0)',
'unordered(hierarchy.lvl0)',
'unordered(hierarchy_camel.lvl1)',
'unordered(hierarchy.lvl1)',
'unordered(hierarchy_camel.lvl2)',
'unordered(hierarchy.lvl2)',
'unordered(hierarchy_camel.lvl3)',
'unordered(hierarchy.lvl3)',
'unordered(hierarchy_camel.lvl4)',
'unordered(hierarchy.lvl4)',
'unordered(hierarchy_camel.lvl5)',
'unordered(hierarchy.lvl5)',
'unordered(hierarchy_camel.lvl6)',
'unordered(hierarchy.lvl6)',
'content'
],
distinct: true,
attributeForDistinct: 'url',
customRanking: [
'desc(weight.pageRank)',
'desc(weight.level)',
'asc(weight.position)'
],
ranking: [
'words',
'filters',
'typo',
'attribute',
'proximity',
'exact',
'custom'
],
highlightPreTag: '<span class="algolia-docsearch-suggestion--highlight">',
highlightPostTag: '</span>',
minWordSizefor1Typo: 3,
minWordSizefor2Typos: 7,
allowTyposOnNumericTokens: false,
minProximity: 1,
ignorePlurals: true,
advancedSyntax: true,
attributeCriteriaComputedByMinProximity: true,
removeWordsIfNoResults: 'allOptional'
}
}
})