TL;DR
@ nuxt/content でmarkdownに前処理したいときどうしたらいいんだろうと思ってたんですけど、ソース読んで無理なことを理解したので、ローカルremarkプラグインで強引にテキストとして前処理するってのをやりました
— ねぎまぐろ (@kume_negitoro) July 11, 2020
はじめに
こんにちは、ねぎまぐろです。
突然ですが最近追加された @nuxt/content かなりイイですよね。表示用のコンポーネントを作っておけば markdown ごとにページを作って表示してくれるのでとっても便利です。ですが多少不満があります。markdownに対してテキスト処理をしたい場面があると思うのですが、残念なことに @nuxt/content ではそういう機能は(見た感じ)付いていません。
どこかに元のファイルを置いておいて、 gulp か何かで処理した後に content/
に吐き出すというのも考えましたが、せっかく Nuxt.js を使っているのに泥臭い感じがあまりよくありません。
remark
しかしながら代わりに remarkプラグイン (とrehypeプラグイン)を使うことができます。remarkというのはmarkdownをastにして処理できるパッケージです。ということはつまり、remarkプラグインとはastに対して何か追加で処理できるパッケージということになります。
ちなみにどんなプラグインがあるのかというと、:emoji:
みたいなテキストをUTF-8の絵文字に置き換えてくれるプラグインなどがあります。これはなかなか便利そうですね。
ですが求めているのは普通のテキスト処理です。そういうのはできないでしょうか?
remarkプラグインを作る
よく考えてみるとremarkプラグインというのは astを受け取ってastを返す 関数です。それさえ満たしていればちゃんと実行してくれるはずなので、astを一度テキストに変換してしまえばテキスト処理ができますよね。
自分でプラグインを作れないでしょうか。答えはイエスです。 @nuxt/content ではローカルのプラグインも指定できるようになっています。
早速取り掛かってみましょう!
依存パッケージ
markdownのastをmarkdown文字列に変換したり、その逆をするためにはremarkをインストールします。
$ yarn add -D remark
本体を作る
インストールできたらプラグイン用のファイルを作ります。
const remark = require('remark')()
const process = (text) => {
return text.replace(/きのこ/g, 'たけのこ')
}
module.exports = () => (tree) => remark.parse(process(remark.stringify(tree)))
特に難しいことはしていません。remark.stringify
はastをmarkdown文字列に変換する関数です。それに自前のprocess関数を適用して、最後にremark.parse
でastに戻して返却する関数をexportしています。
一応、astを受け取ってastを返すというremarkプラグインの条件は満たしていますね。
markdownをastにして、そこからまたmarkdownにしたりastにしたりしているので非常に無駄な感じがしますが、この際あまり気にしないことにします。
nuxt.config.js の設定
あとはこれをプラグインとして設定してあげれば良いですね。こんな感じで記述します。
{
content: {
markdown: {
remarkPlugins: ['~/remarkPlugins/myPlugin.js'],
},
},
}
このあたりの設定は公式のドキュメントに載っているので、一度見ておくと良いかと思います。
確認してみる
ではちゃんと動くか確認してみます。次のmarkdownを表示させてみましょう(@nuxt/content でのmarkdownの表示方法については別の記事にお譲りします)。
---
title: アンケート
---
# あなたはどちら派ですか?
私はどちらかというときのこが好きです。あなたはどちらが好きですか?
1. きのこ
2. たけのこ
なるほど、あなたはきのこ派ですね!
無事成功しました!
終わりに
今回は @nuxt/content で markdown テキストに前処理をする方法を試してみました。実際のところ、これより良い方法があるかもしれませんので参考までに、ということでよろしくお願いします...。 もし良い方法があったら教えてもらえると嬉しいです。