Skip to content

Commit

Permalink
added preserveComments option, updated docs, moved to uglify-js prope…
Browse files Browse the repository at this point in the history
…r, added tests (multifile and comments)
  • Loading branch information
Jarrod Overson committed Nov 24, 2012
1 parent a2c2ce2 commit 695347b
Show file tree
Hide file tree
Showing 12 changed files with 9,645 additions and 72 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Please see the [Contributing to grunt](http://gruntjs.com/contributing) guide for information on contributing to this project.
32 changes: 24 additions & 8 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,6 @@ module.exports = function(grunt) {
mangle : false
}
},
compressed_mangled_sourcemap: {
files: {
'/dev/null': ['test/fixtures/lodash.js']
},
options : {
source_map : 'tmp/lodash-c-m-oDEVNULL--source-map.js'
}
},
compressed_mangled_DEFAULT: {
files: {
'tmp/lodash-c-m.js': ['test/fixtures/lodash.js']
Expand All @@ -72,6 +64,30 @@ module.exports = function(grunt) {
mangle : {},
beautify : {}
}
},
multifile_out: {
files: {
'tmp/jquery-lodash-c-m.js': ['test/fixtures/*.js','!test/fixtures/_*']
},
options : {
mangle : false
}
},
preserveComments_some : {
src : 'test/fixtures/_comments.js',
dest : 'tmp/comments.js',
options : {
mangle : false,
preserveComments : 'some'
}
},
compressed_mangled_sourcemap: {
files: {
'/dev/null': ['test/fixtures/lodash.js']
},
options : {
source_map : 'tmp/lodash-c-m-oDEVNULL--source-map.js'
}
}
},

Expand Down
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,22 @@ Default: `false`
Turns on beautification of the generated source code. Any extra options passed are merged with the options sent to `UglifyJS2.OutputStream()`.

#### source_map
Type: `string`
Type: `string`, `Object`
Default: `undefined`

Specify the sourcemap location to output.
Specify the sourcemap location to output or, as an `Object`, specify the options to pass directly to UglifyJS.SourceMap()

#### preserveComments
Type: `Boolean`, `string`, `Function`
Default: `undefined`
Options: `false`, `true` | `'all'`, `'some'`

Turn on preservation of comments.

-`false` will turn off all comments
-`'all'` will preserve all comments in code blocks that have not been squashed or dropped
-`'some'` will preserve all comments that start with a bang (`!`) or a closure compiler style directive (`@preserve`, `@license`, `@cc_on`)
-`Function` specify your own comment preservation function. You will be passed the current node and the current comment and are expected to return a `true`|`false`

#### banner
Type: `string`
Expand Down Expand Up @@ -147,4 +159,4 @@ _(Nothing yet)_
--
Task submitted by <a href="http://benalman.com">"Cowboy" Ben Alman</a>.

*Generated on Sun Nov 18 2012 07:27:10.*
*Generated on Fri Nov 23 2012 23:10:05.*
16 changes: 14 additions & 2 deletions docs/uglify-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,22 @@ Default: `false`
Turns on beautification of the generated source code. Any extra options passed are merged with the options sent to `UglifyJS2.OutputStream()`.

## source_map
Type: `string`
Type: `string`, `Object`
Default: `undefined`

Specify the sourcemap location to output.
Specify the sourcemap location to output or, as an `Object`, specify the options to pass directly to UglifyJS.SourceMap()

## preserveComments
Type: `Boolean`, `string`, `Function`
Default: `undefined`
Options: `false`, `true` | `'all'`, `'some'`

Turn on preservation of comments.

-`false` will turn off all comments
-`'all'` will preserve all comments in code blocks that have not been squashed or dropped
-`'some'` will preserve all comments that start with a bang (`!`) or a closure compiler style directive (`@preserve`, `@license`, `@cc_on`)
-`Function` specify your own comment preservation function. You will be passed the current node and the current comment and are expected to return a `true`|`false`

## banner
Type: `string`
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
},
"dependencies": {
"gzip-js": "~0.3.1",
"uglify-js2": "~2.1.10"
"uglify-js": "~2.2.1"
},
"devDependencies": {
"grunt-contrib-jshint": "0.1.0",
Expand Down
71 changes: 48 additions & 23 deletions tasks/lib/uglify.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
'use strict';

// External libs.
var uglifyjs = require('uglify-js2');
var UglifyJS = require('uglify-js');
var gzip = require('gzip-js');
var fs = require('fs');

Expand All @@ -19,62 +19,87 @@ exports.init = function(grunt) {
// Minify with UglifyJS2.
// From https://github.com/mishoo/UglifyJS2
// API docs at http://lisperator.net/uglifyjs/
exports.minify = function(src, dest, options) {
exports.minify = function(files, dest, options) {

options = options || {};

var code = grunt.file.read(src);
grunt.verbose.write('Minifying with UglifyJS...');
try {

var ast = uglifyjs.parse(code, {
// filename necessary for source map
filename : src
});
var topLevel = null,
totalCode = '';

files.forEach(function(file){
var code = grunt.file.read(file);
totalCode += code;
topLevel = UglifyJS.parse(code, {
filename : file,
toplevel : topLevel
})
})

var outputOptions = {
beautify : false,
source_map : null
};

if (options.preserveComments) {
if (options.preserveComments === 'all' || options.preserveComments === true) {
// preserve all the comments we can
outputOptions.comments = true;
} else if (options.preserveComments === 'some') {
// preserve comments with directives or that start with a bang (!)
outputOptions.comments = function(node, comment) {
return /^!|@preserve|@license|@cc_on/i.test(comment.value);
}
} else if (grunt.util._.isFunction(options.preserveComments)) {
// support custom functions passed in
outputOptions.comments = options.preserveComments;
}
}

if (options.beautify) {
grunt.util._.extend(outputOptions, options.beautify);
outputOptions.beautify = true;
}

if (options.source_map) {
outputOptions.source_map = uglifyjs.SourceMap({
file : dest,
root: undefined,
orig: undefined
});
if (grunt.util._.isObject(options.source_map)) {
outputOptions.source_map = UglifyJS.SourceMap(options.source_map);
} else {
outputOptions.source_map = UglifyJS.SourceMap({
file : dest,
root: undefined,
orig: undefined
});
}
}

var output = uglifyjs.OutputStream(outputOptions);
var output = UglifyJS.OutputStream(outputOptions);

// Need to call this before we mangle or compress,
// and call after any compression or ast altering
ast.figure_out_scope();
topLevel.figure_out_scope();

if (options.compress !== false) {
var compressor = uglifyjs.Compressor(options.compress);
ast = ast.transform(compressor);
if (options.compress.warnings !== true) options.compress.warnings = false;
var compressor = UglifyJS.Compressor(options.compress);
topLevel = topLevel.transform(compressor);

// Need to figure out scope again after source being altered
ast.figure_out_scope();
topLevel.figure_out_scope();
}

if (options.mangle !== false ) {
// compute_char_frequency optimizes names for compression
ast.compute_char_frequency(options.mangle);
topLevel.compute_char_frequency(options.mangle);

// Requires previous call to figure_out_scope
// and should always be called after compressor transform
ast.mangle_names(options.mangle);
topLevel.mangle_names(options.mangle);
}

// Print the ast to OutputStream
ast.print(output);
topLevel.print(output);

var min = output.get();

Expand All @@ -83,7 +108,7 @@ exports.init = function(grunt) {
}

var result = {
max : code,
max : totalCode,
min : min,
source_map : outputOptions.source_map
};
Expand All @@ -93,7 +118,7 @@ exports.init = function(grunt) {
return result;
} catch(e) {
grunt.verbose.error();
if (e instanceof uglifyjs.DefaultsError) {
if (e instanceof UglifyJS.DefaultsError) {
grunt.warn(e.msg);
grunt.verbose.log("Supported options:");
grunt.verbose.debug(e.defs);
Expand Down
64 changes: 29 additions & 35 deletions tasks/uglify.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,49 +17,43 @@ module.exports = function(grunt) {
grunt.registerMultiTask('uglify', 'Minify files with UglifyJS.', function() {
// Merge task-specific and/or target-specific options with these defaults.
var options = this.options({
banner: '',
uglify: {}
banner : '',
compress : {
warnings : false
},
mangle : {},
beautify : false
});

// Process banner.
var banner = grunt.template.process(options.banner);

// Iterate over all specified file groups.
this.files.forEach(function(fileObj) {
// The source file to be minified.
var srcpath = fileObj.src[0];
var files = grunt.file.expandFiles(srcpath);
// Abort if source didn't match any files.
if (files.length === 0) {
grunt.log.error('Source file "' + srcpath + '" not found.');
return;
}
// Abort if source didn't match any files.
if (this.file.src.length === 0) {
grunt.log.error('No source files found.');
return;
}

var src = files[0];
// Get source of specified file.
var result = uglify.minify(this.file.src, this.file.dest, options);

// Get source of specified file.
var result = uglify.minify(src, fileObj.dest, options);

// Concat banner + minified source.
var output = banner + result.min;
// Concat banner + minified source.
var banner = grunt.template.process(options.banner);
var output = banner + result.min;

// Write the destination file.
grunt.file.write(fileObj.dest, output);
// Write the destination file.
grunt.file.write(this.file.dest, output);

// Write sourcemap
if (options.source_map) {
grunt.file.write(options.source_map, result.source_map);
}
// Write sourcemap
if (options.source_map) {
grunt.file.write(options.source_map, result.source_map);
}

// Print a success message.
grunt.log.writeln('File "' + fileObj.dest + '" created.');
// Print a success message.
grunt.log.writeln('File "' + this.file.dest + '" created.');

// ...and report some size information.
minlib.info(result.min, result.max);
}, this);
// ...and report some size information.
minlib.info(result.min, result.max);
}, this);

// Fail task if any errors were logged.
if (this.errorCount > 0) { return false; }
});
// Fail task if any errors were logged.
if (this.errorCount > 0) { return false; }

};
12 changes: 12 additions & 0 deletions test/expected/comments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*!
* I am a comment
*/
function foo(){return 42}// @preserve preserve
// @license license
function bar(){return 2*foo()}/* @preserve
* multiline preserve
*/
/* @license
* multiline license
*/
function baz(){return bar()*bar()}
6 changes: 6 additions & 0 deletions test/expected/jquery-lodash-c-m.js

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions test/fixtures/_comments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*!
* I am a comment
*/
function foo() {
return 42;
}
// @preserve preserve
// @license license
function bar() {
return foo()*2;
}
/* @preserve
* multiline preserve
*/
/* @license
* multiline license
*/
function baz() {
return bar()*bar();
}
// end - not preserved
Loading

0 comments on commit 695347b

Please sign in to comment.