MDX コンポーネントマップ
信頼できる MDX を Vite でコンパイルし、CommonMark と GFM の出力を Tinyrack の React コンポーネントマップでレンダリングします。
最初に信頼境界を決める
アプリケーションと一緒にレビューし、Vite のビルド時にコンパイルする .mdx ファイルに、この連携を使用してください。MDX には JavaScript と JSX を含められるため、アプリケーションと同じ権限で実行されます。リモートから取得した MDX やユーザーが作成した MDX を、この設定へ渡さないでください。信頼できないコンテンツには、コードを実行しない Markdown パイプラインと明示的なサニタイズ方針を使用します。コンテンツの取得元を決める前に、MDX のセキュリティガイドを確認してください。
ビルドツールをインストールする
React 19、Vite、Tailwind CSS 4 を使用するアプリケーションから始めます。Tinyrack は実行時の依存関係としてインストールし、コンパイラープラグインは開発用の依存関係にしてください。
pnpm add @tinyrack/ui react@^19 react-dom@^19
pnpm add -D @mdx-js/rollup @tailwindcss/vite @types/mdx @vitejs/plugin-react remark-gfm tailwindcss@^4 vite
Vite を設定する
React プラグインより先に .mdx を変換するため、MDX プラグインを pre フェーズで実行します。React プラグインの対象に Markdown の拡張子を含め、タスクリスト、表、取り消し線、自動リンク、脚注には remark-gfm を追加してください。コンパイル済みコンポーネントへマップを直接渡すため、@mdx-js/react と providerImportSource は必要ありません。プラグインの順序は MDX の Vite 連携ガイドで確認できます。
import mdx from '@mdx-js/rollup';
import tailwindcss from '@tailwindcss/vite';
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite';
import remarkGfm from 'remark-gfm';
export default defineConfig({
plugins: [
{
enforce: 'pre',
...mdx({ remarkPlugins: [remarkGfm] }),
},
react({ include: /\.(?:js|jsx|ts|tsx|md|mdx)$/ }),
tailwindcss(),
],
});
Tailwind のエントリーを最初に読み込み、Tinyrack のコア、MDX、コンポーネントマップが使用するコンポーネントのスタイルを続けて読み込んでください。
@import 'tailwindcss';
@import '@tinyrack/ui/core.css';
@import '@tinyrack/ui/mdx.css';
@import '@tinyrack/ui/components/code.css';
@import '@tinyrack/ui/components/code-block.css';
@import '@tinyrack/ui/components/link.css';
@import '@tinyrack/ui/components/table.css';
信頼できる MDX をレンダリングする
コンパイル済みの .mdx ファイルをインポートし、components プロパティで tinyrackMdxComponents を渡します。Content はビルド時に生成される React コンポーネントであり、実行時のレンダラーに渡す HTML 文字列ではありません。
import Content from './content.mdx';
import { tinyrackMdxComponents } from '@tinyrack/ui/mdx';
import './app.css';
export function MdxArticle() {
return <Content components={tinyrackMdxComponents} />;
}
実際の MDX ファイルをプレビューする
プレビューでは、現在の言語に対応する実際の .mdx ファイルをインポートします。このサンプルでは、Tinyrack のマップが対応する CommonMark と GFM の要素をすべて使用します。見出し、本文、インライン書式、リスト、画像、引用、ハードブレーク、水平線、タスクリスト、表、コードブロック、脚注をまとめて確認できます。
コンパイル済み MDX の出力 パーマリンク
作成した MDX と、このドキュメント内で使用する React の構成を比較できます。
ページのランドマークを選ぶ
tinyrackMdxComponents の既定の wrapper は、<main className="tr-mdx"> をレンダリングします。MDX ドキュメントがページの主要コンテンツを担う場合は、この既定値を使用してください。アプリケーションにすでに main ランドマークがある場合は、新しいマップを作成して wrapper を article に置き換えます。共通の本文スタイルを適用するため、tr-mdx クラスは残してください。
import type { ComponentPropsWithoutRef } from 'react';
import Content from './content.mdx';
import { createTinyrackMdxComponents } from '@tinyrack/ui/mdx';
import './app.css';
function ArticleWrapper({
children,
className,
...props
}: ComponentPropsWithoutRef<'article'>) {
return (
<article
{...props}
className={['tr-mdx', className].filter(Boolean).join(' ')}
>
{children}
</article>
);
}
const articleComponents = createTinyrackMdxComponents({
components: { wrapper: ArticleWrapper },
});
export function ProductPage() {
return (
<main>
<Content components={articleComponents} />
</main>
);
}
コンポーネントマップをカスタマイズする
createTinyrackMdxComponents({ components }) は、すべての既定キーを含む新しいマップを作成してから、渡された項目で上書きします。tinyrackMdxComponents を変更せずに、見出し、リンク、ラッパー、その他のマッピング要素を置き換える場合に使用してください。セマンティックな HTML、渡された属性、アクセシブル名、置き換えるコンポーネントのスタイルコントラクトに必要なクラスを維持します。
契約と制限
| MDX の出力 | 既定の担当 | 重要な動作 |
|---|---|---|
| ドキュメントのラッパー | main.tr-mdx | 既存の main 内では article.tr-mdx に置き換えます。 |
| インラインコードとコードブロック | TRCode、TRCodeBlock | コードブロックには Shiki のハイライトが段階的に適用されます。 |
| リンク | TRLink | リンクの意味と遷移先には MDX で作成した値が使われます。 |
| 表 | TRTable.Root | 表のコンテナー内だけで横方向にスクロールします。 |
| タスクリストの入力 | ネイティブの無効なチェックボックス | 記述したチェック状態が維持されます。 |
| その他の本文 | セマンティックな React 要素 | 見出し、リスト、引用、画像、脚注に共通の MDX クラスが適用されます。 |
この連携は、実行時に MDX を取得、サンドボックス化、コンパイルしません。Next.js または Astro に固有の設定も扱いません。
連携を確認する
- Vite のプロダクションビルドを実行し、インポートした
.mdxモジュールがコンパイルされることを確認してください。 - ページの主要な
mainランドマークが 1 つだけであることを確認します。別のmainがすでに存在する場合は、articleへの上書きを使用してください。 - タスクリストのチェックボックスが無効になっていること、リンクが意図した遷移先へ移動すること、狭い画面では表が専用コンテナー内でスクロールすることを確認してください。
- 段階的なコードハイライトが完了する前の状態も含め、インラインコードとコードブロックをライトテーマとダークテーマで確認してください。