next-shiki
next-shiki copied to clipboard
Fails to load onig.wasm, themes and languages
In my blog I use tailwind and I have followed the instructions from the README.md. The page I share here is using the pages approach.
https://nextjs-blog-git-replace-code-blocks-highlighting-marcofranssen.vercel.app/git-recipes
components/code-block.tsx
import { Lang } from "shiki";
import { useState, useEffect } from "react";
import { highlight } from "../../lib/highlight";
export default function CodeBlock({
title,
url,
children,
language,
}: {
title?: string;
url?: string;
children?: string;
language: string;
}) {
const [code, setCode] = useState("");
const [isLoading, setIsLoading] = useState(false);
const theme = "one-dark-pro";
useEffect(() => {
if (children) {
setIsLoading(true);
const highlightCode = async () => {
const highlightPromise =
typeof children === "string"
? highlight(children, theme, language as Lang)
: Promise.resolve("You need to define codeblock as a string");
setCode(await highlightPromise);
setIsLoading(false);
};
highlightCode();
} else {
const parsedUrl = !url?.startsWith("http")
? `/downloads/code/${url}`
: url;
const fetchCode = async () => {
setIsLoading(true);
const res = await fetch(parsedUrl);
const body = await res.text();
const highLightedCode = await highlight(body, theme, language as Lang);
setCode(highLightedCode);
setIsLoading(false);
};
fetchCode();
}
}, [children, url, language]);
return isLoading ? (
<div data-rehype-pretty-code-fragment>
{title && <div data-rehype-pretty-code-title>{title}</div>}
<pre data-language={language} data-theme={theme}>
<code data-language={language} data-theme={theme}>
Loading…
</code>
</pre>
</div>
) : (
<div data-rehype-pretty-code-fragment>
{title && <div data-rehype-pretty-code-title>{title}</div>}
<pre data-language={language} data-theme={theme}>
<code
data-language={language}
data-theme={theme}
dangerouslySetInnerHTML={{ __html: code }}
/>
</pre>
</div>
);
}
lib/highlight.js
import { Highlighter, Lang, Theme } from "shiki";
import { renderToHtml, getHighlighter } from "shiki";
export async function highlight(code: string, theme?: Theme, lang?: Lang) {
const highlighter: Highlighter = await getHighlighter({
langs: lang ? [lang] : [],
theme: theme,
});
const tokens = highlighter.codeToThemedTokens(code, lang, theme, {
includeExplanation: false,
});
const html = renderToHtml(tokens, { bg: "transparent" });
return html;
}
On this page I use the code-block as following:
import CodeBlock from "../components/blocks/code-block";
…
…
…
<CodeBlock language="bash">
git cherry-pick --strategy recursive --strategy-option theirs
«mergeCommitHash»^..«mergeCommitHash»
</CodeBlock>
<CodeBlock
title=".gitconfig"
url="https://raw.githubusercontent.com/marcofranssen/dotfiles/master/.gitconfig"
language="ini"
/>
I have following in the next config
experimental: {
appDir: true,
serverComponentsExternalPackages: ["vscode-oniguruma", "shiki"],
},
What am I missing to make it work? 🤔
For other pages you might notice it does work as there I'm prepocessing the md
files using rehype. https://nextjs-blog-git-replace-code-blocks-highlighting-marcofranssen.vercel.app/secure-your-software-supply-chain-using-sigstore-and-github-actions
The code blocks that work are processed via rehype, the ones that don't work are the ones clientside resolving the content on the given url as shown in above example.
It would be really cool if this example could be updated to also show how to use shiki client-side using the wasm module.