MarkedとMermaidを連携ができずうがー！ってなって微調整した

## MerkedとMermaidを連携させたのにうまく行かなくなった！

自分のツールとして作っているコードの中で、MarkedとMermaidの連携について、mermaid.jsの見本である[mermaidjs.github.io - Usage](https://mermaidjs.github.io/usage.html)のExample of a marked rendererをそのまま使っていた。  
しかし、最近なぜかうまく表示されなくなった。原因は、この記事執筆時点でも未だにわからず。

## コードの紹介
Usageにかかれていたコードは以下のとおり。  
要するに、markdownの \`\`\` に当たる部分でmermaidの構文を書いた場合に、mermaidが適用できる（&lt;div class="mermaid"&gt;に記述した構文をmermaidがsvg画像化してくれる）ようにmarkedがDIVタグを加えるようHTML変換する仕組みを取るという、ごく単純な方法だ。

``` javascript
var renderer = new marked.Renderer();
renderer.code = function (code, language) {
    // mermaidはcode部分の冒頭がこの２つの文言になるので、それで判断している
    if(code.match(/^sequenceDiagram/)||code.match(/^graph/)){
        // divタグを加えて上げると、mermaidが認識してくれるのだ！
        return '<div class="mermaid">'+code+'</div>';
    }
    else{
        return '<pre><code>'+code+'</code></pre>';
    }
};
```

HTMLツール全体としては、以下のソースにしていた。これに、mermaidの構文を含むmdファイルを読み込ませることで、mermaidを図化する方式をとっていた。

```html
<!DOCTYPE html>
<html lang="jp">
  <head>
    <meta charset="utf-8">
    <title>MARKUP</title>
    <link rel="stylesheet" href="./styles/default.css" />
    <script src="./lib/jquery-3.3.1.js"></script>
    <script src="./lib/marked.min.js"></script>
    <script src="./lib/mermaid.min.js"></script>
    <script src="./lib/highlight.pack.js"></script>
  </head>
  <body>
    <div id="content"></div>
    <script>
      var renderer = new marked.Renderer();
      renderer.code = function (code, language) {
        if(code.match(/^sequenceDiagram/)||code.match(/^graph/)||code.match(/^gantt/)){
           return '<div class="mermaid">'+code+'</div>';
        }else{
           return '<pre><code>' + hljs.highlightAuto(code).value + '</code></pre>';
        }
      };
      $(document).ready(function(){
        if (location.href.split("#").length > 1){
          var urlParam = location.href.split("#")[1];
          $.get( urlParam, function( data ) {
          // console.log(data);
          $('#content').html(marked(data, { renderer: renderer })); });
        }else{
          $('#content').html('please url#any.md');
        }
      });

      </script>
  </body>
</html>
```

これでうまく動いていた、少し前までは。  
それが、最近いつの間にか動かなくなり、marmaid構文のまま表示されるようになってしまった。
パソコンを変えたタイミングだったので、内部的に何かしらの設定が変わってしまったのかもしれないが…根本的な原因はわからない。

さて、それで３，４時間頭を悩ませ続けて、ようやく対処法に気づいた。

> merked がレンダリングする前に、mermaidが動いてしまっているのだろう

mermaidは &lt;div class="mermaid"&gt;&lt;/div&gt;の中に、コードがなければならないことは、先に書いたとおりだ。  
つまり、下の理想の図になるはずだ。

![](https://i.gyazo.com/06c3cae71fb6b2ddcf6fd7aa185583f0.png)

実際には、mermaidがclass="mermaid"がないmarkdownソースのままにレンダリングしてしまって、それからmarkedがmarkdownをHTMLにレンダリングするということが起こったのだと推測した。  
つまり、下の実際の図のとおりに処理が動いた。

![](https://i.gyazo.com/0e936c65212de691fc332f7870264b57.png)

昔は、パソコンのスペックが少し悪かったから、markedとmermaidの処理の順番が逆になって、理想どおりに動いていた…？　考えにくいがそうかもしれない。

## 対処方法を調べよう

ということで、google先生に聞いたところ、素晴らしい講師を紹介していただいた。
[mermaidを非同期で読み込む \- なおしむ論](https://naosim.hatenablog.jp/entry/2018/02/20/071042)

記事を読めば一目瞭然だが、要するに、読み込んだタイミングでmermaidが動くなら、最初から動かさなければいいじゃないという論理。  
至極、当然の話であった。

さて、この方が書いた内容は自分のコードでも適用できるので、真似させてもらった。

## コード修正

ということで、&lt;HEAD&mt;に、mermaidがHTMLをロード時に勝手に動かないようにするコードを入れる。

``` javascript
// デフォルトのtrueだと、HTMLのロード時にレンダリングしてしまうので、falseで停止してあげる
mermaid.initialize({startOnLoad:false})
```

そして、mermaidを動かしたいタイミング、具体的にはmarkedのレンダリングが終わった直後に以下のコードを入れる。

``` javascript
// このコードで自主的にレンダリングしてくれる。
mermaid.init()
```

あっさりと成功した。

元記事の方もおっしゃっているが、驚くほど簡単だった。３，４時間何に悩んでいたんだろう…。

最終的なコードは以下のようになった。
なお、MDファイルの読み込み方は、URLに「mermaid.html#hoge.md」のようにして#で変換したいmdファイルを付ける[MDwiki \- Markdown based wiki done 100% on the client via javascript](http://dynalon.github.io/mdwiki/#!index.md)リスペクトの方式である。

```html

<!DOCTYPE html>
<html lang="jp">
  <head>
    <meta charset="utf-8">
    <title>MARKUP</title>
    <link rel="stylesheet" href="./styles/default.css" />
    <script src="./lib/jquery-3.3.1.js"></script>
    <script src="./lib/marked.min.js"></script>
    <script src="./lib/mermaid.min.js"></script>
    <script src="./lib/highlight.pack.js"></script>
    <!--
    MEMO: レンダリングを読み込み時にしない
    任意のタイミングで行うために、するのだ。
    ref: https://naosim.hatenablog.jp/entry/2018/02/20/071042
    -->
    <script>mermaid.initialize({startOnLoad:false});</script>
  </head>
  <body id="content">
    <script>
      var renderer = new marked.Renderer();
      renderer.code = function (code, language, escaped) {
        if(code.match(/^sequenceDiagram/)||code.match(/^graph/)||code.match(/^gantt/)){
           return '<div class="mermaid">' + code + '\n</div>';
        }else{
           return '<pre><code>\n' + hljs.highlightAuto(code).value + '\n</code></pre>';
        }
      };
      $(document).ready(function(){
        if (location.href.split("#").length > 1){
          var urlParam = location.href.split("#")[1];
          $.get( urlParam, function( data ) {
            // Memo: markedのレンダリング-> marmaid.init()
            // ただし、あらかじめstartOnLoad:falseにしておかないと、
            // markedの前にmermaidが走ってしまって、mermaidで変換されない。
            $('#content').html(marked(data, { renderer: renderer }));
            mermaid.init();
          });
        }else{
          $('#content').html('please url#any.md');
        }
      });
      </script>

  </body>
</html>
```