決算書の読み方教材: PDF199ページから47枚のSVG図解作成と表示確認の落とし穴
1ヶ月前に「いつかやる」と棚に置いた決算書教材のPDFを、今日ようやく開いた。199ページの分厚いやつだ。「これを全部SVG図解に置き換える」と決めて、pdftoppmにPDFを食わせた瞬間からセッションが走り出した。
夜になる頃には、preview.htmlに47枚のSVGが章ごとに並んでいた。途中で踏んだ地雷と、svg-diagramスキルに追加した新ルールを残しておく。
1. PDF199ページを画像化して、図インベントリを作る
最初にやったのは「どのページに図があるか」のマッピング。これをサボると、後で「あれ、この図やった?」と何度も聞き直すことになる。
pdftoppm -r 150 input.pdf p -png
# → p-001.png 〜 p-199.png
全199ページが画像になった。次に Claude Code に「ページごとに図あり/なしを判定して、図のタイプ(フロー、概念図、ツリー、表)と一行サマリを書いて」と頼んだ。
最初は memo/2026-05-11/figure-pages-1to50.md に1〜50ページ分だけ作った。中身を見て「これでいける」と判断してから、全199ページ版に拡張した。インベントリができた段階で「SVG化対象は47ページ」と確定した。
2. 「1ページ=1図」「下回らない・改善OKルール」で書く
方針は2つだけ決めた。
- 1ページ=1図: ページをまたいで複合図にしない。教材として「このページの図」と参照しやすくする
- 下回らない・改善OKルール: 書籍の図を再現するのが最低ライン。情報量を削らない。ただし配置や表現で改善できるならOK
この方針が後で効いた。サブエージェントに丸投げするときに「元の図と同じ情報を全部入れて、改善は任せる」と一言で渡せた。
3. svg-diagramスキルを起動してバッチ並列で47枚
svg-diagramスキルにはグレー8段階の濃淡、文字サイズ、レイアウト規則、マゼンタ強調のパターンが定義してある。これに従ってサブエージェントを並列起動した。
- 第1バッチ: 22枚を並列生成
- 第2バッチ: 25枚を並列生成
- 合計47枚
人間がやったのは「方針を一言で渡す」「バッチを切る」だけ。実装はサブエージェントが回した。
4. ここから地雷踏みのターン
47枚生成して「できた」と提出したら、ユーザーから「表示確認をちゃんと」と一刺しされた。確かに、preview.htmlで開いてもいない。慌ててChrome DevToolsでpreviewを開いた瞬間、画面が崩れていた。ここから3つのバグを順に潰した。
バグ1: 「セブン&アイ」のXMLエスケープ漏れ
p020あたりのSVGで、テキストがそこから先全部消えていた。SVGをエディタで開いて目で追ったら、<text>セブン&アイ</text> と書いてあった。& は XML予約文字なので & に書かないとパーサーが死ぬ。
3箇所ヒットした。& を & に置換して直した。
<!-- NG -->
<text>セブン&アイ・ホールディングス</text>
<!-- OK -->
<text>セブン&アイ・ホールディングス</text>
バグ2: 反復ラベルの太字が「内容差分」をぼかす
対比図(左に「日本企業A」、右に「日本企業B」のような構造)で、両側に同じ「売上高」「営業利益」というラベルが並ぶ。これを両方とも太字にしていた。
並べてみると、視線がラベルの太字に吸われて、本来見せたい右側の数字差分が頭に入ってこない。「対比図では反復するラベルは太字にしない」とその場で気づいた。
svg-diagramスキルに新ルールを追加した:
## 対比図での反復ラベル太字禁止
左右や上下で対比する図では、両側に同じラベル(「売上高」「営業利益」等)が並ぶ。
このとき反復するラベルを太字にすると、視線がラベルに吸われて
本来見せたい「内容の差分」がぼやける。
- 反復ラベル: regular weight
- 差分の数値・キーワード: bold
ルール追加後、9ファイル35箇所の font-weight="bold" を font-weight="normal" に書き換えた。preview.htmlを再描画したら、視線が数字に向くようになった。
バグ3: テキストはみ出し(p026の現金化スピード列、p050の「。」見切れ)
これが一番やっかいだった。Chrome DevToolsで開いて初めて「右端の文字が切れている」「最下部の句点が見切れている」と気づくケース。SVGのviewBox内に収まっているように見えても、<text> のサイズ計算が甘いと枠外に飛び出す。
Pythonで全47枚を厳密チェックするスクリプトを書いた。
# 各 <text> 要素の x + 文字数 * フォントサイズ係数 を計算し、
# viewBox の幅を超えるテキストを検出
スクリプトで弾かれた候補を、Chrome DevToolsで16枚実画面確認した。p026の「現金化スピード」列のヘッダーが幅をはみ出していたのと、p050の本文最下行の「。」が下にはみ出していたのを修正した。
5. マゼンタ強調を「ここだけ見ればいい」1〜2箇所に追加
47枚の構造修正が落ち着いた後、各SVGに「読者がここだけ見ればこのページの言いたいことが伝わる」という1〜2箇所をマゼンタで強調した。svg-diagramスキルにあるパターンを素直に適用しただけだが、preview.htmlで一気にスクロールすると、マゼンタの位置だけ目で拾える。教材としての「視線の導線」が一段強くなった。
6. preview.htmlで章別に並べる
最後に preview.html を作って、47枚のSVGを章ごとに整理した。全部一画面でスクロールできるので、構成のバランス(第3章だけ図が多すぎないか等)が一目で分かる。
ついでに「サブメッセージ以下は+16pxシフト」の調整も入れた。各図の説明文がメインメッセージに寄りすぎていて読みづらかったので、垂直方向の余白を広げた。
7. 引き継ぎドキュメント session-handover.md
セッションが長くなってきたので、明日以降の続きのために session-handover.md を作った。
- どのページが完了したか(47/47)
- どのバグを潰したか
- svg-diagramスキルに追加した新ルール
- preview.htmlの場所と開き方
明日 /clear してもこのファイルから再開できる。
今日の学び
- インベントリを先に作る: 199ページを「全部見る」のは無理。図あり/なしを先に判定して、対象を47枚に絞ってから着手したのが正解だった
- 「表示確認をちゃんと」は毎回言われる前にやる: 生成して終わり、ではなく Chrome DevTools で1枚ずつ画面で見る。これをサボったので3バグ連続で踏んだ
- 対比図の反復ラベルは太字にしない: スキルに追加した。次回以降のSVG生成でこの罠を踏まなくなる
- XMLエスケープは
&だけで十分死ぬ:<や>以外にも&がトラップ。対象テキストに会社名が出てきたら最初に grep で&を探す癖をつけたい
明日やること
- preview.html を本番ページに組み込む(
/financial-statements-textbookのような専用ページに配置) - 47枚のSVGに alt テキストを追加してアクセシビリティ対応
- 図の下に出典ページ番号(p.026 等)を小さく入れて、原書との突合を可能にする
- svg-diagramスキルの新ルール「対比図での反復ラベル太字禁止」を、過去に作った他のSVG資産にも適用するか検討