Next.js Tutorial で使った path, fs, matter を Node.js のみで試してみた
why
gray-matter と remark の違いが分かってなかったので matter だけ動かしてみたかった
Next React ではなくてまず ES6 だけやった方がいいと言われるので Node でシンプルにやってみた
Next での matter の使用
getStaticProps のためのサンプルに入っていた基礎
path と fs と matter を使って Markdown を取得していた。
lib/posts.js で
import fs from 'fs' import path from 'path' import matter from 'gray-matter'
3 つのライブラリを import して
const postsDirectory = path.join(process.cwd(), 'posts');
path
でルートと読み取る先のディレクトリ名を合わせる。
この場合は ~/posts/ に入っているディレクトリのパスをまず取得する
const fileNames = fs.readdirSync(postsDirectory);
次に fs
, file system の readdirSync
read directory sync でそのディレクトリのパスから中に入っているファイル名を読み取る。これは配列になる。
これが Node org の readdirSync の説明。Dir の D は大文字にならない
const allPostsData = fileNames.map(fileName => { const id = fileName.replace( /\.md$/, ''); const fullPath = path.join(postsDirectory, fileName); const fileContents = fs.readFileSync(fullPath, 'utf8'); const matterResult = matter(fileContents); return { id, ...matterResult.data } })
最後に ファイル名の配列から map してファイル名一つ処理する。
ファイル名から .md を取り除いたものを id とし、
先ほど作った「読み取るディレクトリのパス」に更に map で一つ一つとってくる 「読み取るファイルのパス、ファイル名」を追加して、コンテンツを読み取れる完全なパスにする。
その完全なパスを fs
の readFileSync
read file sync で読み取り、
ついにファイルの中身を手に入れる。
これが readFileSync の Nodejs.org の説明。
そして今度こそ最後の処理として、matter
でファイルの中身を
Converts a string with front-matter, like this: --- title: Hello slug: home --- <h1>Hello world!</h1> Into an object like this:
このメタ空間の下に html テキストがある状態から
{ content: '<h1>Hello world!</h1>', data: { title: 'Hello', slug: 'home' } }
json 形式で
- content の html
- data の title
- data の slug
の形に変換する
return でこのコードでは title と slug だけを返している。
Node.js のみでやってみる
Node.js のみで matter での Markdown の json 変換を試す
import では err が出る
require を使わないといけないのを思い出した
公式サイトを見ると、
const matter = require('gray-matter');
で import 相当をするようだ。
const mdData = `---\ntitle: Front Matter\n---\nThis is content. ` console.log(mdData) const matteredMdData = matter(mdData) console.log(matteredMdData)
Mark Down の データ形式を作って、そのデータと matter を通した後のデータを出力してみると
--- title: Front Matter --- This is content. { content: 'This is content. ', data: { title: 'Front Matter' }, isEmpty: false, excerpt: '' }
このように、ヘッダーデータとコンテンツを分離して json にしているのがわかる。
path と fs で パスとファイル名を読み取る
const path = require('path') const postsDir = path.join(process.cwd(), 'posts') console.log(postsDir)
これを使うと
/Users/kaede/code/node/matter/posts
これが帰ってくる。
これで現在のディレクトリが path によって読み取られており
それに posts を追加できていることがわかる
また fs を使って そのパスから中身を読み取ってみる
const fs = require('fs') const fileNames = fs.readdirSync(postsDir) console.log(fileNames)
これで
[ 'text.md', 'text2.md' ]
が帰ってくる。受け取ったパスのディレクトリの中にあるファイルたちを認識できている。
fs.readFileSyinc と matter で 今の配列を読み取る
const allPostsData = fileNames.map(fileName => { const fullPath = path.join(postsDir, fileName) const fileContents = fs.readFileSync(fullPath, 'utf8') console.log(fileContents) const matterResult = matter(fileContents) console.log(matterResult) })
Next.js Tutorial と同じく、 先ほど得られた fileNames を map して
fs.readFileSync にかけることとで map して一つずつとってきたファイル名で
ファイルの中身を md のまま読み取り
matter をかけることで
{ content: 'hoge' data: { hage: 'hage', date: 'someday' }, isEmpty: false, }
の使いやすい json の形に持ってこれている。
実際の結果は
/Users/kaede/code/node/matter/posts [ 'text.md', 'text2.md' ] --- title: Hello date: '2020-02-03' --- content text here 2nd line 3rd line { content: 'content text here\n2nd line\n3rd line', data: { title: 'Hello', date: '2020-02-03' }, isEmpty: false, excerpt: '' } --- title: Hello date: '2020-02-03' --- text 2 main area here { content: 'text 2 main area here', data: { title: 'Hello', date: '2020-02-03' }, isEmpty: false, excerpt: '' }
こうなった。
まとめ
Next 関係なく、Node 単体でも
path での読み取るディレクトリの指定
fs.readdirSync での中身のファイルたちの認識
認識したファイルたちの配列を map して
path での 先ほど使ったディレクトリのパスへの ファイル名の追加
fs.readFileSync での ファイルの中身の読み取り
matter での ファイルの中身の json 形式への変換
は行うことができた
次回
次回は 似たような Markdown 変換である remark.js を単体で使ってみる。