grunt-ectで快適HTMLコーディング


HTMLファイルの作成時のコピペ祭りに嫌気がさしたので、そこでgrunt-ectを使ってHTMLのコーディングをしてみました。

## そもそもECTとは？
[ECT](http://ectjs.com/)

JavaScriptのテンプレートエンジンです。
Gruntでコンパイルしてつかったり、nodeのexpressと組み合わせてつかったり出来ます。

- インヘリタンス
- パーシャル
- ブロック

などの機能もあるので普通の今時のテンプレートエンジンですね。
あとCoffeeScript書けるらしいです。


## grunt-ectの導入

### インストール

必要なnpmを用意する

```
$ npm init
$ npm install grunt --save-dev
$ npm install grunt-ect --save-dev
$ npm install grunt-contrib-watch --save-dev
```

### Gruntfle

Gruntfileはこんな感じです。
ectの設定の中で`ect.render.files`でコンパイルしたいファイル名:'コンパイル後のファイル名'と指定すればそれだけで大丈夫です。
ちなみに全体の変数として`ect.render.variables`で変数を設定できます。


``` Gruntfile.coffee
"use strict"
module.exports = (grunt) ->

  # task
  grunt.initConfig
    dir: 
      src: "src"
      dest: "dist"
    pkg: grunt.file.readJSON "package.json"

    # grnt ect
    ect:
      options:
        root: '<%= dir.src %>/template'
      render:
        files:
          '<%= dir.dest %>/index.html': ['main/index.ect']
        variables:
          projectName: 'Sample Site'
          menuList:
            'about': '/about.html'
            '２about': '/about.html'

    watch:
      ect:
        files: "src/**/*.ect"
        tasks: "ect"


  # プラグインの読み込み
  grunt.loadNpmTasks 'grunt-ect'
  grunt.loadNpmTasks 'grunt-contrib-watch'

  # タスク登録
  grunt.registerTask 'default', ['watch'] 
```




### 実際にファイルを配置してみる

テンプレートの入れてあるディレクトリ構成はこんな感じ

```tree
src
└── template
    ├── partials
    │   └── menu.ect
    ├── layout
    │   └── default.ect
    └── main
        └── index.ect
```

srcのmainディレクトリに入っている物が、distファイルに展開される感じです。


```partials/menu.ect
<!-- Static navbar -->
<div class="navbar navbar-default" role="navigation">
  <div class="container-fluid">
    <div class="navbar-header">
      <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#"><%- @projectName %></a>
    </div>
    <div class="navbar-collapse collapse">
      <ul class="nav navbar-nav">
        <% for name,link in @menuList : %> 
          <li><a href="<%= link %>"><%= name %></a></li>
        <% end %>
      </ul>
    </div><!--/.nav-collapse -->
  </div><!--/.container-fluid -->
</div>
```

```layout/default.ect
<!doctype html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="<%= content 'description' %>">
  <title><% content 'title' %>| sample page</title>
  <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
  <style>
  body {
  padding-top: 20px;
  padding-bottom: 20px;
}

.navbar {
  margin-bottom: 20px;
}
  </style>
</head>
<body>

    <div class="container">
    <% content %>
    </div> <!-- /container -->

<!-- Scripts -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<% content 'scripts' %>
</body>
</html> 
```
```main/index.ect
<% block 'title': %>トップページ<% end %>

<% extend 'layout/default.ect' %>
<% include 'partials/menu.ect' %>
<h1><%= @projectName %></h1>
ここはトップページです。
<% block 'scripts': %>
<script>
$(function(){
  console.log("load")
})
</script>
<% end %>
```

### あとはGruntを実行するだけ
```
$ grunt
```

これで、distディレクトリの中にindex.htmlが生成されているはずです。
継承が使えるテンプレートってすてきですね。

![スクリーンショット 2014-04-06 4.18.59.png](https://qiita-image-store.s3.amazonaws.com/0/2095/d7fd3bbf-b325-5199-4f5b-53022f5fec13.png "スクリーンショット 2014-04-06 4.18.59.png")



## 一応基本的なECTの構文を書いておきます

### HTMLのエスケープをしない出力
```
<%- someVar %>
```

### HTMLのエスケープをする出力
今回のサンプルはこっちしか使用してません。

```
<%= @projectName %>
```

### CoffeeScriptの記述

```
<% for article in @articles : %>
    <% include 'article', article %>
<% end %>
```
上のテンプレートファイルだとmenu.ectの部分で使用しています。
Grunt側で定義したmenuListって変数をループしてメニューとして表示しています。


```
<% for name,link in @menuList : %> 
    <li><a href="<%= link %>"><%= name %></a></li>
<% end %>
```

### テンプレート継承
extendをつければいいです。

```
<% extend 'layout/default.ect' %>
```

### パーシャル

```
<% include 'partials/menu.ect' %>
```

## おしまい
テンプレートエンジン使う事で、コーディング効率上がのと同時に、PHPやRubyなんかと連携するときも楽になります。
ということでぜひ一度試してみてください。	




## 参考サイト
[Grunt: テンプレートを使って、共通要素をはめ込んだ HTML を生成する（grunt-ect 編）](http://www.d-wood.com/blog/2014/01/07_5215.html#i-4)
[ect](https://github.com/baryshev/ect)