こんにちは!
株式会社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と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-<パッケージ名>', ] },
いくつかの拡張パッケージを紹介します。
脚注
ブログなどで使う脚注を使用することが出来ます。
使用する際は脚注を指定したい箇所に[^n]
を記述し
脚注として表示したい内容は[^n]:
を先頭に付けます。
sample_footnote.md
これは脚注[^1]のテストです [^1]:これは1つ目の脚注の内容です
導入方法は以下となります。
yarn add markdown-it-footnote
nuxt.config.js
markdownit: { use: [ 'markdown-it-footnote', ] },
ハイライト
指定箇所が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では、エンジニア、デザイナーの募集をしております。
興味のある方は、是非下記からご応募お願い致します!