Next.jsのMDXでMarkdown形式のテーブルを表示する(remark-gfm + next-mdx-remote)
問題:MDXでテーブルが文字列として表示される
Next.jsプロジェクトでMDXファイル内にMarkdown形式のテーブルを書いたところ、テーブルとして表示されず文字列のまま表示されてしまった。
| column_name | is_identity | identity_generation | column_default |
| ----------- | ----------- | ------------------- | ----------------------------------- |
| onidazo_id | NO | null | nextval('onidazo_id_seq'::regclass') |この記事では、このようなMarkdown形式のテーブル(パイプテーブル)を正しく<table>要素としてレンダリングできるようにした実装手順を紹介する。
環境
- Next.js 16.0.7 (App Router)
- TypeScript
next-mdx-remote5.0.0 (MDXのレンダリング)rehype-pretty-code0.14.1 (コードブロックの整形)github-markdown-css5.8.1 (GitHubスタイルのMarkdown CSS)shiki3.19.0 (シンタックスハイライト)
原因:GitHub Flavored Markdownのサポートが必要だった
調べてみると、Markdown形式のテーブルは GitHub Flavored Markdown (GFM) の拡張構文であり、標準のMarkdownパーサーではサポートされていないことが分かった。そのため、remark-gfmプラグインを追加する必要があった。
remarkとrehypeの違い
- remark: Markdown → mdast(Markdown抽象構文木)変換を担当
- rehype: HTML操作に特化(コードブロックのシンタックスハイライトなど)
テーブル構文の解析はMarkdownレベルで行われるため、remarkプラグイン(remark-gfm)を使用した。
なお、このプロジェクトでは既にコードブロックのシンタックスハイライトのためにrehype-pretty-codeとshikiをrehypeプラグインとして使用していたが、remarkとrehypeは処理のタイミングが異なるため、両方を併用できた。
実装手順
1. remark-gfmパッケージをインストール
まず、remark-gfmパッケージをインストールした。
yarn add remark-gfm2. mdxOptions に remarkPlugins を追加
今回のプロジェクトではnext-mdx-remoteのcompileMDXを使ってMDXをレンダリングしていたので、mdxOptionsにremarkPluginsを追加した。
既にrehype-pretty-codeやshikiを使用していたため、既存のrehypePluginsはそのままで、remarkPlugins配列にremarkGfmを追加した。
// lib/note.ts
import { compileMDX } from "next-mdx-remote/rsc";
import rehypePrettyCode from "rehype-pretty-code";
import remarkGfm from "remark-gfm";
const { content, frontmatter } = await compileMDX({
source: fileContent,
options: {
parseFrontmatter: true,
mdxOptions: {
remarkPlugins: [remarkGfm], // ← remarkプラグインとして追加
rehypePlugins: [
// 既存のrehypeプラグイン(そのまま残す)
[
rehypePrettyCode,
{
theme: {
light: "vitesse-light",
dark: "vitesse-dark",
},
},
],
],
},
},
components: {
// カスタムコンポーネント
},
});3. テーブルのスタイリング(オプション)
次に、テーブルにカスタムスタイルを適用するため、MDXコンポーネントをカスタマイズした。
// app/mdx-components.tsx
import type { MDXComponents } from "mdx/types";
const components: MDXComponents = {
table: ({ children }) => (
<div>
<table>
{children}
</table>
</div>
),
thead: ({ children }) => (
<thead>{children}</thead>
),
tbody: ({ children }) => (
<tbody>{children}</tbody>
),
tr: ({ children }) => (
<tr>{children}</tr>
),
th: ({ children }) => (
<th>
{children}
</th>
),
td: ({ children }) => (
<td>{children}</td>
),
};
export function useMDXComponents(): MDXComponents {
return components;
}このカスタムコンポーネントをcompileMDXのcomponentsに追加した。
// lib/note.ts
import { useMDXComponents } from "@/app/mdx-components";
const { content, frontmatter } = await compileMDX({
source: fileContent,
options: {
// ...
},
components: {
...useMDXComponents(), // ← カスタムコンポーネントを展開
// その他のコンポーネント
},
});動作確認
開発サーバーを再起動して動作確認した。
yarn dev重要: Next.jsの設定ファイル(next.config.mjsやlib/note.ts)を変更した場合は、必ず再起動が必要である。
トラブルシューティング
テーブルが正しく表示されない場合は、以下を試すと良い。
- 開発サーバーを完全に停止して再起動
- ブラウザのキャッシュをクリア(ハードリロード: Cmd+Shift+R)
.nextフォルダを削除して再ビルド
rm -rf .next
yarn dev結果
これで、Markdown形式のテーブルが正しくHTMLの<table>要素としてレンダリングされるようになった。
| column_name | is_identity | identity_generation | column_default |
|---|---|---|---|
| onidazo_id | NO | null | nextval('onidazo_id_seq'::regclass') |
remark-gfmで使えるその他の機能
remark-gfmを追加したことで、テーブル以外にも以下のGitHub Flavored Markdown機能が使えるようになった。
取り消し線
~~text~~で取り消し線を表示できる。
取り消された文字
タスクリスト
- [ ]と- [x]でチェックボックス付きリストを表示できる。
- 未完了のタスク
- 完了したタスク
自動リンク
URLを書くだけで自動的にリンクになる。
脚注
[^1]のような記法で脚注を追加できる。1
まとめ
- Markdown形式のテーブルを表示するには
remark-gfmプラグインが必要 - 今回は
next-mdx-remoteを使用していたのでmdxOptions.remarkPluginsに追加した - (参考)
@next/mdxを使用している場合はnext.config.mjsに追加する - テーブルのスタイリングは
mdx-components.tsxでカスタマイズした - 設定変更後は開発サーバーの再起動が必須
参考リンク
-
これは脚注の例である。脚注は自動的にページ下部に表示される。 ↩