|
|
@ -5,7 +5,10 @@ import pMap from 'p-map'
|
|
|
|
import path from 'path'
|
|
|
|
import path from 'path'
|
|
|
|
import type { Plugin, ViteDevServer } from 'vite'
|
|
|
|
import type { Plugin, ViteDevServer } from 'vite'
|
|
|
|
import type { SiteConfig } from '../config'
|
|
|
|
import type { SiteConfig } from '../config'
|
|
|
|
import { createMarkdownRenderer } from '../markdown/markdown'
|
|
|
|
import {
|
|
|
|
|
|
|
|
createMarkdownRenderer,
|
|
|
|
|
|
|
|
type MarkdownRenderer
|
|
|
|
|
|
|
|
} from '../markdown/markdown'
|
|
|
|
import {
|
|
|
|
import {
|
|
|
|
resolveSiteDataByRoute,
|
|
|
|
resolveSiteDataByRoute,
|
|
|
|
slash,
|
|
|
|
slash,
|
|
|
@ -29,6 +32,26 @@ interface IndexObject {
|
|
|
|
titles: string[]
|
|
|
|
titles: string[]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let md: MarkdownRenderer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let flagAllIndexed = false
|
|
|
|
|
|
|
|
const taskByLocale = new Map<string, Promise<void>>()
|
|
|
|
|
|
|
|
const filesByLocale = new Map<string, Set<string>>()
|
|
|
|
|
|
|
|
const indexByLocale = new Map<string, MiniSearch<IndexObject>>()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getIndexByLocale(locale: string, options?: any) {
|
|
|
|
|
|
|
|
let index = indexByLocale.get(locale)
|
|
|
|
|
|
|
|
if (!index) {
|
|
|
|
|
|
|
|
index = new MiniSearch<IndexObject>({
|
|
|
|
|
|
|
|
fields: ['title', 'titles', 'text'],
|
|
|
|
|
|
|
|
storeFields: ['title', 'titles'],
|
|
|
|
|
|
|
|
...options
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
indexByLocale.set(locale, index)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return index
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export async function localSearchPlugin(
|
|
|
|
export async function localSearchPlugin(
|
|
|
|
siteConfig: SiteConfig<DefaultTheme.Config>
|
|
|
|
siteConfig: SiteConfig<DefaultTheme.Config>
|
|
|
|
): Promise<Plugin> {
|
|
|
|
): Promise<Plugin> {
|
|
|
@ -48,7 +71,7 @@ export async function localSearchPlugin(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const md = await createMarkdownRenderer(
|
|
|
|
md ??= await createMarkdownRenderer(
|
|
|
|
siteConfig.srcDir,
|
|
|
|
siteConfig.srcDir,
|
|
|
|
siteConfig.markdown,
|
|
|
|
siteConfig.markdown,
|
|
|
|
siteConfig.site.base,
|
|
|
|
siteConfig.site.base,
|
|
|
@ -71,21 +94,6 @@ export async function localSearchPlugin(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const indexByLocales = new Map<string, MiniSearch<IndexObject>>()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getIndexByLocale(locale: string) {
|
|
|
|
|
|
|
|
let index = indexByLocales.get(locale)
|
|
|
|
|
|
|
|
if (!index) {
|
|
|
|
|
|
|
|
index = new MiniSearch<IndexObject>({
|
|
|
|
|
|
|
|
fields: ['title', 'titles', 'text'],
|
|
|
|
|
|
|
|
storeFields: ['title', 'titles'],
|
|
|
|
|
|
|
|
...options.miniSearch?.options
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
indexByLocales.set(locale, index)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return index
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getLocaleForPath(file: string) {
|
|
|
|
function getLocaleForPath(file: string) {
|
|
|
|
const relativePath = slash(path.relative(siteConfig.srcDir, file))
|
|
|
|
const relativePath = slash(path.relative(siteConfig.srcDir, file))
|
|
|
|
const siteData = resolveSiteDataByRoute(siteConfig.site, relativePath)
|
|
|
|
const siteData = resolveSiteDataByRoute(siteConfig.site, relativePath)
|
|
|
@ -125,21 +133,10 @@ export async function localSearchPlugin(
|
|
|
|
return id
|
|
|
|
return id
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function scanForLocales() {
|
|
|
|
async function indexFile(file: string, parallel: boolean = false) {
|
|
|
|
for (const page of siteConfig.pages) {
|
|
|
|
|
|
|
|
const file = path.join(siteConfig.srcDir, page)
|
|
|
|
|
|
|
|
const locale = getLocaleForPath(file)
|
|
|
|
|
|
|
|
// dry-fetch the index for this locale
|
|
|
|
|
|
|
|
getIndexByLocale(locale)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function indexFile(page: string, parallel: boolean = false) {
|
|
|
|
|
|
|
|
const file = path.join(siteConfig.srcDir, page)
|
|
|
|
|
|
|
|
// get file metadata
|
|
|
|
|
|
|
|
const fileId = getDocId(file)
|
|
|
|
const fileId = getDocId(file)
|
|
|
|
const locale = getLocaleForPath(file)
|
|
|
|
const locale = getLocaleForPath(file)
|
|
|
|
const index = getIndexByLocale(locale)
|
|
|
|
const index = getIndexByLocale(locale, options.miniSearch?.options)
|
|
|
|
// retrieve file and split into "sections"
|
|
|
|
// retrieve file and split into "sections"
|
|
|
|
const html = await render(file)
|
|
|
|
const html = await render(file)
|
|
|
|
const sections =
|
|
|
|
const sections =
|
|
|
@ -163,29 +160,28 @@ export async function localSearchPlugin(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function indexAll() {
|
|
|
|
function indexAll() {
|
|
|
|
const concurrency = siteConfig.concurrency
|
|
|
|
if (flagAllIndexed) return
|
|
|
|
let numIndexed = 0
|
|
|
|
flagAllIndexed = true
|
|
|
|
|
|
|
|
|
|
|
|
const updateProgress = () =>
|
|
|
|
|
|
|
|
updateCurrentTask(
|
|
|
|
|
|
|
|
++numIndexed,
|
|
|
|
|
|
|
|
siteConfig.pages.length,
|
|
|
|
|
|
|
|
'indexing local search'
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const parallel = shouldUseParallel(siteConfig, 'local-search')
|
|
|
|
for (const page of siteConfig.pages) {
|
|
|
|
|
|
|
|
const file = path.join(siteConfig.srcDir, page)
|
|
|
|
await pMap(
|
|
|
|
const locale = getLocaleForPath(file)
|
|
|
|
siteConfig.pages,
|
|
|
|
if (!filesByLocale.has(locale)) filesByLocale.set(locale, new Set())
|
|
|
|
(page) => indexFile(page, parallel).then(updateProgress),
|
|
|
|
filesByLocale.get(locale)!.add(file)
|
|
|
|
{ concurrency }
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
updateCurrentTask()
|
|
|
|
async function indexLocale(locale: string) {
|
|
|
|
|
|
|
|
let numIndexed = 0
|
|
|
|
|
|
|
|
const update = () =>
|
|
|
|
|
|
|
|
updateCurrentTask(++numIndexed, files.length, `🔍️ indexing ${locale}`)
|
|
|
|
|
|
|
|
const files = [...filesByLocale.get(locale)!]
|
|
|
|
|
|
|
|
const task = (f: string) => indexFile(f, parallel).then(update)
|
|
|
|
|
|
|
|
await pMap(files, task, { concurrency: siteConfig.concurrency })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let indexAllPromise: Promise<void> | undefined
|
|
|
|
const parallel = shouldUseParallel(siteConfig, 'local-search')
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
name: 'vitepress:local-search',
|
|
|
|
name: 'vitepress:local-search',
|
|
|
@ -213,28 +209,28 @@ export async function localSearchPlugin(
|
|
|
|
|
|
|
|
|
|
|
|
async load(id) {
|
|
|
|
async load(id) {
|
|
|
|
if (id === LOCAL_SEARCH_INDEX_REQUEST_PATH) {
|
|
|
|
if (id === LOCAL_SEARCH_INDEX_REQUEST_PATH) {
|
|
|
|
scanForLocales()
|
|
|
|
indexAll()
|
|
|
|
let records: string[] = []
|
|
|
|
let records: string[] = []
|
|
|
|
for (const [locale] of indexByLocales) {
|
|
|
|
for (const [locale] of filesByLocale) {
|
|
|
|
records.push(
|
|
|
|
records.push(
|
|
|
|
`${JSON.stringify(
|
|
|
|
`${JSON.stringify(
|
|
|
|
locale
|
|
|
|
locale
|
|
|
|
)}: () => import('${LOCAL_SEARCH_INDEX_ID}-${locale}')`
|
|
|
|
)}: () => import('${LOCAL_SEARCH_INDEX_ID}:${locale}')`
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return `export default {${records.join(',')}}`
|
|
|
|
return `export default {${records.join(',')}}`
|
|
|
|
} else if (id.startsWith(LOCAL_SEARCH_INDEX_REQUEST_PATH)) {
|
|
|
|
} else if (id.startsWith(LOCAL_SEARCH_INDEX_REQUEST_PATH)) {
|
|
|
|
const locale = id.slice(LOCAL_SEARCH_INDEX_REQUEST_PATH.length + 1)
|
|
|
|
const locale = id.slice(LOCAL_SEARCH_INDEX_REQUEST_PATH.length + 1)
|
|
|
|
await (indexAllPromise ??= indexAll())
|
|
|
|
await ((taskByLocale as any)[locale] ??= indexLocale(locale))
|
|
|
|
return `export default ${JSON.stringify(
|
|
|
|
return `export default ${JSON.stringify(
|
|
|
|
JSON.stringify(indexByLocales.get(locale) ?? {})
|
|
|
|
JSON.stringify(indexByLocale.get(locale) ?? {})
|
|
|
|
)}`
|
|
|
|
)}`
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
async handleHotUpdate({ file }) {
|
|
|
|
async handleHotUpdate({ file }) {
|
|
|
|
if (file.endsWith('.md')) {
|
|
|
|
if (file.endsWith('.md')) {
|
|
|
|
await indexFile(file)
|
|
|
|
await indexFile(file, parallel)
|
|
|
|
debug('🔍️ Updated', file)
|
|
|
|
debug('🔍️ Updated', file)
|
|
|
|
onIndexUpdated()
|
|
|
|
onIndexUpdated()
|
|
|
|
}
|
|
|
|
}
|
|
|
|