# 怎样编写自己的模板

* 模板仓库下必须有 `template` 目录用于存储模板文件
* 模板仓库下必须有元数据模板定义文件 `meta.js` 或 `meta.json`。该文件包含以下内容：
  * `prompts`：用于问题收集
  * `filters`：用于过滤文件
  * `metalsmith`：用于文件处理流中添加 metalsmith 插件
  * `completeMessage`：用于生成模板后需要向用户输出信息
  * `complete`：相比于 `completeMessage` 可进行一些自定操作
  * `helpers`：注册自定义 `handlbers` 助手函数

## prompts

`prompts` 在 `meta.{js, json}` 中是一个对象。且该对象的每个属性的值都是一个 [Inquirer.js 问题对象](https://github.com/SBoudrias/Inquirer.js/#question)。如：

```json
{
  "prompts": {
    "name": {
      "type": "string",
      "required": true,
      "message": "Project name"
    }
  }
}
```

当所有 `prompts` 提示问题交互完成后，将结合交互结果利用 [handlebars](http://handlebarsjs.com/) 对`template` 目录中所有文件进行渲染或处理。

### conditional prompts

可以使用 `when` 字段来声明此问题的是否询问取决于前面问题的答案，`when` 字段的值为一个 JavaScript 表达式。如：

```json
{
  "prompts": {
    "lint": {
      "type": "confirm",
      "message": "Use a linter?"
    },
    "lintConfig": {
      "when": "lint",
      "type": "list",
      "message": "Pick a lint config",
      "choices": [
        "standard",
        "airbnb",
        "none"
      ]
    }
  }
}
```
上面例子中，只有 `lint` 问题的答案为 `yes` 的时候，`lintConfig` 问题才会被触发提问。

## helpers

可以通过 `helpers` 字段为 handlbers 注册自定义 helpers

### 预注册 handlebars helpers

`if_eq` 及 `unless_eq` 已在脚手架中注册，可直接使用：

```
{{#if_eq lintConfig "airbnb"}}
;
{{/if_eq}}
```

### 自定义 handlebars helpers

也可以自定义 handlebars 的 helpers

```js
module.exports = {
  helpers: {
    if_or(v1, v2, options) {
      if (v1 || v2) {
        return options.fn(this)
      }
      return options.inverse(this)
    }
  },
}
```

## File filters

`filters` 字段值是一个包含文件过滤规则的对象。对于每个键值对，其键是一个 [minimatch glob pattern](https://github.com/isaacs/minimatch，其值是 javaScript 表达式。


```
{
  "filters": {
    "test/**/*": "needTests"
  }
}
```

`test` 目录下的文件只有当用户对 `needTests` 问题的回答是 `yes` 的时候才会被生成到目标项目。


## skipInterpolation

`skipInterpolation` 字段值是一个数组，数组里的每一项都是 [minimatch glob pattern](https://github.com/isaacs/minimatch)。对于这个字段所匹配的文件跳过渲染步骤。

```
{
  skipInterpolation: [
    'client/components/*/*.vue'
  ]
}
```

## metalsmith

脚手架使用 [metalsmith](https://github.com/segmentio/metalsmith) 去生成项目。因此，可以通过 `metalsmith` 字段自定义 metalsmith 插件。

```
{
  "metalsmith": function (metalsmith, opts, helpers) {
    function customMetalsmithPlugin (files, metalsmith, done) {
      // Implement something really custom here.
      done(null, files)
    }

    metalsmith.use(customMetalsmithPlugin)
  }
}
```

## complete

参数：

* data: 与 `completeMessage` 传参相同

```
{
  complete (data) {
    if (!data.inPlace) {
      console.log(`cd ${data.destDirName}`)
    }
  }
}
```

*  helpers: 提供一些工具去输出结果
  * `chalk`
  * `logger` - 脚手架自定义函数
  * `files` - 已生成的文件数组

```
{
  complete (data, {logger, chalk}) {
    if (!data.inPlace) {
      logger.log(`cd ${chalk.yellow(data.destDirName)}`)
    }
  }
}
```
