1 /*global module:false*/
2 module.exports = function(grunt) {
5 // Project configuration
8 pkg: grunt.file.readJSON('package.json'),
9 fragments: './build/fragments/',
11 ' * Knockout JavaScript library v<%= pkg.version %>\n' +
12 ' * (c) Steven Sanderson - <%= pkg.homepage %>\n' +
13 ' * License: <%= pkg.licenses[0].type %> (<%= pkg.licenses[0].url %>)\n' +
16 checktrailingspaces: {
19 "**/*.{js,html,css,bat,ps1,sh}",
27 debug: './build/output/knockout-latest.debug.js',
28 min: './build/output/knockout-latest.js'
31 debug: './dist/knockout.debug.js',
32 min: './dist/knockout.js'
35 phantomjs: 'spec/runner.phantom.js',
36 node: 'spec/runner.node.js'
40 grunt.registerTask('clean', 'Clean up output files.', function (target) {
41 var output = grunt.config('build');
42 var files = [ output.debug, output.min ];
43 var options = { force: (target == 'force') };
44 _.forEach(files, function (file) {
45 if (grunt.file.exists(file))
46 grunt.file.delete(file, options);
48 return !this.errorCount;
51 var trailingSpaceRegex = /[ ]$/;
52 grunt.registerMultiTask('checktrailingspaces', 'checktrailingspaces', function() {
54 this.files[0].src.forEach(function(filepath) {
55 var content = grunt.file.read(filepath),
56 lines = content.split(/\r*\n/);
57 lines.forEach(function(line, index) {
58 if (trailingSpaceRegex.test(line)) {
59 matches.push([filepath, (index+1), line].join(':'));
64 grunt.log.error("The following files have trailing spaces that need to be cleaned up:");
65 grunt.log.writeln(matches.join('\n'));
70 function getReferencedSources(sourceReferencesFilename) {
71 // Returns the array of filenames referenced by a file like source-references.js
73 global.knockoutDebugCallback = function(sources) { result = sources; };
74 eval(grunt.file.read(sourceReferencesFilename));
78 function getCombinedSources() {
79 var fragments = grunt.config('fragments'),
81 fragments + 'extern-pre.js',
82 fragments + 'amd-pre.js',
83 getReferencedSources(fragments + 'source-references.js'),
84 fragments + 'amd-post.js',
85 fragments + 'extern-post.js'
87 flattenedSourceFilenames = Array.prototype.concat.apply([], sourceFilenames),
88 combinedSources = flattenedSourceFilenames.map(function(filename) {
89 return grunt.file.read('./' + filename);
92 return combinedSources.replace('##VERSION##', grunt.config('pkg.version'));
95 function buildDebug(output) {
97 source.push(grunt.config('banner'));
98 source.push('(function(){\n');
99 source.push('var DEBUG=true;\n');
100 source.push(getCombinedSources());
101 source.push('})();\n');
102 grunt.file.write(output, source.join('').replace(/\r\n/g, '\n'));
105 function buildMin(output, done) {
106 var cc = require('closure-compiler');
108 compilation_level: 'ADVANCED_OPTIMIZATIONS',
109 output_wrapper: '(function() {%output%})();'
111 grunt.log.write('Compiling...');
112 cc.compile('/**@const*/var DEBUG=false;' + getCombinedSources(), options, function (err, stdout, stderr) {
114 grunt.log.error(err);
118 grunt.file.write(output, (grunt.config('banner') + stdout).replace(/\r\n/g, '\n'));
124 grunt.registerMultiTask('build', 'Build', function() {
125 if (!this.errorCount) {
126 var output = this.data;
127 if (this.target === 'debug') {
129 } else if (this.target === 'min') {
130 buildMin(output, this.async());
133 return !this.errorCount;
136 grunt.registerMultiTask('test', 'Run tests', function () {
137 var done = this.async();
138 grunt.util.spawn({ cmd: this.target, args: [this.data] },
139 function (error, result, code) {
140 if (code === 127 /*not found*/) {
141 grunt.verbose.error(result.stderr);
145 grunt.log.writeln(result.stdout);
147 grunt.log.error(result.stderr);
154 grunt.registerTask('dist', function() {
155 var version = grunt.config('pkg.version'),
156 buildConfig = grunt.config('build'),
157 distConfig = grunt.config('dist');
158 grunt.file.copy(buildConfig.debug, distConfig.debug);
159 grunt.file.copy(buildConfig.min, distConfig.min);
161 console.log('To publish, run:');
162 console.log(' git add bower.json');
163 console.log(' git add -f ' + distConfig.debug);
164 console.log(' git add -f ' + distConfig.min);
165 console.log(' git checkout head');
166 console.log(' git commit -m \'Version ' + version + ' for distribution\'');
167 console.log(' git tag -a v' + version + ' -m \'Add tag v' + version + '\'');
168 console.log(' git checkout master');
169 console.log(' git push origin --tags');
173 grunt.registerTask('default', ['clean', 'checktrailingspaces', 'build', 'test']);