Preserve whitespace around inline <ruby> (#905)
[html-minifier.git] / Gruntfile.js
1 'use strict';
2
3 function qunitVersion() {
4   var prepareStackTrace = Error.prepareStackTrace;
5   Error.prepareStackTrace = function() {
6     return '';
7   };
8   try {
9     return require('qunit').version;
10   }
11   finally {
12     Error.prepareStackTrace = prepareStackTrace;
13   }
14 }
15
16 module.exports = function(grunt) {
17   // Force use of Unix newlines
18   grunt.util.linefeed = '\n';
19
20   grunt.initConfig({
21     pkg: grunt.file.readJSON('package.json'),
22     qunit_ver: qunitVersion(),
23     banner: '/*!\n' +
24             ' * HTMLMinifier v<%= pkg.version %> (<%= pkg.homepage %>)\n' +
25             ' * Copyright 2010-<%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
26             ' * Licensed under the <%= pkg.license %> license\n' +
27             ' */\n',
28
29     browserify: {
30       src: {
31         options: {
32           banner: '<%= banner %>',
33           preBundleCB: function() {
34             var fs = require('fs');
35             var UglifyJS = require('uglify-js');
36             var files = {};
37             UglifyJS.FILES.forEach(function(file) {
38               files[file] = fs.readFileSync(file, 'utf8');
39             });
40             fs.writeFileSync('./dist/uglify.js', UglifyJS.minify(files, {
41               compress: false,
42               mangle: false,
43               wrap: 'exports'
44             }).code);
45           },
46           postBundleCB: function(err, src, next) {
47             require('fs').unlinkSync('./dist/uglify.js');
48             next(err, src);
49           },
50           require: [
51             './dist/uglify.js:uglify-js',
52             './src/htmlminifier.js:html-minifier'
53           ]
54         },
55         src: 'src/htmlminifier.js',
56         dest: 'dist/htmlminifier.js'
57       }
58     },
59
60     eslint: {
61       grunt: {
62         src: 'Gruntfile.js'
63       },
64       src: {
65         src: ['cli.js', 'src/**/*.js']
66       },
67       tests: {
68         src: ['tests/*.js', 'test.js']
69       },
70       web: {
71         src: ['assets/master.js', 'assets/worker.js']
72       },
73       other: {
74         src: ['backtest.js', 'benchmark.js']
75       }
76     },
77
78     qunit: {
79       htmlminifier: ['./tests/minifier', 'tests/index.html']
80     },
81
82     replace: {
83       './index.html': [
84         /(<h1>.*?<span>).*?(<\/span><\/h1>)/,
85         '$1(v<%= pkg.version %>)$2'
86       ],
87       './tests/index.html': [
88         /("[^"]+\/qunit-)[0-9.]+?(\.(?:css|js)")/g,
89         '$1<%= qunit_ver %>$2'
90       ]
91     },
92
93     uglify: {
94       options: {
95         banner: '<%= banner %>',
96         compress: true,
97         mangle: true,
98         preserveComments: false,
99         report: 'min'
100       },
101       minify: {
102         files: {
103           'dist/htmlminifier.min.js': '<%= browserify.src.dest %>'
104         }
105       }
106     }
107   });
108
109   grunt.loadNpmTasks('grunt-browserify');
110   grunt.loadNpmTasks('grunt-contrib-uglify');
111   grunt.loadNpmTasks('gruntify-eslint');
112
113   function report(type, details) {
114     grunt.log.writeln(type + ' completed in ' + details.runtime + 'ms');
115     details.failures.forEach(function(details) {
116       grunt.log.error();
117       grunt.log.error(details.name + (details.message ? ' [' + details.message + ']' : ''));
118       grunt.log.error(details.source);
119       grunt.log.error('Actual:');
120       grunt.log.error(details.actual);
121       grunt.log.error('Expected:');
122       grunt.log.error(details.expected);
123     });
124     grunt.log[details.failed ? 'error' : 'ok'](details.passed + ' of ' + details.total + ' passed, ' + details.failed + ' failed');
125     return details.failed;
126   }
127
128   var phantomjs = require('phantomjs-prebuilt').path;
129   grunt.registerMultiTask('qunit', function() {
130     var done = this.async();
131     var errors = [];
132
133     function run(testType, binPath, testPath) {
134       grunt.util.spawn({
135         cmd: binPath,
136         args: ['test.js', testPath]
137       }, function(error, result) {
138         if (error) {
139           grunt.log.error(result.stderr);
140           grunt.log.error(testType + ' test failed to load');
141           errors.push(-1);
142         }
143         else {
144           var output = result.stdout;
145           var index = output.lastIndexOf('\n');
146           if (index !== -1) {
147             // There's something before the report JSON
148             // Log it to the console -- it's probably some debug output:
149             console.log(output.slice(0, index));
150             output = output.slice(index);
151           }
152           errors.push(report(testType, JSON.parse(output)));
153         }
154         if (errors.length === 2) {
155           done(!errors[0] && !errors[1]);
156         }
157       });
158     }
159
160     run('node', process.argv[0], this.data[0]);
161     run('web', phantomjs, this.data[1]);
162   });
163
164   grunt.registerMultiTask('replace', function() {
165     var pattern = this.data[0];
166     var path = this.target;
167     var html = grunt.file.read(path);
168     html = html.replace(pattern, this.data[1]);
169     grunt.file.write(path, html);
170   });
171
172   grunt.registerTask('dist', [
173     'replace',
174     'browserify',
175     'uglify'
176   ]);
177
178   grunt.registerTask('test', [
179     'eslint',
180     'dist',
181     'qunit'
182   ]);
183
184   grunt.registerTask('default', 'test');
185 };