今回達成すること
ブログのマークダウン記法に対応するため、Nuxtに@nuxtjs/markdownit
を導入します。
作業に入る前にブランチを切っておきます。
% git checkout -b 20220219_add_blog_function_module
@nuxtjs/markdownitとは
@nuxtjs/markdownit
とは、マークダウンをHTMLに変換するmarkdown-itを、Nuxt上で扱えるようにしたモジュールです。
markdown-it
はマークダウン記法で書かれたテキストをHTMLにマークアップするモジュールです。
@nuxtjs/markdownitのインストールとセットアップ
それではインストールを行いましょう。
% yarn add @nuxtjs/markdownit
# インストール確認
% yarn list --pattern @nuxtjs/markdownit
├─ @nuxtjs/markdownit-loader@1.2.0
└─ @nuxtjs/markdownit@2.0.0
セットアップを行う
@nuxtjs/markdownit
のセットアップを行います。
nuxt.config.js
export default {
...
modules: [
...
// 追加
// https://www.npmjs.com/package/@nuxtjs/markdownit
'@nuxtjs/markdownit'
],
...
// 追加
// Doc: https://github.com/markdown-it/markdown-it
markdownit: {
/*
preset: markdownのルールの決定
commonmark: コモンマークモードに設定
default: 利用可能なすべてのルールが有効になる(html, typographer, autolinkerは含まれない)
zero: すべてのルールを無効(太字と斜体のマークアップだけが必要で、他は何も必要ない場合などに使用)
Doc: https://markdown-it.github.io/markdown-it/#MarkdownIt.new
*/
preset: 'default',
// ソース内のHTMLタグを有効にする
html: true,
// 段落の\nを<br>に変換する
breaks: true,
// URLのようなテキストをリンクに変換する
linkify: false,
/*
Nuxt上で$mdを使用できるようにする
runtime: https://github.com/nuxt-community/markdownit-module#using-md-to-render-markdown
*/
runtime: true,
/*
add plugins
use: https://markdown-it.github.io/markdown-it/#MarkdownIt.use
*/
use: []
},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
}
}
runtimeプロパティ
runtime
プロパティにtrue
を渡すことで、Vueファイルやtsファイルで$md
が使用できるようになります。
$md
はmarkdown-it
のクラスインスタンスを呼び出すことができます。
render()
を使用することでマークダウンテキストをHTMLにマークアップすることができます。
<div
v-html="$md.render('# hello')"
/>
オプションのデフォルト値
markdown-it
の各プロパティのデフォルト値は以下のようになります。
var md = require('markdown-it')({
html: false, // Enable HTML tags in source
xhtmlOut: false, // Use '/' to close single tags (<br />).
// This is only for full CommonMark compatibility.
breaks: false, // Convert '\n' in paragraphs into <br>
langPrefix: 'language-', // CSS language prefix for fenced blocks. Can be
// useful for external highlighters.
linkify: false, // Autoconvert URL-like text to links
typographer: false,
quotes: '“”‘’',
highlight: function (/*str, lang*/) { return ''; }
});
型定義ファイルをインストールする
matkdown-it
の型定義ファイルは別に用意されています。
devDependencies
にインストールするので--dev
オプションを付けてインストールします。
% yarn add --dev @types/markdown-it
型定義ファイルの登録
型定義ファイルを
tsconfig.json
{
...
"types": [
...
// 追加
"@types/markdown-it"
]
},
...
}
Nuxtインスタンスに$mdを登録する
$md
は、Nuxtのデフォルトの型定義では用意されていないので、NuxtコンテキストとVueインスタンスに型登録を行います。
types/module.d.ts
// 一番上に追加
import MarkdownIt from 'markdown-it'
declare module 'vue/types/vue' {
// Vueインスタンス(this)の型追加
interface Vue {
...
// 追加
// @nuxtjs/markdownit
$md: MarkdownIt
}
}
declare module '@nuxt/types' {
// Nuxt Contextへの型追加
interface Context {
...
// 追加
// @nuxtjs/markdownit
$md: MarkdownIt
}
...
}
これで$md
とthis.$md
を呼び出してもタイプエラーが発生し無くなりました。
// OK
asyncData ({ $md }: Context) {
console.log($md)
}
// OK
console.log(this.$md)
以上で@nuxtjs/markdownit
のセットアップは完了です。
Markdown記事をContentfulに投稿する
ここまでの実装の確認を行うため、Markdownを使用した記事をContentfulに投稿します。
markdown-it
のデモページから、マークダウンテキストをコピーします。
Contentfulに新しいブログ記事を作成しましょう。
コピーしたテキストをのブログモデルの「body」に貼り付けます。
Contentfulへの記事投稿方法を忘れた方はこちらをご覧ください。
この記事は今後のスタイリングの参考にするので下書きのままでOKです。
Nuxtに記事の内容を表示する
ブログ記事のコンテンツページにbody
を追加します。
pages/posts/_category/_slug.vue
<template>
<div>
Post title: {{ post.fields.title }}
<!-- 追加 -->
<div>
{{ post.fields.body }}
</div>
</div>
</template>
作成した記事をブラウザで表示してみましょう。
テキストベースのbody
が表示されます。
markdown-itでマークアップする
Markdownテキストをマークアップするには$md.render()
を使用します。
pages/posts/_category/_slug.vue
<template>
<div>
Post title: {{ post.fields.title }}
<div>
<!-- 追加 -->
<div
v-html="$md.render(post.fields.body)"
/>
<!-- 削除 -->
<!-- {{ post.fields.body }} -->
</div>
</div>
</template>
v-htmlのESLint警告を非表示にする
v-html
を使用すると、XSS攻撃のきっかけになるのでESLintの警告が出ます。
terminal
WARNING in pages/posts/_category/_slug.vue
vue/no-v-html: 'v-html' directive can lead to XSS attack.
v-html
に渡す値が信頼できる値の場合、この警告は無視して構いません。
ESLintの警告を非表示にする設定を行います。
pages/posts/_category/_slug.vue
<template>
<div>
Post title: {{ post.fields.title }}
<div>
<!-- eslint-disable vue/no-v-html -->
<div
v-html="$md.render(post.fields.body)"
/>
</div>
</div>
</template>
-
eslint-disable <ルール名>
... そのファイルの特定のルールの警告を無効にする。参考: Rules - ESLint
マークアップをブラウザで確認しよう
先程のテキストデータがマークアップされていますね。
ちなみに画像の大きさなどはCSSで調整する必要があります。
今回の作業は以上です。
% git commit -am "Add @nuxtjs/markdownit module"
まとめと次回
今回はマークダウン記法に対応するために、Nuxtに@nuxtjs/markdownit
を導入しました。
markdownit
のデフォルトの挙動は、外部リンクを新規タブで開きません。
そこで次回は内部リンクを同じタブで、外部リンクを新規タブで開く実装を行います。