Tinyrack

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/reactproviderImportSource は必要ありません。プラグインの順序は 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 ランドマークがある場合は、新しいマップを作成して wrapperarticle に置き換えます。共通の本文スタイルを適用するため、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 に置き換えます。
インラインコードとコードブロックTRCodeTRCodeBlockコードブロックには Shiki のハイライトが段階的に適用されます。
リンクTRLinkリンクの意味と遷移先には MDX で作成した値が使われます。
TRTable.Root表のコンテナー内だけで横方向にスクロールします。
タスクリストの入力ネイティブの無効なチェックボックス記述したチェック状態が維持されます。
その他の本文セマンティックな React 要素見出し、リスト、引用、画像、脚注に共通の MDX クラスが適用されます。

この連携は、実行時に MDX を取得、サンドボックス化、コンパイルしません。Next.js または Astro に固有の設定も扱いません。

連携を確認する

  1. Vite のプロダクションビルドを実行し、インポートした .mdx モジュールがコンパイルされることを確認してください。
  2. ページの主要な main ランドマークが 1 つだけであることを確認します。別の main がすでに存在する場合は、article への上書きを使用してください。
  3. タスクリストのチェックボックスが無効になっていること、リンクが意図した遷移先へ移動すること、狭い画面では表が専用コンテナー内でスクロールすることを確認してください。
  4. 段階的なコードハイライトが完了する前の状態も含め、インラインコードとコードブロックをライトテーマとダークテーマで確認してください。