جستجو
جستجوی محلی
ویتپرس از جستجوی متن کامل نامتقارن با استفاده از یک فهرست در مرورگر با تشکر از minisearch پشتیبانی میکند. برای فعالسازی این ویژگی، کافی است گزینه themeConfig.search.provider را به 'local' در فایل .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 استفاده کنید.
بینالمللیسازی
میتوانید با استفاده از تنظیماتی مانند این برای جستجوی چندزبانه استفاده کنید:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
locales: {
fa: { // اگر می خواهید زبان پیش فرض را ترجمه کنید، این را `root` قرار دهید
translations: {
button: {
buttonText: 'جستجو',
buttonAriaLabel: 'جستجو'
},
modal: {
displayDetails: 'نمایش فهرست کامل',
resetButtonTitle: 'بازنشانی جستجو',
backButtonTitle: 'بستن جستجو',
noResultsText: 'نتیجه ای یافت نشد',
footer: {
selectText: 'انتخاب',
selectKeyAriaLabel: 'Enter',
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-async')} md
*/
async _render(src, env, md) {
// رشته HTML را برمی گرداند
}
}
}
}
})این تابع از دادههای سایت سمت کلاینت پاک خواهد شد، بنابراین شما میتوانید از APIهای Node.js در آن استفاده کنید.
مثال: استثنای صفحات از جستجو
میتوانید با اضافه کردن search: false به frontmatter صفحه، صفحات را از جستجو استثنا دهید. به طور جایگزین:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
async _render(src, env, md) {
const html = await md.renderAsync(src, env)
if (env.frontmatter?.search === false) return ''
if (env.relativePath.startsWith('some/path')) return ''
return html
}
}
}
}
})توجه
در صورت ارائه تابع _render سفارشی، باید خودتان بررسی کنید که آیا frontmatter search: false را مدیریت میکند یا خیر. همچنین، شی env قبل از فراخوانی md.renderAsync کاملاً پر نمیشود، بنابراین هر بررسیای روی ویژگیهای اختیاری env مانند frontmatter باید بعد از آن انجام شود.
مثال: تبدیل محتوا - افزودن لینکهای صفحه
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
async _render(src, env, md) {
const html = await md.renderAsync(src, env)
if (env.frontmatter?.title)
return (await md.renderAsync(`# ${env.frontmatter.title}`)) + html
return html
}
}
}
}
})جستجوی Algolia
ویتپرس از جستجو در سایت مستندات شما با استفاده از Algolia DocSearch پشتیبانی میکند. به راهنمای شروع کار آنها مراجعه کنید. در فایل .vitepress/config.ts شما نیاز دارید که حداقل موارد زیر را فراهم کنید تا کار کند:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...'
}
}
}
})بینالمللیسازی
میتوانید با استفاده از تنظیماتی مانند این برای جستجوی چندزبانه استفاده کنید:
برای باز کردن کلیک کنید
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...',
locales: {
zh: {
translations: {
button: {
buttonText: '搜索',
buttonAriaLabel: '搜索'
},
modal: {
searchBox: {
clearButtonTitle: '清除',
clearButtonAriaLabel: '清除查询',
closeButtonText: '关闭',
closeButtonAriaLabel: '关闭',
placeholderText: '搜索文档或向 AI 提问',
placeholderTextAskAi: '再问一个问题...',
placeholderTextAskAiStreaming: '正在回答...',
searchInputLabel: '搜索',
backToKeywordSearchButtonText: '返回关键词搜索',
backToKeywordSearchButtonAriaLabel: '返回关键词搜索',
newConversationPlaceholder: '提问',
conversationHistoryTitle: '我的对话历史',
startNewConversationText: '开始新的对话',
viewConversationHistoryText: '对话历史',
threadDepthErrorPlaceholder: '对话已达上限'
},
newConversation: {
newConversationTitle: '我今天能帮你什么?',
newConversationDescription:
'我会搜索你的文档,快速帮你找到设置指南、功能细节和故障排除提示。'
},
footer: {
selectText: '选择',
submitQuestionText: '提交问题',
selectKeyAriaLabel: '回车键',
navigateText: '导航',
navigateUpKeyAriaLabel: '向上箭头',
navigateDownKeyAriaLabel: '向下箭头',
closeText: '关闭',
backToSearchText: '返回搜索',
closeKeyAriaLabel: 'Esc 键',
poweredByText: '由…提供支持'
},
errorScreen: {
titleText: '无法获取结果',
helpText: '你可能需要检查网络连接。'
},
startScreen: {
recentSearchesTitle: '最近',
noRecentSearchesText: '暂无最近搜索',
saveRecentSearchButtonTitle: '保存此搜索',
removeRecentSearchButtonTitle: '从历史记录中移除此搜索',
favoriteSearchesTitle: '收藏',
removeFavoriteSearchButtonTitle: '从收藏中移除此搜索',
recentConversationsTitle: '最近对话',
removeRecentConversationButtonTitle: '从历史记录中移除此对话'
},
noResultsScreen: {
noResultsText: '未找到相关结果',
suggestedQueryText: '尝试搜索',
reportMissingResultsText: '认为此查询应该有结果?',
reportMissingResultsLinkText: '告诉我们。'
},
resultsScreen: {
askAiPlaceholder: '询问 AI:',
noResultsAskAiPlaceholder: '文档里没找到?让 Ask AI 帮忙:'
},
askAiScreen: {
disclaimerText: '回答由 AI 生成,可能会出错。请核实。',
relatedSourcesText: '相关来源',
thinkingText: '思考中...',
copyButtonText: '复制',
copyButtonCopiedText: '已复制!',
copyButtonTitle: '复制',
likeButtonTitle: '喜欢',
dislikeButtonTitle: '不喜欢',
thanksForFeedbackText: '感谢你的反馈!',
preToolCallText: '搜索中...',
duringToolCallText: '搜索中...',
afterToolCallText: '已搜索',
stoppedStreamingText: '你已停止此回复',
errorTitleText: '聊天错误',
threadDepthExceededMessage: '为保持回答准确,此对话已关闭。',
startNewConversationButtonText: '开始新的对话'
}
}
},
askAi: {
sidePanel: {
button: {
translations: {
buttonText: '询问 AI',
buttonAriaLabel: '询问 AI'
}
},
panel: {
translations: {
header: {
title: '询问 AI',
conversationHistoryTitle: '我的对话历史',
newConversationText: '开始新的对话',
viewConversationHistoryText: '对话历史'
},
promptForm: {
promptPlaceholderText: '提问',
promptAnsweringText: '正在回答...',
promptAskAnotherQuestionText: '再问一个问题',
promptDisclaimerText: '回答由 AI 生成,可能会出错。',
promptLabelText: '按回车发送,Shift+回车换行。',
promptAriaLabelText: '问题输入'
},
conversationScreen: {
preToolCallText: '搜索中...',
searchingText: '搜索中...',
toolCallResultText: '已搜索',
conversationDisclaimer:
'回答由 AI 生成,可能会出错。请核实。',
reasoningText: '推理中...',
thinkingText: '思考中...',
relatedSourcesText: '相关来源',
stoppedStreamingText: '你已停止此回复',
copyButtonText: '复制',
copyButtonCopiedText: '已复制!',
likeButtonTitle: '喜欢',
dislikeButtonTitle: '不喜欢',
thanksForFeedbackText: '感谢你的反馈!',
errorTitleText: '聊天错误'
},
newConversationScreen: {
titleText: '我今天能帮你什么?',
introductionText:
'我会搜索你的文档,快速帮你找到设置指南、功能细节和故障排除提示。'
},
logo: {
poweredByText: '由…提供支持'
}
}
}
}
}
}
}
}
}
}
})برای اطلاعات بیشتر به مستندات رسمی Algolia مراجعه کنید. برای شروع سریعتر، میتوانید ترجمههای استفادهشده در این سایت را از مخزن GitHub ما کپی کنید.
پشتیبانی Algolia Ask AI
برای فعالسازی Ask AI کافی است گزینه askAi را اضافه کنید:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...',
// askAi: "شناسه-دستیار-شما"
// یا
askAi: {
// حداقل باید assistantId دریافت شده از Algolia را ارائه کنید
assistantId: 'XXXYYY',
// بازنویسی های اختیاری — اگر حذف شوند، مقادیر appId/apiKey/indexName سطح بالا دوباره استفاده می شوند
// apiKey: '...',
// appId: '...',
// indexName: '...'
}
}
}
}
})نکته
اگر فقط به جستجوی کلمات کلیدی نیاز دارید، askAi را اضافه نکنید.
پنل کناری Ask AI
DocSearch v4.5+ از پنل کناری Ask AI اختیاری پشتیبانی میکند. وقتی فعال باشد، به طور پیشفرض میتوان آن را با Ctrl/Cmd+I باز کرد. مرجع API پنل کناری شامل لیست کامل گزینهها است.
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...',
askAi: {
assistantId: 'XXXYYY',
sidePanel: {
// آینه API @docsearch/sidepanel-js SidepanelProps
panel: {
variant: 'floating', // یا 'inline'
side: 'right',
width: '360px',
expandedWidth: '580px',
suggestedQuestions: true
}
}
}
}
}
}
})اگر نیاز به غیرفعال کردن میانبر صفحهکلید دارید، از گزینه keyboardShortcuts پنل کناری استفاده کنید:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...',
askAi: {
assistantId: 'XXXYYY',
sidePanel: {
keyboardShortcuts: {
'Ctrl/Cmd+I': false
}
}
}
}
}
}
})حالت (auto / sidePanel / hybrid / modal)
میتوانید به صورت اختیاری نحوه ادغام جستجوی کلمات کلیدی و Ask AI در VitePress را کنترل کنید:
mode: 'auto'(پیشفرض): وقتی جستجوی کلمات کلیدی پیکربندی شده باشدhybridرا استنباط میکند، در غیر این صورت وقتی پنل کناری Ask AI پیکربندی شده باشدsidePanelرا استنباط میکند.mode: 'sidePanel': فقط پنل کناری را اعمال میکند (دکمه جستجوی کلمات کلیدی را پنهان میکند).mode: 'hybrid': مودال جستجوی کلمات کلیدی + پنل کناری Ask AI را فعال میکند (نیاز به پیکربندی جستجوی کلمات کلیدی دارد).mode: 'modal': Ask AI را درون مودال DocSearch نگه میدارد (حتی اگر پنل کناری را پیکربندی کرده باشید).
فقط Ask AI (بدون جستجوی کلمات کلیدی)
اگر میخواهید فقط پنل کناری Ask AI را استفاده کنید، میتوانید پیکربندی جستجوی کلمات کلیدی سطح بالا را حذف کرده و اعتبارنامهها را در askAi ارائه دهید:
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
mode: 'sidePanel',
askAi: {
assistantId: 'XXXYYY',
appId: '...',
apiKey: '...',
indexName: '...',
sidePanel: true
}
}
}
}
})پیکربندی Crawler
در اینجا یک پیکربندی نمونه بر اساس آنچه که این سایت استفاده میکند آمده است:
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: 'section.has-active div h2',
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'
}
}
})