title: 'Perlで良い感じに使えるMarkdownをパースする方法とライブラリについて' categories:

- 'perl'

この記事では、Perlでマークダウンをパースする方法について解説していく。

PerlではMarkdownをパースするのに良い感じのライブラリがいくつかある。

Text::Markdown::DiscountDiscountというC言語実装のMarkdown parserがもとになったC拡張ライブラリ。 一方で、Text::MultiMarkdownはpure perl実装になっている。

C拡張ライブラリだとWindowsで上手くビルドできない場合が多々あるので、今回はpure perl実装である Text::MultiMarkdownを使っていく。

Text::MultiMarkdownの使い方

まずはライブラリをインストールする。(cpmを使う)

cpm install Text::MultiMarkdown

そしてコードを書いていく。使い方はいたってシンプルでよい。

```perl use v5.38; use Text::MultiMarkdown;

my $text = <

こんにちは

これがマークダウンです。

  • たろう
  • はなこ
  • さとし

TEXT

my $m = Text::MultiMarkdown->new; my $html = $m->markdown($text); ```

Text::MultiMarkdownを拡張していく。

しかし、素のText::MultiMarkdownでは色々と機能が足りておらず、自分で拡張していくのがよい。

例えば、 ``` で囲んだからコードをかけるcode fence blockがあると便利だが、その機能は用意されていない。

そこでText::MultiMarkdown::Extendedというクラスを自作して拡張していくとよい。

```perl package Text::MultiMarkdown::Extended { use strict; use warnings; use utf8; use parent 'Text::MultiMarkdown';

sub _RunBlockGamut {
    my ( $self, $text ) = @_;
    $text = $self->_DoCodeFenceBlocks($text);      # 先に code fence block を処理
    $text = $self->SUPER::_RunBlockGamut($text);
    return $text;
}

sub _DoCodeFenceBlocks {
    my ( $self, $text ) = @_;

    $text =~ s{
    (?:\n|\A)             # 行頭または文書の先頭
    (`{3,})               # $1 = 開始バッククォート(3つ以上)
    ([^\n]*)\n            # $2 = 言語指定(オプション)
    (.*?)                 # $3 = コード本体(非貪欲マッチ)
    \n\1                  # 終了バッククォート(開始と同じ数)
    (?:\n|\Z)             # 行末または文書の終端
}{
    my $fence = $1;
    my $lang = $2;
    my $code = $3;
    my $class_attr = $lang ? " class=\"language-$lang\"" : "";
    my $encoded_code = $self->_EncodeCode($code);
    "\n\n<pre><code$class_attr>$encoded_code\n</code></pre>\n\n";
}egsx;

    return $text;
}

}; ```

これでcode fence blockが使えるようになった。使い方は先ほどと同じようにつかえる。

```perl use Text::MultiMarkdown::Extended;

my $m = Text::MultiMarkdown::Extended->new; my $html = $m->markdown($text); ```

参考文献