hpdft-0.4.6.0: dev/0.3-roadmap.md
# hpdft 0.3 開発ロードマップ
hpdft 0.3 開発ロードマップ(**0.3.0.0 リリース済み**、2026-07-05)。
`master` @ 0.3.0.0。0.2.0.0 からの非互換変更を含む。
## テキスト抽出パイプライン(現行)
既定の `hpdft FILE` は次の順でパイプラインを選択する。
```
tagged(StructTreeRoot + MCID ≥50%)
↓ 不可
geometry(PDF.Interpret → PDF.Layout)
↓ 座標 unusable(<70%)
stream-order fallback(Layout 内)
```
| フラグ | パイプライン |
|--------|-------------|
| (なし) | tagged → geometry(上記) |
| `--geom` | geometry のみ |
| `--tagged` | tagged → geometry フォールバック |
| `--legacy` | 旧 ContentStream 抽出(0.2 以前) |
| `--footnotes` | geometry 系で脚注本文を `<footnote>…</footnote>` にインライン化 |
`-p` / `-g` も geometry パイプラインを使用(`--legacy` 除く)。
### geometry パイプラインの内部段階
1. **PDF.Interpret** — コンテンツストリームをオペランドスタックで解釈し、`PageItem`(グリフ + グラフィック矩形)を生成
2. **行形成** (`buildLines`) — ストリーム順でグリフを行にマージ(上付き・下付き・ハイフン継続)
3. **ヘッダ/フッタ除去** — 全ページ横断で反復する上下帯テキストを除去(document-level)
4. **脚注処理** (`--footnotes`) — ページ下部の小字体 + マーカー行を検出し、アンカーへインライン
5. **読み順ソート** (`sortLinesByReadingOrder`) — 行の先頭座標で並べ替え
- 横書き (wmode 0): 上→下、左→右
- 縦書き (wmode 1): 右→左(列)、列内上→下
- RTL 横書き: **未対応**
- wmode 混在ページ: 横書きブロック → 縦書きブロック(interleave なし)
6. **段落化** — ベースライン跳躍・インデント・グラフィック要素で段落境界を判定
7. **ページ跨ぎ結合** — 終端句読点・インデント・フォントサイズ変化で段落を連結
### ライブラリ API(主要)
| モジュール | 役割 |
|-----------|------|
| `PDF.Document` | 1 回読込の Document ハンドル |
| `PDF.Error` | `PdfError` / `PdfResult` / `PdfWarning` |
| `PDF.Interpret` | 幾何インタプリタ → `[Glyph]` / `[PageItem]` |
| `PDF.Layout` | 行・段落・document-level レイアウト |
| `PDF.Structure` | Tagged PDF 構造ツリー解析 |
| `PDF.Text` | 抽出ドライバ(legacy / geom / tagged) |
| `PDF.Matrix` | 2D アフィン変換 |
---
## 完了したフェーズ
### A: 堅牢性(完了)
- [x] A1 xref/trailer 系の `Either` 化
- [x] A2 パーサ全域化(`error` / 部分関数排除)
- [x] A3 CLI エラー表面化(exit code・メッセージ)
- [x] A4 stream 読み取りのバイナリ安全化(`/Length` 主導)
- [x] A5 `orError` 解消 + Show/表示分離
- [x] A6 診断を `PdfWarning` チャネルへ
### B: 性能・API(完了)
- [x] B1 `Document` ハンドル(1 回読込)
- [x] B2 xref 遅延パース + type 2 直接解決
- [x] B3 `Dict` / `PDFObjIndex` の Map 化
- [x] B4 CMap/Encoding lookup の Map 化
### C: テキスト表現(完了)
- [x] C1a `PDF.Matrix`
- [x] C1b `FontInfo` 幅テーブル・WMode・bytesPerCode
- [x] C1c `PDF.Interpret` 幾何インタプリタ(オペランドスタック)
- [x] C1c-CID hex トークナイザ修正 + inline Dict フォント解決
- [x] C1d `PDF.Layout` 段落ヒューリスティック + グラフィックマーク
- [x] C1e Tagged PDF(MCID + StructTreeRoot)論理順抽出
- [x] C1f コーパス比較・既定パイプライン切替(tagged→geom、`--legacy` 退避)
- [x] document-level ヘッダ/フッタ除去 + ページ跨ぎ段落結合
- [x] 上付き文字インライン化 + `--footnotes` オプション
- [x] Latin 語間スペース + ハイフン行結合修正
- [x] 座標ベース読み順ソート
- [x] **C2** String→Text 移行(PdfText/PdfName/CMap/出力系)
### D: インフラ(D1・D2・D4 完了、D3・D5–D7 未着手)
- [x] D1 cabal test-suite + フィクスチャ拡充(golden 11 × 2 パイプライン、unit 267)
- [x] **D2** GitHub Actions CI(v0.4.4.0)
- [ ] **D3** パーサ基盤統一(attoparsec/parsec 二本立て解消)
- [x] **D4** cryptonite→crypton 移行
- [ ] **D5** Filter 拡充(LZW/ASCII85/ASCIIHex/RunLength/カスケード)
- [ ] **D6** AES-256(R5/R6)鍵導出
- [ ] **D7** CLI サブコマンド化
---
## テスト
```bash
cabal build
cabal test # golden 22件 + unit 267件
bash scripts/verify_text.sh # 全 fixture(default + legacy)
HPDFT=dist-newstyle/build/.../hpdft bash scripts/verify_xref.sh # data/sample
```
| スクリプト | 用途 |
|-----------|------|
| `scripts/gen_fixtures.hs` | CI 安全な synthetic PDF 生成 |
| `scripts/verify_text.sh [--update]` | golden テキスト比較 |
| `scripts/verify_xref.sh` | `data/sample/*.pdf` スモーク |
| `cabal run interpret-page -- FILE PAGE [--full]` | ページのグリフ/グラフィックダンプ |
フィクスチャ: `data/fixtures/`(公開可)。期待値は `expected/`(default)と `expected-legacy/`(`--legacy`)。
ローカル PDF: `data/sample/`(`.gitignore`、公開リポジトリ非収載)。
---
## 既知の制限・フォローアップ
| 項目 | 状態 | メモ |
|------|------|------|
| RTL 横書き | 未対応 | 明示的にスコープ外 |
| wmode 混在ページ | 制限あり | 横→縦ブロック連結 |
| 同一行内ストリーム逆順 | 未対応 | 行内 LTR 補正は将来タスク |
| ページ外アーティファクト | 残存 | 例: irtls p19 の `22360`(MediaBox 外フィルタ要) |
| SecureFont / ToUnicode 欠損 | 部分 | heatstroke 等で文字化け(poppler も同様) |
| Form XObject の MCID | 簡易 | 親スタック引継ぎのみ |
| tagged パスの artifact 脚注 | 未統合 | geometry フォールバック時のみ `--footnotes` 有効 |
| CLI | フラグ連鎖 | D7 でサブコマンド化予定 |
---
## 推奨する次の作業順
0.3.0.0 リリース済み。以降は [0.4 ロードマップ](0.4-roadmap.md) を参照。
1. **0.3.1** — ルビ抽出(青空文庫記法、`--ruby`、Structure 優先)
2. **0.4.0 E0** — 公開 API 整備(`PDF.Page` 等)
3. **D2 CI** — E0 前後で導入
4. **0.4.1 D7** — CLI サブコマンド化
5. **0.4.2 D5+E2** — DCTDecode + 段落 diff
6. **0.4.3 E3** — `hpdft extract images -p PAGE FILE`
---
## コミット履歴(feature/0.3-error-model、新しい順)
`master` から約 30 コミット。主要マイルストーン:
| コミット | 内容 |
|---------|------|
| f27e78f | 座標ベース読み順ソート |
| 1d2187b | Latin 語間スペース + ハイフン行結合 |
| 1453624 | 上付きインライン化 + `--footnotes` |
| 56778da | document-level ヘッダ/フッタ + ページ跨ぎ段落 |
| fc312ce | 既定パイプライン切替(tagged→geom、`--legacy`) |
| 05a0c6d | PDF.Layout + `--geom` |
| e6f5118 | PDF.Interpret 幾何インタプリタ |
| 47fa202 | 0.3.0.0 + PDF.Error 骨格 |
| … | A/B フェーズ(堅牢性・Document API・Map 化) |