Skip to content

Instantly share code, notes, and snippets.

@tom-sherman
Created April 15, 2023 13:03
Show Gist options
  • Save tom-sherman/514d4d1ce9f029bafe40bccf335ee86e to your computer and use it in GitHub Desktop.
Save tom-sherman/514d4d1ce9f029bafe40bccf335ee86e to your computer and use it in GitHub Desktop.
Perfect syntax highlighting with Shiki and React Server Components in under 50 lines of code
import { getHighlighter as shikiGetHighlighter } from "shiki";
import { cache } from "react";
interface ShikiProps {
code: string;
lang: string;
theme: string;
}
export async function Shiki({ code, lang, theme }: ShikiProps) {
const highlighter = await getHighlighter(lang, theme);
const html = highlighter.codeToHtml(code, {
lang,
theme,
});
return <div dangerouslySetInnerHTML={{ __html: html }} />;
}
const highlighterPromise = shikiGetHighlighter({});
const getHighlighter = cache(async (language: string, theme: string) => {
console.log("Loading highlighter", language, theme);
const highlighter = await highlighterPromise;
const loadedLanguages = highlighter.getLoadedLanguages();
const loadedThemes = highlighter.getLoadedThemes();
let promises = [];
if (!loadedLanguages.includes(language as any)) {
promises.push(highlighter.loadLanguage(language as any));
}
if (!loadedThemes.includes(theme as any)) {
promises.push(highlighter.loadTheme(theme));
}
await Promise.all(promises);
return highlighter;
});
@tom-sherman
Copy link
Author

tom-sherman commented Nov 3, 2023

@shellscape this is a server component, you need to be using it in a framework that supports it like Next.js 13+

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment