schedule2020-12-13

remarkでnuxt/contentのマークダウン書式を拡張する

nuxt/contentで作ったサイトに絵文字や数式のプラグインを追加して、マークダウンの書式を拡張します。 nuxt/contentを使っていなくても、remarkのプラグイン選びの参考にはなるかと思います。

Table of Contents

マークダウンのプラグイン

markdown - @nuxt/contet

@nuxt/contentではremarkというプラグインでマークダウンの構文を解析しています。 HTMLへのパースはremark-htmlを使ったりと、マークダウンを拡張するremark-*の豊富なエコシステムがあります。 目的に応じて役割ごとに細かなプラグインを組み合わせて扱うことができる。

yarn または npm でプラグインをインストールしてnuxt.config.jsに追加するだけで利用できます。 下はここで使っている絵文字や数式(KaTeX\KaTeX)のプラグインを追加したところです。 コードを書かなくてよいので管理しやすい。

nuxt.config.js
export default {
  // Content module configuration (https://go.nuxtjs.dev/config-content)
  content: {
    markdown: {
      remarkPlugins: [
        'remark-emoji',
        'remark-math',
        'remark-toc',
        'remark-footnotes',
        'remark-code-titles'
      ],
      rehypePlugins: [
        'rehype-katex'
      ]
    }
  },
}

2つのpuluginがあります。 remarkはMarkdownの構文を解析するプロセッサで、rehypeがHTMLを構築するプロセッサです。 例えば、remark-mathがMarkdownの構造を解析してrehype-katexKaTeX\KaTeXに対応するHTMLに変換している。 remark-emojiのように単体で両方こなすものもある。

remarkについて読み応えのある熱い記事を見つけたので載せておきます。独自のParserの拡張の仕方も載ってます。


以下からremarkの拡張プラグインを紹介していきます。 利用できる公式オススメのプラグインはawesome-remarkにまとまってます。

絵文字

remark-emoji

# インストール
$ yarn add remark-emoji

nuxt.config.jscontent.markdown.remarkPluginsremark-emojiを追加する。 これでパースできるようになっています。

マークダウンの中の対応する文字を絵文字に変換してくれます。

入力
Emojis in this text will be replaced: :dog: :+1:

Toilet Time
:toilet: = 2 Minutes
:toilet: + :iphone: = 5 Minutes
:toilet: + :iphone: + ⁣:signal_strength: = 10 Minutes
:toilet: + :iphone: + :signal_strength: + :battery: = Infinite 

出力結果(引用符で囲ってます)

Emojis in this text will be replaced: :dog: :+1:

Toilet Time
:toilet: = 2 Minutes
:toilet: + :iphone: = 5 Minutes
:toilet: + :iphone: + ⁣:signal_strength: = 10 Minutes
:toilet: + :iphone: + :signal_strength: + :battery: = Infinite

EMOJI CHEAT SHEETの絵文字のコードは使えるはずです。

数式

数式に対応するremarkPluginsremark-mathです。 数式を$$で囲うか、文中の場合は$で囲います。

対応するrehypeにはKaTeX\KaTeXMathJaxがあります。

どちらもLaTeXですが、HTMLの描画方法が少し違います。 個人的には描画速度が早くてKaTeXを選んでます。

# インストール
$ yarn add remark-emoji

nuxt.config.jscontent.markdown.remarkPluginsremark-mathを、rehypePluginsrehype-katexを追加する。 そして、表示のためにKaTeX\KaTeXのスタイルシートも当てます。

export default {
    link: [
      // Add style sheet
      {
        rel: 'stylesheet',
        href: 'https://cdn.jsdelivr.net/npm/katex@0.11.0/dist/katex.min.css'
      },
    ],
  },

  // Content module configuration (https://go.nuxtjs.dev/config-content)
  content: {
    markdown: {
      remarkPlugins: [
        'remark-math'
      ],
      rehypePlugins: [
        'rehype-katex'
      ]
    }
  },
}

マークダウンで数式を書いてみる。

**オイラーの等式**
$$
e^{i\pi}+1= 0
$$
ネイピア数$e$、虚数$i$、円周率$\pi$と有名な定数に$0$と$1$がある全部入りの数式。

**正規分布(ガウス分布)**
$$
f(x) = \frac{1}{\sqrt{2\pi\sigma^2}}\exp{-\frac{(x-\mu)^2}{2\sigma^2}}
$$
平均を$\mu$, 分散を$\sigma^2 \gt 0$とする正規分布とは、確率密度関数が次の形で与えられる確率密度関数。

出力結果

オイラーの等式

eiπ+1=0e^{i\pi}+1= 0

ネイピア数ee、虚数ii、円周率π\piと有名な定数に0011がある全部入りの数式。

正規分布(ガウス分布)

f(x)=12πσ2exp(xμ)22σ2f(x) = \frac{1}{\sqrt{2\pi\sigma^2}}\exp{-\frac{(x-\mu)^2}{2\sigma^2}}

平均をμ\mu, 分散をσ2>0\sigma^2 \gt 0とする正規分布とは、確率密度関数が次の形で与えられる確率密度関数。

備考:@nuxt/content で数式を表示するの記事と同様に、数式が表示されずはまりました。スタイルシートが足りなかったことが原因でした。

見出しの目次を作る

remark-toc

マークダウンの中で目次を出したいところに## Table of Contentsを書くとその位置に目次が出ます。 見出し(#)が自動的に目次になる。

## Table of Contents

この記事のTable of Contentsもこれを利用しています。

改行をHTMLに適用する

マークダウンでは末尾にスペース2個で改行となります(1行間を空けると別のpタグで囲まれる)。 ただ、それを知らないとテキストと表示がずれているように感じます。

マークダウン
This is a
paragraph.
↓
HTML
<p>This is a
paragraph.</p>
<!-- 1行になる -->

remark-breaksはマークダウンの改行をHTMLでも改行してくれます。

マークダウン
This is a
paragraph.
↓
HTML
<p>This is a<br>
paragraph.</p>

マークダウンの原理主義でないなら直感的にわかりやすいと思う。

コードブロックにタイトルをつける

Qiitaなどのブログではコードブロックにファイル名などの補足があります。 あれを実現するためのパーサーがremark-code-titlesです。

# インストール
$ yarn add remark-code-titles
nuxt.config.jsに追加する
export default {content: {
      remarkPlugins: [
        'remark-code-titles'
      ],
    }
  },

コードブロックの先頭に ```拡張子:コードブロックのタイトル と書くとタイトルが <div class="remark-code-title">コードブロックのタイトル</div>と決まったクラスの<div>に囲まれる。 そこにスタイルを当ててタイトルっぽくしてます。

```python:Hello.py
printf(&quot;Hello, World!&quot;);
return 0;
```

▼変換したHTML。

<div data-v-f58a9f50="" class="remark-code-title">hello.c</div>
<!-- ↓コードブロック↓ -->
<div data-v-f58a9f50="" class="nuxt-content-highlight">
  <pre data-v-f58a9f50="" class="line-numbers language-c"><code data-v-f58a9f50=""><span data-v-f58a9f50="" class="token function">printf</span><span data-v-f58a9f50="" class="token punctuation">(</span><span data-v-f58a9f50="" class="token string">"Hello, World!"</span><span data-v-f58a9f50="" class="token punctuation">)</span><span data-v-f58a9f50="" class="token punctuation">;</span>
<span data-v-f58a9f50="" class="token keyword">return</span> <span data-v-f58a9f50="" class="token number">0</span><span data-v-f58a9f50="" class="token punctuation">;</span>
</code></pre>
</div>

▼コードブロックのCSSの例。公開すると位置がずれているけどCSSわからん。

.remark-code-title {
    background: #d9d7e0;
    border-radius: 0px 0px 4px 4px;
    color: #3a3a3a;
    font-size: 0.75rem;
    letter-spacing: 0.075em;
    line-height: 1;
    padding: 0.25rem 0.5rem;
    position: absolute;
    left: 1rem;
    text-align: right;
}

折り畳みを追加する

冗長な説明や長いコードブロックを折り畳むと、文章の流れを良くしつつ補足できる。 そんな折り畳み機能を追加するのがremark-collapseです。

$ yarn add remark-collapse

使い方

&lt;details&gt;&lt;summary&gt;Open tango&lt;/summary&gt;

target content

&lt;/details&gt;

出力結果

target content

脚注を作る

最高!これを探していました!

remark-footnotes1を利用しています。 脚注はマークダウンのコンテンツの下部に作成されます。 文章の途中に脚注の補足を書いても下部に移動する。

2や日本語3など数字以外の文字もいけるが、 対応する脚注は数字が自動で割り振られている。 そのため、自分で数字を合わせなければならない4

文章中の脚注[^1]

[^1]: 脚注の補足

星[^★]や日本語[^日本語]など数字以外の文字もいけるが、
対応する脚注は数字が自動で割り振られている。

[^★]: 星マーク
[^日本語]: 日本語も大丈夫です。

ページの下部(パースしたコンテンツの最後)に脚注が出る。

Footnotes

  1. remark-footnotes: https://github.com/remarkjs/remark-footnotes

  2. 星マーク

  3. 日本語も大丈夫です。

  4. 自動で数字が割り振られる。ここは[^2]と書いている。