|
|
|
@ -1,7 +1,9 @@
|
|
|
|
import MiniSearch from 'minisearch'
|
|
|
|
import MiniSearch from 'minisearch'
|
|
|
|
import { resolveConfig } from 'node/config'
|
|
|
|
import { resolveConfig } from 'node/config'
|
|
|
|
|
|
|
|
import { disposeMdItInstance } from 'node/markdown/markdown'
|
|
|
|
|
|
|
|
import { createMarkdownToVueRenderFn } from 'node/markdownToVue'
|
|
|
|
import { localSearchPlugin } from 'node/plugins/localSearchPlugin'
|
|
|
|
import { localSearchPlugin } from 'node/plugins/localSearchPlugin'
|
|
|
|
import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises'
|
|
|
|
import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
|
|
|
|
import { tmpdir } from 'node:os'
|
|
|
|
import { tmpdir } from 'node:os'
|
|
|
|
import path from 'node:path'
|
|
|
|
import path from 'node:path'
|
|
|
|
|
|
|
|
|
|
|
|
@ -12,6 +14,9 @@ describe('node/plugins/localSearchPlugin', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
beforeEach(() => {
|
|
|
|
nodeEnv = process.env.NODE_ENV
|
|
|
|
nodeEnv = process.env.NODE_ENV
|
|
|
|
process.env.NODE_ENV = 'production'
|
|
|
|
process.env.NODE_ENV = 'production'
|
|
|
|
|
|
|
|
// createMarkdownRenderer is a module-level singleton keyed on nothing —
|
|
|
|
|
|
|
|
// reset it so each test's config actually reaches the renderer
|
|
|
|
|
|
|
|
disposeMdItInstance()
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
afterEach(async () => {
|
|
|
|
afterEach(async () => {
|
|
|
|
@ -102,6 +107,83 @@ describe('node/plugins/localSearchPlugin', () => {
|
|
|
|
expect(zhIndex.search('rootonlytoken')).toEqual([])
|
|
|
|
expect(zhIndex.search('rootonlytoken')).toEqual([])
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
test('applies per-locale markdown options (#5350)', async () => {
|
|
|
|
|
|
|
|
root = await mkdtemp(path.join(tmpdir(), 'vitepress-local-search-'))
|
|
|
|
|
|
|
|
const configDir = path.join(root, '.vitepress')
|
|
|
|
|
|
|
|
await mkdir(configDir)
|
|
|
|
|
|
|
|
await mkdir(path.join(root, 'zh'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const content = '::: tip\ntipcontent\n:::\n'
|
|
|
|
|
|
|
|
await writeFile(path.join(root, 'index.md'), `# Home\n\n${content}`)
|
|
|
|
|
|
|
|
await writeFile(
|
|
|
|
|
|
|
|
path.join(root, 'zh', 'index.md'),
|
|
|
|
|
|
|
|
`# Chinese home\n\n${content}`
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
await writeFile(
|
|
|
|
|
|
|
|
path.join(configDir, 'config.ts'),
|
|
|
|
|
|
|
|
[
|
|
|
|
|
|
|
|
'export default {',
|
|
|
|
|
|
|
|
' locales: {',
|
|
|
|
|
|
|
|
" root: { label: 'English', lang: 'en' },",
|
|
|
|
|
|
|
|
' zh: {',
|
|
|
|
|
|
|
|
" label: 'Chinese',",
|
|
|
|
|
|
|
|
" lang: 'zh',",
|
|
|
|
|
|
|
|
" markdown: { container: { tipLabel: 'zhtiplabel' } }",
|
|
|
|
|
|
|
|
' }',
|
|
|
|
|
|
|
|
' },',
|
|
|
|
|
|
|
|
' themeConfig: {',
|
|
|
|
|
|
|
|
" search: { provider: 'local' }",
|
|
|
|
|
|
|
|
' }',
|
|
|
|
|
|
|
|
'}'
|
|
|
|
|
|
|
|
].join('\n')
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const siteConfig = await resolveConfig(root, 'build', 'production')
|
|
|
|
|
|
|
|
const plugin = await localSearchPlugin(siteConfig)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// configResolved hooks run concurrently, so the search plugin may be the
|
|
|
|
|
|
|
|
// one that creates the shared markdown renderer — page renders must still
|
|
|
|
|
|
|
|
// pick up per-locale options from it
|
|
|
|
|
|
|
|
await (plugin.configResolved as any)?.call(
|
|
|
|
|
|
|
|
{},
|
|
|
|
|
|
|
|
{ publicDir: siteConfig.publicDir }
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const render = await createMarkdownToVueRenderFn(
|
|
|
|
|
|
|
|
siteConfig.srcDir,
|
|
|
|
|
|
|
|
siteConfig.markdown ?? {},
|
|
|
|
|
|
|
|
siteConfig.site.base,
|
|
|
|
|
|
|
|
false,
|
|
|
|
|
|
|
|
false,
|
|
|
|
|
|
|
|
siteConfig
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const rootFile = path.join(root, 'index.md')
|
|
|
|
|
|
|
|
const zhFile = path.join(root, 'zh', 'index.md')
|
|
|
|
|
|
|
|
const rootPage = await render(await readFile(rootFile, 'utf-8'), rootFile)
|
|
|
|
|
|
|
|
const zhPage = await render(await readFile(zhFile, 'utf-8'), zhFile)
|
|
|
|
|
|
|
|
expect(rootPage.vueSrc).toContain('TIP')
|
|
|
|
|
|
|
|
expect(zhPage.vueSrc).toContain('zhtiplabel')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// the indexed text must use the localized labels too
|
|
|
|
|
|
|
|
await (plugin.load as any)?.handler.call({}, '/@localSearchIndex')
|
|
|
|
|
|
|
|
const rootIndex = loadIndex(
|
|
|
|
|
|
|
|
(await (plugin.load as any)?.handler.call(
|
|
|
|
|
|
|
|
{},
|
|
|
|
|
|
|
|
'/@localSearchIndexroot'
|
|
|
|
|
|
|
|
)) as string
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
const zhIndex = loadIndex(
|
|
|
|
|
|
|
|
(await (plugin.load as any)?.handler.call(
|
|
|
|
|
|
|
|
{},
|
|
|
|
|
|
|
|
'/@localSearchIndexzh'
|
|
|
|
|
|
|
|
)) as string
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
expect(zhIndex.search('zhtiplabel')).toHaveLength(1)
|
|
|
|
|
|
|
|
expect(rootIndex.search('zhtiplabel')).toEqual([])
|
|
|
|
|
|
|
|
expect(rootIndex.search('tip')).toHaveLength(1)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
test('warns and skips pages that fail to render', async () => {
|
|
|
|
test('warns and skips pages that fail to render', async () => {
|
|
|
|
root = await mkdtemp(path.join(tmpdir(), 'vitepress-local-search-'))
|
|
|
|
root = await mkdtemp(path.join(tmpdir(), 'vitepress-local-search-'))
|
|
|
|
const configDir = path.join(root, '.vitepress')
|
|
|
|
const configDir = path.join(root, '.vitepress')
|
|
|
|
|