docs: add theme to highlight code block (#831)

This commit is contained in:
xiaomo 2024-10-28 20:02:30 +08:00 committed by GitHub
parent e0d4980e31
commit 52b9b20b3c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 1475 additions and 1380 deletions

View File

@ -4,7 +4,6 @@ import autoprefixer from 'autoprefixer'
import tailwind from 'tailwindcss' import tailwind from 'tailwindcss'
import Icons from 'unplugin-icons/vite' import Icons from 'unplugin-icons/vite'
import { defineConfig } from 'vitepress' import { defineConfig } from 'vitepress'
import { cssVariables } from './theme/config/shiki'
import { siteConfig } from './theme/config/site' import { siteConfig } from './theme/config/site'
import CodeWrapperPlugin from './theme/plugins/codewrapper' import CodeWrapperPlugin from './theme/plugins/codewrapper'
@ -31,7 +30,6 @@ export default defineConfig({
['meta', { name: 'og:site_name', content: siteConfig.name }], ['meta', { name: 'og:site_name', content: siteConfig.name }],
['meta', { name: 'og:image', content: siteConfig.ogImage }], ['meta', { name: 'og:image', content: siteConfig.ogImage }],
['meta', { name: 'twitter:image', content: siteConfig.ogImage }], ['meta', { name: 'twitter:image', content: siteConfig.ogImage }],
], ],
sitemap: { sitemap: {
@ -58,7 +56,6 @@ export default defineConfig({
srcDir: path.resolve(__dirname, '../src'), srcDir: path.resolve(__dirname, '../src'),
markdown: { markdown: {
theme: cssVariables,
codeTransformers: [ codeTransformers: [
transformerMetaWordHighlight(), transformerMetaWordHighlight(),
], ],

View File

@ -4,9 +4,8 @@ import { cn } from '@/lib/utils'
import { useConfigStore } from '@/stores/config' import { useConfigStore } from '@/stores/config'
import { useClipboard } from '@vueuse/core' import { useClipboard } from '@vueuse/core'
import MagicString from 'magic-string' import MagicString from 'magic-string'
import { codeToHtml } from 'shiki'
import { computed, ref, watch } from 'vue' import { computed, ref, watch } from 'vue'
import { cssVariables } from '../config/shiki' import { highlight } from '../config/shiki'
import CodeSandbox from './CodeSandbox.vue' import CodeSandbox from './CodeSandbox.vue'
import ComponentLoader from './ComponentLoader.vue' import ComponentLoader from './ComponentLoader.vue'
import Stackblitz from './Stackblitz.vue' import Stackblitz from './Stackblitz.vue'
@ -37,10 +36,7 @@ function transformImportPath(code: string) {
watch([style, codeConfig], async () => { watch([style, codeConfig], async () => {
try { try {
rawString.value = await import(`../../../src/lib/registry/${style.value}/example/${props.name}.vue?raw`).then(res => res.default.trim()) rawString.value = await import(`../../../src/lib/registry/${style.value}/example/${props.name}.vue?raw`).then(res => res.default.trim())
codeHtml.value = await codeToHtml(transformedRawString.value, { codeHtml.value = highlight(transformedRawString.value, 'vue')
lang: 'vue',
theme: cssVariables,
})
} }
catch (err) { catch (err) {
console.error(err) console.error(err)

View File

@ -1,6 +1,41 @@
import { createCssVariablesTheme } from 'shiki' import type { HighlighterCore } from 'shiki/core'
import type { ThemeOptions } from 'vitepress'
import { computedAsync } from '@vueuse/core'
import { createHighlighterCore } from 'shiki/core'
import { createJavaScriptRegexEngine } from 'shiki/engine/javascript'
export const cssVariables = createCssVariablesTheme({ export const shikiThemes: ThemeOptions = {
variablePrefix: '--shiki-', light: 'github-light-default',
variableDefaults: {}, dark: 'github-dark-default',
}
export const highlighter = computedAsync<HighlighterCore>(async (onCancel) => {
const shiki = await createHighlighterCore({
engine: createJavaScriptRegexEngine(),
themes: [
() => import('shiki/themes/github-dark-default.mjs'),
() => import('shiki/themes/github-light-default.mjs'),
],
langs: [
() => import('shiki/langs/javascript.mjs'),
() => import('shiki/langs/vue.mjs'),
],
})
onCancel(() => shiki?.dispose())
return shiki
}) })
export function highlight(code: string, lang: string) {
if (!highlighter.value)
return code
return highlighter.value.codeToHtml(code, {
lang,
defaultColor: false,
themes: {
dark: 'github-dark-default',
light: 'github-light-default',
},
})
}

View File

@ -127,6 +127,15 @@
scrollbar-color: hsl(215.4 16.3% 56.9% / 0.3); scrollbar-color: hsl(215.4 16.3% 56.9% / 0.3);
} }
html.dark .shiki,
html.dark .shiki span {
color: var(--shiki-dark);
}
html:not(.dark) .shiki,
html:not(.dark) .shiki span {
color: var(--shiki-light);
}
.antialised { .antialised {
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
@ -154,7 +163,7 @@
} }
div[class^="language-"] { div[class^="language-"] {
@apply mb-4 mt-6 max-h-[650px] overflow-x-auto md:rounded-lg border !bg-secondary-foreground dark:!bg-secondary @apply mb-4 mt-6 max-h-[650px] overflow-x-auto md:rounded-lg border
} }
pre { pre {
@apply py-4; @apply py-4;

View File

@ -68,7 +68,7 @@
"markdown-it": "^14.1.0", "markdown-it": "^14.1.0",
"pathe": "^1.1.2", "pathe": "^1.1.2",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"shiki": "^1.17.7", "shiki": "^1.22.1",
"tailwind-merge": "^2.5.2", "tailwind-merge": "^2.5.2",
"tailwindcss": "^3.4.12", "tailwindcss": "^3.4.12",
"tsx": "^4.19.1", "tsx": "^4.19.1",

View File

@ -54,8 +54,8 @@ import { Switch } from '@/components/ui/switch'
<template> <template>
<Switch :checked="isDark" @update:checked="toggleTheme"> <Switch :checked="isDark" @update:checked="toggleTheme">
<template #thumb> <template #thumb>
<Icon v-if="isDark" icon="lucide:moon" class="size-3"></Icon> <Icon v-if="isDark" icon="lucide:moon" class="size-3" />
<Icon v-else icon="lucide:sun" class="size-3"></Icon> <Icon v-else icon="lucide:sun" class="size-3" />
</template> </template>
</Switch> </Switch>
</template> </template>

View File

@ -8,14 +8,20 @@ import {
useForwardPropsEmits, useForwardPropsEmits,
} from 'radix-vue' } from 'radix-vue'
import { computed, type HTMLAttributes } from 'vue' import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<SwitchRootProps & { class?: HTMLAttributes['class'] }>() const props = defineProps<SwitchRootProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<SwitchRootEmits>() const emits = defineEmits<SwitchRootEmits>()
const delegatedProps = computed(() => { const delegatedProps = computed(() => {
const { class: _, ...delegated } = props const { class: _, ...delegated } = props
return delegated return delegated
}) })
const forwarded = useForwardPropsEmits(delegatedProps, emits) const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script> </script>
<template> <template>
<SwitchRoot <SwitchRoot
v-bind="forwarded" v-bind="forwarded"

View File

@ -7,7 +7,7 @@
"files": [ "files": [
{ {
"name": "Switch.vue", "name": "Switch.vue",
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport {\n SwitchRoot,\n type SwitchRootEmits,\n type SwitchRootProps,\n SwitchThumb,\n useForwardPropsEmits,\n} from 'radix-vue'\nimport { computed, type HTMLAttributes } from 'vue'\nconst props = defineProps<SwitchRootProps & { class?: HTMLAttributes['class'] }>()\nconst emits = defineEmits<SwitchRootEmits>()\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n return delegated\n})\nconst forwarded = useForwardPropsEmits(delegatedProps, emits)\n</script>\n<template>\n <SwitchRoot\n v-bind=\"forwarded\"\n :class=\"cn(\n 'peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',\n props.class,\n )\"\n >\n <SwitchThumb\n :class=\"cn('pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5')\"\n >\n <slot name=\"thumb\" />\n </SwitchThumb>\n </SwitchRoot>\n</template>\n" "content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport {\n SwitchRoot,\n type SwitchRootEmits,\n type SwitchRootProps,\n SwitchThumb,\n useForwardPropsEmits,\n} from 'radix-vue'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<SwitchRootProps & { class?: HTMLAttributes['class'] }>()\n\nconst emits = defineEmits<SwitchRootEmits>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwarded = useForwardPropsEmits(delegatedProps, emits)\n</script>\n\n<template>\n <SwitchRoot\n v-bind=\"forwarded\"\n :class=\"cn(\n 'peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',\n props.class,\n )\"\n >\n <SwitchThumb\n :class=\"cn('pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5')\"\n >\n <slot name=\"thumb\" />\n </SwitchThumb>\n </SwitchRoot>\n</template>\n"
}, },
{ {
"name": "index.ts", "name": "index.ts",

File diff suppressed because it is too large Load Diff