diff --git a/apps/www/.vitepress/config.mts b/apps/www/.vitepress/config.mts index a1d702e01..df4c7e92c 100644 --- a/apps/www/.vitepress/config.mts +++ b/apps/www/.vitepress/config.mts @@ -4,7 +4,6 @@ import autoprefixer from 'autoprefixer' import tailwind from 'tailwindcss' import Icons from 'unplugin-icons/vite' import { defineConfig } from 'vitepress' -import { cssVariables } from './theme/config/shiki' import { siteConfig } from './theme/config/site' import CodeWrapperPlugin from './theme/plugins/codewrapper' @@ -31,7 +30,6 @@ export default defineConfig({ ['meta', { name: 'og:site_name', content: siteConfig.name }], ['meta', { name: 'og:image', content: siteConfig.ogImage }], ['meta', { name: 'twitter:image', content: siteConfig.ogImage }], - ], sitemap: { @@ -58,7 +56,6 @@ export default defineConfig({ srcDir: path.resolve(__dirname, '../src'), markdown: { - theme: cssVariables, codeTransformers: [ transformerMetaWordHighlight(), ], diff --git a/apps/www/.vitepress/theme/components/BlockPreview.vue b/apps/www/.vitepress/theme/components/BlockPreview.vue index ccfcc04ac..593a5a46f 100644 --- a/apps/www/.vitepress/theme/components/BlockPreview.vue +++ b/apps/www/.vitepress/theme/components/BlockPreview.vue @@ -2,10 +2,9 @@ import { useConfigStore } from '@/stores/config' import { CircleHelp, Info, Monitor, Smartphone, Tablet } from 'lucide-vue-next' import MagicString from 'magic-string' -import { codeToHtml } from 'shiki' import { reactive, ref, watch } from 'vue' import { compileScript, parse, walk } from 'vue/compiler-sfc' -import { cssVariables } from '../config/shiki' +import { highlight } from '../config/shiki' import BlockCopyButton from './BlockCopyButton.vue' import Spinner from './Spinner.vue' import StyleSwitcher from './StyleSwitcher.vue' @@ -79,10 +78,7 @@ watch([style, codeConfig], async () => { }) } - codeHtml.value = await codeToHtml(rawString.value, { - lang: 'vue', - theme: cssVariables, - }) + codeHtml.value = highlight(rawString.value, 'vue') } catch (err) { console.error(err) diff --git a/apps/www/.vitepress/theme/components/ComponentPreview.vue b/apps/www/.vitepress/theme/components/ComponentPreview.vue index aa68e46b1..dbcf8e920 100644 --- a/apps/www/.vitepress/theme/components/ComponentPreview.vue +++ b/apps/www/.vitepress/theme/components/ComponentPreview.vue @@ -4,9 +4,8 @@ import { cn } from '@/lib/utils' import { useConfigStore } from '@/stores/config' import { useClipboard } from '@vueuse/core' import MagicString from 'magic-string' -import { codeToHtml } from 'shiki' import { computed, ref, watch } from 'vue' -import { cssVariables } from '../config/shiki' +import { highlight } from '../config/shiki' import CodeSandbox from './CodeSandbox.vue' import ComponentLoader from './ComponentLoader.vue' import Stackblitz from './Stackblitz.vue' @@ -37,10 +36,7 @@ function transformImportPath(code: string) { watch([style, codeConfig], async () => { try { 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, { - lang: 'vue', - theme: cssVariables, - }) + codeHtml.value = highlight(transformedRawString.value, 'vue') } catch (err) { console.error(err) diff --git a/apps/www/.vitepress/theme/config/shiki.ts b/apps/www/.vitepress/theme/config/shiki.ts index b0e9745df..eef91cfcf 100644 --- a/apps/www/.vitepress/theme/config/shiki.ts +++ b/apps/www/.vitepress/theme/config/shiki.ts @@ -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({ - variablePrefix: '--shiki-', - variableDefaults: {}, +export const shikiThemes: ThemeOptions = { + light: 'vitesse-light', + dark: 'vitesse-dark', +} + +export const highlighter = computedAsync(async (onCancel) => { + const shiki = await createHighlighterCore({ + engine: createJavaScriptRegexEngine(), + themes: [ + () => import('shiki/themes/vitesse-dark.mjs'), + () => import('shiki/themes/vitesse-light.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: 'vitesse-dark', + light: 'vitesse-light', + }, + }) +} diff --git a/apps/www/.vitepress/theme/style.css b/apps/www/.vitepress/theme/style.css index 483768395..9cec5415b 100644 --- a/apps/www/.vitepress/theme/style.css +++ b/apps/www/.vitepress/theme/style.css @@ -6,7 +6,7 @@ :root { --font-geist-sans: "geist-sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; - + --background: 0 0% 100%; --foreground: 240 10% 3.9%; --card: 0 0% 100%; @@ -121,6 +121,15 @@ 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); + } + .hide-scrollbar::-webkit-scrollbar { display: none; } @@ -147,7 +156,7 @@ @apply absolute w-9 h-9 bg-muted rounded-full font-mono font-medium text-center text-base inline-flex items-center justify-center -indent-px border-4 border-background; @apply -ml-[50px] -mt-1; content: counter(step); - } + } } @media (max-width: 640px) { @@ -157,7 +166,7 @@ } 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 { @apply py-4; @@ -177,7 +186,7 @@ pre code { pre code .line { @apply px-4 min-h-4 !py-0.5 w-full inline-block leading-[--vp-code-line-height]; -} +} .line-number { @apply !text-[.75rem] !inline-block text-muted-foreground leading-[--vp-code-line-height]; diff --git a/apps/www/package.json b/apps/www/package.json index 708e551d6..d4f6842f4 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -68,7 +68,7 @@ "markdown-it": "^14.1.0", "pathe": "^1.1.2", "rimraf": "^6.0.1", - "shiki": "^1.17.7", + "shiki": "^1.22.1", "tailwind-merge": "^2.5.2", "tailwindcss": "^3.4.12", "tsx": "^4.19.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 70aa25bdc..b862be7a9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -214,8 +214,8 @@ importers: specifier: ^6.0.1 version: 6.0.1 shiki: - specifier: ^1.17.7 - version: 1.22.0 + specifier: ^1.22.1 + version: 1.22.1 tailwind-merge: specifier: ^2.5.2 version: 2.5.3 @@ -2137,18 +2137,30 @@ packages: '@shikijs/core@1.22.0': resolution: {integrity: sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q==} + '@shikijs/core@1.22.1': + resolution: {integrity: sha512-bqAhT/Ri5ixV4oYsvJNH8UJjpjbINWlWyXY6tBTsP4OmD6XnFv43nRJ+lTdxd2rmG5pgam/x+zGR6kLRXrpEKA==} + '@shikijs/engine-javascript@1.22.0': resolution: {integrity: sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw==} + '@shikijs/engine-javascript@1.22.1': + resolution: {integrity: sha512-540pyoy0LWe4jj2BVbgELwOFu1uFvRI7lg4hdsExrSXA9x7gqfzZ/Nnh4RfX86aDAgJ647gx4TCmRwACbnQSvw==} + '@shikijs/engine-oniguruma@1.22.0': resolution: {integrity: sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw==} + '@shikijs/engine-oniguruma@1.22.1': + resolution: {integrity: sha512-L+1Vmd+a2kk8HtogUFymQS6BjUfJnzcWoUp1BUgxoDiklbKSMvrsMuLZGevTOP1m0rEjgnC5MsDmsr8lX1lC+Q==} + '@shikijs/transformers@1.22.0': resolution: {integrity: sha512-k7iMOYuGQA62KwAuJOQBgH2IQb5vP8uiB3lMvAMGUgAMMurePOx3Z7oNqJdcpxqZP6I9cc7nc4DNqSKduCxmdg==} '@shikijs/types@1.22.0': resolution: {integrity: sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww==} + '@shikijs/types@1.22.1': + resolution: {integrity: sha512-+45f8mu/Hxqs6Kyhfm98Nld5n7Q7lwhjU8UtdQwrOPs7BnM4VAb929O3IQ2ce+4D7SlNFlZGd8CnKRSnwbQreQ==} + '@shikijs/vscode-textmate@9.3.0': resolution: {integrity: sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==} @@ -3305,7 +3317,7 @@ packages: resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==} concat-map@0.0.1: - resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} concat-stream@1.6.2: resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} @@ -3885,7 +3897,7 @@ packages: engines: {node: '>=0.8'} ee-first@1.1.1: - resolution: {integrity: sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=} + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} electron-to-chromium@1.5.36: resolution: {integrity: sha512-HYTX8tKge/VNp6FGO+f/uVDmUkq+cEfcxYhKf15Akc4M5yxt5YmorwlAitKWjWhWQnKcDRBAQKXkhqqXMqcrjw==} @@ -5347,7 +5359,7 @@ packages: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} media-typer@0.3.0: - resolution: {integrity: sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=} + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} meow@12.1.1: @@ -6672,6 +6684,9 @@ packages: shiki@1.22.0: resolution: {integrity: sha512-/t5LlhNs+UOKQCYBtl5ZsH/Vclz73GIqT2yQsCBygr8L/ppTdmpL4w3kPLoZJbMKVWtoG77Ue1feOjZfDxvMkw==} + shiki@1.22.1: + resolution: {integrity: sha512-PbJ6XxrWLMwB2rm3qdjIHNm3zq4SfFnOx0B3rEoi4AN8AUngsdyZ1tRe5slMPtn6jQkbUURLNZPpLR7Do3k78g==} + shortid@2.2.16: resolution: {integrity: sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==} deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. @@ -9686,17 +9701,37 @@ snapshots: '@types/hast': 3.0.4 hast-util-to-html: 9.0.3 + '@shikijs/core@1.22.1': + dependencies: + '@shikijs/engine-javascript': 1.22.1 + '@shikijs/engine-oniguruma': 1.22.1 + '@shikijs/types': 1.22.1 + '@shikijs/vscode-textmate': 9.3.0 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.3 + '@shikijs/engine-javascript@1.22.0': dependencies: '@shikijs/types': 1.22.0 '@shikijs/vscode-textmate': 9.3.0 oniguruma-to-js: 0.4.3 + '@shikijs/engine-javascript@1.22.1': + dependencies: + '@shikijs/types': 1.22.1 + '@shikijs/vscode-textmate': 9.3.0 + oniguruma-to-js: 0.4.3 + '@shikijs/engine-oniguruma@1.22.0': dependencies: '@shikijs/types': 1.22.0 '@shikijs/vscode-textmate': 9.3.0 + '@shikijs/engine-oniguruma@1.22.1': + dependencies: + '@shikijs/types': 1.22.1 + '@shikijs/vscode-textmate': 9.3.0 + '@shikijs/transformers@1.22.0': dependencies: shiki: 1.22.0 @@ -9706,6 +9741,11 @@ snapshots: '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 + '@shikijs/types@1.22.1': + dependencies: + '@shikijs/vscode-textmate': 9.3.0 + '@types/hast': 3.0.4 + '@shikijs/vscode-textmate@9.3.0': {} '@sindresorhus/merge-streams@2.3.0': {} @@ -15177,6 +15217,15 @@ snapshots: '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 + shiki@1.22.1: + dependencies: + '@shikijs/core': 1.22.1 + '@shikijs/engine-javascript': 1.22.1 + '@shikijs/engine-oniguruma': 1.22.1 + '@shikijs/types': 1.22.1 + '@shikijs/vscode-textmate': 9.3.0 + '@types/hast': 3.0.4 + shortid@2.2.16: dependencies: nanoid: 2.1.11 @@ -16215,7 +16264,7 @@ snapshots: focus-trap: 7.6.0 mark.js: 8.11.1 minisearch: 7.1.0 - shiki: 1.22.0 + shiki: 1.22.1 vite: 5.4.8(@types/node@22.7.5)(stylus@0.57.0)(terser@5.34.1) vue: 3.5.11(typescript@5.6.3) optionalDependencies: