1818 * ```
1919 */
2020
21- import type { Highlighter , BundledLanguage } from "shiki" ;
22- import type { ShikiEngine } from "./types" ;
21+ import type { HighlighterCore } from "shiki/core " ;
22+ import type { ShikiEngine , SupportedLanguage } from "./types" ;
2323import type { ReactNode } from "react" ;
2424
25+ /**
26+ * Pre-bundled languages - only these languages are included in the Kumo bundle.
27+ * Using fine-grained imports from @shikijs/langs to minimize bundle size.
28+ */
29+ const BUNDLED_LANGS : Record <
30+ SupportedLanguage ,
31+ ( ) => Promise < { default : unknown } >
32+ > = {
33+ javascript : ( ) => import ( "@shikijs/langs/javascript" ) ,
34+ typescript : ( ) => import ( "@shikijs/langs/typescript" ) ,
35+ jsx : ( ) => import ( "@shikijs/langs/jsx" ) ,
36+ tsx : ( ) => import ( "@shikijs/langs/tsx" ) ,
37+ json : ( ) => import ( "@shikijs/langs/json" ) ,
38+ jsonc : ( ) => import ( "@shikijs/langs/jsonc" ) ,
39+ html : ( ) => import ( "@shikijs/langs/html" ) ,
40+ css : ( ) => import ( "@shikijs/langs/css" ) ,
41+ python : ( ) => import ( "@shikijs/langs/python" ) ,
42+ yaml : ( ) => import ( "@shikijs/langs/yaml" ) ,
43+ markdown : ( ) => import ( "@shikijs/langs/markdown" ) ,
44+ graphql : ( ) => import ( "@shikijs/langs/graphql" ) ,
45+ sql : ( ) => import ( "@shikijs/langs/sql" ) ,
46+ bash : ( ) => import ( "@shikijs/langs/bash" ) ,
47+ shell : ( ) => import ( "@shikijs/langs/shellscript" ) ,
48+ diff : ( ) => import ( "@shikijs/langs/diff" ) ,
49+ } ;
50+
2551export interface HighlightCodeOptions {
2652 /** Highlighting engine (default: "javascript") */
2753 engine ?: ShikiEngine ;
@@ -31,12 +57,12 @@ export interface CreateHighlighterOptions {
3157 /** Highlighting engine (default: "javascript") */
3258 engine ?: ShikiEngine ;
3359 /** Languages to support */
34- languages : BundledLanguage [ ] ;
60+ languages : SupportedLanguage [ ] ;
3561}
3662
3763export interface ServerHighlighter {
3864 /** Highlight code and return HTML string */
39- highlight : ( code : string , lang : BundledLanguage ) => string ;
65+ highlight : ( code : string , lang : SupportedLanguage ) => string ;
4066 /** Dispose the highlighter when done */
4167 dispose : ( ) => void ;
4268}
@@ -56,10 +82,10 @@ export interface ServerHighlighter {
5682 */
5783export async function highlightCode (
5884 code : string ,
59- lang : BundledLanguage ,
85+ lang : SupportedLanguage ,
6086 options : HighlightCodeOptions = { } ,
6187) : Promise < string > {
62- const { createHighlighter } = await import ( "shiki" ) ;
88+ const { createHighlighterCore } = await import ( "shiki/core " ) ;
6389
6490 const engine = options . engine ?? "javascript" ;
6591 const engineInstance =
@@ -71,9 +97,19 @@ export async function highlightCode(
7197 m . createJavaScriptRegexEngine ( ) ,
7298 ) ;
7399
74- const highlighter = await createHighlighter ( {
75- themes : [ "github-light" , "vesper" ] ,
76- langs : [ lang ] ,
100+ // Load themes
101+ const [ githubLight , vesper ] = await Promise . all ( [
102+ import ( "@shikijs/themes/github-light" ) ,
103+ import ( "@shikijs/themes/vesper" ) ,
104+ ] ) ;
105+
106+ // Load only the requested language
107+ const langModule = await BUNDLED_LANGS [ lang ] ( ) ;
108+
109+ const highlighter = await createHighlighterCore ( {
110+ themes : [ githubLight . default , vesper . default ] ,
111+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
112+ langs : [ langModule . default ] as any ,
77113 engine : engineInstance ,
78114 } ) ;
79115
@@ -113,7 +149,7 @@ export async function highlightCode(
113149export async function createServerHighlighter (
114150 options : CreateHighlighterOptions ,
115151) : Promise < ServerHighlighter > {
116- const { createHighlighter } = await import ( "shiki" ) ;
152+ const { createHighlighterCore } = await import ( "shiki/core " ) ;
117153
118154 const engine = options . engine ?? "javascript" ;
119155 const engineInstance =
@@ -125,14 +161,30 @@ export async function createServerHighlighter(
125161 m . createJavaScriptRegexEngine ( ) ,
126162 ) ;
127163
128- const highlighter : Highlighter = await createHighlighter ( {
129- themes : [ "github-light" , "vesper" ] ,
130- langs : options . languages ,
164+ // Load themes
165+ const [ githubLight , vesper ] = await Promise . all ( [
166+ import ( "@shikijs/themes/github-light" ) ,
167+ import ( "@shikijs/themes/vesper" ) ,
168+ ] ) ;
169+
170+ // Load only the requested languages from our bundled set
171+ const validLanguages = options . languages . filter (
172+ ( lang ) : lang is SupportedLanguage => lang in BUNDLED_LANGS ,
173+ ) ;
174+
175+ const langModules = await Promise . all (
176+ validLanguages . map ( ( lang ) => BUNDLED_LANGS [ lang ] ( ) ) ,
177+ ) ;
178+
179+ const highlighter : HighlighterCore = await createHighlighterCore ( {
180+ themes : [ githubLight . default , vesper . default ] ,
181+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
182+ langs : langModules . map ( ( m ) => m . default ) as any ,
131183 engine : engineInstance ,
132184 } ) ;
133185
134186 return {
135- highlight : ( code : string , lang : BundledLanguage ) : string => {
187+ highlight : ( code : string , lang : SupportedLanguage ) : string => {
136188 return highlighter . codeToHtml ( code , {
137189 lang,
138190 themes : {
0 commit comments