next-shiki icon indicating copy to clipboard operation
next-shiki copied to clipboard

Fails to load onig.wasm, themes and languages

Open marcofranssen opened this issue 1 year ago • 1 comments

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.

marcofranssen avatar May 02 '23 09:05 marcofranssen