Perlで良い感じに使えるMarkdownをパースする方法とライブラリについて
この記事では、Perlでマークダウンをパースする方法について解説していく。
PerlではMarkdownをパースするのに良い感じのライブラリがいくつかある。
Text::Markdown::Discount
はDiscount
というC言語実装のMarkdown parserがもとになったC拡張ライブラリ。
一方で、Text::MultiMarkdown
はpure perl実装になっている。
C拡張ライブラリだとWindowsで上手くビルドできない場合が多々あるので、今回はpure perl実装である
Text::MultiMarkdown
を使っていく。
Text::MultiMarkdownの使い方
まずはライブラリをインストールする。(cpmを使う)
cpm install Text::MultiMarkdown
そしてコードを書いていく。使い方はいたってシンプルでよい。
use v5.38;
use Text::MultiMarkdown;
my $text = <<TEXT;
# こんにちは
これがマークダウンです。
- たろう
- はなこ
- さとし
TEXT
my $m = Text::MultiMarkdown->new;
my $html = $m->markdown($text);
Text::MultiMarkdownを拡張していく。
しかし、素のText::MultiMarkdown
では色々と機能が足りておらず、自分で拡張していくのがよい。
例えば、 ``` で囲んだからコードをかけるcode fence blockがあると便利だが、その機能は用意されていない。
そこでText::MultiMarkdown::Extended
というクラスを自作して拡張していくとよい。
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が使えるようになった。使い方は先ほどと同じようにつかえる。
use Text::MultiMarkdown::Extended;
my $m = Text::MultiMarkdown::Extended->new;
my $html = $m->markdown($text);