mcpField
G
glmv-pdf-to-web

glmv-pdf-to-web

github.com/zai-orgデザイン・UI47538 回インストール28 週間前に更新
リポジトリ

glmv-pdf-to-web について

glmv-pdf-to-webは、論文や技術文書のPDFを1ページ構成の学術プロジェクトサイトに変換するスキルです。ページ画像のローカル変換、構成案の作成、図の切り出しを行い、ローカル画像を参照するHTMLを生成します。

主な機能

  1. 01PDFページを画像に変換
  2. 02構造化されたサイト構成案の作成
  3. 03ページ画像から図を切り出し
  4. 041ページ構成のHTMLサイトを生成
  5. 05ローカル画像素材の利用

活用シーン

  1. 01研究論文のプロジェクトページ作成
  2. 02技術PDFのウェブサイト化
  3. 03論文の図表や結果のオンライン紹介
  4. 04ローカルまたはURLのPDFから学術ページを作成

インストール

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

$npx skills add https://github.com/zai-org/glm-skills --skill glmv-pdf-to-web

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

同梱ファイル

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

.DS_Store
scripts/
crop.py
generate_web.py
pdf_to_images.py

詳細

PDF → 学術プロジェクトウェブサイトのスキル

研究論文または技術文書の PDF を、NeurIPS/CVPR/ICLR の論文公開で使われるような、洗練された 1 ページのプロジェクトウェブサイトに変換します。ページはローカルで DPI 120 にて変換され、構造化された outline.json が保存されます。画像はローカルで切り抜かれ、最終ページは generate_web.py で保存されます。

スクリプトの保存先: {SKILL_DIR}/scripts/

依存関係

Python パッケージ(一度だけインストールします):

pip install pymupdf pillow

システムツール:curl(macOS/Linux にプリインストールされています)。

使用するタイミング

PDF からウェブページやプロジェクトページを作成するようユーザーに依頼された場合に使用します。たとえば、「PDF からプロジェクトページを作って」「論文のウェブサイトを作成して」「この論文の学術ウェブサイトを作って」「论文主页」「做项目主页」「根据pdf做网页」「把论文做成主页」など、中国語または英語で同様の意図を示す依頼が該当します。

出力ディレクトリの規則

すべての出力は {WORKSPACE}/web/<pdf_stem>_<timestamp>/ に保存します。

web/
└── <pdf_stem>_<timestamp>/
    ├── outline.json        ← structured web plan (WebPlan schema)
    ├── crops/              ← locally-saved cropped images
    │   ├── fig_arch_crop.png
    │   ├── table_results_crop.png
    │   └── ...
    └── index.html          ← the website
  • <pdf_stem> = 拡張子を除いた PDF ファイル名
  • <timestamp> = YYYYMMDD_HHMMSS 形式
  • HTML では相対パス crops/<name>_crop.png で画像を参照します

入力

$ARGUMENTS は PDF ファイルのパス(ローカル)または HTTP/HTTPS URL です。

  • ユーザーが URL を指定した場合:まず curl でダウンロードしてから変換します
  • ユーザーが ローカル PDF パス を指定した場合:そのまま変換します

ワークフロー

フェーズ 0 — 出力ディレクトリの作成
import os, datetime
pdf_stem = os.path.splitext(os.path.basename(pdf_path))[0]
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
out_dir = os.path.join(workspace, "web", f"{pdf_stem}_{timestamp}")
mkdir -p "<out_dir>/crops"

フェーズ 1 — PDF ページを画像に変換(DPI 120)

入力が URL の場合は、最初にダウンロードします。

pdf_stem=$(basename "$ARGUMENTS" .pdf)
curl -L -o "/tmp/${pdf_stem}.pdf" "$ARGUMENTS"

次に変換します(ダウンロードしたパスまたは元のローカルパスのいずれかを渡します)。

python {SKILL_DIR}/scripts/pdf_to_images.py "<pdf_path>" --dpi 120

JSON が標準出力に出力されます。

[{"page": 1, "path": "/abs/path/page_001.png"}, ...]

完全な page → path マップを解析して保存します。


フェーズ 2 — すべてのページを順番に読む

計画を立てる前に、すべてのページ画像を順番に確認します。目的は、文書の内容、図、構成を正確に理解することです。

読みながら、以下を記録します。

  • タイトル、著者、所属、掲載先、年
  • アブストラクトのテキスト(原文のまま)
  • 主な貢献
  • 論文/コード/データセットへのリンク(arXiv、GitHub など)
  • 図、表、ダイアグラム — 掲載ページとおおよその領域
  • ティーザー/ヒーロー画像があれば、その画像

まだセクションを計画しないでください。まず、すべてを読みます。


フェーズ 3 — セクションを計画して outline.json を保存

ウェブサイトのセクションを計画します。学術論文の標準的な構成は以下のとおりです(必要に応じて調整してください)。

section_id目的
heroタイトル、著者、掲載先バッジ、リンクボタン
abstractアブストラクト全文
contributions主な貢献を紹介する 3~5 枚のカード
methodアーキテクチャ図と手法の説明
results定量的な表と定性的な図
conclusion簡潔な結論
citationBibTeX ブロック

画像が必要な各セクションについて、以下を特定します。

  • 画像の掲載ページ(フェーズ 1 のローカルページパス)
  • ビジュアルに何が示されているか、またそのセクションに適している理由の説明

以下のスキーマを厳密に使用して、<out_dir>/outline.json として保存します。

{
  "project_title": "Paper Title",
  "lang": "English",
  "authors": ["Author One", "Author Two"],
  "sections_plan": [
    {
      "section_index": 1,
      "section_id": "hero",
      "title": "Hero",
      "content": "Title, authors, venue, teaser figure description",
      "required_images": [
        {
          "url": "<local_page_path_from_phase1>",
          "visual_description": "Figure 1: teaser showing input-output examples",
          "usage_reason": "Hero section visual to immediately show the paper's output"
        }
      ]
    }
  ]
}

フィールドに関する注意:

  • lang:"Chinese" または "English" — PDF の言語に合わせます
  • required_images:セクションに画像が不要な場合は、空の配列 []
  • url:ソースページのローカルファイルパス(フェーズ 1 の path フィールド)
  • 切り抜きが必要な画像は、おおよその領域を記録します — 正確な切り抜き範囲はフェーズ 4 で決定します

Write ツールを使って、<out_dir>/outline.json に outline.json を書き込みます。


Phase 4 — 必要な画像の切り抜き(グラウンディング + サブエージェント)

重要:すべての切り抜き処理は、Agent ツールを使って、コンテキストを持たないサブエージェントに必ず委任してください。 このフェーズまでに、コンテキストは非常に長くなっています(ページ画像すべて + 概要)。そのため、視覚的な座標の精度が低下します。対象画像だけを扱う新しいサブエージェントを使うと、座標の精度が大幅に高まります。

重要:すべての画像の切り抜きには、必ず指定の {SKILL_DIR}/scripts/crop.py スクリプトを使用してください。独自の切り抜きコードを書いたり、PIL/Pillow を直接使ったり、ほかの方法を使用したりしないでください。

outline.json を読み込みます。必要な切り抜きをすべて集めてから、元ページごとに 1 つのサブエージェント(ページが異なる場合は切り抜きごとに 1 つ)を起動します。サブエージェントはグラウンディング形式の位置特定を行います。画像を見て対象要素の位置を特定し、0〜999 の正規化座標で正確なバウンディングボックスを出力します。

Agent ツールは次のように使用します。

Agent tool call:
  description: "Grounding crop page N"
  prompt: |
    You are a visual grounding and cropping assistant. Your task is to precisely
    locate specified visual elements in a page image and crop them out.

    ## Grounding method

    Use visual grounding to locate each target:
    1. Read the source image using the Read tool to view it
    2. Identify the target element described below
    3. Determine its bounding box as normalized coordinates in the 0–999 range:
       - 0 = left/top edge of the image
       - 999 = right/bottom edge of the image
       - These are thousandths, NOT pixels, NOT percentages (0–100)
       - Format: [x1, y1, x2, y2] where (x1,y1) is top-left, (x2,y2) is bottom-right
       - Example: [0, 0, 500, 500] = top-left quarter of the image
    4. Be precise: tightly bound the target element with a small margin (~10–20 units)
       around it. Do NOT crop too wide or too narrow.

    ## Source image
    <page_image_path>

    ## Crops needed

    For each crop below, first do grounding (locate the element), then crop:

    1. Name: "<descriptive_name>"
       Target: "<visual_description from outline.json>"
       Context: "<usage_reason from outline.json>"

    ## Crop command

    After determining the bounding box [X1, Y1, X2, Y2] for each target, run:
    ```bash
    python <SKILL_DIR>/scripts/crop.py \
        --path "<page_image_path>" \
        --box X1 Y1 X2 Y2 \
        --name "<crop_name>" \
        --out-dir "<out_dir>/crops"
    ```

    ## Verification

    After each crop, READ the output image to visually verify the correct region
    was captured. If the crop missed the target or is too wide/narrow, adjust the
    coordinates and re-run crop.py.

    ## Output

    Report the final results as a list:
    - crop_name: <name>, file: <output_filename>, box: [X1, Y1, X2, Y2]

<page_image_path>、<SKILL_DIR>、<out_dir>、切り抜きの詳細を、コンテキスト内の実際の値に置き換えてください。

crop.py スクリプトは JSON を出力します:{"path": "/abs/path/<name>_crop.png"}

すべてのサブエージェントから結果を集め、HTML で参照するためのマッピング section_id → [crop filename, ...] を作成します。

可能であれば、独立したページ用のサブエージェントを並行して起動します。次に進む前に、すべての処理が完了するまで待ちます。


Phase 5 — 切り抜いた画像の寸法を測定する
python3 -c "
from PIL import Image; import os, json
d = '<out_dir>/crops'
sizes = {}
for f in sorted(os.listdir(d)):
    if f.endswith('.png'):
        w, h = Image.open(os.path.join(d, f)).size
        sizes[f] = {'width': w, 'height': h, 'aspect': round(w/h, 2)}
print(json.dumps(sizes, indent=2))
"
アスペクト比レイアウトの推奨
< 0.7(縦長/細長い)max-width: 400–500px、中央揃え
0.7 – 1.3(ほぼ正方形)max-width: 600–700px
> 1.3(横長)全幅、max-width: 100%
> 2.0(非常に横長。例:表)全幅、横スクロールのフォールバックあり

Phase 6 — 1 ページの HTML を生成する

ステップ A — HTML を /tmp/website.html に書き込みます

  • すべての <img src="..."> で相対パスを使用します:crops/<name>_crop.png
  • 絶対パスは使用しないでください

ステップ B — 保存します:

python {SKILL_DIR}/scripts/generate_web.py \
    --html-file /tmp/website.html \
    --title "<paper title>" \
    --out-dir "<out_dir>/"

HTML 仕様

単独で完結する 1 つの HTML ファイル(CSS を埋め込み、最小限のバニラ JS のみ)。外部 JS フレームワークは使用しません。Google Fonts CDN は使用できます。

ページレイアウト:

  • コンテンツの最大幅:900px、中央揃え、適度な左右のパディング
  • セクションへのアンカーリンクとスムーズスクロールを備えた、上部固定ナビゲーション
  • 幅 1200px で見栄えよく、幅 768px で読みやすいレイアウト

タイポグラフィ:

  • 見出し用と本文用に、Google Fonts を 2 種類使用
  • 本文:17〜18px、行の高さ 1.7
  • 明確な見出し階層(h1 >> h2 >> h3)

ビジュアルスタイル:

  • ユーザーがスタイルを指定している場合は、指定どおりにします
  • それ以外の場合は、論文の分野と文調から適切なデザインを推測します(例:CV/ML 論文 → モダンでクリーンな学術風、システム論文 → ダークなテクニカル風、人文学 → 温かみのあるエディトリアルなセリフ体)
  • 色とフォントは CSS 変数として定義します。決まった配色やフォントの指定はありません

セクションのガイドライン:

hero:

  • 大きなタイトル(2〜3rem)、所属機関の上付き文字を付けた著者一覧、会場バッジのピル
  • リンクボタン:[📄 Paper] [💻 Code] [🗄️ Dataset] — URL がない場合はグレーアウト
  • 見つかった場合は、その下にティーザー図版

abstract:

  • 原文をそのまま掲載し、左側に控えめなアクセントボーダーを付けます

contributions:

  • 2〜3 列の CSS グリッドにカードを配置します。各カードに Unicode 記号、見出し、説明を含めます

method:

  • 全幅のアーキテクチャ図版(<figure><img><figcaption>)+ 説明文

results:

  • 定量的な表は実際の <table> として作成し、PDF の実際の数値を使用します。最高値は太字にします
  • 定性的な図版はグリッドに配置します(画像 2〜4 点、キャプション付き)

conclusion:

  • 2〜3 段落

citation:

  • PDF のメタデータをもとに再構成した BibTeX を <pre><code> ブロックで掲載
  • バニラ JS の navigator.clipboard を使った「コピー」ボタン

画像:

  • すべての <img> で相対パスを使用します:crops/<name>_crop.png
  • loading="lazy" と説明的な alt を追加します
  • <figure> で囲み、<figcaption> を付けます

アニメーション(控えめに):

  • IntersectionObserver と CSS トランジションを使った、スクロール時のフェードイン
  • ボタン/カードにホバー状態を設定


品質チェックリスト

  • 出力ディレクトリ名が <pdf_stem>_<timestamp>/ になっている
  • 有効な WebPlan スキーマで outline.json が保存されている
  • すべての切り抜き画像が crops/ に保存されている(ローカルのみ)
  • すべてのメタデータ(タイトル、著者、掲載先、年)が PDF の内容に基づいている
  • 要旨が原文どおりである
  • 定量データの表に論文中の実際の数値が記載されている
  • すべての切り抜き画像が crops/<name>_crop.png で参照されている
  • BibTeX ブロックが正確で、コピーできる
  • ナビゲーションのアンカーから正しいセクションに移動できる
  • generate_web.py が呼び出され、成功が確認されている

言語

PDF の言語に合わせてください。英語の論文なら英語のウェブサイト、中国語の論文なら中国語にしてください。混在させないでください。

コメント