おれおれGruntfile.js: メモ

```js:Gruntfile.js
module.exports = function(grunt) {

  var pkg = grunt.file.readJSON('package.json');

  grunt.initConfig({

    pkg: pkg,

    /* ===== config ===== */
    paths: {
      source:  'source',
      develop: 'develop',
      release: 'release',
      compass: 'compass/core/stylesheets'
    },

    /* ===== /config ===== */

    /* ===== compile ===== */
    coffee: {
      render: {
        expand: true,
        cwd: '<%= paths.source %>',
        src: ['**/*.coffee'],
        dest: '<%= paths.develop %>',
        ext: '.js'
      }
    },

    copy: {
      render: {
        expand: true,
        cwd: '<%= paths.source %>',
        src: [
          '**/*.php',
          '**/*.html',
          '**/*.css',
          '**/*.js'
        ],
        dest: '<%= paths.develop %>',
      }
    },

    sass: {
      render: {
        options: {
          loadPath: '<%= paths.compass %>'
        },
        expand: true,
        cwd: '<%= paths.source %>',
        src: [
          '**/*.sass',
          '**/*.scss'
        ],
        dest: '<%= paths.develop %>',
        ext: '.css'
      }
    },

    ect: {
      render: {
        options: {
          root: '<%= paths.source %>',
        },
        expand: true,
        cwd: '<%= paths.source %>',
        src: ['**/*.html.ect'],
        dest: '<%= paths.develop %>',
        ext: '.html',
        variables: {
          projectName: 'サイトタイトル',
          links: [
            {name: 'Google',   url: 'http://google.com'},
            {name: 'Facebook', url: 'http://facebook.com'},
            {name: 'Twitter',  url: 'http://twitter.com'},
          ]
        }
      }
    },

    /* ===== /compile ===== */

    /* ===== lint ===== */
    // html lint
    validation: {
      check: {
        src: ['<%= paths.develop %>/**/*.html'],
      }
    },

    csslint: {
      check: {
        src: ['<%= paths.develop %>/**/*.css'],
      }
    },

    jshint: {
      check: {
        src: ['<%= paths.develop %>/**/*.js'],
      }
    },

    /* ===== /lint ===== */

    /* ===== compress ===== */
    htmlmin: {
      compress: {
        options: {
          collapseWhitespace: true
        },
        expand: true,
        cwd: '<%= paths.develop %>',
        src: [
          '**/*.html',
          '**/*.php'
        ],
        dest: '<%= paths.release %>'
      }
    },

    cssmin: {
      compress: {
        expand: true,
        cwd: '<%= paths.develop %>',
        src: ['**/*.css'],
        dest: '<%= paths.release %>'
      }
    },

    uglify: {
      compress: {
        expand: true,
        cwd: '<%= paths.develop %>',
        src: ['**/*.js'],
        dest: '<%= paths.release %>'
      }
    },
    /* ===== /compress ===== */


    /* ===== server ===== */
    connect: {
      server: {
        options: {
          port: 8080,
          hostname: 'localhost',
          base: '<%= paths.release %>'
        }
      }
    },
    /* ===== /server ===== */


    /* ===== watch ===== */
    watch: {
      options: {
        livereload: true
      },
      html: {
        files: [
          '<%= paths.source %>/**/*.html',
          '<%= paths.source %>/**/*.php'
        ],
        tasks: ['copy', 'htmlmin:compress']
      },
      css: {
        files: ['<%= paths.source %>/**/*.css'],
        tasks: ['copy', 'cssmin:compress']
      },
      js: {
        files: ['<%= paths.source %>/**/*.js'],
        tasks: ['copy', 'cssmin:compress']
      },
      coffee: {
        files: ['<%= paths.source %>/**/*.coffee'],
        tasks: ['coffee', 'uglify:compress']
      },
      sass: {
        files: [
          '<%= paths.source %>/**/*.sass',
          '<%= paths.source %>/**/*.scss'
        ],
        tasks: ['sass', 'cssmin:compress']
      },
      ect: {
        files: ['<%= paths.source %>/**/*.html.ect'],
        tasks: ['ect', 'htmlmin:compress']
      }
    },
    /* ===== /watch ===== */

  });

  grunt.loadNpmTasks('grunt-contrib-coffee');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-csslint');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-htmlmin');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-sass');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-ect');
  grunt.loadNpmTasks('grunt-html-validation');

  grunt.registerTask('default', [
    'coffee:render',
    'copy:render',
    'sass:render',
    'ect:render',
    // 'validation:check',
    'csslint:check',
    'jshint:check',
    'htmlmin:compress',
    'cssmin:compress',
    'uglify:compress',
    'connect',
    'watch'
  ]);

  grunt.registerTask('release', [
    'coffee:render',
    'copy:render',
    'sass:render',
    'ect:render',
    // 'validation:check',
    'csslint:check',
    'jshint:check',
    'htmlmin:compress',
    'cssmin:compress',
    'uglify:compress',
  ]);
};
```

```json:package.json
{
  "name": "test_grunt",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "grunt": "^0.4.5",
    "grunt-contrib-coffee": "^0.13.0",
    "grunt-contrib-connect": "^0.10.1",
    "grunt-contrib-copy": "^0.8.0",
    "grunt-contrib-csslint": "^0.4.0",
    "grunt-contrib-cssmin": "^0.12.2",
    "grunt-contrib-htmlmin": "^0.4.0",
    "grunt-contrib-jshint": "^0.11.1",
    "grunt-contrib-sass": "^0.9.2",
    "grunt-contrib-uglify": "^0.8.1",
    "grunt-contrib-watch": "^0.6.1",
    "grunt-ect": "^0.1.2",
    "grunt-html-validation": "^0.1.18"
  }
}
```