@@ -4,6 +4,8 @@ import fs from 'node:fs';
4
4
import path from 'node:path' ;
5
5
import ts from 'typescript' ;
6
6
import * as prettier from 'prettier' ;
7
+ import { codeToHtml , createCssVariablesTheme } from 'shiki' ;
8
+ import { transformerTwoslash } from '@shikijs/twoslash' ;
7
9
import { SHIKI_LANGUAGE_MAP , escape , normalizeSlugify , smart_quotes , transform } from './utils' ;
8
10
import type { Declaration , TypeElement , Modules } from './index' ;
9
11
@@ -31,7 +33,12 @@ interface RenderContentOptions {
31
33
const METADATA_REGEX =
32
34
/ (?: < ! - - - \s * | \/ \/ \/ \s * | # # # \s * ) (?< key > f i l e | l i n k | c o p y ) : \s * (?< value > .* ?) (?: \s * - - - > | $ ) \n / gm;
33
35
34
- let twoslash_module : typeof import ( 'shiki-twoslash' ) ;
36
+ const theme = createCssVariablesTheme ( {
37
+ name : 'css-variables' ,
38
+ variablePrefix : '--shiki-' ,
39
+ variableDefaults : { } ,
40
+ fontStyle : true
41
+ } ) ;
35
42
36
43
/**
37
44
* A super markdown renderer function. Renders svelte and kit docs specific specific markdown code to html.
@@ -126,10 +133,6 @@ export async function render_content_markdown(
126
133
resolveTypeLinks
127
134
} : RenderContentOptions = { }
128
135
) {
129
- twoslash_module ??= await import ( 'shiki-twoslash' ) ;
130
-
131
- const highlighter = await twoslash_module . createShikiHighlighter ( { theme : 'css-variables' } ) ;
132
-
133
136
const { type_links, type_regex } = create_type_links ( modules , resolveTypeLinks ) ;
134
137
const snippets = await create_snippet_cache ( cacheCodeSnippets ) ;
135
138
@@ -177,19 +180,17 @@ export async function render_content_markdown(
177
180
178
181
html += '</div>' ;
179
182
180
- html += syntax_highlight ( {
183
+ html += await syntax_highlight ( {
181
184
filename,
182
- highlighter,
183
185
language : token . lang ,
184
186
source,
185
187
twoslashBanner,
186
188
options
187
189
} ) ;
188
190
189
191
if ( converted ) {
190
- html += syntax_highlight ( {
192
+ html += await syntax_highlight ( {
191
193
filename,
192
- highlighter,
193
194
language : token . lang === 'js' ? 'ts' : token . lang ,
194
195
source : converted ,
195
196
twoslashBanner,
@@ -932,32 +933,27 @@ function replace_blank_lines(html: string) {
932
933
return html . replaceAll ( / < d i v c l a s s = ' l i n e ' > ( & n b s p ; ) ? < \/ d i v > / g, '<div class="line">\n</div>' ) ;
933
934
}
934
935
935
- function syntax_highlight ( {
936
+ async function syntax_highlight ( {
936
937
source,
937
938
filename,
938
939
language,
939
- highlighter,
940
940
twoslashBanner,
941
941
options
942
942
} : {
943
943
source : string ;
944
944
filename : string ;
945
945
language : string ;
946
- highlighter : Awaited < ReturnType < typeof import ( 'shiki-twoslash' ) . createShikiHighlighter > > ;
947
946
twoslashBanner ?: TwoslashBanner ;
948
947
options : SnippetOptions ;
949
948
} ) {
950
949
let html = '' ;
951
950
952
951
if ( / ^ ( d t s | y a m l | y m l ) / . test ( language ) ) {
953
952
html = replace_blank_lines (
954
- twoslash_module . renderCodeToHTML (
955
- source ,
956
- language === 'dts' ? 'ts' : language ,
957
- { twoslash : false } ,
958
- { themeName : 'css-variables' } ,
959
- highlighter
960
- )
953
+ await codeToHtml ( source , {
954
+ lang : language === 'dts' ? 'ts' : language ,
955
+ theme
956
+ } )
961
957
) ;
962
958
} else if ( / ^ ( j s | t s ) / . test ( language ) ) {
963
959
try {
@@ -974,41 +970,18 @@ function syntax_highlight({
974
970
}
975
971
}
976
972
977
- const twoslash = twoslash_module . runTwoSlash ( source , language , {
978
- defaultCompilerOptions : {
979
- allowJs : true ,
980
- checkJs : true ,
981
- target : ts . ScriptTarget . ES2022 ,
982
- types : [ 'svelte' , '@sveltejs/kit' ]
983
- }
973
+ html = await codeToHtml ( source , {
974
+ lang : 'ts' ,
975
+ theme,
976
+ transformers : [ transformerTwoslash ( { } ) ]
984
977
} ) ;
985
-
986
- html = twoslash_module . renderCodeToHTML (
987
- twoslash . code ,
988
- 'ts' ,
989
- { twoslash : true } ,
990
- // @ts -ignore Why shiki-twoslash requires a theme name?
991
- { } ,
992
- highlighter ,
993
- twoslash
994
- ) ;
995
978
} catch ( e ) {
996
979
console . error ( `Error compiling snippet in ${ filename } ` ) ;
997
980
// @ts -ignore
998
981
console . error ( e . code ) ;
999
982
throw e ;
1000
983
}
1001
984
1002
- // we need to be able to inject the LSP attributes as HTML, not text, so we
1003
- // turn < into &lt;
1004
- html = html . replace (
1005
- / < d a t a - l s p l s p = ' ( [ ^ ' ] * ) ' ( [ ^ > ] * ) > ( \w + ) < \/ d a t a - l s p > / g,
1006
- ( _ , lsp , attrs , name ) => {
1007
- if ( ! lsp ) return name ;
1008
- return `<data-lsp lsp='${ lsp . replace ( / & / g, '&' ) } '${ attrs } >${ name } </data-lsp>` ;
1009
- }
1010
- ) ;
1011
-
1012
985
html = replace_blank_lines ( html ) ;
1013
986
} else if ( language === 'diff' ) {
1014
987
const lines = source . split ( '\n' ) . map ( ( content ) => {
@@ -1031,8 +1004,9 @@ function syntax_highlight({
1031
1004
} )
1032
1005
. join ( '' ) } </code></pre>`;
1033
1006
} else {
1034
- const highlighted = highlighter . codeToHtml ( source , {
1035
- lang : SHIKI_LANGUAGE_MAP [ language as keyof typeof SHIKI_LANGUAGE_MAP ]
1007
+ const highlighted = await codeToHtml ( source , {
1008
+ lang : SHIKI_LANGUAGE_MAP [ language as keyof typeof SHIKI_LANGUAGE_MAP ] ,
1009
+ theme
1036
1010
} ) ;
1037
1011
1038
1012
html = replace_blank_lines ( highlighted ) ;
0 commit comments