From 5b10b3b940fe8476412b06d301ba23587b56b136 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Thu, 9 Mar 2023 10:10:43 +0100 Subject: [PATCH 1/7] feat: editLink can accept function --- docs/reference/default-theme-edit-link.md | 18 ++++++++++++++++++ .../theme-default/composables/edit-link.ts | 7 ++++++- types/default-theme.d.ts | 2 +- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/docs/reference/default-theme-edit-link.md b/docs/reference/default-theme-edit-link.md index 64e74b316965..d643e39c97ed 100644 --- a/docs/reference/default-theme-edit-link.md +++ b/docs/reference/default-theme-edit-link.md @@ -14,6 +14,24 @@ export default { The `pattern` option defines the URL structure for the link, and `:path` is going to be replaced with the page path. +You can also put a function that accepts `relativePath` as the argument and returns the URL string. + +```js +export default { + themeConfig: { + editLink: { + pattern: ({ relativePath }) => { + if (relativePath.startsWith('packages/')) { + return `https://github.com/acme/monorepo/edit/main/${relativePath}` + } else { + return `https://github.com/acme/monorepo/edit/main/docs/${relativePath}` + } + } + } + } +} +``` + By default, this will add the link text "Edit this page" at the bottom of the doc page. You may customize this text by defining the `text` option. ```js diff --git a/src/client/theme-default/composables/edit-link.ts b/src/client/theme-default/composables/edit-link.ts index 929b645ae4a6..818998b655ce 100644 --- a/src/client/theme-default/composables/edit-link.ts +++ b/src/client/theme-default/composables/edit-link.ts @@ -7,7 +7,12 @@ export function useEditLink() { return computed(() => { const { text = 'Edit this page', pattern = '' } = theme.value.editLink || {} const { relativePath } = page.value - const url = pattern.replace(/:path/g, relativePath) + let url: string + if (typeof pattern === 'function') { + url = pattern({ relativePath }) + } else { + url = pattern.replace(/:path/g, relativePath) + } return { url, text } }) diff --git a/types/default-theme.d.ts b/types/default-theme.d.ts index 7abab0b6fdfe..69e50b647274 100644 --- a/types/default-theme.d.ts +++ b/types/default-theme.d.ts @@ -216,7 +216,7 @@ export namespace DefaultTheme { * * @example 'https://github.com/vuejs/vitepress/edit/main/docs/:path' */ - pattern: string + pattern: string | ((payload: { relativePath: string }) => string) /** * Custom text for edit link. From ffa200b8fe0ddd059daf2089d303cf9f855aef43 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Thu, 9 Mar 2023 10:37:17 +0100 Subject: [PATCH 2/7] fix: serialize the function --- src/client/app/utils.ts | 15 +++++++++++++++ src/client/index.ts | 2 +- src/node/plugin.ts | 7 +++++-- src/node/utils/fnSerialize.ts | 14 ++++++++++++++ 4 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 src/node/utils/fnSerialize.ts diff --git a/src/client/app/utils.ts b/src/client/app/utils.ts index 7f64ee5da13b..9fe766c8175d 100644 --- a/src/client/app/utils.ts +++ b/src/client/app/utils.ts @@ -56,3 +56,18 @@ export function pathToFile(path: string): string { return pagePath } + +export function deserializeFunctions (value: any): any { + if (Array.isArray(value)) { + return value.map(deserializeFunctions) + } else if (typeof value === 'object' && value !== null) { + return Object.keys(value).reduce((acc, key) => { + acc[key] = deserializeFunctions(value[key]) + return acc + }, {} as any) + } else if (typeof value === 'string' && value.startsWith('_vp-fn_')) { + return new Function(`return ${value.slice(7)}`)() + } else { + return value + } +} diff --git a/src/client/index.ts b/src/client/index.ts index 1ed560d902a1..e58c61ef8f28 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -19,7 +19,7 @@ export { useData } from './app/data.js' export { useRouter, useRoute } from './app/router.js' // utilities -export { inBrowser, withBase } from './app/utils.js' +export { inBrowser, withBase, deserializeFunctions } from './app/utils.js' // components export { Content } from './app/components/Content.js' diff --git a/src/node/plugin.ts b/src/node/plugin.ts index 6441ba744b50..86ee7e5b3f06 100644 --- a/src/node/plugin.ts +++ b/src/node/plugin.ts @@ -22,6 +22,7 @@ import { staticDataPlugin } from './plugins/staticDataPlugin' import { webFontsPlugin } from './plugins/webFontsPlugin' import { dynamicRoutesPlugin } from './plugins/dynamicRoutesPlugin' import { rewritesPlugin } from './plugins/rewritesPlugin' +import { serializeFunctions } from './utils/fnSerialize.js' declare module 'vite' { interface UserConfig { @@ -158,9 +159,11 @@ export async function createVitePressPlugin( if (config.command === 'build') { data = { ...siteData, head: [] } } - return `export default JSON.parse(${JSON.stringify( + data = serializeFunctions(data) + return `import { deserializeFunctions } from 'vitepress/client' + export default deserializeFunctions(JSON.parse(${JSON.stringify( JSON.stringify(data) - )})` + )}))` } }, diff --git a/src/node/utils/fnSerialize.ts b/src/node/utils/fnSerialize.ts new file mode 100644 index 000000000000..1e0992bff852 --- /dev/null +++ b/src/node/utils/fnSerialize.ts @@ -0,0 +1,14 @@ +export function serializeFunctions (value: any): any { + if (Array.isArray(value)) { + return value.map(serializeFunctions) + } else if (typeof value === 'object' && value !== null) { + return Object.keys(value).reduce((acc, key) => { + acc[key] = serializeFunctions(value[key]) + return acc + }, {} as any) + } else if (typeof value === 'function') { + return `_vp-fn_${value.toString()}` + } else { + return value + } +} From 5123d51020b72c71a25dc9dc096601eed9556de1 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Thu, 9 Mar 2023 10:38:51 +0100 Subject: [PATCH 3/7] docs: serialization note --- docs/.vitepress/config.ts | 3 ++- docs/reference/default-theme-edit-link.md | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index db4a23d9c0d1..cfc101b19c22 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -23,7 +23,8 @@ export default defineConfig({ }, editLink: { - pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + // pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + pattern: ({ relativePath }) => `https://github.com/vuejs/vitepress/edit/main/docs/${relativePath}`, text: 'Edit this page on GitHub' }, diff --git a/docs/reference/default-theme-edit-link.md b/docs/reference/default-theme-edit-link.md index d643e39c97ed..7f068f295ed9 100644 --- a/docs/reference/default-theme-edit-link.md +++ b/docs/reference/default-theme-edit-link.md @@ -14,7 +14,7 @@ export default { The `pattern` option defines the URL structure for the link, and `:path` is going to be replaced with the page path. -You can also put a function that accepts `relativePath` as the argument and returns the URL string. +You can also put a pure function that accepts `relativePath` as the argument and returns the URL string. ```js export default { @@ -32,6 +32,8 @@ export default { } ``` +It should not have side-effects nor access anything outside of its scope since it will be serialized and executed in the browser. + By default, this will add the link text "Edit this page" at the bottom of the doc page. You may customize this text by defining the `text` option. ```js From 5a0ded92785d6e78b18c6b5c70c3a39f77a90fbc Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Thu, 9 Mar 2023 10:39:38 +0100 Subject: [PATCH 4/7] revert: config change --- docs/.vitepress/config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index cfc101b19c22..04d96fa3d092 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -23,8 +23,8 @@ export default defineConfig({ }, editLink: { - // pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', - pattern: ({ relativePath }) => `https://github.com/vuejs/vitepress/edit/main/docs/${relativePath}`, + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + // pattern: ({ relativePath }) => `https://github.com/vuejs/vitepress/edit/main/docs/${relativePath}`, text: 'Edit this page on GitHub' }, From 86034e1f00e08c6bcc349da9bf4bbad037fa8476 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Thu, 9 Mar 2023 10:51:11 +0100 Subject: [PATCH 5/7] fix: prettier --- src/client/app/utils.ts | 2 +- src/node/utils/fnSerialize.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/app/utils.ts b/src/client/app/utils.ts index 9fe766c8175d..d126d7412e4a 100644 --- a/src/client/app/utils.ts +++ b/src/client/app/utils.ts @@ -57,7 +57,7 @@ export function pathToFile(path: string): string { return pagePath } -export function deserializeFunctions (value: any): any { +export function deserializeFunctions(value: any): any { if (Array.isArray(value)) { return value.map(deserializeFunctions) } else if (typeof value === 'object' && value !== null) { diff --git a/src/node/utils/fnSerialize.ts b/src/node/utils/fnSerialize.ts index 1e0992bff852..6b87035ef768 100644 --- a/src/node/utils/fnSerialize.ts +++ b/src/node/utils/fnSerialize.ts @@ -1,4 +1,4 @@ -export function serializeFunctions (value: any): any { +export function serializeFunctions(value: any): any { if (Array.isArray(value)) { return value.map(serializeFunctions) } else if (typeof value === 'object' && value !== null) { From 87f7952556e9bcd08a8e5d13dff73f8afeb576bb Mon Sep 17 00:00:00 2001 From: Divyansh Singh <40380293+brc-dd@users.noreply.github.com> Date: Sat, 11 Mar 2023 21:51:09 +0530 Subject: [PATCH 6/7] chore: organize imports --- src/client/index.ts | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/client/index.ts b/src/client/index.ts index f52d16db700b..d00b9876ebd6 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -2,24 +2,31 @@ // so the user can do `import { useRoute, useSiteData } from 'vitepress'` // generic types -export type { Router, Route } from './app/router.js' export type { VitePressData } from './app/data.js' +export type { Route, Router } from './app/router.js' + // theme types -export type { Theme, EnhanceAppContext } from './app/theme.js' +export type { EnhanceAppContext, Theme } from './app/theme.js' + // shared types export type { - PageData, - SiteData, HeadConfig, - Header + Header, + PageData, + SiteData } from '../../types/shared.js' // composables export { useData } from './app/data.js' -export { useRouter, useRoute } from './app/router.js' +export { useRoute, useRouter } from './app/router.js' // utilities -export { inBrowser, withBase, deserializeFunctions, onContentUpdated } from './app/utils.js' +export { + deserializeFunctions, + inBrowser, + onContentUpdated, + withBase +} from './app/utils.js' // components export { Content } from './app/components/Content.js' From 84272e09f502fdf6e0f98b143d4fbf4549434b36 Mon Sep 17 00:00:00 2001 From: Divyansh Singh <40380293+brc-dd@users.noreply.github.com> Date: Sat, 11 Mar 2023 22:02:25 +0530 Subject: [PATCH 7/7] chore: remove comment --- docs/.vitepress/config.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 3d886a333730..2b6e4c86206b 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -39,7 +39,6 @@ export default defineConfig({ editLink: { pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', - // pattern: ({ relativePath }) => `https://github.com/vuejs/vitepress/edit/main/docs/${relativePath}`, text: 'Edit this page on GitHub' },