From a99dcf94436d6cbbd53ef5481a6ec5ffd8d887d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=83=BD=E5=AE=81?= Date: Mon, 3 Jul 2023 13:02:04 +0800 Subject: [PATCH 01/36] fix(types): export duplicate type `Sidebar` (#2573) --- docs/reference/default-theme-sidebar.md | 2 +- theme.d.ts | 2 +- types/default-theme.d.ts | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/reference/default-theme-sidebar.md b/docs/reference/default-theme-sidebar.md index ab7e729b..9a64a074 100644 --- a/docs/reference/default-theme-sidebar.md +++ b/docs/reference/default-theme-sidebar.md @@ -186,7 +186,7 @@ export default { Returns sidebar-related data. The returned object has the following type: ```ts -export interface Sidebar { +export interface DocSidebar { isOpen: Ref sidebar: ComputedRef sidebarGroups: ComputedRef diff --git a/theme.d.ts b/theme.d.ts index 7119c7d1..42f592e9 100644 --- a/theme.d.ts +++ b/theme.d.ts @@ -20,4 +20,4 @@ declare const theme: { export default theme export type { DefaultTheme } from './types/default-theme.js' -export const useSidebar: () => DefaultTheme.SideBar +export const useSidebar: () => DefaultTheme.DocSideBar diff --git a/types/default-theme.d.ts b/types/default-theme.d.ts index bb9dac05..d4cc4cbf 100644 --- a/types/default-theme.d.ts +++ b/types/default-theme.d.ts @@ -1,3 +1,4 @@ +import { type ComputedRef, type Ref } from 'vue' import type { DocSearchProps } from './docsearch.js' import type { LocalSearchTranslations } from './local-search.js' import type { PageData } from './shared.js' @@ -222,7 +223,7 @@ export namespace DefaultTheme { /** * ReturnType of `useSidebar` */ - export interface Sidebar { + export interface DocSidebar { isOpen: Ref sidebar: ComputedRef sidebarGroups: ComputedRef From faab56f23520165f861cc29d341513f7f269ffd3 Mon Sep 17 00:00:00 2001 From: Divyansh Singh <40380293+brc-dd@users.noreply.github.com> Date: Mon, 3 Jul 2023 10:34:18 +0530 Subject: [PATCH 02/36] release: v1.0.0-beta.5 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 137380d0..5ce5c80c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# [1.0.0-beta.5](https://github.com/vuejs/vitepress/compare/v1.0.0-beta.4...v1.0.0-beta.5) (2023-07-03) + +### Bug Fixes + +- **types:** `Sidebar` was exported multiple times breaking the config ([#2573](https://github.com/vuejs/vitepress/issues/2573)) ([a99dcf9](https://github.com/vuejs/vitepress/commit/a99dcf94436d6cbbd53ef5481a6ec5ffd8d887d2)) + # [1.0.0-beta.4](https://github.com/vuejs/vitepress/compare/v1.0.0-beta.3...v1.0.0-beta.4) (2023-07-02) ### Bug Fixes diff --git a/package.json b/package.json index c525f8f5..a6a5555d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vitepress", - "version": "1.0.0-beta.4", + "version": "1.0.0-beta.5", "description": "Vite & Vue powered static site generator", "type": "module", "packageManager": "pnpm@8.6.5", From 32d65d40c55b7df1a814820d5117c360f9d449a4 Mon Sep 17 00:00:00 2001 From: Divyansh Singh <40380293+brc-dd@users.noreply.github.com> Date: Tue, 4 Jul 2023 11:48:35 +0530 Subject: [PATCH 03/36] perf: fix race conditions with cache (#2579) --- src/node/build/build.ts | 4 ++-- src/node/build/bundle.ts | 12 ++++++------ src/node/build/render.ts | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/node/build/build.ts b/src/node/build/build.ts index 3713ead3..ed71ffc3 100644 --- a/src/node/build/build.ts +++ b/src/node/build/build.ts @@ -56,12 +56,12 @@ export async function build( ) as OutputChunk) const cssChunk = ( - siteConfig.mpa ? serverResult : clientResult + siteConfig.mpa ? serverResult : clientResult! ).output.find( (chunk) => chunk.type === 'asset' && chunk.fileName.endsWith('.css') ) as OutputAsset - const assets = (siteConfig.mpa ? serverResult : clientResult).output + const assets = (siteConfig.mpa ? serverResult : clientResult!).output .filter( (chunk) => chunk.type === 'asset' && !chunk.fileName.endsWith('.css') ) diff --git a/src/node/build/bundle.ts b/src/node/build/bundle.ts index 179b908c..fda61462 100644 --- a/src/node/build/bundle.ts +++ b/src/node/build/bundle.ts @@ -31,7 +31,7 @@ export async function bundle( config: SiteConfig, options: BuildOptions ): Promise<{ - clientResult: RollupOutput + clientResult: RollupOutput | null serverResult: RollupOutput pageToHashMap: Record }> { @@ -142,16 +142,16 @@ export async function bundle( } }) - let clientResult: RollupOutput + let clientResult: RollupOutput | null let serverResult: RollupOutput const spinner = ora() spinner.start('building client + server bundles...') try { - ;[clientResult, serverResult] = await (Promise.all([ - config.mpa ? null : build(await resolveViteConfig(false)), - build(await resolveViteConfig(true)) - ]) as Promise<[RollupOutput, RollupOutput]>) + clientResult = config.mpa + ? null + : ((await build(await resolveViteConfig(false))) as RollupOutput) + serverResult = (await build(await resolveViteConfig(true))) as RollupOutput } catch (e) { spinner.stopAndPersist({ symbol: failMark diff --git a/src/node/build/render.ts b/src/node/build/render.ts index b3be8cc9..6bd51f13 100644 --- a/src/node/build/render.ts +++ b/src/node/build/render.ts @@ -24,8 +24,8 @@ export async function renderPage( config: SiteConfig, page: string, // foo.md result: RollupOutput | null, - appChunk: OutputChunk | undefined, - cssChunk: OutputAsset | undefined, + appChunk: OutputChunk | null, + cssChunk: OutputAsset | null, assets: string[], pageToHashMap: Record, hashMapString: string, From d5ccc52048d64c0e85bf44f36da8b42978f075b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=83=BD=E5=AE=81?= Date: Tue, 4 Jul 2023 15:02:16 +0800 Subject: [PATCH 04/36] refactor: optimize snippet markdown plugin code (#2580) --- src/node/markdown/plugins/snippet.ts | 56 ++++++++++++++-------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/src/node/markdown/plugins/snippet.ts b/src/node/markdown/plugins/snippet.ts index 480baf4a..4efea38a 100644 --- a/src/node/markdown/plugins/snippet.ts +++ b/src/node/markdown/plugins/snippet.ts @@ -145,36 +145,38 @@ export const snippetPlugin = (md: MarkdownIt, srcDir: string) => { // @ts-ignore const [src, regionName] = token.src ?? [] - if (src) { - if (loader) { - loader.addDependency(src) - } - const isAFile = fs.lstatSync(src).isFile() - if (fs.existsSync(src) && isAFile) { - let content = fs.readFileSync(src, 'utf8') - - if (regionName) { - const lines = content.split(/\r?\n/) - const region = findRegion(lines, regionName) - - if (region) { - content = dedent( - lines - .slice(region.start, region.end) - .filter((line: string) => !region.regexp.test(line.trim())) - .join('\n') - ) - } - } + if (!src) return fence(...args) - token.content = content - } else { - token.content = isAFile - ? `Code snippet path not found: ${src}` - : `Invalid code snippet option` - token.info = '' + if (loader) { + loader.addDependency(src) + } + + const isAFile = fs.lstatSync(src).isFile() + if (!fs.existsSync(src) || !isAFile) { + token.content = isAFile + ? `Code snippet path not found: ${src}` + : `Invalid code snippet option` + token.info = '' + return fence(...args) + } + + let content = fs.readFileSync(src, 'utf8') + + if (regionName) { + const lines = content.split(/\r?\n/) + const region = findRegion(lines, regionName) + + if (region) { + content = dedent( + lines + .slice(region.start, region.end) + .filter((line) => !region.regexp.test(line.trim())) + .join('\n') + ) } } + + token.content = content return fence(...args) } From f60b32f02f4236ec0c29f450c4fe79d6aabf5995 Mon Sep 17 00:00:00 2001 From: Divyansh Singh <40380293+brc-dd@users.noreply.github.com> Date: Tue, 4 Jul 2023 13:06:46 +0530 Subject: [PATCH 05/36] fix(hmr): allow disabling md cache during dev (#2581) --- src/node/markdown/env.ts | 1 + src/node/markdown/markdown.ts | 1 + src/node/markdown/plugins/snippet.ts | 6 +++--- src/node/markdownToVue.ts | 17 +++++++++++------ 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/node/markdown/env.ts b/src/node/markdown/env.ts index b079c281..7ed29a31 100644 --- a/src/node/markdown/env.ts +++ b/src/node/markdown/env.ts @@ -36,4 +36,5 @@ export interface MarkdownEnv { relativePath: string cleanUrls: boolean links?: string[] + includes?: string[] } diff --git a/src/node/markdown/markdown.ts b/src/node/markdown/markdown.ts index 64de3b18..22298c8e 100644 --- a/src/node/markdown/markdown.ts +++ b/src/node/markdown/markdown.ts @@ -50,6 +50,7 @@ export interface MarkdownOptions extends MarkdownIt.Options { languages?: ILanguageRegistration[] toc?: TocPluginOptions externalLinks?: Record + cache?: boolean } export type MarkdownRenderer = MarkdownIt diff --git a/src/node/markdown/plugins/snippet.ts b/src/node/markdown/plugins/snippet.ts index 4efea38a..b558f35b 100644 --- a/src/node/markdown/plugins/snippet.ts +++ b/src/node/markdown/plugins/snippet.ts @@ -140,15 +140,15 @@ export const snippetPlugin = (md: MarkdownIt, srcDir: string) => { const fence = md.renderer.rules.fence! md.renderer.rules.fence = (...args) => { - const [tokens, idx, , { loader }] = args + const [tokens, idx, , { includes }] = args const token = tokens[idx] // @ts-ignore const [src, regionName] = token.src ?? [] if (!src) return fence(...args) - if (loader) { - loader.addDependency(src) + if (includes) { + includes.push(src) } const isAFile = fs.lstatSync(src).isFile() diff --git a/src/node/markdownToVue.ts b/src/node/markdownToVue.ts index 1629f2d8..483c3791 100644 --- a/src/node/markdownToVue.ts +++ b/src/node/markdownToVue.ts @@ -67,10 +67,12 @@ export async function createMarkdownToVueRenderFn( const relativePath = slash(path.relative(srcDir, file)) const cacheKey = JSON.stringify({ src, file }) - const cached = cache.get(cacheKey) - if (cached) { - debug(`[cache hit] ${relativePath}`) - return cached + if (isBuild || options.cache !== false) { + const cached = cache.get(cacheKey) + if (cached) { + debug(`[cache hit] ${relativePath}`) + return cached + } } const start = Date.now() @@ -125,7 +127,8 @@ export async function createMarkdownToVueRenderFn( const env: MarkdownEnv = { path: file, relativePath, - cleanUrls + cleanUrls, + includes } const html = md.render(src, env) const { @@ -243,7 +246,9 @@ export async function createMarkdownToVueRenderFn( deadLinks, includes } - cache.set(cacheKey, result) + if (isBuild || options.cache !== false) { + cache.set(cacheKey, result) + } return result } } From e8074e60ec5941e7b447f21a289e59e9a91a9e33 Mon Sep 17 00:00:00 2001 From: Divyansh Singh <40380293+brc-dd@users.noreply.github.com> Date: Wed, 5 Jul 2023 11:22:51 +0530 Subject: [PATCH 06/36] fix(build): resolve nested md inclusions properly closes #2584 closes #2586 Co-authored-by: Jeff Tian --- .../markdown-extensions/markdown-extensions.test.ts | 11 ++++++++++- __tests__/e2e/markdown-extensions/nested-include.md | 2 ++ .../markdown-extensions/subfolder/inside-subfolder.md | 3 +++ .../markdown-extensions/subfolder/subsub/subsub.md | 3 +++ .../subfolder/subsub/subsubsub/subsubsub.md | 1 + src/node/markdownToVue.ts | 8 ++++---- 6 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 __tests__/e2e/markdown-extensions/subfolder/inside-subfolder.md create mode 100644 __tests__/e2e/markdown-extensions/subfolder/subsub/subsub.md create mode 100644 __tests__/e2e/markdown-extensions/subfolder/subsub/subsubsub/subsubsub.md diff --git a/__tests__/e2e/markdown-extensions/markdown-extensions.test.ts b/__tests__/e2e/markdown-extensions/markdown-extensions.test.ts index d3c38c0f..750d598e 100644 --- a/__tests__/e2e/markdown-extensions/markdown-extensions.test.ts +++ b/__tests__/e2e/markdown-extensions/markdown-extensions.test.ts @@ -65,7 +65,7 @@ describe('Table of Contents', () => { test('render toc', async () => { const items = page.locator('#table-of-contents + nav ul li') const count = await items.count() - expect(count).toBe(33) + expect(count).toBe(35) }) }) @@ -242,6 +242,15 @@ describe('Markdown File Inclusion', () => { expect(await h1.getAttribute('id')).toBe('foo-1') }) + test('render markdown using nested inclusion inside sub folder', async () => { + const h1 = page.locator('#after-foo + h1') + expect(await h1.getAttribute('id')).toBe('inside-sub-folder') + const h2 = page.locator('#after-foo + h1 + h2') + expect(await h2.getAttribute('id')).toBe('sub-sub') + const h3 = page.locator('#after-foo + h1 + h2 + h3') + expect(await h3.getAttribute('id')).toBe('sub-sub-sub') + }) + test('support selecting range', async () => { const h2 = page.locator('#markdown-file-inclusion-with-range + h2') expect(trim(await h2.textContent())).toBe('Region') diff --git a/__tests__/e2e/markdown-extensions/nested-include.md b/__tests__/e2e/markdown-extensions/nested-include.md index fd6cb58a..eb7eb718 100644 --- a/__tests__/e2e/markdown-extensions/nested-include.md +++ b/__tests__/e2e/markdown-extensions/nested-include.md @@ -1,3 +1,5 @@ ### After Foo + + diff --git a/__tests__/e2e/markdown-extensions/subfolder/inside-subfolder.md b/__tests__/e2e/markdown-extensions/subfolder/inside-subfolder.md new file mode 100644 index 00000000..8477113a --- /dev/null +++ b/__tests__/e2e/markdown-extensions/subfolder/inside-subfolder.md @@ -0,0 +1,3 @@ +# Inside sub folder + + diff --git a/__tests__/e2e/markdown-extensions/subfolder/subsub/subsub.md b/__tests__/e2e/markdown-extensions/subfolder/subsub/subsub.md new file mode 100644 index 00000000..70d0332e --- /dev/null +++ b/__tests__/e2e/markdown-extensions/subfolder/subsub/subsub.md @@ -0,0 +1,3 @@ +## Sub sub + + diff --git a/__tests__/e2e/markdown-extensions/subfolder/subsub/subsubsub/subsubsub.md b/__tests__/e2e/markdown-extensions/subfolder/subsub/subsubsub/subsubsub.md new file mode 100644 index 00000000..9b4e5e69 --- /dev/null +++ b/__tests__/e2e/markdown-extensions/subfolder/subsub/subsubsub/subsubsub.md @@ -0,0 +1 @@ +### Sub sub sub diff --git a/src/node/markdownToVue.ts b/src/node/markdownToVue.ts index 483c3791..f8edcbd4 100644 --- a/src/node/markdownToVue.ts +++ b/src/node/markdownToVue.ts @@ -90,7 +90,7 @@ export async function createMarkdownToVueRenderFn( // resolve includes let includes: string[] = [] - function processIncludes(src: string): string { + function processIncludes(src: string, file: string): string { return src.replace(includesRE, (m: string, m1: string) => { if (!m1.length) return m @@ -100,7 +100,7 @@ export async function createMarkdownToVueRenderFn( try { const includePath = atPresent ? path.join(srcDir, m1.slice(m1[1] === '/' ? 2 : 1)) - : path.join(path.dirname(fileOrig), m1) + : path.join(path.dirname(file), m1) let content = fs.readFileSync(includePath, 'utf-8') if (range) { const [, startLine, endLine] = range @@ -114,14 +114,14 @@ export async function createMarkdownToVueRenderFn( } includes.push(slash(includePath)) // recursively process includes in the content - return processIncludes(content) + return processIncludes(content, includePath) } catch (error) { return m // silently ignore error if file is not present } }) } - src = processIncludes(src) + src = processIncludes(src, fileOrig) // reset env before render const env: MarkdownEnv = { From 9fee5542cb4bd0b83ccad5d625cb4eca8f8abb25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=83=BD=E5=AE=81?= Date: Wed, 5 Jul 2023 14:51:17 +0800 Subject: [PATCH 07/36] feat(search): support `minisearch` customization (#2576) Co-authored-by: Divyansh Singh <40380293+brc-dd@users.noreply.github.com> --- docs/reference/default-theme-search.md | 36 +++++++++++++++++++ .../components/VPLocalSearchBox.vue | 34 +++++++++++++----- src/node/plugins/localSearchPlugin.ts | 16 +++++---- types/default-theme.d.ts | 17 ++++++++- 4 files changed, 87 insertions(+), 16 deletions(-) diff --git a/docs/reference/default-theme-search.md b/docs/reference/default-theme-search.md index 6f5925ca..13f5ded0 100644 --- a/docs/reference/default-theme-search.md +++ b/docs/reference/default-theme-search.md @@ -1,3 +1,7 @@ +--- +outline: deep +--- + # Search ## Local Search @@ -58,6 +62,38 @@ export default defineConfig({ }) ``` +### miniSearch options + +You can configure MiniSearch like this: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + search: { + provider: 'local', + options: { + miniSearch: { + /** + * @type {Pick} + */ + options: { /* ... */ }, + /** + * @type {import('minisearch').SearchOptions} + * @default + * { fuzzy: 0.2, prefix: true, boost: { title: 4, text: 2, titles: 1 } } + */ + searchOptions: { /* ... */ } + } + } + } + } +}) +``` + +Learn more in [MiniSearch docs](https://lucaong.github.io/minisearch/classes/_minisearch_.minisearch.html). + ## Algolia Search VitePress supports searching your docs site using [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch). Refer their getting started guide. In your `.vitepress/config.ts` you'll need to provide at least the following to make it work: diff --git a/src/client/theme-default/components/VPLocalSearchBox.vue b/src/client/theme-default/components/VPLocalSearchBox.vue index 5614e336..0e1eddac 100644 --- a/src/client/theme-default/components/VPLocalSearchBox.vue +++ b/src/client/theme-default/components/VPLocalSearchBox.vue @@ -80,8 +80,12 @@ const searchIndex = computedAsync(async () => searchOptions: { fuzzy: 0.2, prefix: true, - boost: { title: 4, text: 2, titles: 1 } - } + boost: { title: 4, text: 2, titles: 1 }, + ...(theme.value.search?.provider === 'local' && + theme.value.search.options?.miniSearch?.searchOptions) + }, + ...(theme.value.search?.provider === 'local' && + theme.value.search.options?.miniSearch?.options) } ) ) @@ -396,8 +400,16 @@ function formMarkRegex(terms: Set) {
-