markdown-itの導入方法

こんにちは!
株式会社SCOUTER開発部フロントエンドエンジニアの佐藤(@r_sato1201)です

先日、業務でCMSでコンテンツを管理するLPをNuxtプロジェクトで作成しました。 その際に、Markdownをhtmlにパースする必要がありmarkdown-itを触ったので、 備忘録も兼ねてNuxtプロジェクトを使用する際のmarkdown-itについて書きたいと思います。

導入方法

@nuxtjs/markdownitのインストール

まずは、markdown-itのnpmパッケージをインストールします。

yarn add @nuxtjs/markdownit

nuxt.config.jsにmarkdownitの設定を記述

nuxt.config.jsにnuxtjs/markdownitのモジュール読み込みと主なオプションを記述します。 ※各オプションデフォルト値です

nuxt.config.js

modules: [
    '@nuxtjs/markdownit'
  ],
markdownit: {
    preset: 'default'
    injected: true, 
    breaks: true, 
    html: true, 
    linkify: true,
    typography: true, 
    xhtmlOut: true,
    langPrefix: 'language-',
    quotes: '“”‘’',
    highlight: function (/*str, lang*/) { return ''; },
  },

各オプションを説明します。

オプション名 説明
preset パースするファイルの規格(Markdown/CommonMark)を指定します (※詳細は後で記述します)
injected $mdを利用してMarkdownをhtmlにパースする
breaks Markdown内の改行コードを<br>に変換する
html HTMLタグを有効にする
linkify URLに似たテキストをリンクに自動変換する
typography 言語に依存していない引用符などを綺麗にする
xhtmlOut 単一のタグを閉じるには 「/」を使用する
langPrefix コードブロックのCSSクラス名の接頭辞に付加します。
quotes typographyが有効になっていて'"を同時に使用している際に自動で識別し変換してくれます。
highlight 第1引数で指定したタグ名に対して、第2引数で指定した言語名のシンタックスハイライトを行う処理を指定できます。返り値にシンタックスハイライト後の内容を返すよう指定できます。

CommonMarkとMarkdownについて

CommonMarkとはMarkdownで曖昧になっている細部の構文仕様を明確化したものです。 (CommonMarkについて詳しく知りたい方は以下を参照して下さい)

commonmark.org

CommonMarkとMarkdownでは細かい仕様の差異があります。 例えば、リストの見出しです。 Markdownでは、見出しを以下のように記述することが出来ます。

# Heading

CommonMarkでは、これはリスト内の見出しとして解釈されてしまうため、エスケープする必要があります。

\# Heading

このような差異があるため、前述したpresetで規格を指定することにより 適切にhtmlにパースすることが出来ます。

利用方法

$md を使ってパースする場合

オプションのinjected:trueに設定すると、$mdという変数が使えます。 sample.vue

<template>
  <div v-html="$md.render(model)"></div>
</template>

<script>
export default {
  data() {
    return {
      model: '# Hello World!'
    }
  }
}
</script>

CMSからMarkdown形式のデータが渡ってきている場合は $md.render(model) 上記のrenderの引数に、Markdown形式のデータを渡すことでパースされHTMLにレンダリングされます。

.mdファイルを使ってパースする場合

どこかのディレクトリに格納されているMarkdownファイルをimportしcomputedで返し、v-htmlでレンダリングすることで表示できます。
sample.md

# Hello World!!

sample.vue

<template>
  <div v-html="sample"></div>
</template>

<script>
  import sample from '../sample.md'

  export default {
    computed: {
      sample() {
        return sample
      }
    }
  }
</script>

パースしたhtmlにスタイルを当てる際の注意点

v-html によって作成された DOM コンテンツはの子要素には、data 属性がつかなく、 <style scoped>とスコープをつけCSSの影響範囲をコンポーネント内に収めている場合 data属性がついていない要素にはCSSが当たりません。
つまり、markdown-it で$md を使ってパースする場合、通常通りCSSを当ててもうまく効かないので ディープセレクタを使用して当てるようにしましょう。

※ディープセレクタを仕様する際はsass環境が必要となるのでnode-sass および sass-loaderのパッケージをインストールしてください

sample.vue

<template>
    <div class="sample-wrapper">
      <div v-html="$md.render(model)"></div>
    </div>
</template>

<script>
export default {
  data() {
    return {
      model: '# Hello World!'
    }
  }
}
</script>

<style  lang="scss" scoped>
.sample-wrapper /deep/ h1 {
  border-left: solid 2px #6ac5b6;
}
</style>

拡張方法

markdown-itには機能を拡張できるパッケージが複数あります。 まず、yarnなどでパッケージをインストールします。

yarn add markdown-it-<パッケージ名>

nuxt.config.jsのmarkdownitオプションに以下の記述でパッケージを読み込むよう設定することで markdown機能を拡張することができます。

nuxt.config.js

markdownit: {
    use: [
      'markdown-it-<パッケージ名>',
    ]
  },

いくつかの拡張パッケージを紹介します。

脚注

f:id:ryonnsui1201:20190123230953p:plain

ブログなどで使う脚注を使用することが出来ます。 使用する際は脚注を指定したい箇所に[^n]を記述し 脚注として表示したい内容は[^n]:を先頭に付けます。

sample_footnote.md

これは脚注[^1]のテストです

[^1]:これは1つ目の脚注の内容です

導入方法は以下となります。

yarn add markdown-it-footnote

nuxt.config.js

markdownit: {
    use: [
      'markdown-it-footnote',
    ]
  },

ハイライト

f:id:ryonnsui1201:20190123231001p:plain

指定箇所がmark要素で囲まれ、ハイライト表示をすることができます。 使用する際は適用させたい箇所の前後に==を記述します。 デフォルの背景色は黄色ですが、mark要素にcssを当てることで自由なスタイルで表示させることが出来ます。

sample_highlight.md

==ハイライト表示==のテストです

導入方法は以下となります。

yarn add markdown-it-mark

nuxt.config.js

markdownit: {
    use: [
      'markdown-it-mark',
    ]
  },

Youtube埋め込み

YouTubeの埋め込みをすることができます。 使用する際は以下のサンプルのように、[]内にyoutubeを指定し()内に表示させたい動画のIDを指定します。 動画のIDではなく、動画のURLでも可能です。
sample_video.md

[youtube](movie id)

導入方法は以下となります。

yarn add markdown-it-video

nuxt.config.js

markdownit: {
    use: [
      'markdown-it-video',
    ]
  },

さいごに

私のような経験が浅いエンジニアの方の力に少しでもなることができればと思い書きました。

現在、株式会社SCOUTERでは、エンジニア、デザイナーの募集をしております。

興味のある方は、是非下記からご応募お願い致します!

www.wantedly.com

www.wantedly.com

www.wantedly.com