こんにちは、CX事業本部 Delivery部の若槻です。
マークダウン(Markdown)文書では、次のようにファイルの冒頭で---
を使ってmetadata(yaml header)を定義することができます。
---
title: This is a test
description: Once upon a time...
---
# Title of my great post
Lorem ipsum dolor...
レンダリング側がサポートしているかに依りますが、VS Codeのマークダウンプレビュー機能であれば、ソース側で記述されていたmetadataをプレビュー側ではちゃんと消してくれます。
逆にGitHubではテーブル形式で表示してくれます。
今回は、このマークダウンのmetadataをNode.jsでパースする方法を確認してみました。
方法
npmパッケージのparse-mdが良さそうだったので使ってみます。
インストール
npm i parse-md
コード
parse.js
import fs from 'fs'
import parseMD from 'parse-md'
const fileContents = fs.readFileSync('posts/first.md', 'utf8');
const { metadata, content } = parseMD(fileContents);
console.log(metadata);
console.log(content);
実行するとmetadataおよびcontentをパースできました。
$ node parse.js
{ title: 'This is a test', description: 'Once upon a time...' }
# Title of my great post
Lorem ipsum dolor...
実行がnode:65885エラーとなる場合
$ node parse.js
(node:65885) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_sample_app/parse.js:1
import fs from 'fs'
^^^^^^
SyntaxError: Cannot use import statement outside a module
at Object.compileFunction (node:vm:352:18)
at wrapSafe (node:internal/modules/cjs/loader:1033:15)
at Module._compile (node:internal/modules/cjs/loader:1069:27)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
at node:internal/main/run_main_module:17:47
package.json
に次の記述を追加して、パッケージ内の全ての.jsファイルがcommonjsではなくESモジュールとして扱われるようにします。
package.json
{
"type": "module"
}
TypeScriptで書くなら
TypeScriptで書く場合は次のようになりました。
parse.ts
import * as fs from 'fs';
import parseMD from './node_modules/parse-md/dist/index.js';
const fileContents = fs.readFileSync('posts/first.md', 'utf8');
const { metadata, content } = parseMD(fileContents);
console.log(metadata);
console.log(content);
ちなみにインポートをimport parseMD from 'parse-md'
としたら、parse-md
の定義ファイルが無いよと怒られます。
Could not find a declaration file for module 'parse-md'. '/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_sample_app/parse-md.js' implicitly has an 'any' type.
JavaScriptの時と同じですが、package.json
に次の記述を追加して、パッケージ内の全ての.jsファイルがcommonjsではなくESモジュールとして扱われるようにします。
package.json
{
"type": "module"
}
tsconfig.json
の記述を次のようにします。compilerOptions.module
でesnext
またはes2020
を指定してモジュールをESモジュールとして読み込むようにします。また"ts-node": {"esm": true}
を追加してERR_UNKNOWN_FILE_EXTENSIONを回避します。(ts-node-esm
またはts-node --esm
でも回避できます。)
tsconfig.json
{
"compilerOptions": {
"module": "esnext",
},
"ts-node": {
"esm": true
}
}
実行できました。
$ npx ts-node parse.ts
{ title: 'This is a test', description: 'Once upon a time...' }
# Title of my great post
Lorem ipsum dolor...
参考
以上