feat: generate code dynamically

This commit is contained in:
zernonia 2024-03-13 23:42:14 +08:00
parent 4d08adc81e
commit 3832ea3043
6 changed files with 44 additions and 18 deletions

View File

@ -3,17 +3,12 @@ import { defineConfig } from 'vitepress'
import Icons from 'unplugin-icons/vite' import Icons from 'unplugin-icons/vite'
import tailwind from 'tailwindcss' import tailwind from 'tailwindcss'
import autoprefixer from 'autoprefixer' import autoprefixer from 'autoprefixer'
import { createCssVariablesTheme } from 'shiki' import { cssVariables } from './theme/config/shiki'
// import { transformerMetaWordHighlight, transformerNotationWordHighlight } from '@shikijs/transformers' // import { transformerMetaWordHighlight, transformerNotationWordHighlight } from '@shikijs/transformers'
import { siteConfig } from './theme/config/site' import { siteConfig } from './theme/config/site'
import ComponentPreviewPlugin from './theme/plugins/previewer' import ComponentPreviewPlugin from './theme/plugins/previewer'
const cssVariables = createCssVariablesTheme({
variablePrefix: '--shiki-',
variableDefaults: {},
})
// https://vitepress.dev/reference/site-config // https://vitepress.dev/reference/site-config
export default defineConfig({ export default defineConfig({
title: siteConfig.name, title: siteConfig.name,

View File

@ -1,10 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref } from 'vue' import { onMounted, ref, toRefs, watch } from 'vue'
import { Icon } from '@iconify/vue' import { Icon } from '@iconify/vue'
import { makeCodeSandboxParams } from '../utils/codeeditor' import { makeCodeSandboxParams } from '../utils/codeeditor'
import Tooltip from './Tooltip.vue' import Tooltip from './Tooltip.vue'
import { Button } from '@/lib/registry/new-york/ui/button' import { Button } from '@/lib/registry/new-york/ui/button'
import { type Style } from '@/lib/registry/styles' import type { Style } from '@/lib/registry/styles'
const props = defineProps<{ const props = defineProps<{
name: string name: string
@ -12,11 +12,12 @@ const props = defineProps<{
style: Style style: Style
}>() }>()
const { code } = toRefs(props)
const sources = ref<Record<string, string>>({}) const sources = ref<Record<string, string>>({})
onMounted(() => { watch(code, () => {
sources.value['App.vue'] = props.code sources.value['App.vue'] = code.value
}) }, { immediate: true })
</script> </script>
<template> <template>

View File

@ -1,4 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, watch } from 'vue'
import { codeToHtml } from 'shiki'
import { cssVariables } from '../config/shiki'
import StyleSwitcher from './StyleSwitcher.vue' import StyleSwitcher from './StyleSwitcher.vue'
import ComponentLoader from './ComponentLoader.vue' import ComponentLoader from './ComponentLoader.vue'
import Stackblitz from './Stackblitz.vue' import Stackblitz from './Stackblitz.vue'
@ -11,7 +14,7 @@ defineOptions({
inheritAttrs: false, inheritAttrs: false,
}) })
withDefaults(defineProps<{ const props = withDefaults(defineProps<{
name: string name: string
align?: 'center' | 'start' | 'end' align?: 'center' | 'start' | 'end'
sfcTsCode?: string sfcTsCode?: string
@ -19,6 +22,22 @@ withDefaults(defineProps<{
}>(), { align: 'center' }) }>(), { align: 'center' })
const { style } = useConfigStore() const { style } = useConfigStore()
const codeString = ref('')
const codeHtml = ref('')
watch(style, async () => {
try {
codeString.value = await import(`../../../src/lib/registry/${style.value}/example/${props.name}.vue?raw`).then(res => res.default.trim())
codeHtml.value = await codeToHtml(codeString.value, {
lang: 'vue',
theme: cssVariables,
})
}
catch (err) {
console.error(err)
}
}, { immediate: true })
</script> </script>
<template> <template>
@ -47,8 +66,8 @@ const { style } = useConfigStore()
<StyleSwitcher /> <StyleSwitcher />
<div class="flex items-center gap-x-1"> <div class="flex items-center gap-x-1">
<Stackblitz :key="style" :style="style" :name="name" :code="decodeURIComponent(sfcTsCode ?? '')" /> <Stackblitz :key="style" :style="style" :name="name" :code="codeString" />
<CodeSandbox :key="style" :style="style" :name="name" :code="decodeURIComponent(sfcTsCode ?? '')" /> <CodeSandbox :key="style" :style="style" :name="name" :code="codeString" />
</div> </div>
</div> </div>
<div <div
@ -62,7 +81,7 @@ const { style } = useConfigStore()
</div> </div>
</TabsContent> </TabsContent>
<TabsContent value="code"> <TabsContent value="code">
<div v-if="sfcTsHtml" class="language-vue" style="flex: 1;" v-html="decodeURIComponent(sfcTsHtml)" /> <div v-if="codeHtml" class="language-vue" style="flex: 1;" v-html="codeHtml" />
<slot v-else /> <slot v-else />
</TabsContent> </TabsContent>
</Tabs> </Tabs>

View File

@ -1,10 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref } from 'vue' import { onMounted, ref, toRefs, watch } from 'vue'
import { Icon } from '@iconify/vue' import { Icon } from '@iconify/vue'
import { makeStackblitzParams } from '../utils/codeeditor' import { makeStackblitzParams } from '../utils/codeeditor'
import Tooltip from './Tooltip.vue' import Tooltip from './Tooltip.vue'
import { Button } from '@/lib/registry/new-york/ui/button' import { Button } from '@/lib/registry/new-york/ui/button'
import { type Style } from '@/lib/registry/styles' import type { Style } from '@/lib/registry/styles'
const props = defineProps<{ const props = defineProps<{
name: string name: string
@ -12,10 +12,14 @@ const props = defineProps<{
style: Style style: Style
}>() }>()
const { code } = toRefs(props)
const sources = ref<Record<string, string>>({}) const sources = ref<Record<string, string>>({})
onMounted(() => { onMounted(() => {
sources.value['App.vue'] = props.code })
watch(code, () => {
sources.value['App.vue'] = code.value
}) })
function handleClick() { function handleClick() {

View File

@ -0,0 +1,6 @@
import { createCssVariablesTheme } from 'shiki'
export const cssVariables = createCssVariablesTheme({
variablePrefix: '--shiki-',
variableDefaults: {},
})

View File

@ -18,6 +18,7 @@ export function makeCodeSandboxParams(componentName: string, style: Style, sourc
export function makeStackblitzParams(componentName: string, style: Style, sources: Record<string, string>) { export function makeStackblitzParams(componentName: string, style: Style, sources: Record<string, string>) {
const files: Record<string, string> = {} const files: Record<string, string> = {}
Object.entries(constructFiles(componentName, style, sources)).forEach(([k, v]) => (files[`${k}`] = typeof v.content === 'object' ? JSON.stringify(v.content, null, 2) : v.content)) Object.entries(constructFiles(componentName, style, sources)).forEach(([k, v]) => (files[`${k}`] = typeof v.content === 'object' ? JSON.stringify(v.content, null, 2) : v.content))
console.log({ files, componentName, style, sources })
return sdk.openProject({ return sdk.openProject({
title: `${componentName} - Radix Vue`, title: `${componentName} - Radix Vue`,
files, files,