diff --git a/apps/svelte.dev/vite.config.ts b/apps/svelte.dev/vite.config.ts index e1d4ffc832..e73a094470 100644 --- a/apps/svelte.dev/vite.config.ts +++ b/apps/svelte.dev/vite.config.ts @@ -71,7 +71,7 @@ const config: UserConfig = { } }, optimizeDeps: { - exclude: ['@sveltejs/site-kit', '@sveltejs/repl', '@rollup/browser'] + exclude: ['@sveltejs/site-kit', '@sveltejs/repl', '@rollup/browser', 'svelte2tsx'] }, ssr: { noExternal: ['@sveltejs/site-kit', '@sveltejs/repl'], diff --git a/packages/site-kit/package.json b/packages/site-kit/package.json index 84abf82b95..de717af9ad 100644 --- a/packages/site-kit/package.json +++ b/packages/site-kit/package.json @@ -37,6 +37,7 @@ "@fontsource/eb-garamond": "^5.1.0", "@fontsource/fira-mono": "^5.1.0", "@fontsource/fira-sans": "^5.1.0", + "@hugokorte/twoslash-svelte": "^0.0.3", "@lezer/common": "^1.0.4", "@replit/codemirror-lang-svelte": "^6.0.0", "@shikijs/twoslash": "^1.22.0", diff --git a/packages/site-kit/src/lib/markdown/renderer.ts b/packages/site-kit/src/lib/markdown/renderer.ts index bd79475332..848e7d6b1c 100644 --- a/packages/site-kit/src/lib/markdown/renderer.ts +++ b/packages/site-kit/src/lib/markdown/renderer.ts @@ -7,6 +7,7 @@ import ts from 'typescript'; import * as marked from 'marked'; import { codeToHtml, createCssVariablesTheme } from 'shiki'; import { transformerTwoslash } from '@shikijs/twoslash'; +import { createTwoslasher } from '@hugokorte/twoslash-svelte'; import { SHIKI_LANGUAGE_MAP, slugify, smart_quotes, transform } from './utils'; interface SnippetOptions { @@ -262,7 +263,6 @@ export async function render_content_markdown( if (needs_controls) { html += ''; } - html += await syntax_highlight({ filename, language: token.lang, prelude, source, check }); if (converted) { @@ -662,6 +662,8 @@ function highlight_spans(content: string, classname: string) { .join('\n'); } +const twoslasherSvelte = createTwoslasher(); + async function syntax_highlight({ prelude, source, @@ -684,7 +686,7 @@ async function syntax_highlight({ theme }) ); - } else if (language === 'js' || language === 'ts') { + } else if (['js', 'ts', 'svelte'].includes(language)) { /** We need to stash code wrapped in `---` highlights, because otherwise TS will error on e.g. bad syntax, duplicate declarations */ const redactions: string[] = []; @@ -695,11 +697,13 @@ async function syntax_highlight({ try { html = await codeToHtml(prelude + redacted, { - lang: 'ts', + lang: language === 'svelte' ? language : 'ts', theme, transformers: check ? [ transformerTwoslash({ + langs: ['svelte', 'js', 'ts'], + twoslasher: twoslasherSvelte, twoslashOptions: { compilerOptions: { types: ['svelte', '@sveltejs/kit'] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 65b17938ae..eaa9edf3cf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -455,6 +455,9 @@ importers: '@fontsource/fira-sans': specifier: ^5.1.0 version: 5.1.0 + '@hugokorte/twoslash-svelte': + specifier: ^0.0.3 + version: 0.0.3(svelte2tsx@0.7.30(svelte@5.1.11)(typescript@5.5.4))(typescript@5.5.4) '@lezer/common': specifier: ^1.0.4 version: 1.2.2 @@ -932,6 +935,12 @@ packages: '@fontsource/fira-sans@5.1.0': resolution: {integrity: sha512-qfAjF5WcrL6qQh9eIWLK7lOh9wbCgCnVWh2Nu2gozrTgsUgYBLR8sbCGYwlK1K0yZoQsR2i9VSiQ16wwPCBkSw==} + '@hugokorte/twoslash-svelte@0.0.3': + resolution: {integrity: sha512-bxV5ZIbUhlYLPaw2u6CAAkYNHDIQ08dcT5RUwChCM+ldiNU4U+QFzFEfks9kVlGtjHB6IG4paiYYxnoxX0uriQ==} + peerDependencies: + svelte2tsx: '*' + typescript: '*' + '@img/sharp-darwin-arm64@0.33.4': resolution: {integrity: sha512-p0suNqXufJs9t3RqLBO6vvrgr5OhgbWp76s5gTRvdmxmuv9E1rcaqGUsl3l4mKVmXPkTkTErXediAui4x+8PSA==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} @@ -1657,6 +1666,12 @@ packages: '@vitest/utils@2.1.2': resolution: {integrity: sha512-zMO2KdYy6mx56btx9JvAqAZ6EyS3g49krMPPrgOp1yxGZiA93HumGk+bZ5jIZtOg5/VBYl5eBmGRQHqq4FG6uQ==} + '@volar/language-core@2.4.10': + resolution: {integrity: sha512-hG3Z13+nJmGaT+fnQzAkS0hjJRa2FCeqZt6Bd+oGNhUkQ+mTFsDETg5rqUTxyzIh5pSOGY7FHCWUS8G82AzLCA==} + + '@volar/source-map@2.4.10': + resolution: {integrity: sha512-OCV+b5ihV0RF3A7vEvNyHPi4G4kFa6ukPmyVocmqm5QzOd8r5yAtiNvaPEjl8dNvgC/lj4JPryeeHLdXd62rWA==} + '@webcontainer/api@1.1.9': resolution: {integrity: sha512-Sp6PV0K9D/3f8fSbCubqhfmBFH8XbngZCBOCF+aExyGqnz2etmw+KYvbQ/JxYvYX5KPaSxM+asFQwoP2RHl5cg==} @@ -2970,8 +2985,8 @@ packages: typescript: optional: true - svelte2tsx@0.7.8: - resolution: {integrity: sha512-ABK3RDFcy59AqAiU1N5Kxu1RnKrb1GDMrQjLgNgJfE8Q+coCKpjCAPtUVKQM2HnmuqeNWcT3NqfXbE+ZmN5Pow==} + svelte2tsx@0.7.30: + resolution: {integrity: sha512-sHXK/vw/sVJmFuPSq6zeKrtuZKvo0jJyEi8ybN0dfrqSYVvHu8zFbO0zQKAL8y/fYackYojH41EJGe6v8rd5fw==} peerDependencies: svelte: ^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0 typescript: ^4.9.4 || ^5.0.0 @@ -3701,6 +3716,17 @@ snapshots: '@fontsource/fira-sans@5.1.0': {} + '@hugokorte/twoslash-svelte@0.0.3(svelte2tsx@0.7.30(svelte@5.1.11)(typescript@5.5.4))(typescript@5.5.4)': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + '@volar/language-core': 2.4.10 + svelte2tsx: 0.7.30(svelte@5.1.11)(typescript@5.5.4) + twoslash: 0.2.12(typescript@5.5.4) + twoslash-protocol: 0.2.12 + typescript: 5.5.4 + transitivePeerDependencies: + - supports-color + '@img/sharp-darwin-arm64@0.33.4': optionalDependencies: '@img/sharp-libvips-darwin-arm64': 1.0.2 @@ -4364,7 +4390,7 @@ snapshots: sade: 1.8.1 semver: 7.6.2 svelte: 5.1.11 - svelte2tsx: 0.7.8(svelte@5.1.11)(typescript@5.5.4) + svelte2tsx: 0.7.30(svelte@5.1.11)(typescript@5.5.4) transitivePeerDependencies: - typescript @@ -4559,6 +4585,12 @@ snapshots: loupe: 3.1.1 tinyrainbow: 1.2.0 + '@volar/language-core@2.4.10': + dependencies: + '@volar/source-map': 2.4.10 + + '@volar/source-map@2.4.10': {} + '@webcontainer/api@1.1.9': {} abbrev@1.1.1: {} @@ -5860,7 +5892,7 @@ snapshots: postcss: 8.4.45 typescript: 5.5.4 - svelte2tsx@0.7.8(svelte@5.1.11)(typescript@5.5.4): + svelte2tsx@0.7.30(svelte@5.1.11)(typescript@5.5.4): dependencies: dedent-js: 1.0.1 pascal-case: 3.1.2