Skip to content

Commit 695347b

Browse files
author
Jarrod Overson
committedNov 24, 2012
added preserveComments option, updated docs, moved to uglify-js proper, added tests (multifile and comments)
1 parent a2c2ce2 commit 695347b

12 files changed

+9645
-72
lines changed
 

‎CONTRIBUTING.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Please see the [Contributing to grunt](http://gruntjs.com/contributing) guide for information on contributing to this project.

‎Gruntfile.js

+24-8
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,6 @@ module.exports = function(grunt) {
3939
mangle : false
4040
}
4141
},
42-
compressed_mangled_sourcemap: {
43-
files: {
44-
'/dev/null': ['test/fixtures/lodash.js']
45-
},
46-
options : {
47-
source_map : 'tmp/lodash-c-m-oDEVNULL--source-map.js'
48-
}
49-
},
5042
compressed_mangled_DEFAULT: {
5143
files: {
5244
'tmp/lodash-c-m.js': ['test/fixtures/lodash.js']
@@ -72,6 +64,30 @@ module.exports = function(grunt) {
7264
mangle : {},
7365
beautify : {}
7466
}
67+
},
68+
multifile_out: {
69+
files: {
70+
'tmp/jquery-lodash-c-m.js': ['test/fixtures/*.js','!test/fixtures/_*']
71+
},
72+
options : {
73+
mangle : false
74+
}
75+
},
76+
preserveComments_some : {
77+
src : 'test/fixtures/_comments.js',
78+
dest : 'tmp/comments.js',
79+
options : {
80+
mangle : false,
81+
preserveComments : 'some'
82+
}
83+
},
84+
compressed_mangled_sourcemap: {
85+
files: {
86+
'/dev/null': ['test/fixtures/lodash.js']
87+
},
88+
options : {
89+
source_map : 'tmp/lodash-c-m-oDEVNULL--source-map.js'
90+
}
7591
}
7692
},
7793

‎README.md

+15-3
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,22 @@ Default: `false`
5858
Turns on beautification of the generated source code. Any extra options passed are merged with the options sent to `UglifyJS2.OutputStream()`.
5959

6060
#### source_map
61-
Type: `string`
61+
Type: `string`, `Object`
6262
Default: `undefined`
6363

64-
Specify the sourcemap location to output.
64+
Specify the sourcemap location to output or, as an `Object`, specify the options to pass directly to UglifyJS.SourceMap()
65+
66+
#### preserveComments
67+
Type: `Boolean`, `string`, `Function`
68+
Default: `undefined`
69+
Options: `false`, `true` | `'all'`, `'some'`
70+
71+
Turn on preservation of comments.
72+
73+
-`false` will turn off all comments
74+
-`'all'` will preserve all comments in code blocks that have not been squashed or dropped
75+
-`'some'` will preserve all comments that start with a bang (`!`) or a closure compiler style directive (`@preserve`, `@license`, `@cc_on`)
76+
-`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`
6577

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

150-
*Generated on Sun Nov 18 2012 07:27:10.*
162+
*Generated on Fri Nov 23 2012 23:10:05.*

‎docs/uglify-options.md

+14-2
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,22 @@ Default: `false`
2323
Turns on beautification of the generated source code. Any extra options passed are merged with the options sent to `UglifyJS2.OutputStream()`.
2424

2525
## source_map
26-
Type: `string`
26+
Type: `string`, `Object`
2727
Default: `undefined`
2828

29-
Specify the sourcemap location to output.
29+
Specify the sourcemap location to output or, as an `Object`, specify the options to pass directly to UglifyJS.SourceMap()
30+
31+
## preserveComments
32+
Type: `Boolean`, `string`, `Function`
33+
Default: `undefined`
34+
Options: `false`, `true` | `'all'`, `'some'`
35+
36+
Turn on preservation of comments.
37+
38+
-`false` will turn off all comments
39+
-`'all'` will preserve all comments in code blocks that have not been squashed or dropped
40+
-`'some'` will preserve all comments that start with a bang (`!`) or a closure compiler style directive (`@preserve`, `@license`, `@cc_on`)
41+
-`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`
3042

3143
## banner
3244
Type: `string`

‎package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
},
3030
"dependencies": {
3131
"gzip-js": "~0.3.1",
32-
"uglify-js2": "~2.1.10"
32+
"uglify-js": "~2.2.1"
3333
},
3434
"devDependencies": {
3535
"grunt-contrib-jshint": "0.1.0",

‎tasks/lib/uglify.js

+48-23
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
'use strict';
1010

1111
// External libs.
12-
var uglifyjs = require('uglify-js2');
12+
var UglifyJS = require('uglify-js');
1313
var gzip = require('gzip-js');
1414
var fs = require('fs');
1515

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

2424
options = options || {};
2525

26-
var code = grunt.file.read(src);
2726
grunt.verbose.write('Minifying with UglifyJS...');
2827
try {
29-
30-
var ast = uglifyjs.parse(code, {
31-
// filename necessary for source map
32-
filename : src
33-
});
28+
var topLevel = null,
29+
totalCode = '';
30+
31+
files.forEach(function(file){
32+
var code = grunt.file.read(file);
33+
totalCode += code;
34+
topLevel = UglifyJS.parse(code, {
35+
filename : file,
36+
toplevel : topLevel
37+
})
38+
})
3439

3540
var outputOptions = {
3641
beautify : false,
3742
source_map : null
3843
};
3944

45+
if (options.preserveComments) {
46+
if (options.preserveComments === 'all' || options.preserveComments === true) {
47+
// preserve all the comments we can
48+
outputOptions.comments = true;
49+
} else if (options.preserveComments === 'some') {
50+
// preserve comments with directives or that start with a bang (!)
51+
outputOptions.comments = function(node, comment) {
52+
return /^!|@preserve|@license|@cc_on/i.test(comment.value);
53+
}
54+
} else if (grunt.util._.isFunction(options.preserveComments)) {
55+
// support custom functions passed in
56+
outputOptions.comments = options.preserveComments;
57+
}
58+
}
59+
4060
if (options.beautify) {
4161
grunt.util._.extend(outputOptions, options.beautify);
4262
outputOptions.beautify = true;
4363
}
4464

4565
if (options.source_map) {
46-
outputOptions.source_map = uglifyjs.SourceMap({
47-
file : dest,
48-
root: undefined,
49-
orig: undefined
50-
});
66+
if (grunt.util._.isObject(options.source_map)) {
67+
outputOptions.source_map = UglifyJS.SourceMap(options.source_map);
68+
} else {
69+
outputOptions.source_map = UglifyJS.SourceMap({
70+
file : dest,
71+
root: undefined,
72+
orig: undefined
73+
});
74+
}
5175
}
5276

53-
var output = uglifyjs.OutputStream(outputOptions);
77+
var output = UglifyJS.OutputStream(outputOptions);
5478

5579
// Need to call this before we mangle or compress,
5680
// and call after any compression or ast altering
57-
ast.figure_out_scope();
81+
topLevel.figure_out_scope();
5882

5983
if (options.compress !== false) {
60-
var compressor = uglifyjs.Compressor(options.compress);
61-
ast = ast.transform(compressor);
84+
if (options.compress.warnings !== true) options.compress.warnings = false;
85+
var compressor = UglifyJS.Compressor(options.compress);
86+
topLevel = topLevel.transform(compressor);
6287

6388
// Need to figure out scope again after source being altered
64-
ast.figure_out_scope();
89+
topLevel.figure_out_scope();
6590
}
6691

6792
if (options.mangle !== false ) {
6893
// compute_char_frequency optimizes names for compression
69-
ast.compute_char_frequency(options.mangle);
94+
topLevel.compute_char_frequency(options.mangle);
7095

7196
// Requires previous call to figure_out_scope
7297
// and should always be called after compressor transform
73-
ast.mangle_names(options.mangle);
98+
topLevel.mangle_names(options.mangle);
7499
}
75100

76101
// Print the ast to OutputStream
77-
ast.print(output);
102+
topLevel.print(output);
78103

79104
var min = output.get();
80105

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

85110
var result = {
86-
max : code,
111+
max : totalCode,
87112
min : min,
88113
source_map : outputOptions.source_map
89114
};
@@ -93,7 +118,7 @@ exports.init = function(grunt) {
93118
return result;
94119
} catch(e) {
95120
grunt.verbose.error();
96-
if (e instanceof uglifyjs.DefaultsError) {
121+
if (e instanceof UglifyJS.DefaultsError) {
97122
grunt.warn(e.msg);
98123
grunt.verbose.log("Supported options:");
99124
grunt.verbose.debug(e.defs);

‎tasks/uglify.js

+29-35
Original file line numberDiff line numberDiff line change
@@ -17,49 +17,43 @@ module.exports = function(grunt) {
1717
grunt.registerMultiTask('uglify', 'Minify files with UglifyJS.', function() {
1818
// Merge task-specific and/or target-specific options with these defaults.
1919
var options = this.options({
20-
banner: '',
21-
uglify: {}
20+
banner : '',
21+
compress : {
22+
warnings : false
23+
},
24+
mangle : {},
25+
beautify : false
2226
});
2327

24-
// Process banner.
25-
var banner = grunt.template.process(options.banner);
26-
27-
// Iterate over all specified file groups.
28-
this.files.forEach(function(fileObj) {
29-
// The source file to be minified.
30-
var srcpath = fileObj.src[0];
31-
var files = grunt.file.expandFiles(srcpath);
32-
// Abort if source didn't match any files.
33-
if (files.length === 0) {
34-
grunt.log.error('Source file "' + srcpath + '" not found.');
35-
return;
36-
}
28+
// Abort if source didn't match any files.
29+
if (this.file.src.length === 0) {
30+
grunt.log.error('No source files found.');
31+
return;
32+
}
3733

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

40-
// Get source of specified file.
41-
var result = uglify.minify(src, fileObj.dest, options);
42-
43-
// Concat banner + minified source.
44-
var output = banner + result.min;
37+
// Concat banner + minified source.
38+
var banner = grunt.template.process(options.banner);
39+
var output = banner + result.min;
4540

46-
// Write the destination file.
47-
grunt.file.write(fileObj.dest, output);
41+
// Write the destination file.
42+
grunt.file.write(this.file.dest, output);
4843

49-
// Write sourcemap
50-
if (options.source_map) {
51-
grunt.file.write(options.source_map, result.source_map);
52-
}
44+
// Write sourcemap
45+
if (options.source_map) {
46+
grunt.file.write(options.source_map, result.source_map);
47+
}
5348

54-
// Print a success message.
55-
grunt.log.writeln('File "' + fileObj.dest + '" created.');
49+
// Print a success message.
50+
grunt.log.writeln('File "' + this.file.dest + '" created.');
5651

57-
// ...and report some size information.
58-
minlib.info(result.min, result.max);
59-
}, this);
52+
// ...and report some size information.
53+
minlib.info(result.min, result.max);
54+
}, this);
6055

61-
// Fail task if any errors were logged.
62-
if (this.errorCount > 0) { return false; }
63-
});
56+
// Fail task if any errors were logged.
57+
if (this.errorCount > 0) { return false; }
6458

6559
};

‎test/expected/comments.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*!
2+
* I am a comment
3+
*/
4+
function foo(){return 42}// @preserve preserve
5+
// @license license
6+
function bar(){return 2*foo()}/* @preserve
7+
* multiline preserve
8+
*/
9+
/* @license
10+
* multiline license
11+
*/
12+
function baz(){return bar()*bar()}

‎test/expected/jquery-lodash-c-m.js

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎test/fixtures/_comments.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*!
2+
* I am a comment
3+
*/
4+
function foo() {
5+
return 42;
6+
}
7+
// @preserve preserve
8+
// @license license
9+
function bar() {
10+
return foo()*2;
11+
}
12+
/* @preserve
13+
* multiline preserve
14+
*/
15+
/* @license
16+
* multiline license
17+
*/
18+
function baz() {
19+
return bar()*bar();
20+
}
21+
// end - not preserved

‎test/fixtures/jquery-1.8.3.js

+9,472
Large diffs are not rendered by default.

‎test/uglify_test.js

+2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ exports.contrib_uglify = {
1313
'lodash-c-m.js',
1414
'lodash-c-m-rarrayRef.js',
1515
'lodash-c-m-b.js',
16+
'comments.js',
1617
'lodash-c-m-oDEVNULL--source-map.js',
18+
'jquery-lodash-c-m.js',
1719
];
1820

1921
test.expect(files.length);

0 commit comments

Comments
 (0)
Please sign in to comment.