html2pptx について
html2pptxは、レンダリング済みHTMLページを編集可能な図形で構成されたPowerPointに変換するスキルです。HTMLポスターをプレゼン資料として渡す用途向けに、DOM抽出、デッキ生成、描画、見た目の監査と修正反復を行います。
主な機能
- 01HTMLを編集可能なPPTXに変換
- 02キャンバスサイズとフォントを検出
- 03スライドと比較画像を描画
- 04視覚的な忠実度の問題を監査
- 05隔離コピー内で修正を実行
活用シーン
- 01HTML研究ポスターをPPTXとして引き渡す
- 02変換後のスライドとHTML表示を比較
- 03個別ポスターの再現性を反復修正
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ microsoft/ researchstudio --skill html2pptxインストール後、Claude Code で/html2pptxを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
__init__.py.gitignoredifference.mdGOTCHAS.mdREADME.mdrequirements.txtscripts/__init__.pyauto_correct_loop.pyauto_fix_loop.pyfont_embedder.pyfont_resolver.pyhtml_to_pptx.pyvision_aggregate.pyvision_audit.pyvision_compare.pyvision_eval_harness.py詳細
html2pptx
レンダリング済みの HTML ページを、編集可能な図形を備えたネイティブの PowerPoint .pptx に変換します(スライド内に PNG を配置する方法ではありません)。
使用する場面
- 「この HTML のポスターを PPT に変換してください。」
- 「HTML ページを編集可能な PowerPoint 形式にしたいです。」
- 「poster.html を 1:1 で PPT に再現してください。フォント/色/レイアウトも同じにしてください。」
- 「ポスターを PPT 形式で開発者以外の人に引き渡します。」
使用しない場面
- フラットな PNG スライドが必要な場合 →
paper2poster/demo/presentation/posters.pptxを使用してください。 - HTML で重い JS アニメーションや動画を使用している場合 → PPT の図形には変換されません。
- KaTeX を多用したコンテンツの場合 → 数式はフォールバックとしてラスタライズされます(数式を編集できなくなります)。
セットアップ(初回のみ)
1. Python の依存関係
pip install python-pptx playwright pdf2image lxml Pillow pyphen cairosvg
playwright install chromium # ~110MB headless browser
2. soffice(検証用)
# Linux:
sudo apt install libreoffice-impress
# Mac:
brew install --cask libreoffice
3. Web フォント — 再現性に不可欠(GOTCHAS.md をお読みください)
デフォルトは Arial です → このセクション全体をスキップできます。 paper2poster のデフォルトは Arial なので、ポスターは Arial(または PPT で安全に使える別のフォントファミリー:Calibri、 Aptos、Cambria、Times New Roman、Verdana、Georgia、Trebuchet MS)でレンダリングされます。これらは Mac と Windows の PowerPoint にあらかじめインストールされているため、以下のフォントを インストールする必要はなく、
.pptxはフォントを埋め込まなくても そのまま持ち運べます。以下の Inter / Source Serif 4 / JetBrains Mono のセットアップが必要なのは、ポスターのレンダリング時にオプションの Inter Web フォントを指定した場合のみです。
Inter / Source Serif 4 / JetBrains Mono がインストールされていない場合、soffice は DejaVu Sans(Linux)または Helvetica(Mac)にフォールバックします。文字幅が変わり、テキストの折り返し方が異なり、すべての要素の位置が連鎖的にずれます。
Linux:
# Download static-weight TTFs (variable fonts register under wrong family name)
mkdir -p /tmp/fonts-dl && cd /tmp/fonts-dl
curl -sL "https://github.com/rsms/inter/releases/download/v4.0/Inter-4.0.zip" -o Inter.zip
curl -sL "https://github.com/adobe-fonts/source-serif/releases/download/4.005R/source-serif-4.005_Desktop.zip" -o SourceSerif4.zip
curl -sL "https://github.com/JetBrains/JetBrainsMono/releases/download/v2.304/JetBrainsMono-2.304.zip" -o JetBrainsMono.zip
unzip -qo Inter.zip -d Inter/
unzip -qo SourceSerif4.zip -d SourceSerif4/
unzip -qo JetBrainsMono.zip -d JetBrainsMono/
mkdir -p ~/.local/share/fonts
cp Inter/extras/ttf/Inter-{Regular,Medium,SemiBold,Bold,Italic,SemiBoldItalic,BoldItalic}.ttf ~/.local/share/fonts/
cp SourceSerif4/source-serif-4.005_Desktop/TTF/SourceSerif4-{Regular,Semibold,Bold,It,SemiboldIt,BoldIt}.ttf ~/.local/share/fonts/
cp JetBrainsMono/fonts/ttf/JetBrainsMono-{Regular,Medium,Bold,Italic,BoldItalic}.ttf ~/.local/share/fonts/
fc-cache -f ~/.local/share/fonts/
# Verify: fc-match MUST return the font itself, not a fallback
fc-match "Inter" "Source Serif 4" "JetBrains Mono"
Mac: ダウンロードするものは同じですが、~/Library/Fonts/ にコピーし、新しいフォントを認識させるために PowerPoint を完全に終了してから再起動してください(Cmd+Q)。
デフォルトの Arial(または PPT で安全に使えるフォントファミリー)を使用したポスターの場合、閲覧者側で準備するものはありません。これらのフォントは PowerPoint に同梱されているため、pptx はそのまま持ち運べます。オプションの Inter 指定を使用する場合に限り、閲覧者は Inter をインストールするか、オプトイン方式の scripts/font_embedder.py の手順で pptx にフォントを埋め込む必要があります(Inter の 4 種類のウェイトを pptx に埋め込みます。約 3 MB)。
クイックスタート — 1 つのコマンドで実行
cd skills/paper2poster/html2pptx
python -m scripts.auto_correct_loop --html /path/to/poster.html
出力先はデフォルトで入力 HTML の親ディレクトリです(同じ階層に配置する規約、2026-06-12 仕様)。例:my_paper/poster.html → my_paper/poster.pptx。同じディレクトリで続けて実行すると、前回の .pptx は上書きされます。--outdir /custom/path/ で出力先を変更できます。
バンドルの契約(paper2 パイプライン)。* ポスターのパイプラインの最終引き渡しとして呼び出す場合、呼び出し元は --outdir <bundle>/assets/_pptx_build/ を渡し、すべての html2pptx アーティファクト(DOM json、検証用 PNG、soffice のレンダリング結果)が assets/ の下に残るようにします。その後、デッキをバンドルのルートに移します — cp <bundle>/assets/_pptx_build/poster.pptx <bundle>/poster.pptx — poster.pptx は最上位の成果物(assets/ の外に出る唯一の html2pptx 出力)だからです。入力の poster.html は、図、ロゴ、フォントを ルート相対の assets/… src パスで参照します。コンバーターは HTML を file:// 経由で読み込むため、これらは HTML 自体のディスク上の場所を基準に自動的に解決されます。コンバーター側でパスを処理する必要はありません。
これが標準のエントリーポイントです。次の処理を行います。
- CSS の
@page { size: ... }からキャンバスを自動検出し、ポスターが 56" を超える場合は(PPT の上限)比率を保って 55" に縮小します - 同じ階層の
poster.pdfを自動検出します(存在する場合)。そのファイルに対してpdffontsを実行し、CSS 名 → PDF フォントのエイリアスマップを作成します。fontconfig の<match>実行時オーバーライドを書き込み、ブラウザーが参照 PDF と同じフォントを使うようにします — マッチは 1:1 で対応します。atexitでクリーンアップされます。 - HTML から参照されるその他のフォントを Google Fonts から自動ダウンロードします(
font_resolver.py) - DOM を抽出します(playwright の実行は 1 回で、
<name>_dom.jsonにキャッシュされます) - pptx をビルド → soffice でレンダリング → PNG を出力します
- 比較用 PNG を保存します:
<name>_html_print.png(印刷ビューポート。PPT キャンバスと一致)と<name>_html_browser.png(1920×1080 のブラウザービューポート、fullPage) - ビジョン監査(デフォルトで有効):Claude vision を呼び出して
<name>_html_print.pngと<name>.pngの差分を確認し、構造化された忠実度の問題(severity、category、block_idx、where、description)を含む<name>_audit.jsonを書き込みます。以前の監査 JSON がある場合は、差分を表示します(例:前回から問題が 3 件増減)。デフォルトモデル:Opus 4.8(ポスター 1 件あたり約 $0.10。コストを検出率より重視する場合は--vision-model claude-sonnet-4-6でポスター 1 件あたり約 $0.02 に変更できます)。実行時間が約 70 秒増加します。
モデルの選択(このスキルを呼び出すオーケストレーター向け)
このスキルには、独立した 2 つのモデル設定があります。ユーザーが「Opus を使って」「Sonnet を使って」「安い方で」などと指定した場合、オーケストレーションを行う Claude は適切なフラグに変換する必要があります。スキルのスクリプトは自然言語を解析しません。
| ユーザーの意図 | 渡すフラグ | 適用対象 |
|---|---|---|
| 「Opus を使って」/「最高品質」/モデルの指定なし(デフォルト) | (フラグを省略 — デフォルトは Opus 4.8) | 両方 |
| 「Sonnet を使って」/「安い方で」 | --vision-model claude-sonnet-4-6(auto_fix_loop を実行する場合は --fix-model claude-sonnet-4-6 も指定) | 両方 |
| 「監査しないで」/「ビジョンをスキップ」/バッチ自動化 | --no-vision-audit | auto_correct_loop |
| 「ビジョンは Opus、修正は Sonnet」(まれ) | --vision-model claude-opus-4-8 --fix-model claude-sonnet-4-6 | auto_fix_loop のみ |
2 つの独立した設定と、2 つのスクリプト:
scripts/auto_correct_loop.py(ビルド + 監査)→--vision-model <MODEL>scripts/auto_fix_loop.py(ビルド + 監査 + 自律型コード修正サブエージェント)→--vision-model <MODEL>と--fix-model <MODEL>(どちらもデフォルトは Opus 4.8。--fix-modelはサブエージェントがオーケストレーターの CLI 設定を暗黙に引き継がないよう、claude -p --modelに明示的に渡されます)
再現性:どちらのスクリプトも開始時にモデルの選択をログに記録します。ビジョン監査は [vision-audit] calling Claude vision (claude-opus-4-8, auth=...) と記録し、auto_fix_loop は [fix-loop] models: vision-audit=..., fixer=... と記録します。ユーザーから予期しない動作の報告があった場合、実行ログで使用されたモデルを確認できます。
ビジョン監査の認証
方法は2つあり、どちらでも機能します。
| モード | 環境変数 | 用途 |
|---|---|---|
| 直接 API | ANTHROPIC_AUTH_TOKEN(または ANTHROPIC_API_KEY) | 個人用キーを使って api.anthropic.com に直接接続します |
| ベース URL プロキシ | ANTHROPIC_AUTH_TOKEN + ANTHROPIC_BASE_URL | 企業プロキシ/Vertex/Bedrock/社内ゲートウェイ向けです。ローカル開発マシンではこの設定を使用しています。 |
どちらの認証も設定されていない場合、監査は1行のヒントを表示して何もせずにスキップされます(そのため、オフライン/CI の実行では --no-vision-audit を指定する必要はありません)。バッチ自動化で明示的に無効にするには、--no-vision-audit を渡します(ポスター100枚で約2ドル+追加で約2時間)。
3ラウンドの修正ワークフロー(開発サイクル)
ビジョン監査は、PIL ベースの従来の L2 ループに代わり、より有用なシグナルを提供します。コスメティックなフォント縮小ではなく、構造的な忠実度の差分を確認できます。実行するたびに監査が再実行され、前回からの問題の増減数が +/- N issues vs previous と表示されます。開発の反復サイクルは次のとおりです。
# round 1: baseline (defaults to ./output/<timestamp>/)
python -m scripts.auto_correct_loop --html poster.html
# → look at output/<ts>/poster_audit.json, identify top systemic bug
# round 2: after fixing the bug in html_to_pptx.py
python -m scripts.auto_correct_loop --html poster.html --outdir output/<ts>/
# → output shows e.g. `[vision-audit] 2 issues (-9 vs previous)`
# round 3: fix next bug, target near-zero high-severity
python -m scripts.auto_correct_loop --html poster.html --outdir output/<ts>/
実績では、新しい HTML テンプレートの問題の大半は2~3ラウンドで解消します。各ラウンドの所要時間は約1分で、費用は約0.02ドルです。
ポスター横断の集計:python -m scripts.vision_aggregate <root_dir> を実行すると、各 <poster>/poster_audit.json を走査し、カテゴリごとの頻度とポスターごとの問題数を出力します。これにより、コード側で修正する価値のある、複数のポスターに同じカテゴリの問題が現れる SYSTEMIC なバグと、単発の問題を見分けられます。
自律修正ループ(auto_fix_loop.py)—完全自律型
ポスターごとの忠実度修正を、リリースするスキルに反映させずに行うには、次を実行します。
python -m scripts.auto_fix_loop --html /path/poster.html --max-rounds 3
各ラウンドでは、次の処理を行います。
output/<ts>/_skill_run_copy/のscripts/の隔離コピーを使って、ビルドと監査を行います。- 監査結果から、対応可能な問題のうち最も優先度の高いものを選びます(カテゴリの許可リストにより、
alignment_offなど、画像認識に起因しやすい誤検出を除外します)。 claude -pサブエージェントを起動します。サブエージェントはコピー内に隔離され(--add-dir <copy>)、使用できるツールは Read/Edit/Grep/Glob のみです(Bash と git は使えず、コピーの外には出られません)。- サブエージェントは
GOTCHAS.mdとコピー内のhtml_to_pptx.pyを読み、最小限の差分を作成します。 - 再ビルドし、再監査します。
- 問題数が減った場合は、コピー内の git に変更を保持します。
それ以外の場合は、コピー内で
git reset --hardを実行して、次の問題を試します。 - 対応可能な問題がなくなる(収束する)、最大ラウンド数に達する、または連続失敗数の上限に達すると、ループを終了します。
実行ごとの隔離が、この設計の重要なポイントです。リリース済みの skills/paper2poster/html2pptx/ が変更されることは決してありません。各実行では次のファイルが生成されます。
output/<ts>/<name>.pptx— パッチ適用後の最終 PPToutput/<ts>/<name>_audit.json— 最終監査結果(目標:問題 0 件)output/<ts>/<name>_run_patches.diff— ベースラインとの差分を累積したサブエージェントの変更(ぜひレビューしてください!)output/<ts>/_skill_run_copy/— パッチ適用済みスキルのコピー(同じ HTML で再実行できます)output/<ts>/<name>_fix_loop_summary.json— 各ラウンドの推移
.diff をレビューして修正が実際に汎用的(ポスター固有ではない)だとわかった場合は、通常の PR を通じてリリース済みのスキルに cherry-pick してください。それ以外の場合、パッチはその出力ディレクトリだけに適用され、他のポスターや他のユーザーのインストールには影響しません。
コスト:デフォルトのモデル(画像認識による監査と修正サブエージェントの両方に Opus 4.8 を使用)では、収束した実行 1 回あたり約 1~3 ドルです。--vision-model / --fix-model(例:claude-sonnet-4-6)でどちらかのモデルを上書きすると、問題の検出率や根本原因の特定能力が低下する代わりに、コストを約 1/5 に抑えられます。実行の再現性を完全に確保するため、使用する両方のモデルは実行開始時に記録されます。
認証:--vision-audit と同じです(ANTHROPIC_AUTH_TOKEN を直接指定するか、企業プロキシ経由の場合は ANTHROPIC_BASE_URL も指定します)。
2026-06-05 に削除:以前の「L2 クローズドループ」によるフォント縮小ラウンドは削除されました。PIL が予測したオーバーフローは soffice の実際のレンダリングと連動しておらず(
paper_4_dでは監査の結果、4 ラウンドにわたりオーバーフロー数が 17→17→17→17 のままでした)、縮小処理によって、正常な本文段落が誤って縮小されることもありました。この処理は--vision-auditに置き換えられています(デフォルトで有効)。これにより、PIL では検出できなかった実際の忠実度の問題(ロゴの欠落、span の脱落、誤った折り返し)を検出します。折り返しの忠実度そのものは、後処理ではなく DOM の抽出時に解決するようになりました(CSS の line-height しきい値を使用するブラウザーのextractWrapLines)。既存の呼び出し元が壊れないよう、--rounds/--shrink-stepフラグは引き続き解析されますが、何も行いません。
出力先の規則:デフォルトでは dirname(input_html)/(ソース HTML と同じディレクトリ)に出力されます。変更するには --outdir <path> を指定します。
デフォルトのスライドサイズは 47×33.1"(横向き A0)です。--width-inch / --height-inch で変更できます。
フォントのワークフロー
このスキルは、次の優先順位でフォントを解決します。
-
同じディレクトリに
poster.pdfが存在する場合(または--reference-pdfフラグが指定されている場合):このスキルはpdffontsを使って PDF の実際のフォントを抽出し、エイリアスマップ(例:CSS のInter→ PDF のArimo)を作成して、PDF フォントをローカルにインストールします。さらに、ブラウザーで CSS 名のフォントではなく PDF のフォントを使ってレンダリングするよう強制する、fontconfig の<match>ランタイムオーバーライドを書き込みます。PPT XML のフォント名 = PDF のフォント名になります。最も高い忠実度で、CSS デザイナーが意図したフォントとは異なるフォントにマシン上で置き換えられている、同僚の既存 PDF のレンダリングを再現する場合に適しています。 -
同じディレクトリに PDF がない場合:このスキルは HTML 内のすべての
font-family宣言を調べ、インストールされていないフォントを Google Fonts から自動的にダウンロードします(font_resolver.py)。Google Fonts で入手できるデザイナーの意図したフォント(Inter、Source Serif 4、JetBrains Mono、Roboto、Playfair Display など)は、すべて自動的にインストールされます。 -
Google Fonts に同等のフォントがない CSS/Mac/Win のシステムフォント(Helvetica Neue、SF Pro、Menlo など)は、
html_to_pptx.pyのFONT_ALIASESを使い、ブラウザー側の fontconfig エイリアスと PPT 側の run.font.name の両方で、インストール済みの代替フォント(Inter、JetBrains Mono、Source Serif 4)にマッピングされます。
出力の検証
# Open the last round's PNG; compare with the HTML render PNG:
ls /tmp/uframe_round_*.png
# soffice → PDF → PNG at 96 DPI to match playwright (DPI mismatch = false font-size-look-smaller bug)
重要:すべての箇所で dpi=96 を使用してください。比較用 PNG の DPI が一致しないと、フォントサイズのバグではないのに、見た目のサイズに差が生じます。
soffice のレンダリング ≠ PowerPoint のレンダリングです。 最終的な .pptx は、実際の PowerPoint(Mac/Win)で必ず確認してください。soffice では、影のぼかし、フォントシェーパーのカーニング、グラデーションの停止位置が異なることがよくあります。
アーキテクチャ
HTML
↓ [playwright chromium] render + DOM walk
↓ getComputedStyle on every visible element
↓ canvas.fillStyle = anyColor → normalized rgba()
DOM extract (cached as <name>_dom.json)
├─ elements → boxes (bg/border/gradient/shadow) + images (with object-fit + decoration tile)
└─ text_blocks → block-level (p/li/h1-h6/figcaption/td/th) with inline runs
(incl. ::before/::after pseudo-element content as inherited-style runs)
↓ [python-pptx + lxml] generate native shapes (Z-order by DOM depth)
PPTX
- Picture (object-fit:contain math → centered, letterboxed inside content area = bbox - padding)
+ optional decoration tile UNDER picture (CSS background-color/border-radius/box-shadow)
+ SVG → PNG via cairosvg before embed
- Rectangle / RoundedRect (CSS border-radius → exact roundRect adj)
+ solid fill / linear gradient (gradFill XML)
+ border (line.color/width)
+ box-shadow (outerShdw effect)
- TextBox per block element
+ multiple inline Runs (one per <strong>/<em>/text node/pseudo-element)
+ CSS padding → tf.margin_*
+ CSS line-height → absolute Pt line_spacing
+ CSS text-transform applied per-run (so ::before uppercase doesn't inherit paragraph 'none')
+ CSS letter-spacing → OOXML rPr spc
+ CSS hyphens:auto → pyphen-inserted U+00AD soft hyphens
+ <li> → native OOXML <a:buChar> with hanging indent + section color marker
+ overflow:hidden + line-clamp → PIL-measured truncation + "…"
+ single-word short text (≤6 chars, no spaces) → word_wrap=False (honors browser-proven fit)
PPTX (final)
↓ [optional: --vision-audit] Claude vision diff (html_print.png vs ppt.png)
↓ structured fidelity report (<name>_audit.json): 12 categories × 3 severities
↓ delta vs previous audit if one exists → dev-cycle smoke test
機能一覧
| 機能 | 状態 |
|---|---|
| 位置/サイズのピクセル単位での完全一致 | ✓ |
| 計算済みの色(oklab / color-mix / color() / hsl / 名前付き色) | ✓ canvas 経由 |
| アルファ合成(α<1 の rgba → 白背景に合成) | ✓ |
同じ段落内の Runs としてのインライン <strong>/<em> | ✓ |
| セクションの色付きバナー(h3 の背景+テキスト+番号マーカー) | ✓ |
| 線形グラデーション | ✓ (gradFill) |
| ボックスシャドウ | ✓ (outerShdw) |
| 角丸(CSS の正確な px 値 → roundRect adj) | ✓ |
| 辺ごとの境界線(border-top/right/bottom/left、非対称) | ✓ 存在する辺ごとに細い Rect |
| インラインテキストの背景 → ランのハイライト(テキストの蛍光ペンの色) | ✓ スキーマ準拠の rPr 順序 |
上付き/下付き(<sup>/<sub> または CSS vertical-align) | ✓ ベースラインオフセット+可読性の下限 |
| 画像の object-fit:contain(bbox 内にレターボックス表示) | ✓ |
| CSS padding → テキストボックスの余白 | ✓ |
| CSS の絶対値 line-height(末尾の空白を除去) | (必要に応じて活用) |
| CSS hyphens:auto(libhyphen → pyphen のソフトハイフン) | ✓ |
| 吊り下げインデント+セクションカラーを使ったネイティブ OOXML 箇条書き | ✓ |
| overflow:hidden と line-clamp による切り詰め | ✓ |
@page { size: ... } からのキャンバスサイズの自動検出 | ✓ |
| スライドを PPT の 56" に合わせて比例縮小 | ✓ |
| Google Fonts からのフォント自動ダウンロード | ✓ (font_resolver 経由) |
| 同階層の poster.pdf の自動検出 → フォント抽出、エイリアスマップ作成 | ✓ 存在する場合 |
継承スタイルの Runs としての CSS ::before/::after 生成コンテンツ | ✓(「So what →」のコールアウト、コンテンツ矢印アイコンを検出) |
| ランごとの text-transform の上書き(疑似要素のコンテンツの uppercase と段落の 'none' の不一致) | ✓ |
<img> の装飾タイル(透明 PNG ロゴの下に白い角丸長方形を配置) | ✓(CSS background-color+border-radius+padding) |
| SVG の埋め込み(cairosvg 経由でラスタライズ → PNG) | ✓ |
| 1 語の短いテキスト → word_wrap=False(ICLR/ICML などのバッジ) | ✓(6 文字以下、スペースなし) |
| ビジョン監査による忠実度レポート(Claude のビジョン差分、12 カテゴリー) | ✓ デフォルトで有効(ポスターあたり約 $0.02。認証情報がない場合は通知なしでスキップ) |
| 自律型コード修正ループ(分離されたスキルコピー内の claude-p サブエージェント) | ✓ scripts/auto_fix_loop.py 経由(実行あたり約 $0.50-1.50。配布されたスキルは変更されません) |
| ポスター横断のシステム的なバグ集約 | ✓ scripts/vision_aggregate.py 経由 |
| オーバーフロー時の閉ループ型フォント縮小(L2) | ✗ 2026-06-05 に削除(PIL の予測と soffice の切り離しにより何もしなくなり、誤検出のリスクがあったため。--vision-audit に置き換え) |
| Match-wrap(ブラウザー上の位置で PPT の折り返しを強制) | ✗ デフォルトでは無効。フラグで有効化可能 |
| pptx へのフォント埋め込み(異なるマシン間でのポータビリティ) | ✗(フェーズ 3 は未定) |
| KaTeX の数式 | ✗(フェーズ 4 では PNG にフォールバック) |
| CSS transforms / filters | ✗(フェーズ 4 では PNG にフォールバック) |
スクリプト
scripts/html_to_pptx.py— DOM の抽出と PPTX の構築を行います(従来の--correctionsと、ブラウザーの折り返し位置を強制する--match-wrapに対応)。::before/::afterの疑似要素コンテンツの抽出(「つまり?→」のような CSS コールアウト)、実行単位のテキスト変換、<img>の装飾タイル(透過 PNG ロゴの下に白い角丸の四角形を配置)、cairosvg による SVG のラスタライズに対応しています。scripts/auto_correct_loop.py— 標準のエントリーポイント:DOM 抽出 → 構築 → レンダリング → PNG 比較を一度に実行する生成ツールです。同じディレクトリにある PDF のフォントエイリアスと、Google Fonts の自動ダウンロードに対応しています。デフォルトの出力先はdirname(input_html)/(入力ファイルと同じディレクトリ)です。--vision-audit(デフォルトで有効)を指定すると、レンダリング後にビジョン差分を実行します。scripts/auto_fix_loop.py— 自律修正ループ:スキルのスクリプトをoutput/<ts>/_skill_run_copy/にコピーし、各ラウンドでclaude -pを起動して、コピー内の監査における最優先の問題を修正します(--add-dirでサンドボックス化)。再構築と再監査を行い、コピー内の git を使って変更を保持またはロールバックします。配布されたスキルには手を加えず、実行ごとの差分を人間がチェリーピックできるようにエクスポートします。scripts/vision_audit.py— Claude のビジョン忠実度監査ツールです。(html_truth.png、ppt.png、dom.json)を受け取り、重要度と block_idx を含む、12 カテゴリー(missing_element、wrap_mismatch、text_clipped、color_drift、...)に分類された構造化された問題リストを返します。廃止された PIL ベースの L2 ループに代わるものです。scripts/vision_aggregate.py— ポスターを横断したカテゴリー頻度の集計ツールです。<root>/*/poster_audit.jsonを走査し、どの不具合が何度発生するかを出力して、単発の問題と SYSTEMIC な問題を見分けやすくします。scripts/font_resolver.py— Google Fonts の自動ダウンロード、同じディレクトリにある PDF のフォント検出、fontconfig の実行時エイリアス設定を行います。
ピクセルベースの PDF→PPTX コンバーターより優れている理由
→ difference.md を参照してください。iLovePDF/Smallpdf 形式のラスターコンバーターと比べた具体的な利点として、インラインのテキストハイライトを浮動図形ではなく実行プロパティとして保持すること、孤立したグリフではなくネイティブのリストの箇条書きを使うこと、太字にしても似た別のフォントに置き換えずフォントファミリーを維持することなど、ネイティブ要素による意味情報の保持について説明しています。
注意点
→ GOTCHAS.md を参照してください。実運用で遭遇した、分かりにくい失敗モード、その根本原因、修正方法をすべて記載しています。
クイックリンク:
- G1:フォント名とファミリーの違い(Inter Variable ≠ Inter)
- G2:soffice ≠ PowerPoint(必ず PowerPoint で動作を確認してください)
- G3:PNG 比較における DPI の一貫性
- G4:
line_spacingは正しいフォントでのみ機能します - G5:CSS の color-mix は oklab を返します — canvas 経由で正規化してください
- G6:
isInlineOnlyは CSS の display ではなく、タグ名に基づきます - G7:h3 の番号マーカー(装飾を省き、テキストを再着色)
- G8:object-fit:contain — 手動でレターボックスを計算します
- G9:pyphen と U+00AD による hyphens:auto
- G10:
::markerは生成コンテンツです — OOXML のネイティブ箇条書きを使ってください - G11:Mac の PowerPoint でもフォントのインストールが必要です
- G12:可変フォントは fontconfig に問題を起こします — 静的ウェイトを使ってください
- G15:
<img>の装飾タイルは画像の下に描画する必要があります(透過ロゴの下に白いタイルを配置) - G16:短い単語のみのテキストには
word_wrap=Falseを設定します(ICLR/ICML のバッジ) - G17:DOM ウォーカーは
::before/::afterを認識しません —getComputedStyle(el, '::before')で取得してください - G18:ビジョン監査の誤検出:幅の広い bbox 内で左揃えのテキストが中央揃えに見える
依存関係
| パッケージ | 用途 |
|---|---|
| playwright | DOM 抽出用の chromium |
| python-pptx | OOXML 構築 API |
| lxml | python-pptx で対応していない場合の直接 OOXML 操作(グラデーション、影、箇条書き) |
| Pillow | 画像のデコードとテキストの計測 |
| pdf2image | PDF → PNG プレビュー |
| pyphen | CSS hyphens:auto による任意ハイフンの挿入 |
| cairosvg | 埋め込み前に SVG <img> を PNG にラスタライズ(PIL は SVG をデコードできません) |
オプション(--vision-audit 用):
| ANTHROPIC_AUTH_TOKEN | ビジョン差分に使用する Claude API 認証 |
検証用:
| libreoffice | soffice 経由で PPTX → PDF |
| poppler-utils | pdf2image のバイナリバックエンド(pdftoppm) |
ロードマップ
- Phase 3(未定):pptx への Web フォントの埋め込み(
ppt/fonts/*.fntdata+embeddedFontLst)。pptx あたり約 3 MB 増える代わりに、Mac/Win での「フォントが見つからない」問題を解消します。 - Phase 4(未定):未対応のサブツリー(KaTeX の数式、複雑な SVG、CSS の変換)に対する PNG フォールバック。