TL;DR
Markdownを書くフォルダを作成して、それを変換、Nuxtへの組み込みについて
Markdownの変換機構
はじめに
processmd というライブラリを使用しますが、markdown-itに今後できればと思っていたりします
他にもremark 等がありますが、Reactやその静的サイトジェネレータであるgatsbyがremarkに対応していて、nuxtやvuepressはmarkdown-itの方っぽいのでmarkdown-itにしようかなという感じです
変更したら追記しますが、今回はprocessmdを使用します。
追記
変更しました!
Nuxt.jsとFirebaseでサイトを作った話 続編-1- markdown変換の見直し
フォルダツリー
コードの構造がややこしくなるので、先にフォルダツリーを紹介します。
├── note
| ├── draft
| | └── nuxt-firebase-blog.md
| ├── json
| | └── 2018-04-13-generate-stylelint-report-by-rule.json
| ├── markdown
| | └── 2018-04-13-generate-stylelint-report-by-rule.md
| └── summary.json
プロジェクトルートに note
というフォルダを作成してそこで書いています。
一発でかけないものは draft
に書き溜めていって、公開する時に日付を添えてmarkdownフォルダに入れて公開します。
mdの中にプロパティみたいなものを書けるのでmarkdownの中で公開用のステータスを保持するのも有りだと思います。
実際に変換する
フォルダーツリーを踏まえた上で変換タスクの作成です。
"convertmd": "processmd \"note/markdown/**/*.md\" --preview 160 --stdout --outputDir note/json > note/summary.json"
jsonフォルダに一つ一つのmarkdownの変換されたjsonデータ、
summary.json に全体の概要データが出力されます。
また、 --preview
のオプションで一覧表示用の短い文章抽出を行っています。
そしてこの機能がたまに上手くいっていません(空白文字が出てきたりする)
一旦はこれでスタートは切れているものの、結構多くの無駄なデータが含まれるのでいい感じに変換できる何かが欲しいかもしれませんね。
vuepressとかのコード読んでどういうことやってるか見るのもいいかもしれません。
一覧/記事ページを作る
記事ページの作成
pages/note/_date/_slug/index.vue
を作成します。
template:
<div class="post" v-html="bodyHtml"></div>
scripts:
import { sourceFileArray } from '../../../../note/summary.json';
export default {
data: function () {
return {
tag: null
}
},
validate({ params }) {
return sourceFileArray.includes(`note/markdown/${params.date}-${params.slug}.md`);
},
asyncData({ params }) {
return Object.assign({}, require(`~/note/json/${params.date}-${params.slug}.json`), { params });
},
head() {
const url = `${this.url}/note/${this.params.date}/${this.params.slug}/`;
},
};
見た目等は変換後のhtmlを見つつ調整します。
一覧ページの作成
pages/note/index.vue
を作成して
一覧ページも似たような感じでsummary.jsonからデータを取得して記事の簡易情報表の示と記事に対するリンクを設定します。
この問題として記事数が数百とかになっても恐らく全データの概要のデータを取得してしまうという点です。
テキストなのでサイズ的には大したことはないとはいえども延々と膨れ上がるデータになってしまうため、
こちらも思いつきでいえば同じプロジェクトで開発しているのでsummaryのデータを読み取って一部を返すAPIを作ってもよいかもしれません。
ただそういうことばっかりやっていると nuxt generate
でやっている意味がなさげ…にも思えなくもないですね。
generateタスクの編集
nuxtのgenerateはデフォルトでは _date
_slug
という動的な部分については nuxt generate
しても生成されません。
なので手動でこれらのパスを教えて生成するようにしなければいけないのでnuxt.config.jsを編集します。
最終形はこんな感じです
generate: {
...
routes: generateDynamicRoutes,
},
この関数の実装はこんな感じです。
const { sourceFileArray } = require('./note/summary.json')
const generateDynamicRoutes = callback => {
const routes = sourceFileArray.map(sourceFileName => {
return sourceFileNameToUrl(sourceFileName);
});
callback(null, routes);
};
sourceFileNameToUrl
はこんな感じです(雑コード…)
sourceFileNameToUrl(filepath) {
const deleteExt = filepath.replace('.md', '')
const fileName = deleteExt.split('/')[deleteExt.split('/').length - 1]
const splitArray = fileName.split('-')
return `/note/${splitArray.slice(0, 3).join('-')}/${splitArray.slice(3,).join('-')}`
}
こうすることで動的で無視される部分を手動で登録できるので、
これによってそのURLはgenerate時にもHTMLが生成されるようになります。
おわりに
ちょっとまだ課題が多い記事詳細、記事一覧部分ですが、一旦は上記のような感じで作れると思います。
目次
このサイト作ったぞシリーズです。