Featured image of post 見出しの階層をif/elseで組むと分岐が爆発する。PerlとMooのCompositeで目次ツリーを組み直す全8回【目次】

見出しの階層をif/elseで組むと分岐が爆発する。PerlとMooのCompositeで目次ツリーを組み直す全8回【目次】

Perl と Moo で Markdown の目次ジェネレーターを作りながら、見出しの入れ子を if/else で組もうとして行き詰まり、Composite パターンとスタックのパーサーで組み直す全8回の連載の目次です。困りごとからも選べます。

Perl と Moo で、Markdown ファイルの見出しから目次を作るツールを作る全8回の連載です。ファイルを読み込み、正規表現で見出しを抜き出し、インデントを付けただけの目次から始めます。そのあと入れ子の HTML 目次を if/else で組もうとして、見出しのレベルが飛んだだけで壊れる様子を確かめます。そこから、子を持つ見出しも持たない見出しも同じ render で描く Composite パターンに組み替え、スタックで見出しの配列からツリーを自動で組み、Markdown・HTML・JSON の3形式とリンク付きの目次まで仕上げます。

各回は前の回のコードに手を足していく作りなので、通して読むなら第1回からが早道です。このページは目次を兼ねた案内板です。入口は「どこから読むか」で、困りごとが決まっているなら「困りごとから探す」で、順に追うなら「全話一覧」で選んでください。

どこから読むか

  • 第1回 — 最初から順に作るなら。Markdown を全行読み込む MarkdownReader を作る。前提は Moo のクラス定義の基礎
  • 第4回 — なぜパターンが要るのかを先に見たいなら。if/else で組んだ HTML 目次が、見出しのレベルが飛んだだけで壊れる
  • 第5回 — Composite パターンの組み方だけ知りたいなら。Role・Leaf・Composite の3つを作り、再帰の render で階層を描く

困りごとから探す

入れ子の HTML リストを組むと、ul の開け閉めが合わない

  • 第4回 — レベル差で ul を開け閉めすると、H1 の次の H3 で構造が崩れる
  • 第7回 — 子が自分の子を描く再帰で、入れ子の ul を正しく閉じる

フラットな配列から親子関係を組み立てたい

  • 第3回 — 配列のままではどの見出しがどの見出しの下にあるかが分からない
  • 第6回 — スタックで親を決め、配列からツリーを自動で組む

子を持つ要素と持たない要素で、処理を書き分けている

  • 第5回 — 同じ Role を実装して、どちらも render 1つで描く

出力形式を増やしたい

  • 第7回 — 1つのツリーから Markdown・HTML・JSON を出す
  • 第8回 — 既存のクラスを書き換えず、レンダラーを足して出力を増やす

目次の項目を見出しへのリンクにしたい

  • 第8回 — 見出しテキストからアンカー ID を作り、リンク付きの目次を出す

全話一覧

  1. Markdown を全行読み込むクラス(lazy)
  2. 正規表現で見出しのレベルとテキストを抜く(キャプチャ)
  3. インデント付きで目次を表示する(フラット配列)
  4. if/else で入れ子の HTML を組んで壊れる(条件分岐の爆発)
  5. 同じ render で階層を描く(Composite)
  6. 見出しの配列からツリーを自動で組む(スタック)
  7. Markdown・HTML・JSON で出力する(複数フォーマット出力)
  8. アンカー ID でリンク付きの目次にする(開放閉鎖原則)

前提知識

  • Perl v5.36 以降の基本文法(signatures、postfix dereference など)
  • Moo によるクラス定義の基礎(has)と Moo::Role(第5回から使う)
  • Moo が初めてなら、先に「Mooで覚えるオブジェクト指向プログラミング」シリーズを読むとスムーズに進みます

完成するもの

Markdown ファイルを読み込んで見出しを抜き出し、見出しのツリーを組んで、Markdown のリスト・入れ子の HTML・JSON の3形式で目次を出すツールです。Markdown のリストは、見出しへのリンク付きでも出せます。追加の CPAN モジュールは Moo だけで、JSON の出力には Perl 標準の JSON::PP を使います。

関連シリーズ

構造パターン

comments powered by Disqus
システム開発・AIワークフローのご相談は Meetsource へ
Hugo で構築されています。
テーマ Stack は Jimmy によって設計されています。