diff --git a/apps/www/.vitepress/config.mts b/apps/www/.vitepress/config.mts index cfb84614..d729444e 100644 --- a/apps/www/.vitepress/config.mts +++ b/apps/www/.vitepress/config.mts @@ -8,6 +8,7 @@ import { cssVariables } from './theme/config/shiki' // import { transformerMetaWordHighlight, transformerNotationWordHighlight } from '@shikijs/transformers' import { siteConfig } from './theme/config/site' import ComponentPreviewPlugin from './theme/plugins/previewer' +import CodeWrapperPlugin from './theme/plugins/codewrapper' // https://vitepress.dev/reference/site-config export default defineConfig({ @@ -60,6 +61,7 @@ export default defineConfig({ ], config(md) { md.use(ComponentPreviewPlugin) + md.use(CodeWrapperPlugin) }, }, rewrites: { diff --git a/apps/www/.vitepress/theme/components/CodeWrapper.ts b/apps/www/.vitepress/theme/components/CodeWrapper.ts new file mode 100644 index 00000000..68526dcf --- /dev/null +++ b/apps/www/.vitepress/theme/components/CodeWrapper.ts @@ -0,0 +1,37 @@ +import { type VNode, cloneVNode, defineComponent } from 'vue' +import { useConfigStore } from '@/stores/config' + +export default defineComponent( + (props, { slots }) => { + const { codeConfig } = useConfigStore() + + return () => { + const clonedVNode = slots.default?.()?.[0] ? cloneVNode(slots.default?.()?.[0]) : undefined + // @ts-expect-error cloneVNode + const preVNode = [...clonedVNode?.children].find((node: VNode) => node.type === 'pre') as VNode + // @ts-expect-error cloneVNode + const codeVNode = preVNode.children?.at(0) as VNode + if (codeVNode) { + // @ts-expect-error cloneVNode + [...codeVNode.children] + .filter((node: VNode) => node.type === 'span') + .forEach((node: VNode) => { + if (node.children) { + // @ts-expect-error cloneVNode + [...node.children].forEach((childNode: VNode) => { + if (typeof childNode.children === 'string') { + childNode.children = childNode.children.replaceAll('@/components', codeConfig.value.componentsPath) + childNode.children = childNode.children.replaceAll('@/libs', codeConfig.value.utilsPath) + } + }) + } + }) + + return clonedVNode + } + else { + return slots.default?.() + } + } + }, +) diff --git a/apps/www/.vitepress/theme/components/index.ts b/apps/www/.vitepress/theme/components/index.ts index b254f15f..8e6df429 100644 --- a/apps/www/.vitepress/theme/components/index.ts +++ b/apps/www/.vitepress/theme/components/index.ts @@ -1,3 +1,4 @@ +export { default as CodeWrapper } from './CodeWrapper' export { default as ComponentPreview } from './ComponentPreview.vue' export { default as TabPreview } from './TabPreview.vue' export { default as TabMarkdown } from './TabMarkdown.vue' diff --git a/apps/www/.vitepress/theme/plugins/codewrapper.ts b/apps/www/.vitepress/theme/plugins/codewrapper.ts new file mode 100644 index 00000000..1314d44b --- /dev/null +++ b/apps/www/.vitepress/theme/plugins/codewrapper.ts @@ -0,0 +1,19 @@ +import type { MarkdownRenderer } from 'vitepress' + +export default function (md: MarkdownRenderer) { + const defaultFenceRenderer = md.renderer.rules.fence + if (!defaultFenceRenderer) + return + + md.renderer.rules.fence = function (tokens, idx, options, env, self) { + // Check if this is a code block + const token = tokens[idx] + if (token && token.tag === 'code' && token.info) { + // Wrap the code block in CodeWrapper + return `${defaultFenceRenderer(tokens, idx, options, env, self)}` + } + + // If not a code block, return the default rendering + return defaultFenceRenderer(tokens, idx, options, env, self) + } +}