homeIcon

Rehype Pretty Code を使って、自分好みのシンタックスハイライトを手に入れる

フロントエンド
2025.08.10
2025.08.11

技術系ブログを書くならシンタックスハイライトは必須ですよね。
というわけで、今回はシンタックスハイライトの導入を行っていこうと思います。

ライブラリは rehype-pretty-code という rehype のプラグインを使用します。
このパッケージは、 Shiki を使ってシンタックスハイライトを行います。シンタックスハイライトといえば Prism が有名ですが、今回は Shiki を使用したパッケージを採用しました。

Prism よりも Shiki の方が精度が高い

他の導入事例を見たところ、 Prism はハイライトの精度が完全でなく、崩れることもあるようでした。
syntax highlighter を shiki に切り替えた | blog.ojisan.io 参照。
その点、Shiki は VS Code と同じシンタックスハイライトのエンジンを使っているようなので安心です。

ちなみに、Astro でも、 Shiki がデフォルトのシンタックスハイライトとして使われているようです。
Markdown in Astro | Astro Docs 参照。

そんなわけで、 Shiki を使うのがよかろうと結論しました。
で、 Shiki を使うために色々と調べているときに出会ったのが Rehype Pretty Code (rehype-pretty-code) という rehype プラグインです。

Rehype Pretty Code

Beautiful code blocks for Markdown or MDX powered by the Shiki syntax highlighter.

no-image

Rehype Pretty Code とは?

Rehype Pretty Code は、MD/MDX ドキュメントに美しいコードブロックを提供する rehype プラグインです。
主に次のような特徴があります。

  • VSCodeテーマ互換(既存テーマやカスタムテーマを使用可能)
  • 行番号・ハイライト行・差分表示に対応
  • コードブロックのメタ情報からファイル名を表示可能
  • サーバーサイドで完全変換 → Hydrationエラー回避

例えば以下のように、ファイル名や特定の行のハイライト・diffの表示などを行うことができます。

app.js
const add = (a, b) => a + b;
 
console.log('removed') 
console.log('added') 
 
add(2, 3); // 5

Rehype Pretty Code の導入

前提

今回は、Markdown(MDX) から html にパースするライブラリである next-mdx-remote-client が導入済みであることを前提としています。
next-mdx-remote-client の導入については、以下の記事に記載していますので、併せてご覧ください。

ブログ記事をMDXで管理したくて、next-mdx-remote-clientを導入した話

No description available.

my-profile-mu-gold.vercel.app

OGP Image

インストール

まずは 公式ドキュメント に沿って、必要なパッケージをインストールします。

npm install rehype-pretty-code shiki

MDX 変換オプションの設定

次に、/libs/mdxOptions.tsrehype-pretty-code をインポートします。また、それを使用するために rehypePlugins: [] を追加します。

/src/libs/mdxOptions.ts
import remarkGfm from "remark-gfm";
import type { MDXRemoteOptions } from "next-mdx-remote-client/rsc";
import rehypePrettyCode from "rehype-pretty-code"; 
import { prettyCodeOptions } from "@/libs/prettyCodeOptions"; 
import type { PluggableList } from "unified"; 
 
export const mdxOptions: MDXRemoteOptions = {
  mdxOptions: {
    remarkPlugins: [remarkGfm],
    rehypePlugins: [[rehypePrettyCode, prettyCodeOptions]] as PluggableList, 
    format: "mdx",
  },
  parseFrontmatter: true,
};

Rehype Pretty Code の設定

続けて、Rehype Pretty Code の設定を行なっていきます。上記で使用している prettyCodeOptions の部分です。

/src/libs/prettyCodeOptions.ts
import type { Options } from "rehype-pretty-code";
 
export const prettyCodeOptions: Options = {
  theme: "plastic",
  keepBackground: true,
  defaultLang: "plaintext",
  bypassInlineCode: true,
};
  • theme: "plastic":シンタックスハイライトのテーマを指定。Shiki に含まれるテーマは Shiki | Themes から確認できます。
  • keepBackground: true:コードブロックの背景色をテーマの設定通りに保持。
  • defaultLang: "plaintext":言語指定がないコードブロックをプレーンテキストとして処理。
  • bypassInlineCode: true:インラインコードはrehype-pretty-codeの処理対象から除外。

ページ表示

そして、設定した mdxOptions は以下のように使用します。コードの具体的な説明に関しては、上記の記事をご参照ください。

/src/app/blog/[slug]/page.tsx
import React from "react";
import { getAllBlogSlugs, getBlogBySlug } from "@/libs/microcms";
import { notFound } from "next/navigation";
import { fetchOgpDataFromMdx } from "@/libs/fetchOgpDataFromMdx";
import { MdxComponents } from "@/components/PortfolioAndBlog/ContentPage/MdxComponents";
import { MDXRemote } from "next-mdx-remote-client/rsc";
import { mdxOptions } from "@/libs/mdxOptions";
import BlogClientWrapper from "@/components/PortfolioAndBlog/ContentPage/BlogClientWrapper";
 
 
type PageProps = {
  params: Promise<{ slug: string }>;
};
 
export async function generateStaticParams() {
  const slugs = await getAllBlogSlugs();
  return (slugs ?? []).map(({ articleSlug }) => ({ slug: articleSlug }));
}
 
export default async function BlogContentPage({ params }: PageProps) {
  const { slug } = await params;
  const blogContentData = await getBlogBySlug(slug);
 
  if (!blogContentData) return notFound();
 
  const { ogpDataList } = await fetchOgpDataFromMdx(blogContentData.body);
  const components = MdxComponents(ogpDataList);
 
  return (
    <BlogClientWrapper blogContent={blogContentData}>
      <MDXRemote
        source={blogContentData.body}
        options={mdxOptions} 
        components={components}
      />
    </BlogClientWrapper>
  );
}

これで、rehype-pretty-code を用いたシンタックスハイライトが適用されました。
ちなみに、Shiki に含まれていないテーマでも、 JSON があればそれを読み込んで使用することもできます。詳しくはドキュメントをご参照あれ。

以降は、より自分好みにカスタマイズしていくために、ファイル名や特定の行のハイライト・diffの表示などを行なっていきます。

ファイル名・ハイライト・diffの表示

コードブロックにファイル名を表示する

コードブロックにファイル名を設定するには、マークダウンのコードブロックに title="..." を使用します。

\```js title="app.js"
const add = (a, b) => a + b
add(2, 3) // 5
\```

title="..." を使うと、 次のような要素が HTML に挿入されます。
data-rehype-pretty-code-title という data attribute を持つ figcaption 内に、 title="..." の値(ここでは app.js)が入っています。

<figcaption data-rehype-pretty-code-title="" data-language="js" data-theme="plastic">
  app.js
</figcaption>

こうすることで、以下のようにファイル名がコードブロックに付与されます。

app.js
const add = (a, b) => a + b
add(2, 3) // 5

ハイライト・diff を表示させる

Rehype Pretty Code は、 Shiki を使っているので、 @shikijs/transformers から transformerNotationHighlighttransformerNotationDiff をインポートし、 それを Rehype Pretty Code のオプションとして渡すことで、ハイライトや diff を表示できます。

準備

まずは、@shikijs/transformers をインストールします。

npm i -D @shikijs/transformers

次に、先ほどの /libs/prettyCodeOptions.ts に追加の設定を行います。

/src/libs/prettyCodeOptions.ts
import type { Options } from "rehype-pretty-code";
import { 
  transformerNotationHighlight, 
  transformerNotationDiff, 
} from "@shikijs/transformers"; 
 
export const prettyCodeOptions: Options = {
  theme: "plastic",
  keepBackground: true,
  defaultLang: "plaintext",
  bypassInlineCode: true,
  transformers: [transformerNotationDiff(), transformerNotationHighlight()], 
};

これで、ハイライト・diff を表示する準備が整いました。

ハイライトを表示する

ハイライトを表示させるには、マークダウン内でハイライトさせたい行の末尾に // [!code highlight] を記述します。

\```ts
console.log('highlight') // [!code highlight]
console.log('unchanged')
\```

すると、次のようにハイライトを表示できます。

console.log('highlight') 
console.log('unchanged')

diff を表示する

Diff の表示は、ハイライトと同様に diff を表示させたい行の末尾に // [!code --] // [!code ++] を記述します。

\```ts
console.log('removed') // [!code --]
console.log('added') // [!code ++]
console.log('unchanged')
\```

すると、次のようにシンタックスハイライトを効かせた状態で diff を表示できます。

console.log('removed') 
console.log('added') 
console.log('unchanged')

これで、無事に自分好みのシンタックスハイライトを手に入れることができました!

さいごに

今回 Rehype Pretty Code を導入して、rehype-pretty-code はデザイン性と機能性を兼ね備えたシンタックスハイライトツールであると感じました。

Shiki互換テーマで開発者に馴染みやすい色を再現可能であり、ハイライトや diff の表示など、記事の見やすさを大幅に向上できたと思います。
また、スタイルを自分好みにカスタマイズできる点が一番の魅力ではないでしょうか。

本記事が、シンタックスハイライトの導入を検討しているという方の参考になれば嬉しいです。
なお、本サイトのソースコードは以下で公開していますので、よければ覗いてみてください!

GitHub - miyazaki-dev01/My_profile: プロフィールサイト(React[Next.js]/TypeScript)

プロフィールサイト(React[Next.js]/TypeScript). Contribute to miyazaki-dev01/My_profile development by creating an account on GitHub.

github.com

プロフィールサイト(React[Next.js]/TypeScript). Contribute to miyazaki-dev01/My_profile development by creating an account on GitHub.

参考

Share