開発環境を作るメモ

※飛ばしている部分があります。 Node.js 、 Middleman、 Hologram などはインストール済みである必要があります。
※Mac 前提です。Windows で試していません。

## Middleman の準備

適当なディレクトリで [Middleman](https://middlemanapp.com/) の新規プロジェクト作成。

```zsh
cd ~/Project
middleman init
```

こんな感じにファイルが生成されます。

```
.gitignore
config.rb
Gemfile
Gemfile.lock
source
¦ index.html.erb
¦
+---layouts
¦   - layout.erb
¦
+---images
¦   - background.png
¦   - middleman.png
¦
+---javascripts
¦   - all.js
¦
+---stylesheets
    - all.css
    - normalize.css
```

この状態で、 `bundle exec middleman` もしくは `bundle exec middleman server` コマンドを使用すると、 `http://localhost:4567/` で、Middleman の初期画面。  `http://localhost:4567/__middleman/` で、ファイルの構造・設定オプションなどが表示されます（ `CTRL-C` でプレビューサーバーを終了）。

### Middleman の設定

JavaScript、CSS の制作には [gulp](http://gulpjs.com/) を使いたいので、ディレクトリ構造などをガッツリ書き直します。

まず、 `source` 以下は気前よく捨てて、以下のような構成に変更します。

```
……略（変更なし）……
¦
+---_gulp ... gulp タスクなど
¦   - .gitkeep
+---assets ... gulp で何かするもの（Sass, CoffeeScript など）
¦   - .gitkeep
+---views ... ページを表示するためのファイル（erb, Slim, Haml など）
    +---_layouts ... レイアウト
    ¦   - .gitkeep
    +---_partials ... パーシャル
        - .gitkeep
```

次に、 `config.rb` を編集します。

```rb
# Compass
#
# * gulp-ruby-sass のために設定を書きます。
# * Compass を使わない場合はもちろん不要。
# * 「Ruby on Rails のプロジェクトなので、最終的に `image-url` や `font-url` 
#   などを残したまま、 Sass ファイルとして書き出したい」のような時に。
http_images_path = '/assets/images'
http_fonts_path = '/assets/fonts'

# Configurations
if defined? Middleman
  set :source, 'views'
  set :layouts_dir, '_layouts'
  set :partials_dir, '_partials'
end
```

### Middleman で Slim を使いたい

Slim 使っていきたいです。
まずは、 `Gemfile` に追加して `bundle install`　。

```lang:Gemfile
# Templating engine
gem "slim"
```

config.rb に設定を追記します。

```rb
# Compass
#
# * gulp-ruby-sass のために設定を書きます。
# * Compass を使わない場合はもちろん不要。
# * 「Ruby on Rails のプロジェクトなので、最終的に `image-url` や `font-url` 
#   などを残したまま、 Sass ファイルとして書き出したい」のような時に。
http_images_path = '/assets/images'
http_fonts_path = '/assets/fonts'

# Configurations
if defined? Middleman
  set :source, 'views'
  set :layouts_dir, 'layouts'
  set :partials_dir, '_partials'
  # ↓これを追記（Jun 6, 2015: format が html5 だと非奨励と言われるので修正）
  set :slim, { :pretty => true, :sort_attrs => false, :format => :html }
end
```

### 動くかどうか試す

以下の様にファイルを追加して、動作確認を行います。

```
……略（変更なし）……
¦
+---views
¦  - index.slim
+---+---_layouts
    ¦   - layout.slim
    +---_partials
        - _header.slim
        - _footer.slim
```

`bundle exec middleman` して、 `http://localhost:4567/` で確認が取れればOK。

ここで、 `Slim::Engine: Option :locals is invalid` と言われたので、 `config.rb` に `Slim::Engine.disable_option_validator!` を追記した（仮の処置）。

```rb
http_images_path = '/assets/images'
http_fonts_path = '/assets/fonts'

if defined? Middleman
  Slim::Engine.disable_option_validator!

  set :source, 'views'
  set :layouts_dir, '_layouts'
  set :partials_dir, '_partials'
  set :slim, { :pretty => true, :sort_attrs => false, :format => :html }
end
```

動いているように見えます。

## gulp の準備

ここでは、以下まで準備します。

* gulp から Middleman を起動
* [Hologram](http://trulia.github.io/hologram/) でスタイルガイドを作る
* Sass（開発用）
* Sass（書き出し用）

### もろもろインストールする

適当に `package.json` を作っておきます。

```json
{
  "name": "ProjectName",
  "version": "0.0.0",
  "devDependencies": {
  }
}
```

使うものをインストールします（長いので改行入ってます）。

```zsh
npm install --save-dev 
autoprefixer-core 
csswring 
gulp 
gulp-combine-media-queries 
gulp-hologram 
gulp-load-plugins 
gulp-notify 
gulp-plumber 
gulp-rename 
gulp-postcss 
gulp-ruby-sass 
gulp-sourcemaps
```

### gulp から Middleman を起動するタスクを追加する

ちょっとまだ納得いってないので、良い案がありましたら、ぜひ教えて欲しいです！

`gulpfile.js` を追加します。

```js
'use static';

var gulp = require('gulp');
var $    = require('gulp-load-plugins')({
             pattern: ['gulp-*', 'gulp.*'],
             replaceString: /\bgulp[\-.]/
           });

// Require tasks
var tasks = './_gulp/tasks';

require(tasks+'/server.js')(gulp, $);

// Run
gulp.task('default', ['server']);
```

Middleman を起動するためのタスクを書くファイル追加します。

```
……略……
¦
gulpfile.js
package.json
¦
+---_gulp
¦   ¦ 
¦   +---tasks
¦      - server.js
……略……
```

Middleman を起動するためのタスクを書きます。

```js
'use static';

module.exports = function(gulp, $)
{
  var spawn = require('child_process').spawn;

  gulp.task('server', function() {
    child = spawn('bundle', ['exec', 'middleman']);
    child.stdout.pipe(process.stdout);
    child.stderr.pipe(process.stderr);

    return;
  });
};
```

この状態で、 `gulp` を実行して、 `http://localhost:4567/` にアクセス出来る事を確認する。

また、 `CTRL+C` で gulp を終了した時に、 `http://localhost:4567/` にアクセス**出来ない**事を確認する。

#### Middleman のプレビューサーバーが止まらない時

動いている様に見えるのだが、 gulp が別のタスクでコケたりした時に、 Middleman のプレビューサーバーがが正しく停止しない……

もちろん、解決したいが、強制的に止める手段をメモしておく。

`ps aux | grep middleman` で、プロセスをチェック。
その後、 `kill -9 チェックしたプロセス` する。

---

[shotgun](https://github.com/rtomayko/shotgun) を使うと、`shotgun -p 4567` とか出来るらしいのですが、試してないです。

### Hologram でスタイルガイドを書き出せるようにする

Hologram のインストールは済んでいる前提で進めます。

#### Hologram の準備

特にテーマなどを触るつもりが無い場合は、 `hologram init` します。すると、以下のようなファイルが書き出されます。

```
……略……
¦
+---code_example_templates
¦     -js_example_template.html.erb
¦     -jsx_example_template.html.erb
¦     -markup_example_template.html.erb
¦     -markup_table_template.html.erb
¦
+---doc_assets
¦     -_footer.html
¦     -_header.html
……略……
hologram_config.yml
……略……
```

2カラムだったり、幅が固定だったりすると、RWD の時に困ったりするなどあるので、個人的にはカスタムテーマを使っていますが、この後の gulp タスクには影響が出ないので、このまま進めます。

`hologram_config.yml` を修正します。

```yaml
##### 以下を #####

# The directory containing the source files to parse recursively
source: ./sass

# The directory that hologram will build to
destination: ./docs

##### このように #####

# The directory containing the source files to parse recursively
source: ./assets/stylesheets

# The directory that hologram will build to
destination: ./views/styleguide
```

その後、設定で指定したディレクトリを作ってから、 `hologram -c` します。
※設定ファイルの場所を変えた場合は、 `hologram -c path/to/config.yml` とかで出来ます。
※指定したディレクトリが無いとエラー出ます。

#### スタイルガイドのタスクを書く

スタイルガイドのタスクを書くファイル追加します。

```
……略……
¦
gulpfile.js
package.json
¦
+---_gulp
¦   ¦ 
¦   +---tasks
¦      - styleguide.js
……略……
```

スタイルガイドのタスクを書きます。

```js
'use static';

module.exports = function(gulp, $)
{
  var hologram = './hologram_config.yml'

  gulp.task('styleguide', function()
  {
    gulp.src(hologram)
        .pipe($.plumber({
          errorHandler: $.notify.onError("Error: <%= error.message %>")
        }))
        .pipe($.hologram());

    return;
  });
};
```

`gulpfile.js` に追記します。

```js
require(tasks+'/styleguide.js')(gulp, $);
```

`gulp styleguide` で実行出来るようになりました。

### Sass （開発用）のタスクを追加する

**やること**
* `image-url` とか使いたいので Compass を有効にする
* sourcemap 使いたい
* autoprefixer 使いたい
* `@media` をまとめたい

**やらないこと**
* CSS Lint とか使うと思うけど、今回は書かない
* sprite とか icon font とかの周辺タスクは今回書かない

Sass （開発用）のタスクを書くファイル追加します。

```
……略……
+---_gulp
¦   ¦ 
¦   +---tasks
¦      - sass.js
……略……
```

Sass （開発用）のタスクを書きます。

```js
'use static';

module.exports = function(gulp, $)
{
  var autoprefixer  = require('autoprefixer-core');

  gulp.task('sass:dev', function() {
    var processors = [
        autoprefixer({browsers: ['last 3 versions', 'Android >= 4']})
    ];
    var sass = {compass: true, style: 'expanded'};
    var src  = './assets/stylesheets';
    var dist = './views/assets';

    return $.rubySass(src, sass)
            .pipe($.sourcemaps.init({loadMaps: true}))
            .pipe($.combineMediaQueries())
            .pipe($.postcss(processors))
            .pipe($.sourcemaps.write())
            .pipe(gulp.dest(dist));
  });
};
```

※ `gulp-ruby-sass` の書き方が変わっていて、 `gulp.src(xxx)` から始めると動作しないのが罠。

`gulpfile.js` に追記します。

```js
require(tasks+'/sass.js')(gulp, $);
```

`gulp sass:dev` で実行出来るようになりました。

### watch を追加する

`watch` のタスクを書くファイル追加します。

```
……略……
+---_gulp
¦   ¦ 
¦   +---tasks
¦      - watch.js
……略……
```

`watch` のタスクを書きます。

```js
'use strict'

module.exports = function(gulp, $)
{
  gulp.task('watch', function()
  {
    var sass = [
      './assets/stylesheets/**/*.sass',
      './assets/stylesheets/**/*.scss'
    ];

    gulp.watch(sass, ['sass:dev', 'styleguide']);

    return;
  });
};
```

gulpfile.js に追記します。

```js
require(tasks+'/watch.js')(gulp, $);

// Run
gulp.task('default', ['server', 'watch']);
```

これで、 `gulp` のみ実行すれば、ファイルの保存時に Sass のコンパイルとスタイルガイドの生成が行われるようになりました。

Sass （書き出し用）のタスクを書きます。

```js
'use static';

module.exports = function(gulp, $)
{
  var autoprefixer  = require('autoprefixer-core');
  var csswring      = require('csswring');
  var browsers      = {browsers: ['last 3 versions', 'Android >= 4']};
  var src           = './assets/stylesheets';
  var cacheLocation = './.sass-cache';

  gulp.task('sass:dev', function() {
    var processors = [autoprefixer(browsers)];
    var sass = {compass: true, style: 'expanded', cacheLocation: cacheLocation};
    var dist = './views/assets';

    return $.rubySass(src, sass)
            .pipe($.sourcemaps.init({loadMaps: true}))
            .pipe($.combineMediaQueries())
            .pipe($.postcss(processors))
            .pipe($.sourcemaps.write())
            .pipe(gulp.dest(dist));
  });

  gulp.task('sass', function() {
    var processors = [autoprefixer(browsers), csswring];
    var sass = {compass: false, cacheLocation: cacheLocation};
    var dist = './build/assets';

    return $.rubySass(src, sass)
            .pipe($.combineMediaQueries())
            .pipe($.postcss(processors))
            .pipe($.rename(function (path) {
              path.extname = ".scss"
            }))
            .pipe(gulp.dest(dist));
  });
};
```

* 共通の変数はまとめた
* CSS を圧縮するので、 `postcss` に `csswring` を追加
* SourceMap は不要
* Compass 無効（ `image-url` などがそのまま書き出される）
* `.css` を `.scss` にリネーム
* 実際には `del` なども組み合わせて使うと思いますが、他の書き出し用タスクと合わせて使うと思われるので、ここでは触れません

## PhantomCSS

色々なツールがある中で、「すごく凝ったテストは書かないけど、表示／非表示の切り替えとかは書く」という場合に、 CasperJS 使えると便利そうで、また、単に使ってみたかった（こっちがメインかも）というのもあって、PhantomCSS を選んだ次第。 BackstopJS もシンプルで簡単そうなので、とても良さそう。

### 準備

まず、インストールします。

```zsh
sudo npm install -g phantomjs
sudo npm install -g casperjs
```

そして、本家から clone してきて、デモを試します。

```zsh
git clone git://github.com/Huddle/PhantomCSS.git
```

動くといいな。

```zsh
cd PhantomCSS
casperjs test demo/testsuite.js
```

これで動作していれば、一旦、OK。

追記（Jun 6, 2015）： SlimerJS 使って Gecko にも対応出来そうなので試してみたい