1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

マークダウン記法をcakephp3で表示する

Last updated at Posted at 2020-10-23

マークダウン記法をcakephp3で表示する

パーサ

何種類か試した結果、比較的レンダリングが早いParsedownにしました。

composer require erusev/parsedown
composer require erusev/parsedown-extra

ParsedownMarkdown Extra 両方インストールします。

色々な図が書けるmermaid.js と シンタックスハイライトに

Google Code Prettifyを使いたいので

ParsedownExtraの拡張クラスを作ります。

<code>のクラスがlanguage-mermaidの時はmermaidに

それ以外のときは<pre>のクラスをprettyprintにします。

<?php
class ParsedownExtraPlus extends ParsedownExtra
{

    # config

    public $blockCodeClassFormat = 'language-%s';
    public $blockPreClassHighlight = 'prettyprint';

    const version = '0.0.0-beta-1';

    public function __construct()
    {
        if (version_compare(parent::version, '0.8.1') < 0) {
            throw new Exception('ParsedownExtraPlugin requires a later version of Parsedown');
        }
        parent::__construct();
    }

    protected function blockFencedCode($Line)
    {
        $Block = parent::blockFencedCode($Line);

        if (isset($Block['element']['name']) && $Block['element']['name'] == 'pre' && isset($Block['element']['text']['name']) && $Block['element']['text']['name'] == 'code') {
            if (isset($Block['element']['text']['attributes']['class'])) {
                if (strpos($Block['element']['text']['attributes']['class'], 'mermaid') === false) {
                    $Block['element']['attributes']['class'] = $this->blockPreClassHighlight;
                } else {
                    $Block['element']['text']['attributes']['class'] = str_replace(sprintf($this->blockCodeClassFormat, 'mermaid'), 'mermaid', $Block['element']['text']['attributes']['class']);
                }
            }
        }
        return $Block;
    }
}

この拡張クラスをvendorに適当にフォルダーを作ってcomposer.jsonのautoloadを書き加えます。ここを参考にして

下さい。

はい、パッケージを作りました。下記でインストールできます。

composer require adjmpwgt/parsedown-extra-plus

ヘルパーを作ります。

bin/cake bake helper Markdown

src/View/Helper/MarkdownHelper.phpが出来ます。

下記のuseを追加します。

use Parsedown;
use ParsedownExtra;
use ParsedownExtraPlus;

ファンクションを追加します。

    public function transform($text)
    {
        if (!is_string($text)) {
            return;
        }

        $parser = new ParsedownExtraPlus();
        // $perser->blockPreClassHighlight = 'highlight';
        return $parser->text($text);
    }

Viewに記述

  スタイルシートはgithub由来のものにする。

// github markdown
$this->Html->css('//cdnjs.cloudflare.com/ajax/libs/github-markdown-css/4.0.0/github-markdown.min.css', ['block' => true]);

様々な図が表現出来るマーメイドを導入

// mermaid
$this->Html->script('//cdnjs.cloudflare.com/ajax/libs/mermaid/8.8.1/mermaid.min.js', ['block' => true]);
$this->Html->scriptBlock('mermaid.initialize({startOnLoad:true});', ['block' => true]);

syntax highlightの設定

Google Code Prettify を使う場合

下記をview.ctpの先頭に追加して下さい。

// prettify <pre class="prettyprint">
$this->Html->script('//cdn.jsdelivr.net/gh/google/code-prettify@master/loader/run_prettify.js', ['block' => true]);

highlight.js を使う場合

下記をヘルパーに追加。

$perser->blockPreClassHighlight = 'highlight';

下記をview.ctpの先頭に追加。

// highlight <pre class="highlight">
$this->Html->css('//cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.2.1/build/styles/default.min.css', ['block' => true]);
$this->Html->script('//cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.2.1/build/highlight.min.js', ['block' => true]);
$this->Html->scriptStart(['block' => true]);
echo <<<EOD
document.addEventListener('DOMContentLoaded', (event) => {
  document.querySelectorAll('pre.highlight code').forEach((block) => {
    hljs.highlightBlock(block);
  });
});
EOD;
$this->Html->scriptEnd();

mermaid.js と highlight.js を同時に使う場合はmermaid.jsのブロックはhighlight.jsが動作しないように細工をしないといけません。MarkdownHelperに以下の行を足すか、

ヘルパーの*$blockPreClassHighlight*を変更しない場合は以下のようにpreタグのクラスをprettyprintにして下さい。

document.querySelectorAll('pre.prettyprint code').forEach((block) =>

mermaid.jsを使わない場合は下記でよい。

// highlight <pre class="highlight">
$this->Html->css('//cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.2.1/build/styles/default.min.css', ['block' => true]);
$this->Html->script('//cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.2.1/build/highlight.min.js', ['block' => true]);
$this->Html->scriptBlock('hljs.initHighlightingOnLoad();', ['block' => true]);

実際のマークダウンの出力は

  <div class="forumcontent">
    <div class="markdown-body markdown">
      <?= $this->Markdown->transform($forum->description); ?>
    </div>
  </div>

参考ページ

CakePHP 4 で Parsedown を使い Markdown をパースして HTML に変換する方法

erusev/Parsedownのcode部分のみ簡易拡張

@tomgoodsunさんの
MarkdownをHTML上に表示するにはどうしたらいいか

見出しのアンカーリンクが作られていないので、作ってみました。
Parsedownを書き換える

を参考にさせて貰いました。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?