paper2poster について
paper2posterは、論文からポスターを作るワークフローのレンダリング段階を担うスキルです。paper2assetsの出力から図を選び、固定キャンバスにレイアウトしてHTML、PDF、PNG、編集可能なPPTXを生成し、セクションごとの音声も作成できます。
主な機能
- 01意味的な役割に基づく図の選択
- 02ポスターレイアウトの作成と反復調整
- 03横向き・縦向きの固定キャンバスに対応
- 04HTML、PDF、PNG、PPTXを出力
- 05セクションごとのナレーション音声を生成
活用シーン
- 01論文素材から学術ポスターを作成
- 02既存のHTMLポスターを編集可能な資料に変換
- 03ポスターのPDF、PNG、音声を作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ microsoft/ researchstudio --skill paper2posterインストール後、Claude Code で/paper2posterを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/fonts/Arimo-LICENSE.txtassets/headers_portrait/pv1.htmlpv2.htmlpv3.htmlpv4.htmlpv5.htmlpv6.htmlpv7.htmlassets/headers/v1.htmlv2.htmlv3.htmlv4.htmlv5.htmlv6.htmlv7.htmlassets/katex/auto-render.min.jskatex.min.csskatex.min.jsLICENSEassets/layouts_portrait/full.htmlhalf.htmlassets/layouts/3col.htmlfull.htmlhalf.htmlmethoddriven.htmlmethoddriven4.htmlassets/math/katex.htmlmathjax.htmlassets/mathjax/LICENSEVERSION詳細
paper2poster — paper_spec.md → HTML ポスター → PDF/PNG + 編集可能な PPTX
このスキルは、3つのスキルで構成されるパイプラインのレンダリング段階です。入力となる <outdir>/ は、paper2assets によってすでに生成されていることを前提とします。この outdir を受け取り、図を選択し、HTML ポスターをレンダリングし、固定ページ(横向き 60×36in または縦向き 33.1×46.8in の A0)に収まるようレイアウトを反復調整し、セクションごとのナレーション音声を生成してから、HTML を同梱の html2pptx サブスキル(html2pptx/ にベンダー同梱)に渡し、編集可能な .pptx を作成して PDF + PNG をエクスポートします。html2pptx への引き渡しは標準の最終ステップであり、省略できません。ユーザーは編集可能なスライド一式も同じ実行で必要としており、html2pptx を別途実行することはないため、1回の実行で poster.{html,pptx,pdf,png} が生成されます。
<outdir>/ (produced by paper2assets)
manifest.json assets/figures/ assets/logos/ assets/qr/ assets/meta/{paper_spec.md, text.txt, figures.json, metadata.json}
│
▼ Step 1 — verify prerequisites
▼ Step 2: select figures from upstream semantics
│ → assets/meta/figure_selection.json
│ (Method / high-confidence optional Motivation / Result)
▼ Step 2.5 — optional per-figure visual box cut (asymmetric noise the
│ paper2assets deterministic chain couldn't catch — most
│ figures need no further work here)
│
▼ Step 3 — compose (layout × style × header) + substitute (references/compose_poster.py → poster.html)
│ → <outdir>/poster.html (lean: 6 core sections, Necessary only)
│
▼ Step 4 — iterative fill loop (check_poster.py slack + polish)
│ → <outdir>/poster.html (every section FULL, every figure ≥90% on one axis)
│
▼ Step 5 — generate_audio.py → <outdir>/assets/audio/<id>.mp3 (free Edge TTS, from <outdir>/assets/meta/narration.json)
│ → the Listen buttons + Full Listen play these clips by id
│
▼ Step 5.9 — fit_logos.py → pack the header institution logos to fill their zone
│ (browser-measure + greedy shape-pack; baked into poster.html)
│
▼ Step 6 — render_poster.py → <outdir>/poster.pdf + <outdir>/poster.png (applies + bakes the expand into poster.html)
│
▼ Step 7 — html2pptx skill → <outdir>/poster.pptx (reads the baked poster.html; users want the editable pptx in one run)
│ (render FIRST — bakes the expand into poster.html; html2pptx then reads it, isolated under assets/_pptx_build/)
│ then check_poster.py verify-final
│
▼ Step 7.5 — check_poster.py deliverables (MANDATORY final gate)
│
└─→ Step 8 — Report absolute paths (html + pptx + pdf + png)
キャンバスはテンプレート内で向きごとに固定されています(横向き 60×36in 5:3/縦向き A0 33.1×46.8in 0.708)。変更しないでください。
必須の仕上げ条件(この範囲を外れた状態では絶対に納品しない)
最終ポスターには、2つの必須条件があります。これは警告でも、参考情報でも、「次回の反復で仕上げる」ものでもありません。いずれかに違反するポスターは、タスク完了とする前に必ず再調整してください。
-
各カードの図は、少なくとも1つの軸(幅または高さ)で、セクションの90~100%を占める必要があります。
check_poster.py polishでは、これをFIG/NARROWとして報告します。両方の軸で90%未満しか占めない図は、カード内に取り残された小さなスタンプのようなもので、明らかな欠陥です。数値で表すと、fillRatio = max(w_fig / w_section, h_fig / h_section)は[0.90, 1.00]に収まる必要があります。調整の順序(上限の調整 → 図のセクションの本文を簡潔化 → 図のキャプションを短縮 → カラムのバランス調整)については、references/staged_fill.mdを参照してください。90%未満の図を残したまま段階的な調整ループを終了しないでください。 -
各セクションの表示が
FULL(fullRatio 0.90~1.00)である必要があります。check_poster.py slackで確認できます。OVERFLOW(>1.10)、SPILLAGE(1.00~1.10)、SPARSE(0.70~0.90)、EMPTY(<0.70)は、すべて許容できない仕上がり状態です。
この2つの条件は連動しています。一方を直した編集によってもう一方が崩れた場合は、編集を元に戻してください。slack で全セクションが FULL と表示され、polish で FIG/NARROW 警告がゼロになるまでループし、その後 PDF/PNG をレンダリングして verify-final + deliverables を実行してください。
各リファレンスを参照するタイミング
| 手順 | 該当するタイミングで読むもの |
|---|---|
| Step 3 — テンプレートを構成する | references/compose_poster.py(レイアウト × スタイル × ヘッダーを組み合わせ、自己完結型の poster.html を作成。横向きと縦向きに対応) |
| Step 3 — プレースホルダーを置換する | references/template_substitution.md(プレースホルダーの対応表、テーマカラーのランダム化、セクションごとのアクセント、縦方向のサイズ調整ルール、軽量レンダリングポリシー) |
| Step 3 — コンテンツのパターン | references/content_patterns.md(12種類のセマンティックなウィジェットファミリー。3種類のコールアウト、重要な統計値、統計ストリップ、比較、番号付き手順、チップ、ハイライトテーブル、数式、タイムライン、バナーを使い、対象となるセクション本文の単調な長文を分割します) |
| Step 3 — 仕上げ | references/visual_polish.md(タイポグラフィ、色とコントラスト、インライン強調のルール、統計グリッド、図の上限、コールアウト、アーチ型バナー、印刷時の整え方) |
| Step 4 — 段階的な調整 | references/staged_fill.md(slack コマンド、計測→選択→適用→レビューの反復ループ、変更方法の一覧、削減時のルール) |
| Step 5.9 — ヘッダーのロゴを配置する | references/fit_logos.py(ブラウザーで各ロゴ領域を計測し、貪欲法で図形を配置して領域を埋めます。行を poster.html に埋め込みます。調整ループの後、レンダリングの前に実行してください) |
| Step 5 — 音声(生成) | scripts/generate_audio.py は、<outdir>/assets/meta/narration.json のスクリプト(上流の paper2assets が生成。無料の Edge TTS を使用)から <outdir>/assets/audio/<id>.mp3 を合成し、Listen ボタンで使用します。references/audio_narration.md を参照してください。 |
ワークフロー
並列実行時の安全性(最初に読むこと — 絶対に違反しないでください)
このスキルは、多数の論文に対して一度に実行されることがよくあります。バッチドライバーは論文ごとに専用の <outdir>(例:papers/foo_portrait/、papers/bar_portrait/、…)を持つ claude -p セッションを起動し、各セッションは並行して実行されます。したがって:
ps、pkill、kill、killallを実行したり、ほかのプロセスを調べたり終了させたりしてはいけません。 目にするほかのclaude/python/chromium/sofficeプロセスは、別の論文を扱う並列実行中のポスター作成ジョブに属しています。これらはあなたのプロセスの重複でも、あなたのファイルを奪い合っているプロセスでもありません。終了させると、ほかの論文の処理が破損します。- 読み書きするのは、指定された自分の
<outdir>内のファイルだけです。 ほかの論文のディレクトリや共有テンプレート/設定ディレクトリには触れないでください。 <outdir>/poster.htmlが Read と Edit の間に「予期せず変更された」ように見える場合、その変更はあなた自身の直前のツール呼び出し(Write、実行した置換スクリプト、以前の Edit)によるものです。競合プロセスのせいではありません。ファイルを再度 Read して作業を続けてください。「ほかの誰かが変更しているのでは」と調べないでください。そのようなプロセスはありません。<config>/skills/paper2poster/assets/*.htmlにある共有テンプレートは読み取り専用の入力です。<outdir>にコピーして使用し、元のファイルは編集しないでください。
上記のいずれかに違反すると、エージェントが実在しない「プロセス競合」を延々と調べ、ポスターを作成しないまま高速失敗(約400秒)に陥ることが最もよくあります。
Step 0 — キャッシュの確認(ほかの作業より先に、必ず最初に実施)
ポスターをレンダリングすると、Stage 2 の反復型ステージドフィルループが実行され(Claude のトークンを約15~30分使用)、<outdir>/poster.html が上書きされます。これにより、ユーザーが行ったインライン編集、手動での図の差し替え、レイアウト調整が失われます。開始前に、納品物がすでに存在するか確認してください:
if [[ -f "$outdir/poster.html" \
&& -f "$outdir/poster.pdf" \
&& -f "$outdir/poster.png" ]]; then
if python ~/.claude/skills/paper2poster/scripts/select_figures.py "$outdir" \
&& python ~/.claude/skills/paper2poster/scripts/check_poster.py \
preflight "$outdir/poster.html"; then
echo "[paper2poster] CACHED in $outdir: semantic preflight passed, reusing."
echo " poster.html $(stat -c%s "$outdir/poster.html") bytes"
echo " poster.pdf $(stat -c%s "$outdir/poster.pdf") bytes"
echo " poster.png $(stat -c%s "$outdir/poster.png") bytes"
[[ -f "$outdir/poster.pptx" ]] && echo " poster.pptx (html2pptx output present)"
[[ -d "$outdir/assets/audio" ]] && echo " assets/audio/ (narration present)"
exit 0
fi
echo "[paper2poster] cached deliverables are semantically stale; upgrading " \
"Paper2Assets and rebuilding instead of reusing them."
fi
コア納品物が3つすべて存在する場合は、セレクターとセマンティック・プリフライトの両方に合格したときに限り、報告して停止してください。古いもの、一部だけのもの、異なる世代のものが混在するもの、または帰属が誤っているキャッシュ済みポスターの場合は、Step 1 に進み、Paper2Assets パッケージをアップグレードして再レンダリングする必要があります。キャッシュ済みの PDF/PNG が存在することだけでは、Motivation 画像が正しい証拠にはなりません。
次の場合に限り、再レンダリングしてください:
- ユーザーがヘッダーテンプレートを変更した場合。明示的な所属機関なしのヘッダーへの切り替え、またはそこからの切り替えも含みます → キャッシュを再利用せず、再構成して再エクスポートしてください
poster.{html,pdf,png}のいずれかが欠けている場合 → 適切なステップから再開してください(poster.htmlがない場合 → Step 2 のフィルループから開始。poster.pdf/poster.pngだけがない場合 → Step 6 のレンダリングだけを実行)- ユーザーが明示的に依頼した場合(「ポスターを再構築」「再生成」「新たにレンダリング」「最初から」「レイアウトをやり直す」など)。その場合は、キャッシュ確認に引っかからないよう、最初に
<outdir>/poster.htmlを削除してください。
Step 1 — paper2assets の前提条件を確認する
機関名やロゴを要求されていませんか? まず、明示的にブランド表示のないヘッダーを選択してください。横向きは v6(中央揃え)/v7(左揃え)、縦向きは pv6(中央揃え)/pv7(左揃え)です。references/branding_free_headers.md をお読みください。これらのテンプレートでは、以下のロゴ復元処理は省略し、共有ロゴアセットはそのまま保持し、必要に応じて QR アセットは復元してください。これらのテンプレートには所属機関やロゴのスロットが意図的に設けられていません。置換やレイアウト調整の際に追加しないでください。この例外は、後述するロゴ取得と所属機関に関するすべての手順にも適用されます。要求されたヘッダーがキャッシュ済みポスターと異なる場合、通常のキャッシュによるショートカットは適用されません。
必須引数:paper2assets スキルによって生成された <outdir>/ パス、またはソース *.pdf へのパスです。作業を始める前に、必須ファイルが存在することを確認してください。
ls <outdir>/assets/meta/paper_spec.md <outdir>/assets/meta/text.txt <outdir>/assets/meta/figures.json <outdir>/assets/meta/metadata.json
必須ファイルが4つのうち1つでも欠けている場合は、ソース PDF に対して paper2assets スキルを自動的に実行し、<outdir>/ を生成または補完してから続行してください。figures.json が空のリストであることは問題ありません。セレクターと事前検証では、空でないすべてのレコードと、そのオンディスクアセットを検証します。
オプションのファイル <outdir>/assets/logos/ と <outdir>/assets/qr/ は存在しない場合があります。ただし、ディレクトリがないという理由だけで、ロゴ/QR の HTML ブロックを黙って削除しないでください。ディレクトリがない一般的な理由は、次の2つです。どちらも復旧できます。
- paper2assets の Step 6 がスキップされた、または
- paper2assets の Step 6 が誤った CLI フラグで呼び出された(paper2assets SKILL.md の Step 6 に記載されている
--spec/--outdir <outdir>/assets/logosの誤用により、ほとんどの論文でロゴの保存先が<outdir>/assets/logos/<slug>.pngではなく<outdir>/assets/logos/logos/<slug>.pngになりました)。
<outdir>/assets/logos/ がない、または空の場合の復旧手順:
# A. Auto-fix the nested-dir bug if present
if [ -d <outdir>/assets/logos/logos ]; then
mv <outdir>/assets/logos/logos/* <outdir>/assets/logos/ 2>/dev/null
rmdir <outdir>/assets/logos/logos
fi
# B. Retry fetch_logos.py from this skill (it's a paper2assets script
# but safe to call from paper2poster as a recovery step).
python ~/.claude/skills/paper2assets/scripts/fetch_logos.py \
--from-spec <outdir>/assets/meta/paper_spec.md --outdir <outdir>
# C. Same for qr/ if missing
python ~/.claude/skills/paper2assets/scripts/make_qr.py \
--from-metadata <outdir>/assets/meta/metadata.json --outdir <outdir>
再試行した後でも logos/ が空の場合に限り(機関名から Wikipedia のインフォボックスを解決できなかった場合です。「Anonymous Institution」の投稿や、あまり知られていない研究室で発生します)、最後の手段として、ポスター HTML から未使用の <img class="logo"> 要素を削除してください。QR コードがない場合も同様です。
ステップ 2 — 図版を選択する
ポスターを構成または差し替える前に、決定論的なセマンティックセレクターを実行します。
python scripts/select_figures.py <outdir>
<outdir>/assets/meta/figure_selection.json に出力されます。このマニフェストを、主要な図版プレースホルダーの唯一の信頼できる情報源として扱います。
selections.method.file->{{METHOD_FIGURE}}selections.motivation.file-> null でない場合は{{TEASER_FIGURE}}selections.result.file->{{SECONDARY_FIGURE}}または Key Result セクションの主要図版
各 null 以外の項目には、安定した figure_id、キャプション、セマンティック信頼度、根拠も含まれます。視覚的な推測に基づいて、選択済みのファイルを別の画像に置き換えないでください。check_poster.py preflight は決定論的な選択を独立して再計算し、古いマニフェスト、役割の不一致、Method/Motivation の使い回しがあればハードエラーにします。
セレクターは、Paper2Assets の追加セマンティックフィールド semantic_roles[] と section_relevance[] を使用します。選択は決定論的かつ相互に重複しません。
- Method 図版には
method >= 0.55が必要で、Result/Ablation/Qualitative のギャラリーが実証的に優勢、またはほぼ同率の場合は除外します。これにより、「our method」と書かれているキャプションだけを根拠に、実際のシステム概要図が押しのけられるのを防ぎます。 - Motivation 図版は任意で、信頼度が高い場合に限ります。
motivation >= 0.62が必要で、method、result、ablation >= 0.55のいずれかを持つ候補はすべて除外し、Method 図版とは常に重複しません。null の場合は Motivation の<figure>ブロック全体を削除します。そのスペースを Method または Result の画像で埋めないでください。 - Result 図版には
resultまたはqualitative >= 0.55が必要で、明らかに Method が優勢な図は除外し、Method および Motivation とは重複しません。適格な実証図版が存在する場合に限り、ポスターあたり 2 点以上の図版を目標にします。目標数に達するために、意味的に無関係な画像でポスターを埋めないでください。 - 図版が豊富な場合 → 3 列レイアウト。 論文に高シグナルの図版が 3 点を超えてある場合(複数の結果プロット、定性サンプルのギャラリー、アーキテクチャ図とコンポーネント図など)は、2 点で止めず、すべて選択します(ソフト上限は約 6 点)。そして、多くの著者作成の正解ポスターと同様に、幅広の列で図版を大きく表示できる3 列レイアウト(
--layout 3col、ステップ 3)で描画します。3 列すべてに図版を配置し、Method 図版はアンカーとして残します。本当に情報価値のある図版だけを選び、数合わせで埋めないでください。
レガシーバンドルはアップグレードが必要です。 figures.json に、完全な figure_semantics.v2 プロデューサー契約がない場合(部分的またはプロトタイプのセマンティックフィールドを含む)、セレクターはゼロ以外で終了し、preflight は失敗します。既存のアセットを再利用し、Paper2Assets の build_package.py --skip-extract --paper-spec ... を実行してから、セレクターを再実行してください。手動または生モデルによる図版選択は、 このゲートが防ぐ Motivation の不一致を再発させるため、許可されている代替手段ではありません。
選択した各図版はファイルパスを使って引用し、利用する前にファイルが存在することを確認してください。
ステップ 2.5 — 図ごとの視覚的なボックス切り抜き(任意。決定論的な処理チェーンで除去できなかった非対称ノイズがある場合)
paper2assets は、すべての図に対して決定論的なクリーンアップパイプライン(top-check → decaption → autotrim)をすでに実行しています。選択した図のほとんどは、これ以上の処理を必要としません。
選択した図に、決定論的な処理チェーンでは除去できなかった非対称ノイズ(SIDE にある複数図ページのはみ出し(隣接パネルの縦長の帯)、しきい値を厳しくした decaption でも除去できなかった明らかなキャプションの残り、または除外したい図の内容領域)がある場合は、視覚的な box 処理を 1 回行います。
- Read ツールで図を読み取ります。
- タイトなピクセル単位の bbox
(X0, Y0, X1, Y1)を決めます。 - 適用します:
これにより、1 回限りのpython ~/.claude/skills/paper2assets/scripts/crop_figure.py box <outdir>/assets/figures/<file>.png --box X0 Y0 X1 Y1<file>.png.bakが書き込まれ(または、paper2assets の以前の処理で作成された既存のバックアップが保持され)、figures.jsonが更新されます。 - 結果を再度読み取ります。図ごとの試行は最大 3 回とし、切り抜きすぎた場合は
cpで.bakから復元します。
ほとんどの論文では、このステップは不要です。paper2assets の決定論的なパイプライン後に選択した図がきれいであれば、省略してください。
ステップ 3 — HTML ポスターをレンダリングする
向きを考慮した構成軸を選んでから、COMPOSE します。
どちらの向きも、assets/ の下にある独立した 4 つの軸を共有します:レイアウト × スタイル × ヘッダー × テーマ。横向きでは 5 つ目の軸として Scan-to-Read が加わりますが、縦向きには独立したスキャン軸はありません。
- 構造: 横向きは
assets/layouts/{full,half,3col}.html、縦向きはassets/layouts_portrait/{full,half}.htmlです。 - ビジュアルスタイル:
assets/styles/*.css。横向きでは 11 種類の処理すべてを使用でき、縦向きではunderlineとdouble-ruleを除く 9 種類を使用できます。 - タイトルバー: 横向きは
assets/headers/{v1,v2,v3,v4,v5,v6,v7}.html、縦向きはassets/headers_portrait/{pv1,pv2,pv3,pv4,pv5,pv6,pv7}.htmlです。*6/*7のバリエーションは、機関名やロゴを含まないオプトイン形式です。 - 色/テーマ:
references/apply_theme.pyにある 9 つのバンドルを、どちらの向きでも使用できます。 - Scan-to-Read: 横向きのみで、
assets/scan/*.htmlから選択します。
references/compose_poster.py は、選択したスタイルを {{STYLE_CSS}} に、選択したヘッダーを {{HEADER}} に、横向き専用のスキャンブロックを {{SCAN_SECTION}} に挿入し、解決済みのテーマを選択したレイアウトに適用します。これにより、自己完結型の poster.html が 1 つだけ書き出されるため、モノリシックなテンプレートが N×M×K×J と膨れ上がることなく、check_poster.py / render_poster.py / ステージング済みフィルループを変更せずに利用できます。
縦向きの合成にも対応しました(--orientation portrait、assets/layouts_portrait/{full,half}.html)。STYLE + COLOR + HEADER の各軸を使用し、利用可能なスタイルは 9 種類、mono を含むテーマは 9 種類、明るい色を既定とするヘッダー上の A0 タイトル形式は pv1~pv5 の 5 種類です。underline と double-rule は、横線が狭い縦向きカラムで誤解を招くセクション区切りを作るため、横向き専用です。縦向きには独立した Scan-to-Read セクションや --scan 軸はありませんが、合成されるヘッダーと、ヘッダーが所有する QR スロットがあります。縦向きのセクションでは、横向きと同じく、5 つ以上の異なるセマンティックファミリーを使用する方針に沿って、コンテンツパターンウィジェット(references/content_patterns.md)を使用してください。A0 の狭いカラムでは通常の箇条書きや表だけにまとめてしまいやすいため、縦向きではウィジェットの種類をより積極的に活用する必要があります。
軸 0 — 向き:
landscape(既定)— ICML / NeurIPS / CVPR 標準の 60×36 in、アスペクト比 5:3。外側のグリッドは 4 列です。ユーザーが縦向きを明示的に選択していない限り、必ず横向きを使用してください。portrait— ACL / NAACL / AAAI 2025 標準の A0 縦向き、33.1×46.8 in、アスペクト比 0.708。halfレイアウトでは本文が 2 列になり、fullレイアウトではコンテンツが 4 つの帯状領域に縦に並びます。POSTER_ORIENTATION=portraitがパイプラインで設定されている場合のみ使用してください。Method 図のアスペクト比から向きを自動判定してはいけません。図の形状が決めるのは、向きの内部でのレイアウト軸(full か half)であり、向きそのものではありません。横向きのポスターに縦長の Method 図を配置する場合は、halfテンプレートの単一カラムに配置します。ポスター全体を縦向きに切り替えるわけではありません。POSTER_ORIENTATIONが未設定(またはlandscapeに設定)の場合、ランドスケープテンプレートを使用します。以上です。
軸 1 — レイアウト(Method 図の形状によって決まります):
-
full(ランドスケープでは--layout full、ポートレートではlayouts_portrait/full.html)— Method 図が横方向に広い場合に使用します。ランドスケープではAR ≥ 2.5、ポートレートではAR ≥ 1.2です。また、figures.jsonで{column=full}の場合にも使用します。ランドスケープでは、これは 4 列の外側グリッドを選択し、中央の 2 列が.mid-wideブロックに統合されます。ポートレートでは、4 つの縦積みコンテンツバンドを選択します: Problem | Motivation、全幅の.method-hero、1.5fr 1fr 1frでの Key Results | Ablation | Headline Numbers、そして全幅の Takeaway です。箇条書きを埋めるためのポートレート疑似セクション: ヒーローバンドの左側の箇条書きセルは
<div class="section method-text" data-section="method-text">…</div>でラップされます — これは段階的充填ループに参加する、視覚的に透明な疑似セクションです。slack.py はその充填率をbullets_content_h / row_hとして測定します。図によって行が箇条書きに必要な高さより高く引き伸ばされると、判定結果にmethod-text SPARSEが表示され、LLM はセルが埋まるまで箇条書きを拡張します。これが、AR しきい値をより安全な 1.8 ではなく 1.2 という緩い値に保てる理由です — 疑似セクションが中程度のアスペクト比の図による余白を自動的に吸収します。 -
half(ランドスケープでは--layout half、ポートレートではlayouts_portrait/half.html)— その向きにおけるデフォルトです。Method 図の AR が中程度または縦長で、かつ figures.json で{column=half}の場合、または Method 図が**Figure:** noneの場合に使用します。ランドスケープでは、Method は 4 列のうち 1 列の半幅カードです。ポートレートでは、Method は 2 列のうち 1 列のカードです。
figures.json から Method 図の width と height を読み取り、AR = width / height を計算してから:
- ランドスケープ: AR ≥ 2.5 または
{column=full}ならfull、それ以外はhalf。 - ポートレート: AR ≥ 1.2 または
{column=full}ならfull、それ以外はhalf。(ヒーローバンドの箇条書きセルは、段階的充填ループによって自動充填される疑似セクションです。中程度のアスペクト比の図は安全です。)
図が多い場合のオーバーライド(ランドスケープ — full/half より優先されます)。 ステップ 2 で 3 つを超える図が選択された場合、Method 図の AR に関係なく 3 列レイアウト(--layout 3col)を使用します — その 3 つの広い等幅列(1fr 1fr 1fr)は、より大きくより多くの図を収め、支配的な author-GT レイアウトに一致します。Method 図のカードは中央列で目立ったままです。他の図は列に分散されます。コンポジションにより、3col は任意のスタイルおよび任意のヘッダーと組み合わせられるようになりました(以前の「solid のみ」という制限はなくなりました)。上記の full/half の選択は、ポスターに 3 つ以下の図しかない場合にのみ適用されます。
手法主導のオーバーライド(オプトイン — ユーザーが「手法主導」のポスターを明示的に求めた場合のみ)。 --layout methoddriven を使用します。手法は中央の幅広ブロック(.mid-wide、中央の列を統合したもの)を占めます。上部に優先度の高い大きな手法図を置き、その下に手法を角丸の塗りつぶしサブセクションカード(.section.msub、data-section="method-1"…"method-N")に分割して、各パートを整理します。ベンチマーク風のフィラーカードは使わず、左右の列には左に問題/動機、右に主な結果/見出し/要点を配置します。これはオプトインです。--layout random で選択されることはなく、その他すべてのレイアウト/スタイルに変更はありません。ルール:
- サブセクション見出しは、
methoddrivenとmethoddriven4のどちらも、輪郭線付きの四角い A、B、C、D… バッジ(.msub-h .n)を使います。カード内の数字付きステップとは分けてください。見出しバッジを塗りつぶしの番号付き円に戻さないでください。カードを追加/並べ替える場合は、計測と Reel の操作用にdata-section="method-1"…"method-N"を維持しながら、読み進める順に文字を続けてください。 - 色はデフォルトで
multi-accentです。テーマの--accentと同じ色相で、カードごとに濃さを変えます(.msub.d1…d4。テーマ由来で、9テーマの軸に追従します)。異なる色相を使う場合は、<body>にクラスmhueを追加してください。 - 手法図を優先します。列の WIDTH 全体に広がるため(幅の 90% 図形充填ゲートをクリアする横長バナーなら、例外は不要です)、高さは余裕を持たせた、充填ループで調整できる上限
--method-fig-max(デフォルトは42cqh)のみで制限されます。--method-fig-maxを上げ下げして、図のサイズとカード用スペースを調整してください。<figcaption>は図の下に配置されます。 - サブセクションカードは図のサイズに合わせて調整されます。充填ループが論文ごとに配置を選択します(2×2 固定ではありません)。
.msubsは組み合わせ可能なグリッドです。個々のカードにクラスを付け、順序を指定してレイアウトを組み立ててください。.msub.wide→ 全幅の長い行(最初のカードが上段、最後のカードが下段).msub.tall→ 2 行にまたがる縦長カード(通常サイズの 2 枚はもう一方の列に配置).msubsにcols-3を追加 → 等幅 3 列の横一列- 例:縦長+2 枚(
.tall1 枚+通常サイズ 2 枚)、上段/下段の行+2 枚(先頭/末尾に.wide1 枚+通常サイズ 2 枚)、2×2(通常サイズ 4 枚)、3 列(.cols-3+通常サイズ 3 枚)。カードは自由に追加/削除できます。
- 図の後に残ったスペースにカードを収めてください。 事前チェック
packを実行し、slackで各.msubを計測してください(それぞれ FULL 0.90–1.00 になる必要があります)。カードがまばら/オーバーフローしている場合やバランスが悪い場合は、文章にパディングを加えるだけでなく、配置を選び直す(.wide/.tallを追加/削除する、カード数を変える、.cols-3に切り替える)か、--method-fig-maxを少し調整してください。複数カードの行では、カードの内容のバランスを取ってください。そうしないと、短いカードの後ろに空白が残ります(仕上げゲート C/カード末尾の余白)。
軸 2 — スタイル(POSTER_STYLE、デフォルトはランダム):
最初の 3 つはフルテーマ(ヘッダーとページ背景のテーマも変更)です。スタイル 4〜11 は、単色テーマ(アクセントカラーのヘッダー、フラットな白いロゴチップ)に適用するブロックのみのカード処理で、セクションカードの見た目だけを変更します。
solid— クラシックな外観です。アクセントカラーで塗りつぶしたタイトルバー(アクセントカラーの背景に白いテキスト)と、色付きのアクセントテキストに細い下線を添えたセクションのh2を使用します。セクションは、上端にアクセントカラーのストライプがある、落ち着いた暖色系のカードです。framed— エディトリアルな外観です。枠線で囲んだ角丸のタイトルバー(白い背景にアクセントカラーの枠線とタイトル)と、端から端までアクセントカラーで塗りつぶしたバナー状のセクションのh2を使用します。セクションカードは白地で、ニュートラルカラーの細い枠線があります。simple— ミニマルなホワイトの外観です。白いヘッダーの下に細い線を1本だけ引き、ほぼ黒のプレーンな見出しを使用します。セクションカードに枠線はなく、上端のごく細い線だけで区切ります。left-bar— カードの左端に太いアクセントカラーのラインを配置し、プレーンなアクセントカラーの見出しを使用します。elevated— 柔らかな濃い影と角丸を付けた、浮き上がって見える白いカードです。neo-brutal— 黒い太枠と、ずらして配置したアクセントカラーのドロップシャドウを使用します。見出しはすべて大文字です。tag— 見出しをインラインのアクセントカラーピルとして表示します。underline— 見出しに寄り添う太いアクセントカラーのラインを使用します。tinted— アクセントカラーを薄く反映した背景のカードです。double-rule— 2本の細いアクセントカラーの線の間に、見出しを中央揃えで配置します。legend-frame— 太いアクセントカラーの枠線を使用し、中央揃えの見出しが上端にまたがって枠線を分断します(fieldset/legendのような外観です)。
デフォルトのスタイルポリシー: --style のデフォルトは random です。そのため、compose_poster.py は向きに応じた使用可能なスタイルのカタログから決定論的に選択します。Landscapeでは11種類すべてのスタイルがランダムに選ばれます。Portraitでは9種類からランダムに選ばれ、underline または double-rule を明示的に指定すると拒否されます。使用可能なスタイルを指定するには、POSTER_STYLE=<name> または --style <name> を指定します。モデルに「ランダムなスタイルを選んで」と依頼しないでください。コンポーザーのランダムモードを使用してください。ブロック専用のスタイルでは、solidヘッダーテーマが使われます。Portraitでは、9種類のテーマと 5種類のA0タイトル形式(pv1~pv5、assets/headers_portrait/)も構成され、いずれもライトデフォルトのヘッダーを使用します。Portraitの各形式は、構造が異なるようになりました。pv1は、バランス型の Venue+QR | centered title | institutions、pv2は、全幅で中央揃えのマストヘッドの下に Venue+QR | institutions のナビゲーションストリップを配置、pv3は、機関名を論文情報の横に配置する left-top-aligned title | institutions | Venue+QR、pv4はpv1を左右反転した institutions | centered title | Venue+QR、pv5はpv3を左右反転した Venue+QR | institutions | right-top-aligned title です。pv2/pv3/pv5では、1本の縦線でユーティリティメニューと機関ロゴを分けます。それぞれの領域は fit_logos.py で独立して計測できます。
軸5 — 色/テーマ(POSTER_THEME、デフォルトは random): 9種類の学術向けアクセントカラーバンドル(blue・teal・green・burgundy・purple・rust・slate・plum・mono)です。論文ギャラリーの色変更で使われたパレットです。それぞれが {--accent, --accent-soft}(およびオーディオの --play-highlight-blue)を置き換えます。結果レジスターの --callout(クリムゾン)は、すべてのテーマで固定されています。ライトデフォルトのヘッダー(--tb-bg: var(--accent-soft)、暗色のタイトル)では、各テーマによって淡い色合いのヘッダーと、白いカード上の色付き <h2> テキスト/下線が適用されます。これはライトな外観であり、濃色で塗りつぶした帯ではありません。--theme random はシードから決定論的にテーマを選び、以前の「モデルが :root を手動編集する」手順を置き換えます。テーマは references/apply_theme.py の THEMES で一元定義され、LandscapeとPortraitで共有されます(どちらも compose_poster.py を使用します)。
軸3 — ヘッダー(POSTER_HEADER、デフォルトではランダムに選択):
機関名を含めない明示的なテンプレート: v6/v7(Landscape)、pv6/pv7
(Portrait)は、テンプレートの構造上、機関名とすべてのヘッダーロゴを省略します。
中央揃え(*6)または左揃え(*7)を選択できます。どちらも著者名、会場
テキスト、向きごとの通常のQRコード動作は維持されます。所属記号付きの {{AUTHORS}} ではなく、{{AUTHORS_PLAIN}} を使用します。
これらはランダム選択の候補から除外されています。完全な仕様については references/branding_free_headers.md を参照してください。
v1— 会場(左)・タイトル(中央)・所属機関のロゴ(右)。対称的な3ゾーン構成です。v2— v1の左右反転:所属機関のロゴ(左)・タイトル(中央)・会場(右)。v3— タイトルを全幅の中央に配置し、その下に高さをそろえたロゴストリップを1つ配置(学会ロゴ+所属機関)。v4— タイトル(左)・会場+所属機関のロゴを縦に配置(右)。GTでよく使われるレイアウトです。v5— クラシック:会場のテキストバッジ(左)・タイトル(中央)・所属機関のロゴ**+論文/コードのQRタイル**(右)。タイトルバーにQRを配置する唯一のヘッダーです。オプトインの場合のみ(POSTER_HEADER=v5)使用できます。選択した場合は、独立したscan-to-readセクションを表示しないようにし({{QR_*}}を両方とも空に設定)、QRの重複を防ぎます。
v1~v4では、assets/logos/_venue.png が存在する場合は学会のロゴを表示し(Step 6 fetch_conf_logo.py)、存在しない場合は同じチップ内に会場名/年のテキストを表示します。v5では、仕様として会場のテキストバッジを使用します。すべて所属機関2~6件に対応します(空の LOGO_n スロットは自動的に非表示になります)。ロゴは各ゾーンを満たすように配置され(会場ロゴ1つ+所属機関の2行グリッド)、ロゴチップは --tb-chip-bg/--tb-chip-shadow を使って選択したスタイルに合わせてテーマ設定されます。solid → アクセントバンド上に影なしのフラットな白いチップ、framed → 白いカード上にフラットな白いチップ、simple → 透明なチップ(枠なし)で、ロゴを白いヘッダー上に直接配置します。デフォルトでは --header random を指定します。compose_poster.py は設定済みシードを使って、5種類(v1~v5)の中から1つを決定論的に選択します。v5では独自のタイトルバーQRを {{HDR_QR_*}} で設定します(QRの仕様を参照)。POSTER_HEADER={v1|v2|v3|v4|v5} で上書きできます。
**デフォルトのフォントポリシー:**ポスター本文のデフォルトフォントは Arial です。--font-latin では、PowerPointで安全に使用できるMac/Windowsのファミリ名8種類から選択できます:Calibri | Aptos | Cambria | Arial | "Times New Roman" | Verdana | Georgia | "Trebuchet MS"。これらのプロプライエタリなOSフォントは、LinuxレンダラーやすべてのHTMLクライアントに確実にインストールされているわけではありません。ブラウザーの描画領域を測定する前に、check_poster.py/render_poster.py はブラウザーのレンダリングフォントを assets/fonts/ にある、軽量で自己完結型のオープンライセンスのフォントセットに固定します。一方、html2pptxは指定されたネイティブフォントファミリを引き続き .pptx に出力します。Arialには、Arialとメトリクス互換のArimo Regular/Boldを同梱して使用します。その他の選択肢では、レンダラーが実際に使用するフォールバックカテゴリから、オープンなDejaVuまたはNotoの書体が維持されます。新規作成のArialポスター、古いArial/DejaVuの忠実度ブロック、またはローカル優先のArimoブロックは、方向性を持つメディアゲートを通じて、パッケージ優先のArimoに移行されます。移行時にはメディアの識別情報を固定し、すべての研究図が絶対値で最低90%の基準を満たし、新たに101%を超える軸がないことを確認する必要があります。この修正を一度行った後は、Arimoレイアウトを、永続的なHTML、PDF、PNG、Reelのチェックにおける厳密なソースベースラインとします。任意の環境変数 POSTER_FONT でも同じ選択を指定できますが、デフォルト値はテンプレートに設定されています。Interを使用するには、--font-latin を Inter, … に戻し、html2pptxのInter埋め込み手順を実行して、.pptx にフォントを含めてください。4つのInterの @font-face ブロックは、この上書き専用としてすべてのテンプレートに定義されています。
構成カタログ(横向きと縦向き):
| 軸 | 選択肢 | ソースファイル | 指定方法 |
|---|---|---|---|
| layout | ランドスケープ full · half · 3col / ポートレート full · half | assets/layouts/<layout>.html · assets/layouts_portrait/<layout>.html | Method-figure AR / 図の数 (軸 1) → --layout |
| style | ランドスケープ: 全 11 種。ポートレート: solid · framed · simple · left-bar · elevated · neo-brutal · tag · tinted · legend-frame (9 種) | assets/styles/<style>.css | POSTER_STYLE (デフォルトは向きのカタログ内でランダム) → --style |
| header | ランドスケープ v1–v5 / ポートレート pv1–pv5; 所属・ロゴなしを選択可能: v6·v7 / pv6·pv7 | assets/headers/<v>.html · assets/headers_portrait/<pv>.html | POSTER_HEADER (デフォルトはランダム、ブランド入りプールのみ) → --header |
| scan | ランドスケープのみ: single · dual (キーワードをグループ化 — 推奨) · aside(デフォルト) · hero · contact · directory · banner · twin · chips | assets/scan/<variant>.html | コード QR が解決できる場合 → --scan dual、それ以外は --scan single (軸 4) → --scan; ポートレートには scan 軸がありません |
| color/theme | blue · teal · green · burgundy · purple · rust · slate · plum · mono (9 種のアクセント) | references/apply_theme.py (THEMES) | POSTER_THEME (デフォルト random、シードごとに決定論的) → --theme。コンポジション経由でランドスケープとポートレートの両方に適用されます。 |
compose_poster.py は各選択肢を検証し、不正な名前の場合は利用可能なオプションを一覧表示して中止します。旧来のモノリシックな poster_*_{solid,framed}.html / poster_portrait_*.html テンプレートは廃止されました — compose_poster.py (layout × style × header × scan × color、A0 には --orientation portrait) が唯一の経路であり、ソースは完全に assets/{layouts,layouts_portrait,styles,headers,headers_portrait,scan}/ に置かれています。
poster.html を生成する際は、その完全な内容を出力チャネル経由で決して送出しないでください — これは必須要件です。 テンプレートは約 100 KB (≈ 30–40k トークン) あり、Write ツールでインラインに書き出すとターンごとの出力トークン上限 (CLAUDE_CODE_MAX_OUTPUT_TOKENS、デフォルト 32000) を超過して実行が強制終了されます — さらに、実測フィルのループでは毎ラウンドそのコストを再支払うことになります。大部分を占めるテンプレートがあなたの出力を通過しないよう、間接的に生成してください:
-
テンプレートを合成します(ディスクからディスクへ出力し、出力トークンはゼロです。
Writeで書き込まないでください):# landscape — assemble layout × style × header into ONE self-contained poster.html python references/compose_poster.py \ --layout <full|half|3col> --style random --header random \ --scan <single|dual> --theme random \ --out <outdir>/poster.html # portrait — composed too (STYLE + COLOR + HEADER axes; 5 A0 title formats pv1-pv5, # no scan section): reads assets/layouts_portrait/ + assets/headers_portrait/ python references/compose_poster.py --orientation portrait \ --layout <full|half> --style random --header random --theme random \ --out <outdir>/poster.htmlcompose_poster.pyは、構造上のフック({{STYLE_CSS}}、{{HEADER}}、および横向き専用の{{SCAN_SECTION}})とカラー軸(解決されたテーマに合わせて:rootのアクセント変数を書き換える処理)を解決します。すべてのコンテンツ用{{...}}プレースホルダーは次のステップまでそのまま残ります。--scan:make_qr.pyが2つのQR枠を生成した場合(重複除去後に、互いに異なるURLが2つ残った場合)に限り、グループキーワードdualを指定します。それ以外はsingleを指定します。compose はグループ内から適合するバリエーションを決定論的に選ぶため、2つのQRを使うレイアウトに、論文・プロジェクト・コードのURLが1つのQRにまとまる1リンク用のデザインが選ばれることはありません。--scan randomまたは明示的なバリエーション名も使用できます。縦向きには独立したスキャンセクションがないため、この軸は無視されますが、ヘッダーのpv1~pv5は通常どおり合成されます。QR数のガード(二重の安全策): QRが1つのコンテキスト(single、または明示的なhero/contact/banner)を指定しても、metadata.jsonにQRファイルが実際には2つ含まれている場合、compose_poster.pyは自動的にdualグループへ切り替えます。これにより、2つ目のQR(プロジェクト/コード)が誤って省かれることはありません。コード用QRが解決された場合は、引き続きdualを明示的に指定してください。--theme: デフォルトのrandomは、シードに基づいて9つの学術テーマから1つを決定論的に選びます。:rootの色を手動で編集しないでください。特定のテーマを指定するには--theme <name>またはPOSTER_THEMEを使用します。--header: デフォルトはrandomです(横向きは v1~v5、縦向きは pv1~pv5)。--math: 数式組版エンジンのデフォルトはkatex(グリフが細く、posterskill に近い見た目です)です。切り替える箇所はcompose_poster.pyのMATH_ENGINE_DEFAULT、または実行ごとの--math mathjax/POSTER_MATH=mathjaxのいずれか1か所です。どちらのエンジンもオフラインでバンドルされています(assets/katex/、assets/mathjax/)。レンダラーと html2pptx(数式処理はエンジンに依存しません)がこれらを読み込むため、切り替えにテンプレートや pptx の変更は必要ありません。すべてのレイアウト(横向きと縦向き)の{{MATH_HEAD}}フックに挿入されます。決定論的な選択と30件以上の論文の一括処理。 通常の実行では、ランダム軸に
--seedが指定されていればそれを使用し、次にPOSTER_SEED、どちらもなければ解決済みの絶対パス--outを使用します。パスを解決することが重要です。出力先ディレクトリが異なる論文は、コマンドでそれぞれ--out poster.htmlと指定しても、同じシードにはなりません。大量の一括処理では、0から始まる連番の--variant-index値と、全体で共通の--variant-seedを指定します。サンプラーは各軸の周辺分布を均等に保ちながら、複数のランダム軸を組み合わせた空間を、重複なしで決定論的に順序付けします。横向きでは11枚のポスターで11種類すべてのスタイルを、縦向きでは9枚で対象となる9種類すべてのスタイルを網羅できます。5枚で縦向きのヘッダー5種類すべてを、9枚でテーマ9種類すべてを網羅できます。レイアウトは Method 図に基づいて決めてください。レイアウト自体も均等なサンプリングに含める場合に限り、--layout randomを指定します:python references/compose_poster.py --orientation portrait \ --layout full --style random --header random --theme random \ --variant-index 17 --variant-seed portrait-wave-20260810 \ --selection-out <outdir>/selection.json \ --out <outdir>/poster.html合成されたHTMLには、解決済みの合成内容が
<script id="paper2poster-composition" type="application/json">内のJSONとして埋め込まれ、主要な軸が<body data-poster-...>属性として記録されます。--selection-outを指定すると、ギャラリーとサンプリングのテスト用に、同じ監査可能な選択結果が別のJSONファイルに書き出されます。 -
Editツールでプレースホルダーを置き換えます。{{...}}トークン(またはセクションブロック)を一度に1つずつ置き換えてください。各Editが出力するのは、小さなプレースホルダーと論文固有の内容だけで、周囲のテンプレートは含まれません。ファイル全体を再構成してWriteで書き込むことは絶対にしないでください。 多数の置換がある場合に使える、Opus スタイルの同等の代替手段:references/build_poster.pyにある既成のスケルトンをコピーしてください(実際のプレースホルダー名、リーンレンダリング用の深さを考慮したオプションセクションの省略、および残存する{{...}}のチェックを備えています)。そのSUBS辞書にこの論文の内容を入力し、構成済みのposter.htmlに対して実行します — テンプレートは実行時にディスクから読み込まれ、あなたの出力には決して入りません。どちらの方法でも構いません。不変条件は同一です: 完全な HTML がツール呼び出しの出力に現れてはなりません(これは小さなモデルが大きなポスターで異常終了する最も一般的な原因です)。
今すぐ references/template_substitution.md を読んでください — そこには完全なプレースホルダーマップ、コード駆動のテーマカラー(9 色のうち 1 色、compose / apply_theme.py によって適用されます — :root を手で編集しないでください)、セクションごとのアクセントパレット、縦方向のサイズ調整の規約(Portrait Half では、各カラムの最下部セクションにちょうど 1 つの grow)、およびリーンな初期レンダリングポリシーが記載されています: 6 つのコアセクションのうち Necessary のみ。3 つのオプションセクション(Contribution、Dataset / Benchmark、Ablation Study)と、すべての Additional 段落は、この段階では意図的に除外されています。
分離型ヘッダー+QRプレースホルダーの仕様。 横向きの v6/v7 は、v1~v4 と同じ本文スキャンルールに従います。縦向きの pv1~pv5 は {{LOGO_1}}~{{LOGO_4}} とヘッダー QR プレースホルダーを公開します。pv6/pv7 が公開するのは QR プレースホルダーのみで、ロゴスロットや所属機関スロットはありません。すべての縦向きヘッダーでは、独立した「Scan-to-Read」セクションとスキャン軸が省略されます。縦向きの QR スロットは、参照先の QR ファイルが存在する場合にのみ入力してください。組み立てたヘッダーは従来のタイトルバーに置き換わるため、プレースホルダーのセットが変更されています。
- 会場: 横向きの
v1~v4では{{VENUE_NAME}}+{{VENUE_YEAR}}と、任意の{{VENUE_LOGO}}を使用します。VENUE_LOGOは、そのファイルが存在する場合に限りassets/logos/_venue.pngに設定し、それ以外の場合は""に設定してください。空の場合、ヘッダーは会場名/年をカンファレンスチップ内に表示します。従来の{{VENUE}}トークンは廃止されています。横向きのv5と縦向きのpv1~pv5では、コンパクトなテキストバッジ用に{{VENUE_LINK}}と{{VENUE_TAG}}を意図的に引き続き使用します。 - 機関ロゴ(ブランド付きヘッダーのみ): 横向きでは
{{LOGO_1}}~{{LOGO_6}}、縦向きでは{{LOGO_1}}~{{LOGO_4}}が使用できます。存在する各機関のパスを入力し、未使用のスロットはすべて""(空)に設定してください(空のチップは自動的に非表示になります)。 - QR の配置はヘッダーのみで決まります。QR は必ず 1 か所だけに表示され、
v5を除き Title Section には表示されません。- ヘッダー
v1/v2/v3/v4/v6/v7→ Title Section には QR を配置しません(これらのヘッダーには QR スロットがありません)。独立した Scan to Read.section(data-section="scan-to-read"、Takeaway の直後)には、必ず{{QR_PAPER}}/{{QR_CODE}}を入力し、ヘッダーの{{HDR_QR_PAPER}}/{{HDR_QR_CODE}}は""に設定してください。機関数は関係ありません。従来の「機関数が 2 以下ならヘッダー QR」というルールは廃止されており、QR がロゴの列に加わることはありません。このセクションの内部レイアウトは--scan軸です(ステップ 3)。コード QR が解決される場合は--scan dual、それ以外は--scan singleを指定してください。これにより、2 つの QR 用のレイアウトが QR 1 つだけのポスターに適用されることを防げます。{{QR_PAPER}}/{{QR_CODE}}に加えて、選択したバリアントによっては表示 URL プレースホルダー{{URL_PAPER}}/{{URL_CODE}}/{{URL_PROJECT}}(metadata.jsonにある短縮 URL テキスト。例:arxiv.org/abs/2106.09711)や{{CONTACT}}も使用できます。存在するものを入力し、残りは""にしてください。どのプレースホルダーも空の場合は自動的に非表示になります。例外 —--layout 3col: 3col レイアウトでは独立した Scan-to-Read セクションは抑制されます(幅 1/3 の列がこのセクションの少ないコンテンツには広すぎ、空に見えるため)。そのため、3col のポスターには意図的に QR を配置しません。--layout 3colで組み立てる場合は、{{QR_PAPER}}/{{QR_CODE}}(およびその他のスキャンコンテンツ用プレースホルダー)を空のままにしてください。いずれにしても非表示のセクションにレンダリングされます。 - ヘッダー
v5(クラシック)はタイトルバーに QR を配置できる唯一のヘッダーです。v5では、必ず{{HDR_QR_PAPER}}/{{HDR_QR_CODE}}を入力し、セクションの{{QR_*}}は空のままにしてください。QR は 1 回だけ(v5 ヘッダー内に)表示され、scan-to-readセクションは自動的に非表示になります。 - レンダリング時の保証(CSS による二重の安全策。ビルドが正しい方に入力することには依存しません): すべてのレイアウトで、タイトルバーに入力済みの QR がある場合は
.section[data-section="scan-to-read"]を非表示にします(body:has(.titlebar img.qr-img[filled]) , body:has(.titlebar .qr-tile .chip.qr img[filled]) -> [data-section="scan-to-read"]{display:none})。そのため、ヘッダー QR とセクション QR の両方が入力されても、レンダリング時に独立した Scan-to-Read セクションが抑制され、QR が二重に表示されることはありません。 - すべての QR プレースホルダーは、空の場合、または
assets/qr/*.pngが存在しない場合に自動的に非表示になります。ファイルが存在する場合にのみパスを設定してください。
- ヘッダー
- ロゴの自動トリミング:
fetch_logos.py/fetch_conf_logo.pyは、透過または白に近い余白をトリミングしてからラスタライズ(SVG→PNG)するようになり、チップがマークにぴったり合うようになりました。自動で最善を尽くして処理されるため、ここでの作業は不要です。 置換後、視覚的な仕上げレイヤーを適用します —references/visual_polish.mdを読んでください。タイポグラフィ、色、インライン強調のボキャブラリー(<strong>/.hi/.num)、統計グリッド、図のキャプション、コールアウトとアーキテクチャのコンポーネント、および印刷時の衛生(キャンバスは向きごとに固定: ランドスケープ 60×36in /cqw/aspect-ratio: 5 / 3、ポートレート 33.1×46.8in /cqw/aspect-ratio: 33.1 / 46.8— 決して編集しないでください)について記載されています。
今すぐ references/content_patterns.md を読み、テキストの壁を分解してください。 これは任意の参考資料ではありません — 視覚的品質のための厳格な要件です。カタログには 12 の意味的なウィジェットファミリーが含まれています: callout-primary、callout-soft、callout-bar、key-stat、stat-strip、vs-compare、numbered-steps、chips、highlight-table、equation、timeline、banner。4 つの timeline レンダリングは 1 つのファミリーとしてカウントされます。これらのパターンが存在するのは、対象となるセクション全体にわたって単純な <p> + <ul> だけでは、ポスターが区別のないテキストとして読まれてしまうからです。ルール:
- 対象となるすべてのセクション本文には、少なくとも 1 つのパターンウィジェットを含める必要があります。 Gate H が免除するのは、構造的な title/titlebar カード、scan カード、Portrait Full の
method-text疑似セクション、すでに.headline-heroを含む Headline Numbers カード、および純粋に図のみのカードだけです。その他の表示されるカードで単純な<p>+<ul>だけになっているのは失敗です。 - ポスター全体で、少なくとも 5 つの異なる意味的ファミリーを使用してください。
.p-callout-softを 9 回使うポスターは依然として単調に読まれます。timeline のバリアントは別々にはカウントされません。隣接するセクションが視覚的に異なって見えるよう、セクション間でファミリーを変えてください。 - セクションごとに最大 2 つのウィジェットを作成してください(視覚的品質のルールであり、Gate H はこの上限を機械的に強制しません)。そうすることで、1 つのカードが競合するコールアウトの山にならずに済みます。
- コンテンツの形にウィジェットを合わせてください: カタログの「Shape of content it suits」列から選んでください — 1 つの数字が支配的なセクションには
key-stat、Theirs/Ours セクションにはvs-compare、パイプラインにはnumbered-steps、タクソノミー/データセット/ベースラインのリストにはchipsなど。
図/ロゴ/QR のアセットは <outdir>/assets/{figures,logos,qr}/ の下に存在し(paper2assets によってそこに配置されます)、poster.html はそれらを src="assets/figures/…"、src="assets/logos/…"、src="assets/qr/…" で参照します。figures.json、fetch_logos.py、make_qr.py のマニフェスト内の path/file の値にはすでに assets/ プレフィックスが付いているため、それらをそのまま src に貼り付ければ、相対パスはポスター自身の場所から追加の操作なしに解決されます。
Step 4 — ページに正確に収まるよう反復的に埋める
まず、カラムパックの事前チェック(埋めるラウンドの前に 1 回の計算)。 python3 scripts/check_poster.py pack <outdir>/poster.html を実行してください。これは、図のフロア + 最小テキストがすでにカラムの高さを超えているカラムを検出します — 負のスラックのカラムは実行不可能(INFEASIBLE)であり、埋めるループはそこで約 20 ラウンド振動します(測定された最大のタイムシンク: ある opus 実行はそのようなカラム 1 つに約 15 分を費やしました)。フラグが立ったカラムは埋める前に再パックしてください — テキストセクションまたは図をより緩い/広いカラムに移動するか、(TOTAL スラックが負の場合)図を削除/縮小するかテキストを削減し、すべてのカラムのスラックが ≥ 0 になってからループに入ってください。詳細: references/staged_fill.md → 「Column-pack pre-check」。
最初の簡素なレンダリングでは、通常いくつかのセクションが内容不足のままになります。すべてのセクションが FULL(fullRatio がカード高さの 90~100%、パディングを含む)と表示されるまで、反復ループでコンテンツを成長させます。各パスでは:まず check_poster.py autofit <outdir>/poster.html を実行します — これは機械が正確にサイズを決定できる連続レバーのギャップ(すべての .grow カードの行間ギャップ、およびスキャン・トゥ・リード QR の高さを、レポートがすでに算出した needPx を用いて、カラムの予算内で)を決定論的に埋め、まだあなた自身のコンテンツ/図の編集が必要な残存セクションを出力します — 次に check_poster.py slack --with-polish で測定し、セクションごとの判定を読み、現在の欠陥に最も適合する1 つまたは 2 つの修正方法を選び、それらを適用し、再度測定してレビューし、維持するかロールバックします。方法に固定の順序はありません — 測定が何が問題かを教え、あなたが対処法を選びます。帯域外の各判定はその対処法を示唆します:
EMPTY(<70%)→ Additional テキストを追加する、またはそのカラムのオプションセクションを追加する。SPARSE(70~90%)→ 既存の文章をポリッシュして強化する(仕様のAdditionalからの素材で補い、カードが埋まるようにする)。SPILLAGE(100~110%)→ コンテンツをポリッシュして削減する(より少ない行数に収まるように文章を引き締める)。OVERFLOW(>110%)→ Additional テキストを削除する、またはオプションセクションを削除して垂直方向のスペースを取り戻す。
2 つの方法が独立している場合(異なるカラム)は、1 つのパスで両方を適用してかまいません。同じカラムに触れる場合は、ロールバックの判断が曖昧にならないよう、一度に 1 つずつ適用します。複数の方法が同じギャップを埋められる場合、埋め草の文章よりも価値の高いコンテンツ(実際の数値、Method 図、名前付きの貢献)を優先します。
機械検証による終了ゲート。 このコマンドが 0 で終了したときにのみ、ループは完了です:
python ~/.claude/skills/paper2poster/scripts/check_poster.py slack \
<outdir>/poster.html --with-polish --strict
--with-polish は、1 つのレンダリング済みページに対してフィルゲート(slack)と視覚的ポリッシュゲート(FIG/NARROW など)を実行します — ブラウザの起動が 2 回ではなく 1 回で済みます — そして --strict の下では両方が合格しなければならないため、この 1 つのコマンドが旧来の別々の slack + polish 呼び出しを置き換えます。非ゼロで終了している間は反復を止めないでください。--strict は各パスで読むのと同じ測定ですが、ハードな終了コードを伴います — 「許容できる SPARSE」や「修正するには厳しすぎる図」といった逃げ道はありません。ゲートが合格するまで、修正方法(そして頑固な図に対しては references/staged_fill.md にあるカラム幅の微調整/垂直方向のスペースに関する方法)を適用し続けてください。
素早く収束させ、ループに上限を設けます(小規模モデルにとって重要)。 slack レポートは、帯域外の各セクションに正確な needPx の差分を与えます — 例えば key-result SPARSE grow +50px [+18..+83] のように。テキスト行数で当て推量して 0.05 幅の FULL 帯域をオーバーシュートするのではなく、その数値どおりに連続的な CSS レバー(margin-bottom / .col のギャップ / 図の max-height)で編集します。最近の測定を追跡し、セクションが SPARSE↔SPILLAGE とピンポンし始めたら即座にレバーを切り替えます。そしてループは上限付きです:約 12 ラウンド/約 20 分経っても両方のゲートが緑にならない場合、最もよく測定された状態をレンダリングし、そのステージを残存する帯域外セクション id とともに DEGRADED とマークして先に進みます — 決して無限に研磨しないでください。これはスクリプトで強制されます:slack は 連続して収束しなかった 測定を <poster_dir>/assets/meta/.fill_budget.json に数え、--max-iterations(デフォルト 80)を超えると CIRCUIT BREAKER バナーとともに終了コード 3 で終了します — コンテキストの圧縮に耐えるディスク上の上限なので、ラウンド数の喪失によって研磨し続けることはありません。収束した測定はカウントをクリアし、ジオメトリをまったく生成しなかった呼び出し(ナビゲーションのタイムアウト、MathJax の settle 失敗)はカウントされません。終了コード 3 はハードストップとして扱ってください(最良の状態をレンダリングし、DEGRADED とマークする)。終了ゲートは厳格なままです;反復回数のみが上限付きです。完全なルール:references/staged_fill.md の冒頭にある 「Convergence protocol」。
.grow セクションが、それ自身の Additional/オプションコンテンツを使い果たした後もずっと EMPTY または SPARSE のままである場合、その1つのセクションを引き伸ばし続けるのではなく、同じカラム内の他の(grow ではない)セクションのコンテンツを改良してください。すなわち、それらの Additional 段落をレンダリングされるカードに引き上げる、簡潔な箇条書きを展開形式に昇格させる、または論文固有のカスタムセクションを折り込む、といった方法です。そうすれば .grow セクションは、1つのカードを埋め草で膨らませるのではなく、残りの余白を自然に吸収します。
カラムが予算上限(slackRatio ≈ 0)なのに偏っている場合 — 1つのカードが SPARSE なのにその兄弟カードが FULL と表示され、コンテンツの追加も削除も機能しない — には、rebalance-adjacent-sections メソッドを使用してください。すなわち、FULL な兄弟カードから SPARSE なカードへ予約済みで話題に合った行を移します(カラムの合計を変えずに高さ予算をシフトする、純増ゼロの入れ替えです)。これは、移行先のセクションに本当に属するコンテンツのみを移動します。
今すぐ references/staged_fill.md を読んでください — そこには check_poster.py slack コマンド、JSON レポートの形式、measure→select→apply→review ループ、修正メソッドのフラットなカタログ、および shave-back の順序が記載されています。
まず preflight(check_poster.py preflight)を実行して、測定前に LaTeX の残留物 / 数式中の生の < / 欠落した画像を検出してください。セマンティックな Paper2Assets バンドルでは、これは必須の figure attribution ゲートでもあります。Motivation、Method、Result のいずれかの画像が assets/meta/figure_selection.json と一致しない場合、Motivation が信頼度を下回るか Method/Result/Ablation の拒否ロールを持つ場合、または Method と Motivation が1つの図を再利用している場合に失敗します。レガシーまたは部分的なバンドルは、Paper2Assets がそのセマンティックメタデータをアップグレードするまで失敗します。
デバッグ支援。 フィルループが誤動作する場合 — slackRatio はあることを示すのに、目には別のことが見える場合 — には、check_poster.py slack --json-out <outdir>/assets/meta/poster_debug.json の出力を書き出し、poster.html をブラウザで開いて d を押してください。すべてのカラム/セクション/図が枠線で囲まれ、バッジには実際のレンダリング高さが推定器の予測とその差分と並べて表示されます。
ステップ 5 — Listen ボタン用のナレーション音声を合成する
paper2assets はナレーションのスクリプト(<outdir>/assets/meta/narration.json)を生成しました。paper2poster はそれを Listen ボタンが再生する mp3 に変換します — TTS が行われるのは paper2poster です(paper2assets では行いません):
python ~/.claude/skills/paper2poster/scripts/generate_audio.py \
<outdir>/assets/meta/narration.json --outdir <outdir>/assets/audio
- バックエンド = デフォルトで無料の Edge TTS —
edge-ttsパッケージ経由の Microsoft Edge オンラインボイス: API キーも設定ファイルも不要で、ネットワークだけあれば使えます。デフォルトボイスはen-US-AndrewNeural、narration.jsonには"provider": "edge"が含まれます。実行ごとに--provider azure(~/.azure/speech.json+AZURE_API_KEYが必要)または--voice <name>で上書きできます。詳細はreferences/audio_narration.mdを参照してください。 - グレースフルスキップ:
edge-ttsがインストールされていないかネットワークがダウンしている場合、スクリプトは明確なメッセージを表示して終了し、何も書き込みません — ポスターの HTML/PDF は引き続きレンダリングされ、Listen ボタンが無音になるだけです。そのメッセージを必ず表示してください。音声を捏造しないでください。 PLAYLISTを同期させて保つ: テンプレートのPLAYLIST(およびセクションごとのdata-sectionid)は、<outdir>/assets/audio/内のクリップ id と一致している必要があります。Listen ボタンと Full Listen は id でassets/audio/<id>.mp3を再生します。ファイルのない id はハイライトを点滅させて無音になります。したがって、レンダリング時にセクションを削除したり(例:dataset-benchmark)、カスタムのものを注入したりする場合は、PLAYLISTを存在する音声ファイルと同期させて保つてください。<outdir>/assets/audio/が完全に存在しない場合、ボタンはグレースフルに何もせず、ポスターは視覚的には引き続き機能します。
ステップ 5.9 — ヘッダーのロゴをゾーンいっぱいに配置する(fit_logos.py)
塗りつぶしループが収束したら、レンダリング前に、ヘッダーの機関ロゴを個数や形状にかかわらずゾーンいっぱいに配置します。
python references/fit_logos.py --poster <outdir>/poster.html
fit_logos.py はポスターをヘッドレスモードで実際のキャンバス倍率で開き、各ロゴゾーン(.logo-grid / .logo-block)を測定して、行分割を貪欲に探索し、すべての機関ロゴで共有する均一な高さを最大化します(ロゴはすべて同時に拡大され、一部だけ大きく、ほかは小さくなることはありません)。ロゴの並べ替えは可能です。機関リソースの安全性:自動補完では、assets/logos/logos.json の承認済みエントリーのみを読み込み、assets/logos/ 内のすべての画像を無差別に検索することはありません。現在のエントリーには approved: true と decision: "approved" が設定されています。古いマニフェストでは承認済みリソースのみが保存されていたため、これらのフィールドがない従来の logos[] エントリーも引き続き使用できます。明示的に却下されたエントリーと、孤立した画像(キャンパスの写真やカバーアートなど)は、ディスク上や古い HTML に残っていても除外されます。logos.json がない場合、フィッティング処理では検出を安全側に倒し、poster.html に明示されている機関ロゴのソースのみを配置します。ディスクから追加することはありません。別管理の会場リソースは、この許可リストとは独立しています。フィッティング処理は assets/logos/_venue.png が存在する場合、これを会議用チップ(.chip.conf)に設定します。これにより :has(img) CSS が適用され、会場の年表示テキストが自動的に非表示になります。マークが重複することはありません。また、横向きの v1~v4 ヘッダーでは、QR コードをタイトルバーから取り出し、独立した読み取り用スキャンセクションに移動します(古いレンダリングで欠落している場合は、Takeaway の後にこのセクションを再作成します)。横向きの v5 ヘッダーとすべての縦向きヘッダーでは、QR コードをタイトルバーに残します。ゾーンを行に再構成し、その内容をディスク上の poster.html に直接書き込みます(完全な HTML を出力チャネルに出力することはありません)。すべてのロゴは同じ高さで、ゾーンに収まる限り大きく表示されます(ロゴが 1 つならゾーンを埋め、複数なら高さのそろったマークが複数の行にバランスよく配置されます)。最も幅の広いマークとヘッダー帯の高さによって、この均一な高さの上限が決まるため、固定の塗りつぶし目標はありません。パッカーは共有する高さを最大化します。render_poster.py(ステップ 6)は、レンダリング直前に fit_logos.py を自動実行するようになりました。手動実行では頻繁に省略されていたためです。これにより、書き出される PDF/PNG には常にロゴが配置されます。プレビュー用に単独で実行することもできます。
ステップ 6 — ポスターを PDF + PNG にレンダリングする(最初に実行 — 拡張を適用して焼き込みます)
python ~/.claude/skills/paper2poster/scripts/render_poster.py <outdir>/poster.html
拡張を poster.html に焼き込んでから html2pptx が読み込めるように、ステップ 7(html2pptx)の前にこの処理を実行してください。これにより、編集可能な poster.pptx は拡張前のレイアウトではなく、PDF/PNG と一致します。このスクリプトは HTML から @page { size: <W> <H> } を読み取り、同梱の Inter Web フォントを <outdir>/assets/fonts/ に複製し、選択された OS フォントスタックをライセンス済みのポータブルなブラウザ用フォントに固定してから、Chromium を印刷エミュレーションで開きます。MathJax の処理完了を待ち、レンダリング時の拡張を適用して、その拡張を poster.html に書き戻してから、<outdir>/poster.pdf と <outdir>/poster.png を出力します(デフォルトの倍率は 0.35 倍です)。そのため、ポスターの HTML と assets/fonts/ は、プラットフォームをまたいで共有できる自己完結型の状態を保ちます。
レンダリング時の「拡張」(デフォルトで自動実行)。 PDF/PNG を書き出す直前に、render_poster.py は自然なポスターの読み取り専用スナップショットを 1 つ取得し、その後、内容が十分に詰まっていない各カードの内側の行間を、POSTER_EXPAND_THRESHOLD(デフォルト 0.98)に向けて暫定的に広げます。これにより、0.90 の FULL ゲートで収束したポスターを、塗りつぶしループをより厳しい約 2 倍遅いゲートに再調整することなく、末尾に余白のない、見た目にも十分に詰まった状態にできます。各調整案は下部パディングの上限で必ず止まり、カードの列/コンテナーの高さが変わった場合は即座に元に戻されます。図/画像カードも対象になることがありますが、そのルールはライブ DOM からは信用されません。レンダラーは暫定ルールを poster.html に書き込み、実際のファイルを再読み込みします。そして、カスケードで引き続き優先され、元のすべてのセクション/親の矩形と表示中のメディアボックスが固定され、メディアのソース/固有サイズ/描画サイズも固定され、さらに追跡対象のすべての図が、はみ出すことなく少なくとも一方の軸でセクションの 90%以上を満たす場合に限り、ルールを保持します。検証に失敗した場合は、その親スコープ内の暫定ルールをすべて削除し、ブロックを書き直して再読み込みし、固定点に達するまで繰り返します。安定化/検証に失敗した場合は、すべてのオプションルールを削除します。最終的なルールセットは、キャプチャの前に、さらに同一ファイルを使った再読み込みを 1 回行っても保持される必要があります。この検証済みの永続的なページだけを、編集可能な HTML、その D オーバーレイ、PDF/PNG、および後続の html2pptx に使用するため、すべての表示で同じレイアウトが共有されます。ルールの書き込みは、Step 4 の後にのみ行われる冪等な <style id="poster-expand-baked"> ブロック 1 つだけです。そのため、段階的な塗りつぶしループでは引き続き自然な上揃えレイアウトを計測でき、0.90 の FULL ゲートも正しく保たれます。
残ったルールは、ウォームリロードだけでなく、新規の BrowserContext でのオープンにも合格する必要があります。従来の反復的なジオメトリフィッターは、配信される HTML 内で、スケーリングされていない固定キャンバスを計測し、ビューアーの変換を正確に復元するよう保護されています。コールドオープン後にページが安定したら、PDF/PNG のキャプチャ前にスクリプト実行を凍結し、遅れて実行されるタイマーによってライブ表示のみの書き出しが生成されないようにします。
2 つの調整ノブ(環境変数)— 通常、変更するレイアウト設定はこれだけです。
| 環境変数 | デフォルト | 制御対象 |
|---|---|---|
POSTER_FULL_THRESHOLD | 0.90 | 段階的な塗りつぶしループの FULL ゲート(Step 4)。各セクションの自然な上揃え時の塗りつぶし率がこの値に達するまで、レイアウトが最適化されます。値を上げる(例:0.94)と、ループ時間が約 2 倍になりますが、より密に配置されます。要素ごとの slack レポートにより、どちらのしきい値でも振動を防ぎます。 |
POSTER_EXPAND_THRESHOLD | 0.98 | レンダリング時の拡張目標(この手順)。各カードを、この値に向けて広げます。下部パディングの上限と列の高さガードにより制限されます。0 に設定すると拡張を無効にし、自然な上揃えレイアウトをそのまま出力します。 |
この組み合わせには意図があります。0.90 でレイアウトをすばやく収束させた後、0.98 でレンダリング時に最終成果物を見た目にも十分に詰まった状態にするため、追加コストはかかりません。どちらも環境変数から読み込まれるため、コードを編集せずに、単発の実行でどちらかを上書きできます。
便利なフラグ(通常はデフォルトのままで問題ありません):
- サムネイルを大きくするには
--thumb-scale 0.5、小さくするには0.2を指定します。 - LaTeX の負荷が高いポスターでは
--mathjax-timeout-ms 15000を指定します。
これは SOFT パスです。 CDN がブロックされている場合、MathJax の取得に失敗した場合、または Web フォントの読み込みが遅い場合は、stderr に警告が出力され、組版された数式の代わりに $...$ がそのまま表示された PDF が生成されることがあります。警告は一字一句そのまま提示してください。ただし、その対応としてスクリプトを再実行してはいけません。上流を修正してください。
前提条件: playwright と Chromium が必要です。スクリプトが ImportError で終了した場合は、スクリプトが表示するインストールコマンドを実行し、再実行してください。
レンダリング後、最終的な寸法ゲートを実行します。
python ~/.claude/skills/paper2poster/scripts/check_poster.py verify-final \
<outdir>/poster.pdf --from-html <outdir>/poster.html
FAIL は、上流の HTML または render_poster.py の呼び出しが誤っていることを意味します(例:@page が削除されている)。エラーを提示して停止してください。HTML を修正せずに再実行しても、同じ失敗が発生します。
ステップ 7 — poster.html を poster.pptx に変換する(html2pptx — 標準の最終引き渡し)
ユーザーはほぼ必ず、同じ実行中に編集可能な PowerPoint を求めます。これをオプション扱いしたり、別途依頼が来るまで待ったりしてはいけません。ステップ 6 でレンダリングし、poster.html に展開を反映したら、同梱の html2pptx サブスキル(このスキル内の html2pptx/ にベンダー同梱されており、独立した git サブモジュールではありません)に渡します。Claude のセッションでは、次のように伝えます。
「html2pptx スキルを使って、
<outdir>/poster.htmlを<outdir>/poster.pptxに変換してください。デフォルトのポスターフォントは Arial で、Mac と Windows の PowerPoint にプリインストールされているため、フォントの埋め込みは不要です。埋め込み手順は省略してください。オプションの Inter オーバーライドを使ってこのポスターをレンダリングした場合に限り、html2pptx の Inter 埋め込み機能(独自のscripts/font_embedder.py)も実行し、フォントを .pptx に同梱してください。」
このスキルは Playwright で DOM を抽出し、ネイティブの .pptx(編集可能なテキスト+ネイティブ図形+画像であり、スライド内に PNG を配置したものではありません)を生成して、soffice による確認用 PNG をレンダリングし、Claude Vision による忠実度監査を実行します(デフォルトで有効)。html2pptx のすべての生成物(DOM JSON、確認用 PNG、soffice のレンダリング結果)を assets/ の下に置くため、--outdir <outdir>/assets/_pptx_build/ を指定して実行し、その後、デッキを最終成果物のトップレベルへ移動します。cp <outdir>/assets/_pptx_build/poster.pptx <outdir>/poster.pptx。最終成果物は <outdir>/poster.pptx(バンドルのルート)です。ビルド生成物は <outdir>/assets/_pptx_build/ の下に隔離されます。ステップ 6 で展開を反映済みの poster.html を読み込むため、pptx にも PDF/PNG と同じ展開済みレイアウトが反映されます。
実行順序。 html2pptx は、展開済みの poster.html を読み込むため、ステップ 6 のレンダリング+反映の後に実行します。soffice による確認用レンダリングは <outdir>/assets/_pptx_build/ に出力されるため、バンドルのルートにある poster.pdf/poster.png を上書きすることはありません(このため、最後に安全に実行できます)。
致命的ではないエラー。 html2pptx を実行できない場合(例:soffice または Python の依存関係がない場合)は、明確な 警告を記録し、ステップ 7.5 に続行します。pptx の失敗によって、主要な poster.{html,pdf,png} の生成を妨げてはいけません。警告は明示的に報告してください。pptx を黙って省略してはいけません。
ステップ 7.5 — 最終成果物の確認(完了を宣言する前に必ず実施)
python ~/.claude/skills/paper2poster/scripts/check_poster.py deliverables <outdir>
これは決定的なゲートであり、参考情報ではありません。<outdir> にある主要な成果物 4 点がすべて存在し、最小サイズのしきい値を満たす場合にのみ、終了コード 0 を返します。
paper_spec.md(paper2assets から)poster.html(ステップ 3~4 から)poster.pdf(ステップ 6 から)poster.png(ステップ 6 から)
終了コードが 0 以外の場合、コマンドは不足しているファイルと、それらを生成するための正確なコマンドを表示します。そのコマンドを実行してから、この確認を再実行してください。終了コードが 0 になるまで繰り返します。その後、poster.pptx(ステップ 7)も存在することを確認してください。html2pptx で警告が出た場合は、黙って省略せず、レポートにその旨を記載してください。
このゲートで検出する失敗パターン — モデルはステップ 4 の入力ループで slack/polish のハードゲートを通過すると、レンダリング手順をすべて省略して終了してしまうことがよくあります。「すべてのゲートに合格したのでタスク完了」と判断するためです。これは誤りです。入力ループで確認できるのは HTML だけであり、PPTX/PDF/PNG は生成も確認もされません。同じ Claude モデルでも、同じ論文に対してステップ 6~7 を実行する場合と省略する場合があり、内部で頼りにできる警告サインはありません。この確認を実行せずに完了を宣言してはいけません。
ステップ 8 — レポート
すべての成果物の絶対パスをユーザーに伝えます。
<outdir>/assets/meta/paper_spec.md(paper2assets から)<outdir>/poster.html<outdir>/poster.pptx(編集可能な PowerPoint、ステップ 7 から — html2pptx が警告を出した場合はその旨を明示してください)<outdir>/poster.pdf<outdir>/poster.png<outdir>/assets/audio/(ここでステップ 5 のgenerate_audio.pyがnarration.jsonから生成します。edge-tts/ネットワークが利用できない場合は存在せず、その場合 Listen ボタンは何もしません)
ファイルの内容をチャットにダンプしないでください — spec と HTML は長く、PPTX/PDF/PNG はバイナリです。PNG については、チャットの画面が画像添付に対応していればインライン表示してください。ユーザーが poster.html をブラウザで直接開けることにも言及してください。ポスターはブラウザウィンドウに自動でフィットします(スクロールは不要です)。s で全画面、a で Listen ボタンの切り替え、d でデバッグオーバーレイの切り替えができます。
全体のチェーンは paper2assets → paper2poster です(後者は現在、同梱の html2pptx を介して編集可能な .pptx を生成して終了します)。各スキルは、Claude セッションから前段の <outdir>/ に対して単独で呼び出すこともできます。
ツール
scripts/
├── check_poster.py ← CLI: slack / preflight / polish / verify-final / deliverables
├── select_figures.py ← figures.json semantics → deterministic figure_selection.json
├── render_poster.py ← CLI: print-emulated PDF + scaled PNG thumbnail (mirrors bundled fonts)
├── generate_audio.py ← CLI: narration.json → assets/audio/<id>.mp3 (free Edge TTS default; --provider azure)
└── utils/ ← internal modules (canvas parser, Playwright + settle, etc.)
check_poster.py slack と render_poster.py はどちらも入力 HTML から @page { size: W H } を読み取ります — テンプレートがこれを設定します — そのため、キャンバスサイズをコマンドラインで渡す必要はありません。
注: 図のクロップツール(crop_figure.py、extract_pdf.py、fetch_logos.py、make_qr.py)は paper2assets スキルにあります。paper2assets の決定論的チェーンで処理できなかった図に対して、単発の視覚的な box 再クロップが必要な場合は、~/.claude/skills/paper2assets/scripts/ を介して呼び出してください(ステップ 2.5 を参照)。
テンプレート
すべてのテンプレートは assets/ にあります。プレースホルダートークン、オーディオマークアップ、キーバインドスクリプト、デザイントークンは共通で、向きやレイアウトによって異なるのはキャンバスサイズと列グリッドのみです。ステップ 3 では、向きのトリガー(POSTER_ORIENTATION=portrait → portrait、それ以外は landscape。図の AR から向きを自動検出しないでください)に基づいてテンプレートを振り分け、その後 Method 図の形状に基づいて振り分けます(landscape:AR ≥ 2.5 または {column=full} → full、それ以外は half。portrait:AR ≥ 1.2 または {column=full} → full、それ以外は half)。
Landscape(60×36in、5:3):
layouts/half.html— 半幅の Method 図向けの4 列グリッドです。landscape のデフォルトレイアウトで、Method は他のセクションと並んで半幅のカードとして配置されます。layouts/full.html— 横長/全幅の Method 図向けの、中央の 2 列を.mid-wideに統合した 4 列の外側グリッドです(AR ≥ 2.5 または{column=full})。.mid-wideブロックはグリッドの 2~3 列目にまたがり、Method(中央の全幅。横長図の最小幅ルールにより、利用可能な幅の 75% 以上を確保)の下に、Dataset と Key Result を配置した 2 列の.mid-subを積み重ねます。
Portrait(33.1×46.8in A0、0.708):
layouts_portrait/half.html— 縦長/中程度の AR の Method 図向けの2 列グリッドです。portrait のデフォルトレイアウトです。左列には Problem/Motivation/Method(図を含む)、右列には Dataset/Key Results/Ablation/Headline Numbers/Takeaway が配置されます。各列の.growは必ず 1 つで、常に最下部のセクションに置かれます。左列では Method、右列では Takeaway です。layouts_portrait/full.html— 横長の Method 図向けの4 つのコンテンツ帯で構成された雑誌風のサンドイッチレイアウトです(AR ≥ 1.2 または{column=full})。読み進める順序は、タイトルバー → Band 1(Problem | Motivation、均等な 2 列)→ Band 2(.method-hero の中心部分、全幅:左側に縦向きに回転した SIDE-TITLE、右側に箇条書きと横長図を配置した、雑誌の編集記事風レイアウト)→ Band 3(Key Results 1.5fr | Ablation 1fr | Headline Numbers 1fr、非対称の 3 列データ帯)→ Band 4(Takeaway、全幅の要点)です。Method の中心部分は最上部ではなく、視覚的な中央に配置されます。これはポスターの一般的なストーリー構成に合わせたものです(Problem/Motivation で WHY を提示し、次に Method で HOW を示し、その後 Results/Numbers で成果を伝え、最後に Takeaway で WIN を印象づけます)。下部の 3 列帯は、データ表示が並列ではなく階層として読めるよう、意図的に不均衡な比率(1.5/1/1)にしています。Takeaway はキャンバス全幅を使い、視線が最後にそこへ着地するようにします。method-hero 内の箇条書きセルは擬似セクション(<div class="section method-text" data-section="method-text">)で囲まれています。これは閲覧者には見えませんが、slack.pyで計測されます。図によって行が箇条書きに必要な高さを超えて伸びると、段階的な塗りつぶしループがmethod-text SPARSEを検出し、セルが埋まるまで LLM が箇条書きを拡充します。これにより、「背の高い図の隣にある幅の狭い箇条書きセルが空白になる」という問題を解消します。省略可能なセクション(Contribution、Dataset/Benchmark)はデフォルトのレイアウトには含まれていません。論文で本当に必要な場合にのみ追加できるよう、テンプレート本文の末尾にインラインコメント付きの手順があります。
テンプレートを追加する場合は、特定の会場に依存しない内容にし、{{...}} プレースホルダーの語彙、data-section 属性、PLAYLIST マークアップを維持してください。また、その向きに対応するキャンバス/cqw/aspect-ratio の固定を維持してください。
assets/fonts/ には、Inter Regular/SemiBold/Bold/ExtraBold が .woff2(Web 用)と .ttf(pptx 埋め込み用)の両形式で同梱されています。HTML テンプレートの @font-face ルールでは相対パス fonts/Inter-*.woff2 を使用し、render_poster.py はこれらを各 <outdir>/fonts/ にコピーして、納品物が単体で完結するようにします。
コンテンツのガイドライン
- セクションの意味:
- Problem — 論文が取り組む具体的な課題や失敗モードです。
- Motivation — なぜ今これが重要なのか、従来のアプローチの何が問題なのかを示します。
- Contribution — 論文が明示している貢献(通常は序論の「we contribute」の箇条書き)です。新しい成果物、データセット、アルゴリズム、定理、知見などが該当します。
- Method — 提案手法がどのように機能するか、貢献を技術的に実現する方法を示します。
- Key equation / Formulation — 論文の中核となる数式です。目的関数、損失関数、支配方程式、または手法を定義する式を指します。意味のある数式を含むポスターには、少なくとも1つの重要な数式を必ず含めてください(ほとんどのML/理論論文が該当します)。数式は
equationウィジェットでレンダリングします(MathJaxで$…$/$$…$$を組版)。配置はモデルが選択します。Methodに組み込むか、数式が中心となる場合は独立したコンパクトなFormulationカードにします。LaTeXはpaper_spec.md(paper2assetsが生成したMethodのKey equationサブフィールド)またはtext.txtから取得してください。作り出してはいけません。数式が本当に存在しない論文(純粋なシステム論文/実証研究)の場合に限り、省略できます。 - Dataset / Benchmark — データセット、分割、規模、および論文で新たに導入されるベンチマークを示します。論文が詳細に説明することなく標準的な公開ベンチマークを使用しているだけなら、このセクションは任意です。論文がデータセットやベンチマークを導入している場合は、主要な貢献として扱ってください。
- Key Result — 実験の主な成果と定性的な要点を示します。
- Ablation Study — どのコンポーネントや設計上の選択が重要かを定量的に示します。上位1~3項目(最大3項目)。アブレーションがない場合は、その旨を記載し、数値は省略してください。
- Headline Numbers — 特に注目すべき定量的な結果を1~4件示します。数値自体をビジュアルとして扱い、図は使いません。テンプレートのヒーロー+補足レイアウトで必ずレンダリングしてください。
.hero-val+.hero-label+.hero-noteを含む<div class="headline-hero">と、.stat-miniタイル(それぞれ.val+.lblを含む)を最低2つ配置した行<div class="supporting">が必要です。箇条書きのみ、または補足タイルなしのヒーローのみではポスターの不備となります(polishゲートのHEADLINE/HEROおよびHEADLINE/SUPPORTINGで検出されます)。 - Takeaway — 「つまり何が重要なのか」を1文で示します。
- 表と図:
captions.jsonにある表は、Methodの図として使用できません(figures/内のPNGのみ使用可能です)。表の数値は、Headline NumbersとKey Resultに必要なテキストとして記載します。 - 採用する図には必ず1行のキャプションを付けてください。
<figure>(Method、Motivation、またはfill中に追加する二次的な図)には、captions.jsonから取得した空でない<figcaption>を必ず付けてください。ラベルのない図は不備です(check_poster.py preflightは空のキャプションに警告を出します)。図のキャプションの出典がない場合は、論文の本文から事実に基づく短いキャプションを作成するか、図を削除してください。キャプションなしで出力してはいけません。 - 3列以上の表を優先してください。
Method | Metricの2列だけの表をセクション幅いっぱいに広げると、空白が目立ち、情報量が少なく見えます。論文で複数の指標を報告している場合は、指標ごとに列を設けて、表の情報量と幅を活用してください。content_patterns.mdのP12を参照してください。 - 情報を捏造しないでください。 数値、主張、図のキャプションはすべて、
text.txt(paper2assetsが生成)またはfigures.jsonの情報に基づいている必要があります。不確かな場合は、創作するより省略してください。
エッジケース
| 状況 | 対応 |
|---|---|
<outdir>/ が存在しない、または必要な paper2assets の出力が不足している | ソース PDF に対して paper2assets スキルを自動的に実行し、<outdir>/ を生成・補完してから続行します。 |
figures.json が空である | そのまま続行します。Method の図は none です。 |
| 選択した図ファイルがディスク上に存在しない | none として扱います。 |
Method の図が none である | 選択した向きに応じて --layout half を指定して構成し、その後 Method の <figure> ブロックを削除します。 |
POSTER_ORIENTATION=portrait が設定されている(唯一のトリガーです。図の AR に基づいて自動で向きを切り替えないでください) | layouts_portrait/{full,half}.html を使用します。A0 の縦向きキャンバス(33.1×46.8 in)です。Half は 2 列、Full は以下で説明する 4 バンドレイアウトです。 |
| 横向きで Method の図の AR ≥ 2.5(横に広い) | --layout full を指定して構成します。横長のパイプライン/アーキテクチャ図は、元の列属性にかかわらず、中央結合レイアウトを使用します。 |
| 縦向きで Method の図の AR ≥ 1.2 | layouts_portrait/full.html を使用します。4 つのコンテンツバンドです。読み順:Problem|Motivation(上部の 2 列)→ .method-hero の中心要素(左側に縦向きに回転した SIDE-TITLE、箇条書き、右側に横長の図を配置した全幅)→ Key Results|Ablation|Headline(非対称の 3 列、1.5/1/1)→ Takeaway(全幅の要点)。箇条書きセルは疑似セクションで、行の高さに合わせて自動的に埋まります。 |
横向きで Method の図が {column=full} | --layout full(中央結合レイアウト)を指定して構成します。 |
縦向きで Method の図が {column=full} | layouts_portrait/full.html(4 コンテンツバンドの雑誌風サンドイッチレイアウト。中央に Method の中心要素を配置し、SIDE-TITLE を縦向きに回転)を使用します。 |
横向きで Method の図が {column=half} かつ AR < 2.5 | --layout half を指定して構成します。 |
| 縦向きで Method の図の AR < 1.2(縦長) | layouts_portrait/half.html を使用します。図は単一列に配置し、上にテキストを置きます。ヒーローバンドはありません。 |
<outdir>/assets/logos/ が空である | 解決できなかった機関の <img class="logo"> 要素を削除します。src に {{LOGO_N}} トークンをそのまま残さないでください。 |
<outdir>/assets/qr/code.png が存在しない | タイトルバーからコード QR の <img> を削除します(論文 QR だけでも問題ありません)。 |
| 見出し用の数値が 4 つ未満である | 未使用の .stat div を削除します(補助タイルは 2 つ以上残してください)。 |
| ベースラインと提案手法を適切に比較できない | <table class="results"> を、Key Result に Necessary を含む <p> に置き換えます。 |
poster.html がすでに存在する | 確認せずに上書きします。 |
| 論文にアブレーション研究がない | アブレーションがないことを記した 1 行の Necessary を記載し、Additional は空にします。Ablation Study の .section ブロックを削除し、PLAYLIST から "ablation-study" を削除します。 |
| 論文が標準的な公開ベンチマークのみを使用している(新しいデータセットがない) | Dataset / Benchmark は任意です。デフォルトでは lean-render の時点で .section ブロックを省略します。列に余裕があれば、段階的な補完ループで「Standard benchmarks: …」のカードを 1 行追加できます。ブロックを省略した場合は、PLAYLIST から "dataset-benchmark" を削除します。 |
| 論文が新しいデータセットまたはベンチマークを 導入している | 初回パスで Dataset / Benchmark セクションをレンダリングします(Method と同様に、主要な要素として扱います)。PLAYLIST に "dataset-benchmark" を残します。 |
主なルール
- 数値を勝手に創作しないこと。
text.txt(paper2assets の出力)から取得してください。すべての統計値、差分、表のセルはスペックに遡れなければなりません。 poster.html全体を出力チャネル経由で出力しないこと。 約 100 KB あり、ファイル全体のWrite(またはテンプレート全体をインラインで出力すること)はターンごとの出力トークン上限(CLAUDE_CODE_MAX_OUTPUT_TOKENS、デフォルト 32000)を超過して実行が中断されます — これは小規模モデルが大きなポスターで失敗する最も一般的な原因です。間接的に生成してください(テンプレートをシェルのcpでコピーし、プレースホルダーを外科的なEditで置換する、またはbuild_poster.pyジェネレーターを使う — ステップ 3 を参照)。そして、フィルループのすべての変更を部分的なEditに保ち、全体の書き換えは決して行わないでください。- フィルループ中に
poster.html全体を再Readしないこと(上記ルールの INPUT コンテキスト側の双子)。 約 100 KB あるため、毎ラウンド再読み込みすると小規模モデルのコンテキストウィンドウが溢れ → 自動コンパクション → フィル状態の喪失 → ループがスラッシングして収束しなくなります。作業はslackレポートから行ってください — 現在はEDIT TARGETSブロックが出力され、バンド外の各セクションの逐語的なソースが含まれているので、Editのold_stringはそこから直接取得し、ファイル全体を再読み込みしないでください。staged_fill.mdのルール 6 を参照してください。 - まずは簡素なレンダリング、次に計測されたフィル。 プレースホルダー置換中にフィットを推測しないでください。コアセクションの
Necessaryのみをレンダリングしてください — Problem、Motivation、Method(主要な数式を含む)、Key Result、Headline Numbers、Takeaway — その後、何を追加するかはcheck_poster.py slackに判断させてください。Contribution はデフォルトで除外されます(論文の目玉となる新規性が Contribution リストそのものである場合のみ保持)。Ablation Study、Dataset / Benchmark、および穴埋めの Takeaway は優先度が下げられます — 本物の第一級のコンテンツを持つ場合のみレンダリングしてください(Dataset は論文がそれを導入する場合のみ、Ablation は実際のアブレーション行がある場合のみ)。フィルループは Ablation、Dataset、または水増しした文章よりも先に、主要な数式、実際の数値、Method の図、および二次的/定性的な図を取りに行きます — そして Contribution を復活させるよりも先です。 - ポスターあたり 2 つ以上の図を目標とすること。 Method だけでは、右側の実証的なストーリーが文章と数値の壁になってしまいます。ステップ 2 では、論文に二次的な図があればそれを選びます — 目は Method の図以外に少なくとも 1 つの実証的なビジュアルを必要とします。図が 1 つのポスターは、残りの図が本当のシグナルを持たない場合にのみ許容されます(稀です)。
- 主要な数式を含めること。 意味のある数学を含む論文のポスターはすべて、少なくとも 1 つの主要な数式/公式(目的関数、損失、または支配的な表現)を
equationウィジェット経由で示さなければなりません — Method に統合するか、コンパクトな Formulation カードとして。数式駆動の論文で数式をゼロしかレンダリングしないのは品質上の失敗です(著者の GT との最も一般的なギャップ)。LaTeX はスペック/text.txtから取得してください。記号を創作しないでください。 - コンテンツのないセクションは禁止。 本物のコンテンツなしでレンダリングされるセクションは、空で表示するのではなく省略されます — プレースホルダーの上に見出しを出したり、単独の「N/A」を載せたりしないでください。これは FULL フィルゲートの裏返しです:優先度を下げられたセクション(Ablation、穴埋めの Takeaway、導入されていない場合の Dataset)は水増しするのではなく削除されます。保持されるすべてのセクションは、本物の、論文固有のコンテンツを持たなければなりません。
- セクションごとの厳格なフィットゲート。 段階的フィルループを停止してよいのは、すべてのセクションが
FULL(fullRatio 0.90~1.00)であり、かつすべてのカード図が少なくとも 1 軸でボックスの 90~100% を埋めている場合のみです(polishがFIG/NARROWゼロを報告)。列ごとの SPARSE 許容はありません —SPARSEカードは完了ではなく、まだ埋め終えていないカードです。 - フィルループの通過 ≠ タスク完了。 slack/polish ゲートを通過したことは、HTML のレイアウトが良好であることを意味するだけで、成果物が生成されたことは意味しません。ステップ 6(PDF/PNG レンダリング)とステップ 7(html2pptx)は別のステップであり、「フィルループが収束した」を「タスク完了」と誤解したモデルによって日常的にスキップされます。ステップ 7.5 の
check_poster.py deliverablesゲートは譲れません:報告前に実行し、終了コード 0 になるまでループしてください。 .growカードは除外されず、ゲート対象です。 flexbox によって残りの列スペースを吸収するために引き伸ばされた.growカードは、古いツールでは FULL と表示されても、依然として末尾に目に見える空白の帯を示すことがあります。同じ fullRatio ゲートを適用してください — 埋める(Additional/追加の箇条書き)か、空白を残す代わりに非 grow の兄弟要素からコンテンツを移してください。- マルチタイルコンテンツの均一性(繰り返し発生する欠陥 — よく読んでください)。 セクションが小さな統計/数値タイルの水平行を出力するときは常に、行内のすべてのタイルが同じ視覚的形状を共有しなければなりません — 大きな数値の行数が同じ、ラベルの行数が同じ。高さが不一致だと壊れて見えます:あるタイルの値が高く位置し、隣は低く位置する、またはラベルが 2 行/3 行のジグザグのベースラインを示します。広く適用されます —
.headline-hero .supportingの.stat-miniタイルだけでなく、.p-stat-stripのセル、Motivation/Method/Key Results内の任意のアドホックな数値カード行、および将来のあらゆるタイルウィジェットにも。- テンプレートはこれを構造的にバックストップするようになりました:
.headline-hero .supportingはalign-items: flex-startを使用し(すべての.val数値が上揃えになり、ラベルの高さに関係なく常に同じ高さに位置します)、.stat-mini .lblはmin-height: 2.4emを持ちます(すべてのラベルが 2 行を確保するため、1 行と 2 行のラベルが同一の垂直スペースを占めます)。これは、折り返すラベルがもはやその値を押し上げて整列を崩せないことを意味します。しかし CSS はスロットを確保するだけです — すべてのラベルを 2 行以下に保たなければなりません、そうでないと 3 行のラベルが確保された 2 行のスロットから溢れ、行が再び壊れます。CSS を不均一なラベルを書く口実として頼ってはいけません。 - 大きな数値:すべてのタイルが 1 行に収まるか、すべてのタイルが 2 行に折り返すかのどちらかです。同じ行内で 1 行と 2 行を混在させないでください。修正は、最も長いタイルの値を短くする(例:
−84% FLOPs Δ→−84%)、または短いタイルも折り返すように言い換える — 通常は前者の選択肢です。 - ラベル:行内のすべてのタイルを同じ行数に保ち、それぞれ 2 行以下にしてください(確保されたスロットはちょうど 2 行)。すべて 1 行(短いトークン:
pts、params、mAP)か、すべて 2 行のどちらかを目標とし、ジグザグに見える混在は決して避けてください。あるラベルが自然に 3 行になり兄弟が 2 行のままの場合、長い方を短くしてください(形容詞を削り、略語を優先し、M/Bのような単位ショートカット、精度にはaccを使う) — 短い方を水増ししないでください。 - 完了と言う前に確認してください。 レンダリングされたポスター内のすべてのマルチタイル行を視覚的にスキャンしてください。値が異なる y 位置にある、またはラベルが階段状のベースラインを示す場合、その行は均一性を満たしていません — サインオフする前にコンテンツを修正してください。
- テンプレートはこれを構造的にバックストップするようになりました:
- キャンバスロックを編集しないこと。 両方のテンプレートの 60×36in/
cqw/aspect-ratio: 5 / 3ルールが、ブラウザプレビュー、印刷 PDF、および PNG サムネイルを異なる倍率で同じレイアウトに見せる所以です。 - paper2assets が図のクリーンアップパイプライン(top-check → decaption → autotrim)を所有しています。 ここで決定論的チェーンを再実行しないでください — すでに完了しています。ステップ 2.5 の視覚的な
boxカットは、残存する非対称なノイズ専用です。