uglifier 2.7.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -0
- data/.travis.yml +9 -8
- data/.yardopts +4 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile +1 -5
- data/README.md +19 -10
- data/Rakefile +1 -26
- data/lib/uglifier.js +111 -0
- data/lib/uglifier.rb +109 -93
- data/lib/uglifier/version.rb +1 -1
- data/lib/uglify.js +3015 -2102
- data/spec/source_map_spec.rb +152 -36
- data/spec/spec_helper.rb +11 -2
- data/spec/uglifier_spec.rb +95 -18
- data/uglifier.gemspec +3 -5
- metadata +16 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 965824e428764606cd1617e6e72b9ab0ad912b7b
|
4
|
+
data.tar.gz: 996b18eac0ad32e9c9ad8b31e7a8ab90c0208039
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d41ff9576c911132ce28f20b530d1c3b925e6caa5416884608e69cbbbe25b1fda4a4a27fb267b320633b6d9bb34c632c9e1c60c5be6b7663309aecb0a17b93df
|
7
|
+
data.tar.gz: 748763a30cd991eec4c52648c0af2a40ae199646cb92b0dc481ff504b1ef388dbfd385817011ca5489dd4ad5f37d0dff0c6d0e52a39fc41b61be6d859946677a
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
@@ -2,12 +2,13 @@ sudo: false
|
|
2
2
|
language: ruby
|
3
3
|
cache: bundler
|
4
4
|
rvm:
|
5
|
-
- 1.8.7
|
6
5
|
- 1.9.3
|
7
6
|
- 2.0.0
|
8
|
-
- 2.1.
|
9
|
-
- 2.2.
|
10
|
-
-
|
7
|
+
- 2.1.7
|
8
|
+
- 2.2.3
|
9
|
+
- 2.3.0
|
10
|
+
- jruby-19mode
|
11
|
+
- jruby-9.0.4.0
|
11
12
|
- rbx-2
|
12
13
|
git:
|
13
14
|
submodules: false
|
@@ -15,16 +16,16 @@ gemfile:
|
|
15
16
|
- Gemfile
|
16
17
|
matrix:
|
17
18
|
include:
|
18
|
-
- rvm: 2.
|
19
|
+
- rvm: 2.3.0
|
19
20
|
gemfile: gemfiles/rubyracer
|
20
|
-
- rvm: 2.1.
|
21
|
+
- rvm: 2.1.7
|
21
22
|
gemfile: gemfiles/rubyracer
|
22
23
|
- rvm: jruby-19mode
|
23
24
|
gemfile: gemfiles/rubyrhino
|
24
|
-
- rvm: 2.
|
25
|
+
- rvm: 2.3.0
|
25
26
|
gemfile: gemfiles/alaska
|
26
27
|
env: ALASKA=1
|
27
28
|
allow_failures:
|
28
|
-
- rvm: 2.
|
29
|
+
- rvm: 2.3.0
|
29
30
|
gemfile: gemfiles/alaska
|
30
31
|
env: ALASKA=1
|
data/.yardopts
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
## 3.0.0 (22 March 2016)
|
2
|
+
|
3
|
+
- drop support for Ruby 1.8
|
4
|
+
- remove json as dependency
|
5
|
+
- discard unused function arguments only in unsafe mode
|
6
|
+
- add `keep_fnames` option to preserve function names in compressed code
|
7
|
+
- add `collapse_vars` option to collapse single-use variables
|
8
|
+
- backwards incompatible changes to source map options
|
9
|
+
- support for inline base64 encoded source maps
|
10
|
+
- mangle property names option (disabled by default)
|
11
|
+
- update UglifyJS to 2.6.2
|
12
|
+
|
1
13
|
## 2.7.2 (26 August 2015)
|
2
14
|
|
3
15
|
- update UglifyJS to 2.4.24
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
# Uglifier
|
1
|
+
# Uglifier
|
2
2
|
|
3
3
|
Ruby wrapper for [UglifyJS](https://github.com/mishoo/UglifyJS2) JavaScript compressor.
|
4
4
|
|
5
|
+
[![Build Status](https://travis-ci.org/lautis/uglifier.svg?branch=master)](https://travis-ci.org/lautis/uglifier)
|
6
|
+
|
5
7
|
## Installation
|
6
8
|
|
7
9
|
Uglifier is available as a ruby gem.
|
@@ -65,6 +67,9 @@ Available options and their defaults are
|
|
65
67
|
:sort => false, # Assign shorter names to most frequently used variables. Often results in bigger output after gzip.
|
66
68
|
:toplevel => false # Mangle names declared in the toplevel scope
|
67
69
|
}, # Mangle variable and function names, set to false to skip mangling
|
70
|
+
:mangle_properties => {
|
71
|
+
:regex => nil # A regular expression to filter property names to be mangled
|
72
|
+
} # Mangle property names, disabled by default
|
68
73
|
:compress => {
|
69
74
|
:sequences => true, # Allow statements to be joined by commas
|
70
75
|
:properties => true, # Rewrite property access using the dot notation
|
@@ -82,22 +87,26 @@ Available options and their defaults are
|
|
82
87
|
:if_return => true, # Optimizations for if/return and if/continue
|
83
88
|
:join_vars => true, # Join consecutive var statements
|
84
89
|
:cascade => true, # Cascade sequences
|
90
|
+
:collapse_vars => false, # Collapse single-use var and const definitions when possible.
|
85
91
|
:negate_iife => true, # Negate immediately invoked function expressions to avoid extra parens
|
86
92
|
:pure_getters => false, # Assume that object property access does not have any side-effects
|
87
93
|
:pure_funcs => nil, # List of functions without side-effects. Can safely discard function calls when the result value is not used
|
88
94
|
:drop_console => false, # Drop calls to console.* functions
|
89
|
-
:angular => false
|
90
|
-
:keep_fargs => false
|
95
|
+
:angular => false, # Process @ngInject annotations
|
96
|
+
:keep_fargs => false, # Preserve unused function arguments
|
97
|
+
:keep_fnames => false # Preserve function names
|
91
98
|
}, # Apply transformations to code, set to false to skip
|
92
99
|
:define => {}, # Define values for symbol replacement
|
93
100
|
:enclose => false, # Enclose in output function wrapper, define replacements as key-value pairs
|
94
|
-
:
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
+
:source_map => {
|
102
|
+
:map_url => false, # Url for source mapping to be appended in minified source
|
103
|
+
:url => false, # Url for original source to be appended in minified source
|
104
|
+
:sources_content => false, # Include original source content in map
|
105
|
+
:filename => nil, # The filename of the input file
|
106
|
+
:root => nil, # The URL of the directory which contains :filename
|
107
|
+
:output_filename => nil, # The filename or URL where the minified output can be found
|
108
|
+
:input_source_map => nil # The contents of the source map describing the input
|
109
|
+
}
|
101
110
|
}
|
102
111
|
```
|
103
112
|
|
data/Rakefile
CHANGED
@@ -1,40 +1,15 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require 'rubygems'
|
4
|
-
require 'bundler'
|
5
3
|
require 'bundler/gem_tasks'
|
6
|
-
|
7
|
-
begin
|
8
|
-
Bundler.setup(:default, :development)
|
9
|
-
rescue Bundler::BundlerError => e
|
10
|
-
$stderr.puts e.message
|
11
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
12
|
-
exit e.status_code
|
13
|
-
end
|
14
|
-
|
15
|
-
require 'rake'
|
16
|
-
|
17
|
-
require 'rspec/core'
|
18
4
|
require 'rspec/core/rake_task'
|
19
5
|
RSpec::Core::RakeTask.new(:spec) do |spec|
|
20
6
|
spec.pattern = FileList['spec/**/*_spec.rb']
|
21
7
|
end
|
22
8
|
|
23
|
-
require 'rdoc/task'
|
24
|
-
Rake::RDocTask.new do |rdoc|
|
25
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
26
|
-
|
27
|
-
rdoc.rdoc_dir = 'rdoc'
|
28
|
-
rdoc.title = "uglifier #{version}"
|
29
|
-
rdoc.rdoc_files.include('README*')
|
30
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
31
|
-
end
|
32
|
-
|
33
9
|
desc "Rebuild lib/uglify.js"
|
34
10
|
task :js do
|
35
11
|
cd 'vendor/source-map/' do
|
36
12
|
`npm install`
|
37
|
-
`node Makefile.dryice.js`
|
38
13
|
end
|
39
14
|
|
40
15
|
cd 'vendor/uglifyjs/' do
|
@@ -54,7 +29,7 @@ end
|
|
54
29
|
begin
|
55
30
|
require 'rubocop/rake_task'
|
56
31
|
RuboCop::RakeTask.new(:rubocop)
|
57
|
-
task :default => [:spec]
|
32
|
+
task :default => [:rubocop, :spec]
|
58
33
|
rescue LoadError
|
59
34
|
task :default => [:spec]
|
60
35
|
end
|
data/lib/uglifier.js
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
function comments(option) {
|
2
|
+
if (Object.prototype.toString.call(option) === '[object Array]') {
|
3
|
+
return new RegExp(option[0], option[1]);
|
4
|
+
} else if (option == "jsdoc") {
|
5
|
+
return function(node, comment) {
|
6
|
+
if (comment.type == "comment2") {
|
7
|
+
return /@preserve|@license|@cc_on/i.test(comment.value);
|
8
|
+
} else {
|
9
|
+
return false;
|
10
|
+
}
|
11
|
+
};
|
12
|
+
} else {
|
13
|
+
return option;
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
function readNameCache(key) {
|
18
|
+
return UglifyJS.readNameCache(null, key);
|
19
|
+
}
|
20
|
+
|
21
|
+
function writeNameCache(key, cache) {
|
22
|
+
return UglifyJS.writeNameCache(null, key, cache);
|
23
|
+
}
|
24
|
+
|
25
|
+
function regexOption(options) {
|
26
|
+
if (typeof options === 'object' && options.regex) {
|
27
|
+
return new RegExp(options.regex[0], options.regex[1]);
|
28
|
+
} else {
|
29
|
+
return null;
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
function parse(source, options) {
|
34
|
+
var ast = UglifyJS.parse(source, options.parse_options);
|
35
|
+
ast.figure_out_scope();
|
36
|
+
|
37
|
+
if (options.compress) {
|
38
|
+
var compressor = UglifyJS.Compressor(options.compress);
|
39
|
+
ast = ast.transform(compressor);
|
40
|
+
ast.figure_out_scope();
|
41
|
+
}
|
42
|
+
|
43
|
+
if (options.mangle) {
|
44
|
+
ast.compute_char_frequency();
|
45
|
+
ast.mangle_names(options.mangle);
|
46
|
+
}
|
47
|
+
|
48
|
+
if (options.mangle_properties) {
|
49
|
+
var regex = regexOption(options.mangle_properties);
|
50
|
+
UglifyJS.mangle_properties(ast, {
|
51
|
+
reserved: [],
|
52
|
+
only_cache: false,
|
53
|
+
regex: regex
|
54
|
+
});
|
55
|
+
}
|
56
|
+
|
57
|
+
if (options.enclose) {
|
58
|
+
ast = ast.wrap_enclose(options.enclose);
|
59
|
+
}
|
60
|
+
return ast;
|
61
|
+
}
|
62
|
+
|
63
|
+
function copySourcesContent(sourceMap, options) {
|
64
|
+
sourceMap.get().setSourceContent(options.parse_options.filename, options.source);
|
65
|
+
|
66
|
+
var original = options.source_map_options.orig;
|
67
|
+
|
68
|
+
if (original && original.sources && original.sourcesContent) {
|
69
|
+
for(var i = 0; i < original.sources.length; i++) {
|
70
|
+
sourceMap.get().setSourceContent(original.sources[i], original.sourcesContent[i]);
|
71
|
+
}
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
function uglifier(options) {
|
76
|
+
var source = options.source;
|
77
|
+
var ast = parse(source, options);
|
78
|
+
var source_map;
|
79
|
+
|
80
|
+
var gen_code_options = options.output;
|
81
|
+
gen_code_options.comments = comments(options.output.comments);
|
82
|
+
|
83
|
+
if (options.generate_map) {
|
84
|
+
source_map = UglifyJS.SourceMap(options.source_map_options);
|
85
|
+
gen_code_options.source_map = source_map;
|
86
|
+
|
87
|
+
if (options.source_map_options.sources_content) {
|
88
|
+
copySourcesContent(source_map, options);
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
var stream = UglifyJS.OutputStream(gen_code_options);
|
93
|
+
ast.print(stream);
|
94
|
+
|
95
|
+
if (options.source_map_options.map_url) {
|
96
|
+
stream += "\n//# sourceMappingURL=" + options.source_map_options.map_url;
|
97
|
+
}
|
98
|
+
|
99
|
+
if (options.source_map_options.url) {
|
100
|
+
stream += "\n//# sourceURL=" + options.source_map_options.url;
|
101
|
+
}
|
102
|
+
|
103
|
+
if (options.generate_map) {
|
104
|
+
if (options.source_map_options.sources_content) {
|
105
|
+
source_map.get().setSourceContent(options.parse_options.filename, options.source);
|
106
|
+
}
|
107
|
+
return [stream.toString(), source_map.toString()];
|
108
|
+
} else {
|
109
|
+
return stream.toString();
|
110
|
+
}
|
111
|
+
}
|
data/lib/uglifier.rb
CHANGED
@@ -1,78 +1,14 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
-
require "execjs"
|
4
3
|
require "json"
|
4
|
+
require "base64"
|
5
|
+
require "execjs"
|
5
6
|
require "uglifier/version"
|
6
7
|
|
7
8
|
# A wrapper around the UglifyJS interface
|
8
9
|
class Uglifier
|
9
10
|
# Error class for compilation errors.
|
10
11
|
Error = ExecJS::Error
|
11
|
-
# JavaScript code to call UglifyJS
|
12
|
-
JS = <<-JS
|
13
|
-
(function(options) {
|
14
|
-
function comments(option) {
|
15
|
-
if (Object.prototype.toString.call(option) === '[object Array]') {
|
16
|
-
return new RegExp(option[0], option[1]);
|
17
|
-
} else if (option == "jsdoc") {
|
18
|
-
return function(node, comment) {
|
19
|
-
if (comment.type == "comment2") {
|
20
|
-
return /@preserve|@license|@cc_on/i.test(comment.value);
|
21
|
-
} else {
|
22
|
-
return false;
|
23
|
-
}
|
24
|
-
}
|
25
|
-
} else {
|
26
|
-
return option;
|
27
|
-
}
|
28
|
-
}
|
29
|
-
|
30
|
-
var source = options.source;
|
31
|
-
var ast = UglifyJS.parse(source, options.parse_options);
|
32
|
-
ast.figure_out_scope();
|
33
|
-
|
34
|
-
if (options.compress) {
|
35
|
-
var compressor = UglifyJS.Compressor(options.compress);
|
36
|
-
ast = ast.transform(compressor);
|
37
|
-
ast.figure_out_scope();
|
38
|
-
}
|
39
|
-
|
40
|
-
if (options.mangle) {
|
41
|
-
ast.compute_char_frequency();
|
42
|
-
ast.mangle_names(options.mangle);
|
43
|
-
}
|
44
|
-
|
45
|
-
if (options.enclose) {
|
46
|
-
ast = ast.wrap_enclose(options.enclose);
|
47
|
-
}
|
48
|
-
|
49
|
-
var gen_code_options = options.output;
|
50
|
-
gen_code_options.comments = comments(options.output.comments);
|
51
|
-
|
52
|
-
if (options.generate_map) {
|
53
|
-
var source_map = UglifyJS.SourceMap(options.source_map_options);
|
54
|
-
gen_code_options.source_map = source_map;
|
55
|
-
}
|
56
|
-
|
57
|
-
var stream = UglifyJS.OutputStream(gen_code_options);
|
58
|
-
|
59
|
-
ast.print(stream);
|
60
|
-
|
61
|
-
if (options.source_map_options.map_url) {
|
62
|
-
stream += "\\n//# sourceMappingURL=" + options.source_map_options.map_url;
|
63
|
-
}
|
64
|
-
|
65
|
-
if (options.source_map_options.url) {
|
66
|
-
stream += "\\n//# sourceURL=" + options.source_map_options.url;
|
67
|
-
}
|
68
|
-
|
69
|
-
if (options.generate_map) {
|
70
|
-
return [stream.toString(), source_map.toString()];
|
71
|
-
} else {
|
72
|
-
return stream.toString();
|
73
|
-
}
|
74
|
-
})
|
75
|
-
JS
|
76
12
|
|
77
13
|
# UglifyJS source path
|
78
14
|
SourcePath = File.expand_path("../uglify.js", __FILE__)
|
@@ -80,6 +16,8 @@ class Uglifier
|
|
80
16
|
ES5FallbackPath = File.expand_path("../es5.js", __FILE__)
|
81
17
|
# String.split shim source path
|
82
18
|
SplitFallbackPath = File.expand_path("../split.js", __FILE__)
|
19
|
+
# UglifyJS wrapper path
|
20
|
+
UglifyJSWrapperPath = File.expand_path("../uglifier.js", __FILE__)
|
83
21
|
|
84
22
|
# Default options for compilation
|
85
23
|
DEFAULTS = {
|
@@ -104,8 +42,10 @@ class Uglifier
|
|
104
42
|
:eval => false, # Mangle names when eval of when is used in scope
|
105
43
|
:except => ["$super"], # Argument names to be excluded from mangling
|
106
44
|
:sort => false, # Assign shorter names to most frequently used variables. Often results in bigger output after gzip.
|
107
|
-
:toplevel => false # Mangle names declared in the toplevel scope
|
45
|
+
:toplevel => false, # Mangle names declared in the toplevel scope
|
46
|
+
:properties => false # Mangle property names
|
108
47
|
}, # Mangle variable and function names, set to false to skip mangling
|
48
|
+
:mangle_properties => false, # Mangle property names
|
109
49
|
:compress => {
|
110
50
|
:sequences => true, # Allow statements to be joined by commas
|
111
51
|
:properties => true, # Rewrite property access using the dot notation
|
@@ -123,23 +63,37 @@ class Uglifier
|
|
123
63
|
:if_return => true, # Optimizations for if/return and if/continue
|
124
64
|
:join_vars => true, # Join consecutive var statements
|
125
65
|
:cascade => true, # Cascade sequences
|
66
|
+
:collapse_vars => false, # Collapse single-use var and const definitions when possible.
|
126
67
|
:negate_iife => true, # Negate immediately invoked function expressions to avoid extra parens
|
127
68
|
:pure_getters => false, # Assume that object property access does not have any side-effects
|
128
69
|
:pure_funcs => nil, # List of functions without side-effects. Can safely discard function calls when the result value is not used
|
129
70
|
:drop_console => false, # Drop calls to console.* functions
|
130
71
|
:angular => false, # Process @ngInject annotations
|
131
|
-
:keep_fargs => false # Preserve unused function arguments
|
72
|
+
:keep_fargs => false, # Preserve unused function arguments
|
73
|
+
:keep_fnames => false # Preserve function names
|
132
74
|
}, # Apply transformations to code, set to false to skip
|
133
75
|
:define => {}, # Define values for symbol replacement
|
134
76
|
:enclose => false, # Enclose in output function wrapper, define replacements as key-value pairs
|
135
|
-
:source_filename => nil, # The filename of the input file
|
136
|
-
:source_root => nil, # The URL of the directory which contains :source_filename
|
137
|
-
:output_filename => nil, # The filename or URL where the minified output can be found
|
138
|
-
:input_source_map => nil, # The contents of the source map describing the input
|
139
77
|
:screw_ie8 => false, # Don't bother to generate safe code for IE8
|
140
|
-
:
|
141
|
-
|
78
|
+
:source_map => false # Generate source map
|
79
|
+
}
|
80
|
+
|
81
|
+
LEGACY_OPTIONS = [:comments, :squeeze, :copyright, :mangle]
|
82
|
+
|
83
|
+
MANGLE_PROPERTIES_DEFAULTS = {
|
84
|
+
:regex => nil # A regular expression to filter property names to be mangled
|
142
85
|
}
|
86
|
+
|
87
|
+
SOURCE_MAP_DEFAULTS = {
|
88
|
+
:map_url => false, # Url for source mapping to be appended in minified source
|
89
|
+
:url => false, # Url for original source to be appended in minified source
|
90
|
+
:sources_content => false, # Include original source content in map
|
91
|
+
:filename => nil, # The filename of the input file
|
92
|
+
:root => nil, # The URL of the directory which contains :filename
|
93
|
+
:output_filename => nil, # The filename or URL where the minified output can be found
|
94
|
+
:input_source_map => nil # The contents of the source map describing the input
|
95
|
+
}
|
96
|
+
|
143
97
|
# rubocop:enable LineLength
|
144
98
|
|
145
99
|
# Minifies JavaScript code using implicit context.
|
@@ -164,7 +118,7 @@ class Uglifier
|
|
164
118
|
#
|
165
119
|
# @param options [Hash] optional overrides to +Uglifier::DEFAULTS+
|
166
120
|
def initialize(options = {})
|
167
|
-
(options.keys - DEFAULTS.keys -
|
121
|
+
(options.keys - DEFAULTS.keys - LEGACY_OPTIONS)[0..1].each do |missing|
|
168
122
|
raise ArgumentError, "Invalid option: #{missing}"
|
169
123
|
end
|
170
124
|
@options = options
|
@@ -176,7 +130,14 @@ class Uglifier
|
|
176
130
|
# @param source [IO, String] valid JS source code.
|
177
131
|
# @return [String] minified code.
|
178
132
|
def compile(source)
|
179
|
-
|
133
|
+
if @options[:source_map]
|
134
|
+
compiled, source_map = run_uglifyjs(source, true)
|
135
|
+
source_map_uri = Base64.strict_encode64(source_map)
|
136
|
+
source_map_mime = "application/json;charset=utf-8;base64"
|
137
|
+
compiled + "\n//# sourceMappingURL=data:#{source_map_mime},#{source_map_uri}"
|
138
|
+
else
|
139
|
+
run_uglifyjs(source, false)
|
140
|
+
end
|
180
141
|
end
|
181
142
|
alias_method :compress, :compile
|
182
143
|
|
@@ -191,25 +152,28 @@ class Uglifier
|
|
191
152
|
private
|
192
153
|
|
193
154
|
def uglifyjs_source
|
194
|
-
[ES5FallbackPath, SplitFallbackPath, SourcePath].map do |file|
|
195
|
-
File.open(file, "r:UTF-8"
|
155
|
+
[ES5FallbackPath, SplitFallbackPath, SourcePath, UglifyJSWrapperPath].map do |file|
|
156
|
+
File.open(file, "r:UTF-8", &:read)
|
196
157
|
end.join("\n")
|
197
158
|
end
|
198
159
|
|
199
160
|
# Run UglifyJS for given source code
|
200
|
-
def run_uglifyjs(
|
161
|
+
def run_uglifyjs(input, generate_map)
|
162
|
+
source = read_source(input)
|
163
|
+
input_map = input_source_map(source, generate_map)
|
201
164
|
options = {
|
202
|
-
:source =>
|
165
|
+
:source => source,
|
203
166
|
:output => output_options,
|
204
167
|
:compress => compressor_options,
|
205
168
|
:mangle => mangle_options,
|
169
|
+
:mangle_properties => mangle_properties_options,
|
206
170
|
:parse_options => parse_options,
|
207
|
-
:source_map_options => source_map_options,
|
171
|
+
:source_map_options => source_map_options(input_map),
|
208
172
|
:generate_map => generate_map,
|
209
173
|
:enclose => enclose_options
|
210
174
|
}
|
211
175
|
|
212
|
-
@context.call(
|
176
|
+
@context.call("uglifier", options)
|
213
177
|
end
|
214
178
|
|
215
179
|
def read_source(source)
|
@@ -221,14 +185,25 @@ class Uglifier
|
|
221
185
|
end
|
222
186
|
|
223
187
|
def mangle_options
|
224
|
-
|
188
|
+
mangle_options = @options.fetch(:mangle, @options[:mangle])
|
189
|
+
conditional_option(mangle_options, DEFAULTS[:mangle])
|
190
|
+
end
|
191
|
+
|
192
|
+
def mangle_properties_options
|
193
|
+
mangle_options = @options.fetch(:mangle_properties, DEFAULTS[:mangle_properties])
|
194
|
+
options = conditional_option(mangle_options, MANGLE_PROPERTIES_DEFAULTS)
|
195
|
+
if options && options[:regex]
|
196
|
+
options.merge(:regex => encode_regexp(options[:regex]))
|
197
|
+
else
|
198
|
+
options
|
199
|
+
end
|
225
200
|
end
|
226
201
|
|
227
202
|
def compressor_options
|
228
203
|
defaults = conditional_option(
|
229
204
|
DEFAULTS[:compress],
|
230
205
|
:global_defs => @options[:define] || {},
|
231
|
-
:screw_ie8 =>
|
206
|
+
:screw_ie8 => screw_ie8?
|
232
207
|
)
|
233
208
|
conditional_option(@options[:compress] || @options[:squeeze], defaults)
|
234
209
|
end
|
@@ -269,24 +244,31 @@ class Uglifier
|
|
269
244
|
|
270
245
|
def screw_ie8?
|
271
246
|
if (@options[:output] || {}).has_key?(:ie_proof)
|
272
|
-
|
247
|
+
!@options[:output][:ie_proof]
|
273
248
|
else
|
274
|
-
@options
|
249
|
+
@options.fetch(:screw_ie8, DEFAULTS[:screw_ie8])
|
275
250
|
end
|
276
251
|
end
|
277
252
|
|
278
|
-
def source_map_options
|
253
|
+
def source_map_options(input_map)
|
254
|
+
options = conditional_option(@options[:source_map], SOURCE_MAP_DEFAULTS)
|
255
|
+
|
279
256
|
{
|
280
|
-
:file =>
|
281
|
-
:root =>
|
282
|
-
:orig =>
|
283
|
-
:map_url =>
|
284
|
-
:url =>
|
257
|
+
:file => options[:output_filename],
|
258
|
+
:root => options.fetch(:root) { input_map ? input_map["sourceRoot"] : nil },
|
259
|
+
:orig => input_map,
|
260
|
+
:map_url => options[:map_url],
|
261
|
+
:url => options[:url],
|
262
|
+
:sources_content => options[:sources_content]
|
285
263
|
}
|
286
264
|
end
|
287
265
|
|
288
266
|
def parse_options
|
289
|
-
|
267
|
+
if @options[:source_map].respond_to?(:[])
|
268
|
+
{ :filename => @options[:source_map][:filename] }
|
269
|
+
else
|
270
|
+
{}
|
271
|
+
end
|
290
272
|
end
|
291
273
|
|
292
274
|
def enclose_options
|
@@ -318,4 +300,38 @@ class Uglifier
|
|
318
300
|
false
|
319
301
|
end
|
320
302
|
end
|
303
|
+
|
304
|
+
def sanitize_map_root(map)
|
305
|
+
if map.nil?
|
306
|
+
nil
|
307
|
+
elsif map.is_a? String
|
308
|
+
sanitize_map_root(JSON.load(map))
|
309
|
+
elsif map["sourceRoot"] == ""
|
310
|
+
map.merge("sourceRoot" => nil)
|
311
|
+
else
|
312
|
+
map
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
def extract_source_mapping_url(source)
|
317
|
+
comment_start = %r{(?://|/\*\s*)}
|
318
|
+
comment_end = %r{\s*(?:\r?\n?\*/|$)?}
|
319
|
+
source_mapping_regex = /#{comment_start}[@#]\ssourceMappingURL=\s*(\S*?)#{comment_end}/
|
320
|
+
rest = /\s#{comment_start}[@#]\s[a-zA-Z]+=\s*(?:\S*?)#{comment_end}/
|
321
|
+
regex = /#{source_mapping_regex}(?:#{rest})*\Z/m
|
322
|
+
match = regex.match(source)
|
323
|
+
match && match[1]
|
324
|
+
end
|
325
|
+
|
326
|
+
def input_source_map(source, generate_map)
|
327
|
+
return nil unless generate_map
|
328
|
+
sanitize_map_root(@options.fetch(:source_map, {}).fetch(:input_source_map) do
|
329
|
+
url = extract_source_mapping_url(source)
|
330
|
+
if url && url.start_with?("data:")
|
331
|
+
Base64.strict_decode64(url.split(",", 2)[-1])
|
332
|
+
end
|
333
|
+
end)
|
334
|
+
rescue ArgumentError, JSON::ParserError
|
335
|
+
nil
|
336
|
+
end
|
321
337
|
end
|