It turns out that by default, Next.js doesn't bundle in shiki, which means
there's a raw require or dynamic import for the text grammars and the themes.
After stumbling across a few different issues, each with different ways to
resolve the problem I was running into, I found the following solution:
import shiki from "shiki";
// Manually import themes and grammars
import cssGrammar from "shiki/languages/css.tmLanguage.json";
import diffGrammar from "shiki/languages/diff.tmLanguage.json";
import jsonGrammar from "shiki/languages/json.tmLanguage.json";
import mdGrammar from "shiki/languages/markdown.tmLanguage.json";
import bashGrammar from "shiki/languages/shellscript.tmLanguage.json";
import tsxGrammar from "shiki/languages/tsx.tmLanguage.json";
import githubDarkDimmed from "shiki/themes/github-dark-dimmed.json";
import githubLight from "shiki/themes/github-light.json";
export default async function CodeBlock({ children, className, ...props }) {
let lang = className ? className.split("-")[1] : "typescript";
if (lang === "tsx" || lang === "jsx" || lang === "js") {
lang = "typescript";
} else if (lang === "sh") {
lang = "bash";
}
let codeToHighlight = children;
let highlighter = await shiki.getHighlighter({
// Pass in manually imported themes and grammars
themes: [githubDarkDimmed, githubLight],
langs: [
{ id: "tsx", scopeName: "source.tsx", grammar: tsxGrammar },
{ id: "typescript", scopeName: "source.tsx", grammar: tsxGrammar },
{ id: "md", scopeName: "text.html.markdown", grammar: mdGrammar },
{ id: "css", scopeName: "source.css", grammar: cssGrammar },
{ id: "diff", scopeName: "source.diff", grammar: diffGrammar },
{ id: "bash", scopeName: "source.shell", grammar: bashGrammar },
{ id: "json", scopeName: "source.json", grammar: jsonGrammar },
],
});
let html = highlighter.codeToHtml(codeToHighlight, { lang });
return (
<Box
is="code"
dangerouslySetInnerHTML={{ __html: html }}
{...props}
className={className ? `${className} ${code}` : `${code}`}
/>
);
}
For some reason, shiki's TypeScript types don't seem to like me passing in the
themes or the grammars manually, so I opted to ts-ignore those errors for the
time being 🙂.