mcpField
R
react-pdf

react-pdf

github.com/molefrogドキュメント169730 回インストール37 週間前に更新
リポジトリ

react-pdf について

TypeScript と JSX で React-PDF を使い、PDF を生成するためのスキルガイドです。ドキュメント部品、レイアウト、フォント、レンダリング、プレビューを扱い、安定した出力に必要な制約も説明します。

主な機能

  1. 01React-PDF コンポーネントで文書を構成
  2. 02再利用可能なスタイルとレイアウト
  3. 03ローカルフォントの登録
  4. 04PDF をファイルやバッファーに出力
  5. 05ページ番号と固定ヘッダーの追加
  6. 06ページ画像によるプレビュー

活用シーン

  1. 01JSX からページ付き文書を生成
  2. 02カスタムローカルフォントで PDF を作成
  3. 03改ページとレンダリング結果を確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/molefrog/skills --skill react-pdf

インストール後、Claude Code で/react-pdfを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

assets/
example-template.tsx
references/
components.md
google-fonts.txt

詳細

React-PDF で PDF を生成する

重要な要件

  1. フォントは必ずローカルファイルにしてください — リモートフォントの URL(http/https)は動作しません。使用する前に、必ずフォントをローカルファイルにダウンロードしてください。
  2. 非同期コードは IIFE で囲んでください — トップレベルの await はエラーの原因になります。常に (async () => { ... })() パターンを使用してください。
  3. カスタムフォントではハイフネーションを無効にしてください — カスタムフォントにはハイフネーション辞書がなく、クラッシュしたり、単語が誤って分割されたりする可能性があります。カスタムフォントを登録した後は、必ず Font.registerHyphenationCallback((word) => [word]); を呼び出してください。

ファイル

  • references/google-fonts.txt — 約 65 種類の人気の Google Fonts のメタデータと TrueType URL。各行はタブ区切り形式のフォントバリアントです:font name、style、category、weight、url。
  • references/components.md — コンポーネント API の完全なリファレンスと、サポートされている CSS プロパティ
  • assets/example-template.tsx — 固定フッター、ページ番号、分割不可のコンテンツを示す、最小構成の動作するサンプルです。基本的なパターンを理解するため、作業を始める前にお読みください。注:ここに示されている API は一部のみです。完全な API については、必ずドキュメントと references/components.md を参照してください。

前提条件

npm install react @react-pdf/renderer
npm install -D tsx @types/react

tsx は Node 上で設定ファイルなしに TypeScript + JSX ファイルを直接実行するため、tsconfig.json は不要です。内部では esbuild を使用し、JSX の変換も自動で処理します。

コアコンポーネント

  • Document:ルートコンポーネント(メタデータ、設定)
  • Page:個々のページ(A4、Letter、またはカスタムサイズ)
  • View:コンテナーコンポーネント(div に類似)
  • Text:テキストコンテンツ。インラインスタイルを適用するためのネストに対応
  • Image:画像の埋め込み(JPG、PNG、base64)
  • Link:クリック可能なハイパーリンク(外部または内部)
  • Note:注釈
  • Canvas:pdfkit のメソッドを使った自由形式の描画
  • Svg:ベクターグラフィックス(Circle、Rect、Path、Line、Polygon など)
  • StyleSheet:再利用可能なスタイルの作成

コンポーネントの props と CSS プロパティの全容については、 references/components.md を参照してください。

基本的な例

import React from "react";
import { Document, Page, Text, View, StyleSheet, renderToFile } from "@react-pdf/renderer";

const styles = StyleSheet.create({
  page: { flexDirection: "column", backgroundColor: "#ffffff", padding: 40 },
  title: { fontSize: 24, marginBottom: 20, fontWeight: "bold" },
  text: { fontSize: 12, lineHeight: 1.5 },
});

const MyDocument = () => (
  <Document>
    <Page size="A4" style={styles.page}>
      <View style={{ margin: 10, padding: 20 }}>
        <Text style={styles.title}>Document Title</Text>
        <Text style={styles.text}>Your content here</Text>
      </View>
    </Page>
  </Document>
);

(async () => {
  await renderToFile(<MyDocument />, "./output.pdf");
  console.log("PDF saved!");
})();

スクリプトの実行

PDF 生成スクリプトでは JSX を使用しますが、Node はそのままでは実行できません。tsx を使って実行してください:

npx tsx my-document.tsx

npx tsx は tsx をグローバルにインストールしなくても動作し、必要に応じてダウンロードします。tsx が開発依存関係としてインストールされている場合(npm install -D tsx)、npx によるダウンロードの手順が不要なため、すぐに実行できます。

レンダリングは必ず非同期 IIFE で囲んでください:

// Good
(async () => {
  await renderToFile(<MyDocument />, "./output.pdf");
})();

// Bad - top-level await may fail
await renderToFile(<MyDocument />, "./output.pdf");

PDF のプレビュー

生成した PDF を目視で確認するには、ページを画像に変換します。まず pdftoppm を試してください(多くの場合、あらかじめインストールされています)。利用できない場合は、Python の PyMuPDF を使用してください。

オプション 1:pdftoppm(poppler-utils) — 多くの環境ではインストール不要のため、こちらを推奨します:

pdftoppm -png -r 200 document.pdf preview
# → preview-1.png, preview-2.png, ...

オプション 2:PyMuPDF(Python) — pdftoppm が利用できない場合の代替手段です:

pip install pymupdf
import fitz

doc = fitz.open("document.pdf")
for i, page in enumerate(doc):
    pix = page.get_pixmap(dpi=200)
    pix.save(f"page-{i+1}.png")

レンダリング方法

import { renderToFile, renderToBuffer } from "@react-pdf/renderer";

// To file
(async () => {
  await renderToFile(<MyDocument />, "./document.pdf");
})();

// To buffer
(async () => {
  const buffer = await renderToBuffer(<MyDocument />);
})();

スタイリング

StyleSheet.create()、インラインオブジェクト、または配列との組み合わせの 3 つの方法があります。

const styles = StyleSheet.create({ container: { padding: 20 } });

<View style={styles.container} />
<View style={{ padding: 20 }} />
<View style={[styles.container, { marginTop: 10 }]} />
サポートされている単位

pt(デフォルト、72 DPI)、in、mm、cm、%、vw、vh

よく使われるスタイルプロパティ
{
  // Flexbox
  flexDirection: "row", justifyContent: "space-between", alignItems: "center",
  flexWrap: "wrap", gap: 10,

  // Box model
  margin: 10, padding: 20, width: "100%", height: 200,

  // Borders
  borderWidth: 1, borderColor: "#333", borderRadius: 5, borderStyle: "solid",

  // Colors
  backgroundColor: "#f0f0f0", color: "#000", opacity: 0.8,

  // Typography
  fontSize: 12, fontWeight: "bold", fontFamily: "Helvetica", fontStyle: "italic",
  lineHeight: 1.5, textAlign: "center", textDecoration: "underline",
  textTransform: "uppercase", letterSpacing: 1,

  // Position
  position: "absolute", top: 0, left: 0, right: 0, bottom: 0, zIndex: 10,

  // Transforms
  transform: "rotate(45deg)", transformOrigin: "center",
}

画像

ローカルファイルが最も確実です。リモート URL はネットワークや CORS の問題により失敗する場合があります。

import { Image } from '@react-pdf/renderer';

<Image src="./images/photo.jpg" style={{ width: 200, height: 150 }} />
<Image src={{ data: buffer, format: 'png' }} />

SVG ファイルは Image のソースとして使用できません。 SVG のソースを読み取り、react-pdf の Svg コンポーネントを使って再現してください。

SVG グラフィックス

import { Svg, Circle, Rect, Path, Line, G, Defs, LinearGradient, Stop } from "@react-pdf/renderer";

<Svg width="200" height="200" viewBox="0 0 200 200">
  <Defs>
    <LinearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
      <Stop offset="0%" stopColor="#3498db" />
      <Stop offset="100%" stopColor="#9b59b6" />
    </LinearGradient>
  </Defs>
  <Circle cx="100" cy="100" r="50" fill="url(#grad1)" />
  <Rect x="10" y="10" width="50" height="50" fill="#e74c3c" />
  <Path d="M10,50 Q50,10 90,50" stroke="#2ecc71" strokeWidth="2" fill="none" />
</Svg>;

アイコンの使用

アイコンライブラリの SVG ソースを読み取り、react-pdf の Svg コンポーネントに変換します:

npm install lucide-static
import { Svg, Path, Rect } from "@react-pdf/renderer";

// Converted from lucide-static/icons/mail.svg
const MailIcon = ({ size = 12, color = "#888" }) => (
  <Svg width={size} height={size} viewBox="0 0 24 24">
    <Path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7" stroke={color} strokeWidth={2} fill="none" />
    <Rect x="2" y="4" width="20" height="16" rx="2" stroke={color} strokeWidth={2} fill="none" />
  </Svg>
);

リンクとナビゲーション

<Link src="https://example.com"><Text>Visit website</Text></Link>

<View id="section-1"><Text>Target</Text></View>
<Link src="#section-1"><Text>Jump to Section 1</Text></Link>

動的コンテンツとページ番号

<Text render={({ pageNumber, totalPages }) => `Page ${pageNumber} of ${totalPages}`} />

固定ヘッダー/フッター

<Page size="A4">
  <View fixed style={{ position: "absolute", top: 20, left: 30, right: 30 }}>
    <Text>Header</Text>
  </View>
  <View style={{ marginTop: 60, marginBottom: 60 }}>
    <Text>Content</Text>
  </View>
  <Text
    fixed
    style={{ position: "absolute", bottom: 20, left: 30, right: 30, textAlign: "center" }}
    render={({ pageNumber, totalPages }) => `Page ${pageNumber} of ${totalPages}`}
  />
</Page>

改ページと折り返し

<View break />                              // Force page break
<View wrap={false}><Text>Keep together</Text></View>  // Prevent breaking inside
<Text orphans={2} widows={2}>Long text...</Text>       // Orphan/widow control
<View minPresenceAhead={100}><Text>Content</Text></View>  // Min space before break

カスタムフォント

重要:フォントのソースはすべてローカルファイルのパスでなければなりません。 リモート URL は動作しません。

import { Font } from "@react-pdf/renderer";

Font.register({
  family: "Roboto",
  fonts: [
    { src: "./fonts/Roboto-Regular.ttf", fontWeight: "normal" },
    { src: "./fonts/Roboto-Bold.ttf", fontWeight: "bold" },
    { src: "./fonts/Roboto-Italic.ttf", fontStyle: "italic" },
  ],
});

// Always disable hyphenation when using custom fonts
Font.registerHyphenationCallback((word) => [word]);

組み込みフォント:Courier、Helvetica、Times-Roman(それぞれ Bold、Italic/Oblique のバリアントがあります)

フォントの太さの値:thin(100)、ultralight(200)、light(300)、normal(400)、medium(500)、semibold(600)、bold(700)、ultrabold(800)、heavy(900)

Google Fonts

references/google-fonts.txt を使ってフォントの URL を確認し、ローカルにダウンロードします。

# Find the font URL
grep "^Roboto" skills/react-pdf/references/google-fonts.txt | grep "700" | grep "normal"

# Download
mkdir -p fonts
curl -sL "<url-from-grep>" -o fonts/Roboto-Bold.ttf

# Verify - must show "TrueType Font data"
file fonts/Roboto-Bold.ttf

file に「HTML document」または「ASCII text」と表示される場合、ダウンロードに失敗しています。別の URL を試すか、GitHub でフォントの公式リポジトリを検索し、TTF ファイルを入手してください。

Emoji

絵文字ソースを登録しないと、絵文字は PDF に表示されません。twemoji-emojis をインストールすると、ローカルの Twemoji PNG アセットを入手できます。レンダリング時にインターネット接続は不要です。

npm install twemoji-emojis
import { Font } from "@react-pdf/renderer";

Font.registerEmojiSource({
  format: "png",
  url: "node_modules/twemoji-emojis/vendor/72x72/",
});

その後、Text 内で絵文字を直接使用できます:<Text>Hello 🚀🎉</Text>

その他の機能

// Canvas drawing
<Canvas style={{ width: 200, height: 200 }}
  paint={(painter, w, h) => { painter.circle(w/2, h/2, 50).fill("#3498db"); }} />

// Annotation notes
<Note style={{ color: "yellow" }}>Annotation text</Note>

// Hyphenation
Font.registerHyphenationCallback((word) => [word]); // disable

// Debug mode - visualize boundaries
<View debug><Text debug>Debug text</Text></View>

// Document metadata
<Document title="My Doc" author="Author" subject="Report" language="en-US" pdfVersion="1.5" />

ベストプラクティス

  1. StyleSheet.create() を使用し、スタイルを一度定義して再利用します
  2. 画像を埋め込む前に圧縮し、リモート画像には cache={true} を使用します
  3. 改ページをテストします。コンテンツの流れ方が想定と異なる場合があります
  4. 絶対位置指定よりもフレックスボックスを優先します
  5. すべてのページにヘッダー/フッターを表示するには fixed プロパティを使用します
  6. 要素の境界を可視化するには debug={true} を使用します
  7. レンダリングを try-catch ブロックで囲みます

よくある問題

テキストのはみ出し:<Text style={{ width: 200, maxLines: 3, textOverflow: "ellipsis" }}>...</Text>

フォントが見つからない:フォントをローカルにダウンロードし、ローカルのファイルパスを指定して登録します。リモート URL は機能しません。

予期しない改ページ:コンテンツをまとめて表示するには wrap={false} を使用するか、改ページを強制するには <View break /> を使用します。

コメント