記事

Last Modified:

コードハイライトに対応しました #CMS #Perl #JavaScript

とりあえずhighlight.js入れた。

対応は超簡単で、まずMarkdown→HTML変換で使ってるText::Markdownを

```言語
コード
```

なFENCED CODE BLOCKSに対応させるために、これを

<pre><code class="言語">
コード
</code></pre>

のようなHTMLに置き換えるプラグインlib/Template/Plugin/Markdown.pmを書いた。

package Template::Plugin::Markdown v0.0.0;
use v5.18.2;
use warnings;
use utf8;
use re 0.18 '/amsx';

use parent qw(Template::Plugin::Filter);
use HTML::Entities qw(encode_entities);
use Text::MultiMarkdown;

sub init {
    my $self = shift;
    $self->{_DYNAMIC} = 1;
    $self->install_filter( $self->{_ARGS}->[0] // 'markdown' );
    return $self;
}

sub filter {
    my ( $self, $text, $args, $config ) = @_;
    $text =~ s{
        \A (\N+)    # first line
    }{
        $_ = $1;
        s{ \h+ [#] ([[:alpha:]]+) }{<span class="hashtag">$1</span>}gr;
    }e;

    # support for fenced code block
    $text =~ s{
        # open line
        ^
        (?<indent>\h*)
        (?<backquote>`{3,})
        (\N*)   # language
        \R

        # code
        \g{indent}  # to remove first indent
        (.*?)
        \R

        # close line
        ^
        \g{indent}  # to remove last indent
        \g{backquote}
        $
    }{
        my ( $indent, $language, $code ) = ( $1, $3, $4 );
        $code = encode_entities($code);
        if ($indent) {
            $code =~ s/^\h*\K$/\0/g;    # bugfix of Text::Markdown
        }
        $language ||= 'nohighlight';
        qq{$indent<pre><code class="$language hljs">$code</code></pre>};
    }eg;
    $text =~ s/([*]+)/\0$1/g;    # to mislead that there is word boundary in japanese
    return Text::MultiMarkdown->new->markdown($text) =~ s/\0//gr;
}

1;

HTMLテンプレート側はこんな感じ。

<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.8.0/styles/github.min.css" />
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.8.0/highlight.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.8.0/languages/lisp.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.8.0/languages/less.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>

cdnjsを使う場合は、同梱されていない言語を追加で読み込む必要があります。

その他のライブラリ

SyntaxHighlighter
人気らしいんだけどcdnjsに無くて導入が面倒だったのでやめた
google-code-prettify
cdnjsにはあるけど、昔使っててなんか微妙だった記憶があるので避けた
JSHighlighter
めんどくさくなって試してすらいない