最近 VuePress で個人ブログの運用をはじめました。
ですが、VuePress 単体では記事の Markdown を自動で生成できないことに悩んでいたので、{{ mustache }}を使った簡易的な記事生成スクリプトを作りました。
イメージ的には hexo
の new コマンドのような感じです。
登場人物
new-post.js
と templates/*.mustache
を新規に追加します。
$ tree vuepress
.
├── new-post.js <------------------------- スクリプト本体
├── package.json
├── docs <-------------------------------- VuePress のプロジェクトフォルダ
│ ├── .vuepress
│ │ └── config.yml
│ └── _posts
│ └── 2019-12-31-newpost.md <------- 生成される markdown
└── templates <--------------------------- テンプレート フォルタ
├── base.mustache
└── header.mustache
スクリプトの実装
まずは、スクリプトです。mustache
を使うのでパッケージを入れておきます。
$ yarn add --dev mustache
スクリプト本体は git で管理してますがここにも記載しておきます。そんな大したことはしてません。
機能:
- 引数で次の 3 つを指定
- ベースとなるテンプレート
- 記事のタイトル
- (optional) markdown のファイル名
- ベースとなるテンプレートに「タイトル」と「日付」を埋め込んで出力
- 出力するファイルは
2019-12-13-lower-case-title.md
のような名前
new-post.js
'use strict';constfs=require("fs");constpath=require('path');constmustache=require('mustache');functionformatedateDate(date,includesDatetime){constdateStr=[date.getFullYear(),("0"+(date.getMonth()+1)).slice(-2),("0"+date.getDate()).slice(-2)].join("-");constdatetimeStr=[("0"+date.getHours()).slice(-2),("0"+date.getMinutes()).slice(-2),("0"+date.getSeconds()).slice(-2),].join(":");returnincludesDatetime?dateStr+""+datetimeStr:dateStr;}functionsanitizeTitle(title){returntitle.replace(/[ ?!@;'\\.]/g,'-').toLowerCase().replace(/^[ -]+|[ -]+$/g,"");}/** Parameters */constpostDir=path.join("docs","_posts");consttemplateEngine={name:"Mustache",dir:"templates",extension:".mustache",};/** Parse arguments */constusage="Usage: node new-post.js <template-name> <title> [<title-for-filename>]";constargs=process.argv.slice(2,process.argv.length);if(args.length!=2&&args.length!=3){console.error("Invalid arguments")console.error(usage);process.exit(1);}consttemplatePath=path.join(templateEngine.dir,args[0]+templateEngine.extension);consttitle=args[1];constfiletitle=args[2]?sanitizeTitle(args[2]):sanitizeTitle(title);constpostFilename=formatedateDate(newDate(),false)+"-"+filetitle+".md";constpostPath=path.join(postDir,postFilename);/** Main */fs.readFile(templatePath,'utf8',function(err,templateData){if(err)throwerr;// render the template with mustache.constrenderedData=mustache.render(templateData,{title:title,date:formatedateDate(newDate(),true),overview:title+"についての記事です。",});// write a markdown file out.fs.writeFile(postPath,renderedData,{flag:'wx'},function(err){if(err){throwerr;}console.log("Created a new post at: "+postPath)});});
テンプレートの実装
templates/<template-name>.mustache
にテンプレートを置いていきます。
base.mustache
---
title: "{{title}}"
date: {{date}}
category: その他
tags:
- タグ
---
{{overview}}<!-- more -->
# {{title}}
[[toc]]
## はじめに
new-post.js
内の以下の部分が、テンプレートに値を代入して markdown をレンダリングする処理に相当します。
// render the template with mustache.constrenderedData=mustache.render(templateData,{title:title,date:formatedateDate(newDate(),true),overview:title+"についての記事です。",});
使い方
$ node new-post.js <template-name> <title> [<title-for-filename>]
# e.g.$ node new-post.js base "はじめての Node.js" getting-started-with-nodejs