mirror of
https://github.com/pengzhanbo/vuepress-theme-plume.git
synced 2026-04-23 10:58:13 +08:00
chore: improve plugin-search code comments
This commit is contained in:
parent
7751e4c798
commit
552f0f5c32
@ -1,2 +1,9 @@
|
||||
/**
|
||||
* Composables Entry Point
|
||||
*
|
||||
* 组合式函数入口
|
||||
*
|
||||
* @module plugin-search/client/composables
|
||||
*/
|
||||
export * from './locale.js'
|
||||
export * from './searchIndex.js'
|
||||
|
||||
@ -1,8 +1,20 @@
|
||||
/**
|
||||
* Locale Composable for Search Plugin
|
||||
*
|
||||
* 搜索插件的语言组合式函数
|
||||
*
|
||||
* @module plugin-search/client/composables/locale
|
||||
*/
|
||||
import type { ComputedRef, MaybeRef } from 'vue'
|
||||
import type { SearchBoxLocales, SearchLocaleOptions } from '../../shared/index.js'
|
||||
import { computed, toRef } from 'vue'
|
||||
import { useRouteLocale } from 'vuepress/client'
|
||||
|
||||
/**
|
||||
* Default locale configuration for search.
|
||||
*
|
||||
* 搜索的默认语言配置。
|
||||
*/
|
||||
const defaultLocales: SearchBoxLocales = {
|
||||
'/': {
|
||||
placeholder: 'Search',
|
||||
@ -21,6 +33,17 @@ const defaultLocales: SearchBoxLocales = {
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Get locale configuration for the current route.
|
||||
*
|
||||
* 获取当前路由的语言配置。
|
||||
*
|
||||
* @param locales - Locale configuration object / 语言配置对象
|
||||
* @returns Computed ref to the current locale settings / 当前语言设置的计算引用
|
||||
* @example
|
||||
* const locale = useLocale(locales)
|
||||
* console.log(locale.value.placeholder) // 'Search' or localized value
|
||||
*/
|
||||
export function useLocale(locales: MaybeRef<SearchBoxLocales>): ComputedRef<Partial<SearchLocaleOptions>> {
|
||||
const localesRef = toRef(locales)
|
||||
const routeLocale = useRouteLocale()
|
||||
|
||||
@ -1,13 +1,44 @@
|
||||
/**
|
||||
* Search Index Composable for Search Plugin
|
||||
*
|
||||
* 搜索插件的搜索索引组合式函数
|
||||
*
|
||||
* @module plugin-search/client/composables/searchIndex
|
||||
*/
|
||||
import type { ShallowRef } from 'vue'
|
||||
import { searchIndex } from '@internal/minisearchIndex'
|
||||
import { shallowRef } from 'vue'
|
||||
|
||||
declare const __VUE_HMR_RUNTIME__: Record<string, any>
|
||||
|
||||
/**
|
||||
* Type definition for search index data.
|
||||
*
|
||||
* 搜索索引数据的类型定义。
|
||||
*
|
||||
* Maps locale paths to functions that load the corresponding search index.
|
||||
*
|
||||
* 将语言路径映射到加载相应搜索索引的函数。
|
||||
*/
|
||||
type SearchIndexData = Record<string, () => Promise<{ default: string }>>
|
||||
|
||||
/**
|
||||
* Reactive reference to the search index data.
|
||||
*
|
||||
* 搜索索引数据的响应式引用。
|
||||
*/
|
||||
const searchIndexData = shallowRef<SearchIndexData>(searchIndex)
|
||||
|
||||
/**
|
||||
* Get the search index data for all locales.
|
||||
*
|
||||
* 获取所有语言的搜索索引数据。
|
||||
*
|
||||
* @returns Shallow ref to the search index data / 搜索索引数据的浅层引用
|
||||
* @example
|
||||
* const indexData = useSearchIndex()
|
||||
* const localeIndex = await indexData.value['/zh/']()
|
||||
*/
|
||||
export function useSearchIndex(): ShallowRef<SearchIndexData> {
|
||||
return searchIndexData
|
||||
}
|
||||
|
||||
@ -1,3 +1,15 @@
|
||||
/**
|
||||
* VuePress Client Configuration for Search Plugin
|
||||
*
|
||||
* 搜索插件的 VuePress 客户端配置
|
||||
*
|
||||
* Registers the SearchBox component globally and provides locale and option
|
||||
* configuration to the search component.
|
||||
*
|
||||
* 全局注册 SearchBox 组件,并向搜索组件提供语言和选项配置。
|
||||
*
|
||||
* @module plugin-search/client/config
|
||||
*/
|
||||
import type { ClientConfig } from 'vuepress/client'
|
||||
import type { SearchBoxLocales, SearchOptions } from '../shared/index.js'
|
||||
import { h } from 'vue'
|
||||
|
||||
@ -1,3 +1,15 @@
|
||||
/**
|
||||
* VuePress Search Plugin - Client Side Entry
|
||||
*
|
||||
* VuePress 搜索插件 - 客户端入口
|
||||
*
|
||||
* Exports the SearchBox component and search index composable for use in
|
||||
* VuePress theme components.
|
||||
*
|
||||
* 导出 SearchBox 组件和搜索索引组合式函数,供 VuePress 主题组件使用。
|
||||
*
|
||||
* @module plugin-search/client
|
||||
*/
|
||||
import SearchBox from './components/Search.vue'
|
||||
import { useSearchIndex } from './composables/index.js'
|
||||
|
||||
|
||||
@ -1 +1,8 @@
|
||||
/**
|
||||
* Utilities Entry Point
|
||||
*
|
||||
* 工具函数入口
|
||||
*
|
||||
* @module plugin-search/client/utils
|
||||
*/
|
||||
export * from './lru.js'
|
||||
|
||||
@ -1,14 +1,63 @@
|
||||
// adapted from https://stackoverflow.com/a/46432113/11613622
|
||||
/**
|
||||
* LRU (Least Recently Used) Cache Implementation
|
||||
*
|
||||
* LRU(最近最少使用)缓存实现
|
||||
*
|
||||
* Adapted from https://stackoverflow.com/a/46432113/11613622
|
||||
*
|
||||
* @module plugin-search/client/utils/lru
|
||||
*/
|
||||
|
||||
/**
|
||||
* Generic LRU Cache implementation using Map.
|
||||
*
|
||||
* 使用 Map 实现的通用 LRU 缓存。
|
||||
*
|
||||
* Automatically evicts the least recently used item when the cache reaches
|
||||
* its maximum size.
|
||||
*
|
||||
* 当缓存达到最大容量时,自动淘汰最近最少使用的项。
|
||||
*
|
||||
* @template K - Key type / 键类型
|
||||
* @template V - Value type / 值类型
|
||||
* @example
|
||||
* const cache = new LRUCache<string, number>(3)
|
||||
* cache.set('a', 1)
|
||||
* cache.set('b', 2)
|
||||
* cache.set('c', 3)
|
||||
* cache.set('d', 4) // 'a' is evicted
|
||||
* cache.get('b') // returns 2, 'b' becomes most recent
|
||||
*/
|
||||
export class LRUCache<K, V> {
|
||||
/** Maximum number of items in the cache / 缓存中的最大项数 */
|
||||
private max: number
|
||||
/** Internal Map storage / 内部 Map 存储 */
|
||||
private cache: Map<K, V>
|
||||
|
||||
/**
|
||||
* Create a new LRU Cache instance.
|
||||
*
|
||||
* 创建新的 LRU 缓存实例。
|
||||
*
|
||||
* @param max - Maximum cache size (default: 10) / 最大缓存大小(默认:10)
|
||||
*/
|
||||
constructor(max: number = 10) {
|
||||
this.max = max
|
||||
this.cache = new Map<K, V>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value from the cache.
|
||||
*
|
||||
* 从缓存中获取值。
|
||||
*
|
||||
* Accessing an item moves it to the end (most recently used position).
|
||||
*
|
||||
* 访问项会将其移动到末尾(最近使用的位置)。
|
||||
*
|
||||
* @param key - Cache key / 缓存键
|
||||
* @returns Cached value or undefined if not found / 缓存值,未找到则返回 undefined
|
||||
*/
|
||||
get(key: K): V | undefined {
|
||||
const item = this.cache.get(key)
|
||||
if (item !== undefined) {
|
||||
@ -19,6 +68,19 @@ export class LRUCache<K, V> {
|
||||
return item
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value in the cache.
|
||||
*
|
||||
* 在缓存中设置值。
|
||||
*
|
||||
* If the key already exists, it is moved to the end. If the cache is full,
|
||||
* the oldest item is evicted.
|
||||
*
|
||||
* 如果键已存在,则将其移动到末尾。如果缓存已满,则淘汰最旧的项。
|
||||
*
|
||||
* @param key - Cache key / 缓存键
|
||||
* @param val - Value to cache / 要缓存的值
|
||||
*/
|
||||
set(key: K, val: V): void {
|
||||
// refresh key
|
||||
if (this.cache.has(key))
|
||||
@ -29,10 +91,22 @@ export class LRUCache<K, V> {
|
||||
this.cache.set(key, val)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first (oldest) key in the cache.
|
||||
*
|
||||
* 获取缓存中的第一个(最旧的)键。
|
||||
*
|
||||
* @returns The oldest key or undefined if cache is empty / 最旧的键,缓存为空则返回 undefined
|
||||
*/
|
||||
first(): K | undefined {
|
||||
return this.cache.keys().next().value
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all items from the cache.
|
||||
*
|
||||
* 清空缓存中的所有项。
|
||||
*/
|
||||
clear(): void {
|
||||
this.cache.clear()
|
||||
}
|
||||
|
||||
@ -1,3 +1,14 @@
|
||||
/**
|
||||
* VuePress Search Plugin - Node Side Entry
|
||||
*
|
||||
* VuePress 搜索插件 - Node 端入口
|
||||
*
|
||||
* Exports the search plugin and search index preparation utilities.
|
||||
*
|
||||
* 导出搜索插件和搜索索引准备工具。
|
||||
*
|
||||
* @module plugin-search/node
|
||||
*/
|
||||
export * from '../shared/index.js'
|
||||
export { prepareSearchIndex } from './prepareSearchIndex.js'
|
||||
export { searchPlugin } from './searchPlugin.js'
|
||||
|
||||
@ -1,6 +1,17 @@
|
||||
/** 德语 */
|
||||
/**
|
||||
* German locale configuration for search plugin.
|
||||
*
|
||||
* 搜索插件的德语本地化配置。
|
||||
*
|
||||
* @module plugin-search/node/locales/de
|
||||
*/
|
||||
import type { SearchLocaleOptions } from '../../shared/index.js'
|
||||
|
||||
/**
|
||||
* German search locale strings.
|
||||
*
|
||||
* 德语搜索本地化字符串。
|
||||
*/
|
||||
export const deSearchLocale: Partial<SearchLocaleOptions> = {
|
||||
placeholder: 'Dokumente durchsuchen',
|
||||
resetButtonTitle: 'Suche zurücksetzen',
|
||||
|
||||
@ -1,5 +1,17 @@
|
||||
/**
|
||||
* English locale configuration for search plugin.
|
||||
*
|
||||
* 搜索插件的英语本地化配置。
|
||||
*
|
||||
* @module plugin-search/node/locales/en
|
||||
*/
|
||||
import type { SearchLocaleOptions } from '../../shared/index.js'
|
||||
|
||||
/**
|
||||
* English search locale strings.
|
||||
*
|
||||
* 英语搜索本地化字符串。
|
||||
*/
|
||||
export const enSearchLocale: Partial<SearchLocaleOptions> = {
|
||||
placeholder: 'Search',
|
||||
resetButtonTitle: 'Reset search',
|
||||
|
||||
@ -1,6 +1,17 @@
|
||||
/** 法语 */
|
||||
/**
|
||||
* French locale configuration for search plugin.
|
||||
*
|
||||
* 搜索插件的法语本地化配置。
|
||||
*
|
||||
* @module plugin-search/node/locales/fr
|
||||
*/
|
||||
import type { SearchLocaleOptions } from '../../shared/index.js'
|
||||
|
||||
/**
|
||||
* French search locale strings.
|
||||
*
|
||||
* 法语搜索本地化字符串。
|
||||
*/
|
||||
export const frSearchLocale: Partial<SearchLocaleOptions> = {
|
||||
placeholder: 'Rechercher dans la documentation',
|
||||
resetButtonTitle: 'Réinitialiser la recherche',
|
||||
|
||||
@ -1,7 +1,14 @@
|
||||
/**
|
||||
* 多语言预设
|
||||
* 除 /zh/ 、 /en/ 外,其它语言预设通过 AI 生成,不保证准确
|
||||
* 如有错误,欢迎提 issue
|
||||
* Multi-language presets for search plugin.
|
||||
*
|
||||
* 搜索插件的多语言预设。
|
||||
*
|
||||
* Language presets other than /zh/ and /en/ are generated by AI and may not be accurate.
|
||||
* If you find any errors, please submit an issue.
|
||||
*
|
||||
* 除 /zh/ 和 /en/ 外,其他语言预设通过 AI 生成,不保证准确。如有错误,欢迎提 issue。
|
||||
*
|
||||
* @module plugin-search/node/locales
|
||||
*/
|
||||
import type { DefaultLocaleInfo } from '@vuepress/helper'
|
||||
import type { SearchLocaleOptions } from '../../shared/index.js'
|
||||
@ -13,6 +20,15 @@ import { ruSearchLocale } from './ru.js'
|
||||
import { zhTwSearchLocale } from './zh-tw.js'
|
||||
import { zhSearchLocale } from './zh.js'
|
||||
|
||||
/**
|
||||
* Default locale configurations for search plugin.
|
||||
*
|
||||
* 搜索插件的默认语言配置。
|
||||
*
|
||||
* Maps language codes to their respective locale strings.
|
||||
*
|
||||
* 将语言代码映射到相应的本地化字符串。
|
||||
*/
|
||||
export const SEARCH_LOCALES: DefaultLocaleInfo<Partial<SearchLocaleOptions>> = [
|
||||
[['en', 'en-US'], enSearchLocale],
|
||||
[['zh', 'zh-CN', 'zh-Hans', 'zh-Hant'], zhSearchLocale],
|
||||
|
||||
@ -1,6 +1,17 @@
|
||||
/** 日语 */
|
||||
/**
|
||||
* Japanese locale configuration for search plugin.
|
||||
*
|
||||
* 搜索插件的日语本地化配置。
|
||||
*
|
||||
* @module plugin-search/node/locales/ja
|
||||
*/
|
||||
import type { SearchLocaleOptions } from '../../shared/index.js'
|
||||
|
||||
/**
|
||||
* Japanese search locale strings.
|
||||
*
|
||||
* 日语搜索本地化字符串。
|
||||
*/
|
||||
export const jaSearchLocale: Partial<SearchLocaleOptions> = {
|
||||
placeholder: 'ドキュメントを検索',
|
||||
resetButtonTitle: '検索をリセット',
|
||||
|
||||
@ -1,6 +1,17 @@
|
||||
/** 俄语 */
|
||||
/**
|
||||
* Russian locale configuration for search plugin.
|
||||
*
|
||||
* 搜索插件的俄语本地化配置。
|
||||
*
|
||||
* @module plugin-search/node/locales/ru
|
||||
*/
|
||||
import type { SearchLocaleOptions } from '../../shared/index.js'
|
||||
|
||||
/**
|
||||
* Russian search locale strings.
|
||||
*
|
||||
* 俄语搜索本地化字符串。
|
||||
*/
|
||||
export const ruSearchLocale: Partial<SearchLocaleOptions> = {
|
||||
placeholder: 'Поиск по документации',
|
||||
resetButtonTitle: 'Сбросить поиск',
|
||||
|
||||
@ -1,6 +1,17 @@
|
||||
/** 繁体中文 */
|
||||
/**
|
||||
* Traditional Chinese (Taiwan) locale configuration for search plugin.
|
||||
*
|
||||
* 搜索插件的繁体中文(台湾)本地化配置。
|
||||
*
|
||||
* @module plugin-search/node/locales/zh-tw
|
||||
*/
|
||||
import type { SearchLocaleOptions } from '../../shared/index.js'
|
||||
|
||||
/**
|
||||
* Traditional Chinese (Taiwan) search locale strings.
|
||||
*
|
||||
* 繁体中文(台湾)搜索本地化字符串。
|
||||
*/
|
||||
export const zhTwSearchLocale: Partial<SearchLocaleOptions> = {
|
||||
placeholder: '搜尋文件',
|
||||
resetButtonTitle: '重設搜尋',
|
||||
|
||||
@ -1,5 +1,17 @@
|
||||
/**
|
||||
* Simplified Chinese locale configuration for search plugin.
|
||||
*
|
||||
* 搜索插件的简体中文本地化配置。
|
||||
*
|
||||
* @module plugin-search/node/locales/zh
|
||||
*/
|
||||
import type { SearchLocaleOptions } from '../../shared/index.js'
|
||||
|
||||
/**
|
||||
* Simplified Chinese search locale strings.
|
||||
*
|
||||
* 简体中文搜索本地化字符串。
|
||||
*/
|
||||
export const zhSearchLocale: Partial<SearchLocaleOptions> = {
|
||||
placeholder: '搜索文档',
|
||||
resetButtonTitle: '重置搜索',
|
||||
|
||||
@ -1,26 +1,71 @@
|
||||
/**
|
||||
* Search Index Preparation Module
|
||||
*
|
||||
* 搜索索引准备模块
|
||||
*
|
||||
* This module handles the creation, update, and management of MiniSearch indexes
|
||||
* for VuePress pages, supporting multiple locales and hot module replacement.
|
||||
*
|
||||
* 本模块处理 VuePress 页面的 MiniSearch 索引的创建、更新和管理,
|
||||
* 支持多语言和热模块替换。
|
||||
*
|
||||
* @module plugin-search/node/prepareSearchIndex
|
||||
*/
|
||||
import type { App, Page } from 'vuepress/core'
|
||||
import type { SearchOptions, SearchPluginOptions } from '../shared/index.js'
|
||||
import MiniSearch from 'minisearch'
|
||||
import pMap from 'p-map'
|
||||
import { colors, logger } from 'vuepress/utils'
|
||||
|
||||
/**
|
||||
* Options for search index preparation.
|
||||
*
|
||||
* 搜索索引准备的配置选项。
|
||||
*/
|
||||
export interface SearchIndexOptions {
|
||||
/** VuePress application instance / VuePress 应用实例 */
|
||||
app: App
|
||||
/** MiniSearch configuration options / MiniSearch 配置选项 */
|
||||
searchOptions: SearchOptions
|
||||
/** Function to filter searchable pages / 过滤可搜索页面的函数 */
|
||||
isSearchable: SearchPluginOptions['isSearchable']
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal index object structure for MiniSearch.
|
||||
*
|
||||
* MiniSearch 的内部索引对象结构。
|
||||
*/
|
||||
interface IndexObject {
|
||||
/** Unique identifier for the indexed item / 索引项的唯一标识符 */
|
||||
id: string
|
||||
/** Text content for searching / 用于搜索的文本内容 */
|
||||
text: string
|
||||
/** Title of the section / 章节标题 */
|
||||
title: string
|
||||
/** Parent titles hierarchy / 父级标题层级 */
|
||||
titles: string[]
|
||||
}
|
||||
|
||||
/** Directory path for storing search index files / 存储搜索索引文件的目录路径 */
|
||||
const SEARCH_INDEX_DIR = 'internal/minisearchIndex/'
|
||||
|
||||
/** Map of locale paths to their MiniSearch instances / 语言路径到 MiniSearch 实例的映射 */
|
||||
const indexByLocales = new Map<string, MiniSearch<IndexObject>>()
|
||||
|
||||
/** Cache for index objects by file path / 按文件路径缓存索引对象 */
|
||||
const indexCache = new Map<string, IndexObject[]>()
|
||||
|
||||
/**
|
||||
* Get or create a MiniSearch index for a specific locale.
|
||||
*
|
||||
* 获取或创建特定语言的 MiniSearch 索引。
|
||||
*
|
||||
* @param locale - Locale path (e.g., '/', '/zh/') / 语言路径
|
||||
* @param lang - Language code for tokenization / 用于分词的语言代码
|
||||
* @param options - Search index options / 搜索索引选项
|
||||
* @returns MiniSearch instance for the locale / 该语言的 MiniSearch 实例
|
||||
*/
|
||||
function getIndexByLocale(locale: string, lang: string, options: SearchIndexOptions['searchOptions']) {
|
||||
let index = indexByLocales.get(locale)
|
||||
if (!index) {
|
||||
@ -38,6 +83,14 @@ function getIndexByLocale(locale: string, lang: string, options: SearchIndexOpti
|
||||
return index
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or create an index cache for a specific file path.
|
||||
*
|
||||
* 获取或创建特定文件路径的索引缓存。
|
||||
*
|
||||
* @param filepath - File path to get cache for / 要获取缓存的文件路径
|
||||
* @returns Array of index objects for the file / 该文件的索引对象数组
|
||||
*/
|
||||
function getIndexCache(filepath: string) {
|
||||
let index = indexCache.get(filepath)
|
||||
if (!index) {
|
||||
@ -47,10 +100,39 @@ function getIndexCache(filepath: string) {
|
||||
return index
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a placeholder search index file for development mode.
|
||||
*
|
||||
* 为开发模式写入占位符搜索索引文件。
|
||||
*
|
||||
* This is used to provide an empty index before the actual index is prepared,
|
||||
* preventing errors when the search component loads before indexing completes.
|
||||
*
|
||||
* 用于在实际索引准备完成之前提供空索引,
|
||||
* 防止搜索组件在索引完成之前加载时出错。
|
||||
*
|
||||
* @param app - VuePress application instance / VuePress 应用实例
|
||||
*/
|
||||
export async function prepareSearchIndexPlaceholder(app: App) {
|
||||
await app.writeTemp(`${SEARCH_INDEX_DIR}index.js`, 'export const searchIndex = {}')
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare search indexes for all pages in the VuePress application.
|
||||
*
|
||||
* 为 VuePress 应用中的所有页面准备搜索索引。
|
||||
*
|
||||
* This function indexes all pages concurrently, creating separate MiniSearch
|
||||
* instances for each locale, and writes the indexes to temporary files.
|
||||
*
|
||||
* 此函数并发索引所有页面,为每个语言创建独立的 MiniSearch 实例,
|
||||
* 并将索引写入临时文件。
|
||||
*
|
||||
* @param options - Search index preparation options / 搜索索引准备选项
|
||||
* @param options.app - VuePress application instance / VuePress 应用实例
|
||||
* @param options.isSearchable - Function to filter searchable pages / 过滤可搜索页面的函数
|
||||
* @param options.searchOptions - MiniSearch configuration / MiniSearch 配置
|
||||
*/
|
||||
export async function prepareSearchIndex({
|
||||
app,
|
||||
isSearchable,
|
||||
@ -78,6 +160,17 @@ export async function prepareSearchIndex({
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle search index update when a page is modified.
|
||||
*
|
||||
* 当页面被修改时处理搜索索引更新。
|
||||
*
|
||||
* @param filepath - Path of the modified file relative to project root / 相对于项目根目录的修改文件路径
|
||||
* @param options - Search index preparation options / 搜索索引准备选项
|
||||
* @param options.app - VuePress application instance / VuePress 应用实例
|
||||
* @param options.isSearchable - Function to filter searchable pages / 过滤可搜索页面的函数
|
||||
* @param options.searchOptions - MiniSearch configuration / MiniSearch 配置
|
||||
*/
|
||||
export async function onSearchIndexUpdated(
|
||||
filepath: string,
|
||||
{
|
||||
@ -97,6 +190,17 @@ export async function onSearchIndexUpdated(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle search index update when a page is removed.
|
||||
*
|
||||
* 当页面被删除时处理搜索索引更新。
|
||||
*
|
||||
* @param filepath - Path of the removed file relative to project root / 相对于项目根目录的删除文件路径
|
||||
* @param options - Search index preparation options / 搜索索引准备选项
|
||||
* @param options.app - VuePress application instance / VuePress 应用实例
|
||||
* @param options.isSearchable - Function to filter searchable pages / 过滤可搜索页面的函数
|
||||
* @param options.searchOptions - MiniSearch configuration / MiniSearch 配置
|
||||
*/
|
||||
export async function onSearchIndexRemoved(
|
||||
filepath: string,
|
||||
{
|
||||
@ -119,6 +223,19 @@ export async function onSearchIndexRemoved(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write all search indexes to temporary files.
|
||||
*
|
||||
* 将所有搜索索引写入临时文件。
|
||||
*
|
||||
* Creates separate JavaScript files for each locale's search index,
|
||||
* enabling lazy loading of indexes in the client.
|
||||
*
|
||||
* 为每个语言的搜索索引创建独立的 JavaScript 文件,
|
||||
* 支持客户端延迟加载索引。
|
||||
*
|
||||
* @param app - VuePress application instance / VuePress 应用实例
|
||||
*/
|
||||
async function writeTemp(app: App) {
|
||||
const records: string[] = []
|
||||
const promises: Promise<string>[] = []
|
||||
@ -145,6 +262,21 @@ async function writeTemp(app: App) {
|
||||
await Promise.all(promises)
|
||||
}
|
||||
|
||||
/**
|
||||
* Index a single page for search.
|
||||
*
|
||||
* 为单个页面建立搜索索引。
|
||||
*
|
||||
* Extracts content from the page, splits it into sections based on headings,
|
||||
* and adds each section to the appropriate locale's MiniSearch index.
|
||||
*
|
||||
* 从页面提取内容,根据标题将其分割为章节,
|
||||
* 并将每个章节添加到相应语言的 MiniSearch 索引中。
|
||||
*
|
||||
* @param page - VuePress page object / VuePress 页面对象
|
||||
* @param options - MiniSearch options / MiniSearch 选项
|
||||
* @param isSearchable - Function to check if page should be indexed / 检查页面是否应被索引的函数
|
||||
*/
|
||||
async function indexFile(page: Page, options: SearchIndexOptions['searchOptions'], isSearchable: SearchPluginOptions['isSearchable']) {
|
||||
if (!page.filePath || page.frontmatter?.search === false)
|
||||
return
|
||||
@ -194,13 +326,27 @@ ${page.contentRendered}`
|
||||
}
|
||||
}
|
||||
|
||||
/** Regex pattern for matching heading tags / 匹配标题标签的正则表达式 */
|
||||
// eslint-disable-next-line regexp/no-super-linear-backtracking
|
||||
const headingRegex = /<h(\d*).*?>(<a.*? href="#.*?".*?>[\s\S]*?<\/a>)<\/h\1>/gi
|
||||
/** Regex pattern for extracting heading content / 提取标题内容的正则表达式 */
|
||||
// eslint-disable-next-line regexp/no-super-linear-backtracking
|
||||
const headingContentRegex = /<a.*? href="#(.*?)".*?><span>([\s\S]*?)<\/span><\/a>/i
|
||||
/** Regex pattern for ignoring template content / 忽略模板内容的正则表达式 */
|
||||
const ignoreHeadingRegex = /<template[^>]*>[\s\S]*<\/template>/gi
|
||||
|
||||
/**
|
||||
* Splits HTML into sections based on headings
|
||||
* Split HTML content into sections based on heading elements.
|
||||
*
|
||||
* 根据标题元素将 HTML 内容分割为章节。
|
||||
*
|
||||
* This generator function parses HTML content and yields section objects
|
||||
* containing anchor, titles hierarchy, and searchable text.
|
||||
*
|
||||
* 此生成器函数解析 HTML 内容并生成包含锚点、标题层级和可搜索文本的章节对象。
|
||||
*
|
||||
* @param html - HTML content to split / 要分割的 HTML 内容
|
||||
* @yields Section objects with anchor, titles, and text / 包含锚点、标题和文本的章节对象
|
||||
*/
|
||||
function* splitPageIntoSections(html: string) {
|
||||
const result = html.split(headingRegex)
|
||||
@ -228,17 +374,41 @@ function* splitPageIntoSections(html: string) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract searchable text from HTML content by removing tags.
|
||||
*
|
||||
* 通过移除标签从 HTML 内容中提取可搜索文本。
|
||||
*
|
||||
* @param content - HTML content / HTML 内容
|
||||
* @returns Plain text content / 纯文本内容
|
||||
*/
|
||||
function getSearchableText(content: string) {
|
||||
content = clearHtmlTags(content)
|
||||
return content
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all HTML tags from a string.
|
||||
*
|
||||
* 移除字符串中的所有 HTML 标签。
|
||||
*
|
||||
* @param str - String containing HTML / 包含 HTML 的字符串
|
||||
* @returns String with HTML tags removed / 移除 HTML 标签后的字符串
|
||||
*/
|
||||
function clearHtmlTags(str: string) {
|
||||
str = str.replace(ignoreHeadingRegex, '')
|
||||
// 移除其他所有HTML标签
|
||||
return str.replace(/<[^>]*>/g, '')
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate HMR (Hot Module Replacement) code for the search index.
|
||||
*
|
||||
* 为搜索索引生成 HMR(热模块替换)代码。
|
||||
*
|
||||
* @param m - Module name / 模块名称
|
||||
* @returns HMR code string / HMR 代码字符串
|
||||
*/
|
||||
function genHmrCode(m: string) {
|
||||
const func = `update${m[0].toUpperCase()}${m.slice(1)}`
|
||||
return `
|
||||
|
||||
@ -8,6 +8,36 @@ import { onSearchIndexRemoved, onSearchIndexUpdated, prepareSearchIndex, prepare
|
||||
|
||||
const __dirname = getDirname(import.meta.url)
|
||||
|
||||
/**
|
||||
* Create a VuePress search plugin instance.
|
||||
*
|
||||
* 创建 VuePress 搜索插件实例。
|
||||
*
|
||||
* @param options - Plugin configuration options / 插件配置选项
|
||||
* @param options.locales - Locale-specific search configurations / 特定语言的搜索配置
|
||||
* @param options.isSearchable - Function to determine if a page should be indexed / 判断页面是否应被索引的函数
|
||||
* @param options.searchOptions - MiniSearch options / MiniSearch 配置选项
|
||||
* @returns VuePress plugin object / VuePress 插件对象
|
||||
* @example
|
||||
* // Basic usage
|
||||
* export default {
|
||||
* plugins: [
|
||||
* searchPlugin()
|
||||
* ]
|
||||
* }
|
||||
*
|
||||
* // With custom options
|
||||
* export default {
|
||||
* plugins: [
|
||||
* searchPlugin({
|
||||
* locales: {
|
||||
* '/zh/': { placeholder: '搜索文档' }
|
||||
* },
|
||||
* isSearchable: (page) => page.path !== '/secret/'
|
||||
* })
|
||||
* ]
|
||||
* }
|
||||
*/
|
||||
export function searchPlugin({
|
||||
locales = {},
|
||||
isSearchable,
|
||||
|
||||
@ -1,40 +1,107 @@
|
||||
/**
|
||||
* Shared Types for VuePress Search Plugin
|
||||
*
|
||||
* VuePress 搜索插件的共享类型
|
||||
*
|
||||
* This module contains type definitions shared between the node and client
|
||||
* sides of the search plugin.
|
||||
*
|
||||
* 本模块包含搜索插件在 Node 端和客户端之间共享的类型定义。
|
||||
*
|
||||
* @module plugin-search/shared
|
||||
*/
|
||||
import type { Options as MiniSearchOptions } from 'minisearch'
|
||||
import type { LocaleConfig, Page } from 'vuepress/core'
|
||||
|
||||
/**
|
||||
* Locale options for search UI strings.
|
||||
*
|
||||
* 搜索 UI 字符串的语言选项。
|
||||
*/
|
||||
export interface SearchLocaleOptions {
|
||||
/** Placeholder text for search input / 搜索输入框的占位文本 */
|
||||
placeholder: string
|
||||
/** Text for search button / 搜索按钮的文本 */
|
||||
buttonText: string
|
||||
/** Title for reset button / 重置按钮的标题 */
|
||||
resetButtonTitle: string
|
||||
/** Title for back/close button / 返回/关闭按钮的标题 */
|
||||
backButtonTitle: string
|
||||
/** Text shown when no results found / 无搜索结果时显示的文本 */
|
||||
noResultsText: string
|
||||
/** Footer keyboard shortcut hints / 底部键盘快捷键提示 */
|
||||
footer: {
|
||||
/** Text for select action / 选择操作的文本 */
|
||||
selectText: string
|
||||
/** ARIA label for select key / 选择键的 ARIA 标签 */
|
||||
selectKeyAriaLabel: string
|
||||
/** Text for navigate action / 导航操作的文本 */
|
||||
navigateText: string
|
||||
/** ARIA label for navigate up key / 向上导航键的 ARIA 标签 */
|
||||
navigateUpKeyAriaLabel: string
|
||||
/** ARIA label for navigate down key / 向下导航键的 ARIA 标签 */
|
||||
navigateDownKeyAriaLabel: string
|
||||
/** Text for close action / 关闭操作的文本 */
|
||||
closeText: string
|
||||
/** ARIA label for close key / 关闭键的 ARIA 标签 */
|
||||
closeKeyAriaLabel: string
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Locale configuration type for search box.
|
||||
*
|
||||
* 搜索框的语言配置类型。
|
||||
*/
|
||||
export type SearchBoxLocales = LocaleConfig<SearchLocaleOptions>
|
||||
|
||||
/**
|
||||
* Options for the search plugin.
|
||||
*
|
||||
* 搜索插件的选项。
|
||||
*/
|
||||
export interface SearchPluginOptions extends SearchOptions {
|
||||
/** Locale-specific search configurations / 特定语言的搜索配置 */
|
||||
locales?: SearchBoxLocales
|
||||
|
||||
/**
|
||||
* Function to determine if a page should be indexed.
|
||||
*
|
||||
* 判断页面是否应被索引的函数。
|
||||
*
|
||||
* @param page - VuePress page object / VuePress 页面对象
|
||||
* @returns Whether the page should be searchable / 页面是否可搜索
|
||||
*/
|
||||
isSearchable?: (page: Page) => boolean
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Search configuration options.
|
||||
*
|
||||
* 搜索配置选项。
|
||||
*/
|
||||
export interface SearchOptions {
|
||||
/**
|
||||
* Whether to disable query persistence in session storage.
|
||||
*
|
||||
* 是否禁用会话存储中的查询持久化。
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
disableQueryPersistence?: boolean
|
||||
|
||||
/**
|
||||
* MiniSearch configuration options.
|
||||
*
|
||||
* MiniSearch 配置选项。
|
||||
*/
|
||||
miniSearch?: {
|
||||
/**
|
||||
* MiniSearch instance options.
|
||||
*
|
||||
* MiniSearch 实例选项。
|
||||
*
|
||||
* @see https://lucaong.github.io/minisearch/modules/_minisearch_.html#options
|
||||
*/
|
||||
options?: Pick<
|
||||
@ -42,6 +109,10 @@ export interface SearchOptions {
|
||||
'extractField' | 'tokenize' | 'processTerm'
|
||||
>
|
||||
/**
|
||||
* MiniSearch search options.
|
||||
*
|
||||
* MiniSearch 搜索选项。
|
||||
*
|
||||
* @see https://lucaong.github.io/minisearch/modules/_minisearch_.html#searchoptions-1
|
||||
*/
|
||||
searchOptions?: MiniSearchOptions['searchOptions']
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user