コードジェネレーター「hygen」入門 ~ブログのテンプレート生成を作る~
December 18, 2020
目次
hygenとは?
hygenをテンプレートを元にコード(ファイル)を生成することが出来るジェネレーターである
あらかじめ用意・設定したテンプレートをベースにファイルを自動生成することができる スケーラブルなコードジェネレーター
hygenセットアップ
インストール
yarn add -D hygen
初期化
% hygen init self
Loaded templates: node_modules/hygen/src/templates
added: _templates/generator/help/index.ejs.t
added: _templates/generator/with-prompt/hello.ejs.t
added: _templates/generator/with-prompt/prompt.ejs.t
added: _templates/generator/new/hello.ejs.t
実行すると_templates
ディレクトと配下にディレクトリとファイルが生成される
├── _templates
│ └── generator
│ ├── help
│ │ └── index.ejs.t
│ ├── new
│ │ └── hello.ejs.t
│ └── with-prompt
│ ├── hello.ejs.t
│ └── prompt.ejs.t
├── package.json
└── yarn.lock
_templates/generator
がジェネレター名_templates/generator/help or /new or /with-prompt
がジェネレターのアクション名 アクションディレクトリの配下に生成するコードのテンプレート等は配置する.ejs.t
となっているファイルがコードテンプレートprompt.ejs.t
がプロンプト設定ファイル
generator //ジェネレータ名
├── help //アクション名
├── new
└── with-prompt
このhygen generator
ジェネレーターを使い、新しくジェネレーターを生成する
ジェネレーターを作る
generator
ジェネレーターには、new
とwith-prompt
が用意してある
% hygen generator help
Loaded templates: hygen
help:
hygen generator new --name [NAME] --action [ACTION]
hygen generator with-prompt --name [NAME] --action [ACTION]
new
は、実行時に引数を渡しでコード生成するジェネレーターwith-prompt
は、対話式でコード生成するジェネレーターを生成する
今回は、対話式のwith-prompt
で作る
% hygen generator with-prompt --name sample --action new
nameにジェネレータ名を指定し、actionにそのコマンドのアクション名を指定する 今回、sampleジェネレーターのnewアクションを作成する
% hygen generator with-prompt --name sample --action new
Loaded templates: _templates
added: _templates/sample/new/hello.ejs.t
added: _templates/sample/new/prompt.js
これによりhygen sample new
実行可能な対話式コードジェネレターが作成される
生成されたファイル一覧
% tree _templates
_templates
├── generator
└── sample
└── new
├── hello.ejs.t
└── prompt.js
各ファイルについて
hello.ejs.t
生成するファイルのテンプレートになるファイル
拡張子にあるとおりejs
記法で記述する
hello.ejs.t
---
to: app/hello.js //①
---
//②
const hello = \```
Hello!
This is your first prompt based hygen template.
Learn what it can do here:
https://github.com/jondot/hygen
\```
console.log(hello)
① 生成するファイルを指定する
②---
以下に生成するコードを記載する
prompt.js
prmpt.js
は、プロンプトファイルで対話(コマンド実行)する内容を記述する
enquirerがプロンプトランナーとして内部で使用されている
page/new/prompt.js
// see types of prompts:
// https://github.com/enquirer/enquirer/tree/master/examples
//
module.exports = [
{
type: 'input', //①
name: 'message', //②
message: "What's your message?" //③
}
]
① 入力方式を指定可能。他に、select
・toggle
・list
など
② ejs.t
内で使用する変数名
③ 質問内容を記載する
必要な質問分配列で{type, name, message}
を追加していく
他にvalidationなど追加する事も可能
実行してみる
% hygen sample new
✔ What's your message? · Hello!
Loaded templates: _templates
added: app/hello.js
app/hello.js
が生成される
※message聞かれるがテンプレートファイルに使用の定義がないので生成ファイルには何も反映されない
% tree app
app
└── hello.js
% cat app/hello.js
const hello = \```
Hello!
This is your first prompt based hygen template.
Learn what it can do here:
https://github.com/jondot/hygen
\```
console.log(hello)
GatsbyのBlogジェネレーターを作る
ここから本題
やりたいことは、
blog new
コマンドでcontent/blog
配下にblogファイル(.md)を作成する- 記事名など対話式で指定できるようにする(以下に記載)
プロンプトの内容
メッセージ | Type | 備考 |
---|---|---|
記事名を入力 | input | 必須 |
記事の日付 | input | デフォルトは今日 |
ドラフトで生成するか? | toggle | デフォルトはtrue。ドラフトとは記事を公開するかのフラグ |
記事の説明 | input | |
タブ名を入力 | list | 必須 |
1.ジェネレーターの作成
hygen blog new
でBlog生成できるようにするので
% hygen generator with-prompt --name blog --action new
でジェネレーターを作成する
% hygen generator with-prompt --name blog --action new
Loaded templates: _templates
added: _templates/blog/new/hello.ejs.t
added: _templates/blog/new/prompt.js
% tree _templates
_templates
├── blog
│ └── new
│ ├── hello.ejs.t
│ └── prompt.js
2.プロンプトを作成する
つづいて、プロンプトの作成
_templates/blog/new/prompt.js
をプロンプトの定義を追加する
// see types of prompts:
// https://github.com/enquirer/enquirer/tree/master/examples
//
module.exports = [
{
type: 'input',
name: 'blogName',
message: "記事名を入力",
validate: (answer) => { //①
if(!answer){
return "必須です。入力してください";
}
return true
}
},
{
type: 'input',
name: 'date',
message: "記事の日付を入力",
hint:'yyyy-MM-dd',
validate: (answer) => { //②
if(answer && !RegExp('^([0-9]{4})-([0-9]{2})-([0-9]{2})$').test(answer)){
return "yyyy-MM-dd形式で入力して下さい。"
}
return true
}
},
{
type: 'toggle',
name: 'draft',
message: "ドラフトで生成する?",
enabled: 'Yes',
disabled: 'No'
},
{
type: 'input',
name: 'description',
message: "記事の説明を入力",
},
{
type: 'list',
name: 'tags',
message: "タブ名を入力",
hint:'カンマ(,)区切りで入力',
validate: (answer) => { //③
if(!answer.length){
return "必須です。入力してください";
}
return true
}
}
]
パラメータtype
・name
・message
を追加する
- type: 入力方式を設定
- name: テンプレートファイルで使用する変数名
- message: 対話式プロントの質問内容
① Blog名がないと生成に困るので、validateパラメータに必須チェックを追加
② 日付はyyyy-MM-dd
形式で入力してほしいのでフォーマットバリデーションを追加
③ タブ名も①同様、必須にしたいのでvalidate追加
3.テンプレートファイルを作成する
まずはファイル名が、_templates/blog/new/hello.ejs.t
なので_templates/blog/new/blog.ejs.t
に変更
---
to: content/blog/<%= blogName.replace(/\//g, '_') %>/index.md //①
---
---
title: <%= blogName ? blogName : '' %>
date: "<%= date ? date : h.moment().format('YYYY-MM-DD') %>" //②
description: <%= description ? description : '' %>
tags: <% for (const tag of tags) { %> //③
- <%- tag %><% } %>
drafts: <%= drafts %>
---
--------------------------------------------------
## <%= blogName %>
テンプレートファイルないでは、ejs記法を使用することが出来る。
<%= 変数名 %>
でpromept.jsで定義したname
パラメータが変数名となり入力値として使用できる
① /
がディレクトリ名にあると階層がズレてしまうので_
に変更している
② デフォルトをmomentを使用して設定する
dataの入力がない場合、デフォルトとして今日を設定する為、momentを利用している。
利用する為には、.hygen.js
を用意して以下の定義を行う。
const moment = require('moment');
module.exports = {
helpers: {
moment
}
};
とすることで、テンプレートファイルでh.moment()
で使用することが出来る
③ for分を使用してtags:
を表示
フォーマットが変な感じになっているが理由があり例えば以下のようにした場合
tags:
<% for (const tag of tags) { %>
- <%- tag %>
<% } %>
↓
tags:
- hello
- hygen
と余計な空白が入ってしまう為、詰めて定義している
4.実行してみる
コマンドは、hygen blog new
% hygen blog new
✔ 記事名を入力 · コードジェネレーター「hygen」入門
✔ 記事の日付を入力 · 2020-12-16
✔ ドラフトで生成する? · No / Yes
✔ 記事の説明を入力 · コードジェネレーターhygenの導入・使用について
✔ タブ名を入力 · hygen, 入門
Loaded templates: _templates
added: content/blog/コードジェネレーター「hygen」入門/index.md
生成を確認
% cat content/blog/コードジェネレーター「hygen」入門/index.md
---
title: コードジェネレーター「hygen」入門
date: 2020-12-16
description: コードジェネレーターhygenの導入・使用について
tags:
- hygen
- 入門
drafts: true
---
----------------------------------------
ディレクトリの変更
デフォルトは、_templates
導入する場合わかりにくいことがあるので
ディレクトリを変更することが可能
.hygen.js
を追加し、下記コードを定義する
module.exports = {
templates: `${__dirname}/hygen`
};
_templates
ディレクトリ名をhygen
に変更する
これでhygen
ディレクトリに変更される