Skip to content

Commit

Permalink
feat: demo plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
JasKang committed Mar 29, 2024
1 parent df23275 commit 2381048
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 14 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
"globals": "^14.0.0",
"happy-dom": "^14.3.6",
"mdast-util-from-markdown": "^2.0.0",
"mdast-util-frontmatter": "^2.0.1",
"mdast-util-to-markdown": "^2.1.0",
"micromark-extension-frontmatter": "^2.0.0",
"mini-svg-data-uri": "^1.4.4",
"prettier": "^3.2.5",
"prettier-plugin-tailwindcss": "^0.5.12",
Expand Down
71 changes: 57 additions & 14 deletions packages/docs/.vitepress/plugins/demo.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import fs from 'node:fs'
import path, { dirname } from 'node:path'
import { relative } from 'node:path'

import type { Plugin, ResolvedConfig } from 'vite'

import { createHash } from 'node:crypto'

import { fromMarkdown } from 'mdast-util-from-markdown'
import { toMarkdown } from 'mdast-util-to-markdown'
import { frontmatter } from 'micromark-extension-frontmatter'
import { frontmatterFromMarkdown, frontmatterToMarkdown } from 'mdast-util-frontmatter'
import { visit } from 'unist-util-visit'
import type { Html } from 'mdast'

Expand All @@ -27,7 +29,10 @@ function praseMeta(meta?: string | null) {
return ret
}
function remarkDemo(id: string, content: string) {
const root = fromMarkdown(content)
const root = fromMarkdown(content, {
extensions: [frontmatter(['yaml', 'toml'])],
mdastExtensions: [frontmatterFromMarkdown(['yaml', 'toml'])],
})

const blocks: Record<string, string> = {}

Expand All @@ -43,9 +48,9 @@ function remarkDemo(id: string, content: string) {
parent!.children.splice(index!, 1, {
type: 'html',
value: `
<DemoWrapper lang="${decodeURIComponent(node.lang || '')}" meta="${decodeURIComponent(node.meta || '')}" code="${encodeURIComponent(node.value)}">
<DemoProxy lang="${encodeURIComponent(node.lang || '')}" meta="${encodeURIComponent(node.meta || '')}" code="${encodeURIComponent(node.value)}">
<${name}/>
</DemoWrapper>`,
</DemoProxy>`,
})
return index! + 1
}
Expand All @@ -55,21 +60,31 @@ function remarkDemo(id: string, content: string) {
if (setup) {
setup.value = setup.value.replace(
/<script setup>/,
`<script setup>\n${Object.keys(blocks)
.map(k => `import ${k} from "${id}.${k}.vue";`)
.join('\n')}`
`<script setup>
import DemoProxy from "virtual:demo-proxy";
${Object.keys(blocks)
.map(k => `import ${k} from "${id}.${k}.vue";`)
.join('\n')}`
)
} else {
root.children.unshift({
const i = root.children[0]?.type === 'yaml' ? 1 : 0
root.children.splice(i, 0, {
type: 'html',
value: '<script setup>\n' + "import { ref } from 'vue'\n" + '\n' + 'const count = ref(0)\n' + '</script>',
value: `<script setup>
import DemoProxy from "virtual:demo-proxy";
${Object.keys(blocks)
.map(k => `import ${k} from "${id}.${k}.vue";`)
.join('\n')}
</script>`,
})
}

const code = toMarkdown(root)
const code = toMarkdown(root, { extensions: [frontmatterToMarkdown(['yaml', 'toml'])] })
return { code, blocks }
}

const virtualDemoId = 'virtual:demo-proxy'
const resolvedVirtualDemoId = '\0' + virtualDemoId

export function demo(): Plugin {
let config: ResolvedConfig
let vuePlugin: any
Expand All @@ -83,13 +98,41 @@ export function demo(): Plugin {
// envType = isVitepress ? 'vitepress' : 'vite'
},
resolveId(id) {
if (id === virtualDemoId) {
return resolvedVirtualDemoId
}
if (CODE_VUE_REGEXP.test(id)) {
return id
}
},
async load(id) {
if (id === resolvedVirtualDemoId) {
return `import { defineComponent, h, resolveComponent } from 'vue'
export default defineComponent({
props: {
lang: { type: String, required: true },
meta: { type: String, required: true },
code: { type: String, required: true },
},
setup(props, { slots }) {
const DemoWrapper = resolveComponent('DemoWrapper')
return () =>
h(
DemoWrapper,
{
lang: decodeURIComponent(props.lang),
meta: decodeURIComponent(props.meta),
code: decodeURIComponent(props.code),
},
slots
)
},
})
`
}

if (CODE_VUE_REGEXP.test(id)) {
const blockId = '/' + path.relative(config.root, id)
const blockId = '/' + relative(config.root, id)
const demoCode = DemoMap.get(id) || DemoMap.get(blockId)
return demoCode
}
Expand All @@ -98,7 +141,7 @@ export function demo(): Plugin {
console.log(code)
for (const k of Object.keys(blocks)) {
const blockKey = `${id}.${k}.vue`
const blockId = '/' + path.relative(config.root, blockKey)
const blockId = '/' + relative(config.root, blockKey)
DemoMap.set(blockId, blocks[k])
}
return code
Expand All @@ -112,7 +155,7 @@ export function demo(): Plugin {
const updates: any[] = []
for (const k of Object.keys(blocks)) {
const blockKey = `${file}.${k}.vue`
const blockId = '/' + path.relative(config.root, blockKey)
const blockId = '/' + relative(config.root, blockKey)
DemoMap.set(blockId, blocks[k])

const mod = moduleGraph.getModuleById(blockId)
Expand Down
1 change: 1 addition & 0 deletions packages/docs/.vitepress/theme/components/DemoWrapper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const props = defineProps({
meta: { type: String, required: true },
code: { type: String, required: true },
})
console.log(props.code)
</script>
<template>
<div class="flex-col">
Expand Down
39 changes: 39 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 2381048

Please sign in to comment.