From 8d5f3f66bab9a5ffb728d03e7d6dbb086d612c76 Mon Sep 17 00:00:00 2001 From: buqiyuan <1743369777@qq.com> Date: Sat, 30 Sep 2023 17:29:19 +0800 Subject: [PATCH] feat(node): localSearchPlugin support interpolation --- src/node/plugins/localSearchPlugin.ts | 32 ++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/node/plugins/localSearchPlugin.ts b/src/node/plugins/localSearchPlugin.ts index dc7ca8da..398efc07 100644 --- a/src/node/plugins/localSearchPlugin.ts +++ b/src/node/plugins/localSearchPlugin.ts @@ -2,6 +2,7 @@ import _debug from 'debug' import fs from 'fs-extra' import MiniSearch from 'minisearch' import path from 'path' +import { toDisplayString } from 'vue' import type { Plugin, ViteDevServer } from 'vite' import type { SiteConfig } from '../config' import { createMarkdownRenderer } from '../markdown/markdown' @@ -24,7 +25,7 @@ interface IndexObject { title: string titles: string[] } - +let mdEnv: MarkdownEnv export async function localSearchPlugin( siteConfig: SiteConfig ): Promise { @@ -56,12 +57,12 @@ export async function localSearchPlugin( function render(file: string) { const { srcDir, cleanUrls = false } = siteConfig const relativePath = slash(path.relative(srcDir, file)) - const env: MarkdownEnv = { path: file, relativePath, cleanUrls } + mdEnv = { path: file, relativePath, cleanUrls } let src = fs.readFileSync(file, 'utf-8') src = processIncludes(srcDir, src, file, []) - if (options._render) return options._render(src, env, md) - const html = md.render(src, env) - return env.frontmatter?.search === false ? '' : html + if (options._render) return options._render(src, mdEnv, md) + const html = md.render(src, mdEnv) + return mdEnv.frontmatter?.search === false ? '' : html } const indexByLocales = new Map>() @@ -260,7 +261,9 @@ function splitPageIntoSections(html: string) { const level = parseInt(result[i]) - 1 const heading = result[i + 1] const headingResult = headingContentRegex.exec(heading) - const title = clearHtmlTags(headingResult?.[1] ?? '').trim() + const title = replaceInterpolation( + clearHtmlTags(headingResult?.[1] ?? '').trim() + ) const anchor = headingResult?.[2] ?? '' const content = result[i + 2] if (!title || !content) continue @@ -284,3 +287,20 @@ function getSearchableText(content: string) { function clearHtmlTags(str: string) { return str.replace(/<[^>]*>/g, '') } + +function replaceInterpolation(str: string) { + if (!mdEnv.frontmatter) { + return str + } + + return str.replace(/{{\s*([^}]+)\s*}}/g, (_, expression: string) => { + const properties = expression.trim().split('.') + let value: Record = { $frontmatter: { ...mdEnv.frontmatter } } + + for (let prop of properties) { + value = value?.[prop] + } + + return value ? toDisplayString(value) : str + }) +}