🚀 BlockNote AI is here! Access the early preview.

Custom Code Block Theme & Language

To configure a code block highlighting theme and language, you can extend the editor's default schema with a new codeBlock, which you can pass options into when creating. You can then use a shiki highlighter to add custom syntax highlighting.

First use the shiki-codegen CLI to create a shiki.bundle.ts file. You can then pass this file into the codeBlock options when creating it.

Relevant Docs:

import { BlockNoteSchema, createCodeBlockSpec } from "@blocknote/core";
import "@blocknote/core/fonts/inter.css";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";
import { useCreateBlockNote } from "@blocknote/react";
// Bundle created from `npx shiki-codegen --langs typescript,javascript,react --themes light-plus,dark-plus --engine javascript --precompiled ./shiki.bundle.ts`
import { createHighlighter } from "./shiki.bundle";

export default function App() {
  // Creates a new editor instance.
  const editor = useCreateBlockNote({
    schema: BlockNoteSchema.create().extend({
      blockSpecs: {
        codeBlock: createCodeBlockSpec({
          indentLineWithTab: true,
          defaultLanguage: "typescript",
          supportedLanguages: {
            typescript: {
              name: "TypeScript",
              aliases: ["ts"],
            },
            javascript: {
              name: "JavaScript",
              aliases: ["js"],
            },
            vue: {
              name: "Vue",
            },
          },
          // This creates a highlighter, it can be asynchronous to load it afterwards
          createHighlighter: () =>
            createHighlighter({
              themes: ["dark-plus", "light-plus"],
              langs: [],
            }),
        }),
      },
    }),
    initialContent: [
      {
        type: "codeBlock",
        props: {
          language: "typescript",
        },
        content: [
          {
            type: "text",
            text: "const x = 3 * 4;",
            styles: {},
          },
        ],
      },
      {
        type: "paragraph",
      },
      {
        type: "heading",
        props: {
          textColor: "default",
          backgroundColor: "default",
          textAlignment: "left",
          level: 3,
        },
        content: [
          {
            type: "text",
            text: 'Click on "Typescript" above to see the different supported languages',
            styles: {},
          },
        ],
      },
      {
        type: "paragraph",
      },
    ],
  });

  // Renders the editor instance using a React component.
  return <BlockNoteView editor={editor} />;
}
/* Generate by @shikijs/codegen */
import type {
  DynamicImportLanguageRegistration,
  DynamicImportThemeRegistration,
  HighlighterGeneric,
} from "@shikijs/types";
import { createdBundledHighlighter } from "@shikijs/core";
import { createJavaScriptRegexEngine } from "@shikijs/engine-javascript";

type BundledLanguage = "typescript" | "ts" | "javascript" | "js" | "vue";
type BundledTheme = "light-plus" | "dark-plus";
type Highlighter = HighlighterGeneric<BundledLanguage, BundledTheme>;

const bundledLanguages = {
  typescript: () => import("@shikijs/langs-precompiled/typescript"),
  ts: () => import("@shikijs/langs-precompiled/typescript"),
  javascript: () => import("@shikijs/langs-precompiled/javascript"),
  js: () => import("@shikijs/langs-precompiled/javascript"),
  vue: () => import("@shikijs/langs-precompiled/vue"),
} as Record<BundledLanguage, DynamicImportLanguageRegistration>;

const bundledThemes = {
  "light-plus": () => import("@shikijs/themes/light-plus"),
  "dark-plus": () => import("@shikijs/themes/dark-plus"),
} as Record<BundledTheme, DynamicImportThemeRegistration>;

const createHighlighter = /* @__PURE__ */ createdBundledHighlighter<
  BundledLanguage,
  BundledTheme
>({
  langs: bundledLanguages,
  themes: bundledThemes,
  engine: () => createJavaScriptRegexEngine(),
});

export { createHighlighter };
export type { BundledLanguage, BundledTheme, Highlighter };