2019-11-28

Nuxt.js に MarkDown を読み込む

Blog Nuxt化
Nuxt.js
Markdown

ブログをHexoからNuxt.jsに移行するに当たり、過去記事のMarkdownファイルは捨てたくありません。
.vueへのコンバートも面倒です。

なので、引き続き記事はMarkdownで書きつつ、Nuxt.jsで Vue テンプレートにロードする方式にします。
Nuxt のジェネレート時にMarkdownファイルを取り込む方式です。

frontmatter 対応で記事に属性をもたせたい

frontmatterとは、md ファイルの先頭に yaml 形式で記事に属性を持たせる方法です。

---  
title: Nuxt.js に MarkDown を読み込む  
tags: [Blog Nuxt化, Nuxt.js, Markdown]  
date: 2019-11-28  
parent: nuxt-blog-index  
---  

ブログを`Hexo`から`Nuxt.js`に移行するに当たり、過去記事の`Markdown`ファイルは捨てたくありません。  
`.vue`へのコンバートも面倒です。...  

↑ md ファイルの頭に --- で囲まれた部分が記事属性になります。
この記事にはtitletagsdateparentの属性が設定されています。

これをvueに読み込ませたい!

nuxt.config.js で md ファイルのロードに対応する

.mdファイルのローダーを設定して、JavaScriptで扱いやすくします。
frontmatterを扱えるローダーがnpmパッケージに公開されていたので、ありがたく利用させていただきます。
frontmatter-markdown-loader

ライブラリのインストール

yarn add -D frontmatter-markdown-loader  

nuxt.config.js に登録する

.mdファイルのローダーとしてfrontmatter-markdown-loaderを登録します。
これで.mdファイルをimportするとJavaScriptオブジェクトになります。
ソースコードのハイライト表示もしたいので、highlight.jsとも連携しています。

import hljs from 'highlight.js'  
export default {  
  build: {  
    extend(config, _ctx) {  
      config.module.rules.push({  
        test: /\.md$/,  
        loader: 'frontmatter-markdown-loader',  
        options: {  
          markdownIt: {  
            html: true,  
            linkify: true,  
            breaks: true,  

            // ソースハイライトするためにhighlight.jsと連携  
            highlight(str, lang) {  
              if (lang && hljs.getLanguage(lang)) {  
                try {  
                  return hljs.highlight(lang, str).value  
                } catch (e) {  
                  console.error(e)  
                }  
              }  

              return '' // use external default escaping  
            }  
          }  
        }  
      })  
    }  
  }  
}  

md ファイルをロードしてみる

test.mdを作成して読み込ませてみる。

md ファイルの作成

---  
title: テストタイトル  
tags: [tag1, tag2, tag3]  
date: 2019-11-28  
---  

# 本文タイトル  

本文のテスト1  
本文のテスト2  

md ファイルのロード

import md from './test.md'  
console.log(JSON.stringify(md))  

ログにこんなのが出る。

{"attributes":{"title":"テストタイトル","tags":["tag1","tag2","tag3"],"date":"2019-11-28T00:00:00.000Z"},"html":"<h1>本文タイトル</h1>\n<p>本文のテスト1<br>\n本文のテスト2</p>\n"}  

おお、できてる!

見やすく整形したのがこちら。

{  
  "attributes": {  
    "title": "テストタイトル",  
    "tags": ["tag1", "tag2", "tag3"],  
    "date": "2019-11-28T00:00:00.000Z"  
  },  
  "html": "<h1>本文タイトル</h1>\n<p>本文のテスト1<br>\n本文のテスト2</p>\n"  
}  

vue ファイルに流し込む

結果の JSON を見るに、

  • attributes属性にfrontmatterで記述された属性
  • html属性にHTML形式に変換された本文

が登録されているようです。

HTML形式になっているので、このまま流し込めばいいですね。

<template lang="pug">  
.posts-contents  
  .title.is-1 {{md.attributes.title}}  
  .markdown-body(v-html="md.html")  
</template>  
<script>  
  import md from './test.md'  
  export default {  
    data() {  
      return {  
        md  
      }  
    }  
  }  
</script>  

ウルトラ上手にできましたー!!
これを応用すればタグや日付表示などにも使えそうです!

frontmatter の記述について補足

hexoのときにできていたfrontmatter記法が、frontmatter-markdown-loaderでは読めないパターンが有りました。

hexoのときに書いていた記法、いわゆるハッシュの中に配列を書く書き方です。

tags:  
  - tag1  
  - tag2  
  - tag3  

これがfrontmatter-markdown-loaderでは読めなかったので、下記のように対応しました。

tags: [tag1, tag2, tag3]  

ここだけほぼ全ファイルに修正が入りましたが、重要な本文はノーメンテで持っていけたので良かったです!


猫派 / 基本インドア / ガジェット大好き / RDP推進派
コロナ禍の趣味はPC+VRでゲーム。
最近のゲーム:Factorio / BeatSaber / にゃんこ大戦争

→ Policy