From c6ff5c76867dc59d5548cb33fd8447e23712bef5 Mon Sep 17 00:00:00 2001 From: g-dx Date: Sun, 10 Sep 2023 15:47:49 +0100 Subject: [PATCH] feat: process md includes before building local search index (#2906) --- src/node/markdownToVue.ts | 37 ++---------------------- src/node/plugins/localSearchPlugin.ts | 4 ++- src/node/utils/processIncludes.ts | 41 +++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 36 deletions(-) create mode 100644 src/node/utils/processIncludes.ts diff --git a/src/node/markdownToVue.ts b/src/node/markdownToVue.ts index e821f74c..c944e379 100644 --- a/src/node/markdownToVue.ts +++ b/src/node/markdownToVue.ts @@ -17,11 +17,10 @@ import { type PageData } from './shared' import { getGitTimestamp } from './utils/getGitTimestamp' +import { processIncludes } from './utils/processIncludes' const debug = _debug('vitepress:md') const cache = new LRUCache({ max: 1024 }) -const includesRE = //g -const rangeRE = /\{(\d*),(\d*)\}$/ export interface MarkdownCompileResult { vueSrc: string @@ -89,39 +88,7 @@ export async function createMarkdownToVueRenderFn( // resolve includes let includes: string[] = [] - - function processIncludes(src: string, file: string): string { - return src.replace(includesRE, (m: string, m1: string) => { - if (!m1.length) return m - - const range = m1.match(rangeRE) - range && (m1 = m1.slice(0, -range[0].length)) - const atPresent = m1[0] === '@' - try { - const includePath = atPresent - ? path.join(srcDir, m1.slice(m1[1] === '/' ? 2 : 1)) - : path.join(path.dirname(file), m1) - let content = fs.readFileSync(includePath, 'utf-8') - if (range) { - const [, startLine, endLine] = range - const lines = content.split(/\r?\n/) - content = lines - .slice( - startLine ? parseInt(startLine, 10) - 1 : undefined, - endLine ? parseInt(endLine, 10) : undefined - ) - .join('\n') - } - includes.push(slash(includePath)) - // recursively process includes in the content - return processIncludes(content, includePath) - } catch (error) { - return m // silently ignore error if file is not present - } - }) - } - - src = processIncludes(src, fileOrig) + src = processIncludes(srcDir, src, fileOrig, includes) // reset env before render const env: MarkdownEnv = { diff --git a/src/node/plugins/localSearchPlugin.ts b/src/node/plugins/localSearchPlugin.ts index 019a7ea4..4b0037cc 100644 --- a/src/node/plugins/localSearchPlugin.ts +++ b/src/node/plugins/localSearchPlugin.ts @@ -11,6 +11,7 @@ import { type DefaultTheme, type MarkdownEnv } from '../shared' +import { processIncludes } from '../utils/processIncludes' const debug = _debug('vitepress:local-search') @@ -56,7 +57,8 @@ export async function localSearchPlugin( const { srcDir, cleanUrls = false } = siteConfig const relativePath = slash(path.relative(srcDir, file)) const env: MarkdownEnv = { path: file, relativePath, cleanUrls } - const src = fs.readFileSync(file, 'utf-8') + 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 diff --git a/src/node/utils/processIncludes.ts b/src/node/utils/processIncludes.ts new file mode 100644 index 00000000..43808ba4 --- /dev/null +++ b/src/node/utils/processIncludes.ts @@ -0,0 +1,41 @@ +import path from 'path' +import fs from 'fs-extra' +import { slash } from '../shared' + +export function processIncludes( + srcDir: string, + src: string, + file: string, + includes: string[] +): string { + const includesRE = //g + const rangeRE = /\{(\d*),(\d*)\}$/ + return src.replace(includesRE, (m: string, m1: string) => { + if (!m1.length) return m + + const range = m1.match(rangeRE) + range && (m1 = m1.slice(0, -range[0].length)) + const atPresent = m1[0] === '@' + try { + const includePath = atPresent + ? path.join(srcDir, m1.slice(m1[1] === '/' ? 2 : 1)) + : path.join(path.dirname(file), m1) + let content = fs.readFileSync(includePath, 'utf-8') + if (range) { + const [, startLine, endLine] = range + const lines = content.split(/\r?\n/) + content = lines + .slice( + startLine ? parseInt(startLine, 10) - 1 : undefined, + endLine ? parseInt(endLine, 10) : undefined + ) + .join('\n') + } + includes.push(slash(includePath)) + // recursively process includes in the content + return processIncludes(srcDir, content, includePath, includes) + } catch (error) { + return m // silently ignore error if file is not present + } + }) +}