Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

138 lines (115 sloc) 4.178 kb
# encoding: UTF-8
require "execjs"
require "multi_json"
class Uglifier
Error = ExecJS::Error
# MultiJson.engine = :json_gem
# Default options for compilation
DEFAULTS = {
:mangle => true, # Mangle variable and function names, use :vars to skip function mangling
:toplevel => false, # Mangle top-level variable names
:except => ["$super"], # Variable names to be excluded from mangling
:max_line_length => 32 * 1024, # Maximum line length
:squeeze => true, # Squeeze code resulting in smaller, but less-readable code
:seqs => true, # Reduce consecutive statements in blocks into single statement
:dead_code => true, # Remove dead code (e.g. after return)
:lift_vars => false, # Lift all var declarations at the start of the scope
:unsafe => false, # Optimizations known to be unsafe in some situations
:copyright => true, # Show copyright message
:ascii_only => false, # Encode non-ASCII characters as Unicode code points
:inline_script => false, # Escape </script
:quote_keys => false, # Quote keys in object literals
:beautify => false, # Ouput indented code
:beautify_options => {
:indent_level => 4,
:indent_start => 0,
:space_colon => false
}
}
SourcePath = File.expand_path("../uglify.js", __FILE__)
ES5FallbackPath = File.expand_path("../es5.js", __FILE__)
# Minifies JavaScript code using implicit context.
#
# source should be a String or IO object containing valid JavaScript.
# options contain optional overrides to Uglifier::DEFAULTS
#
# Returns minified code as String
def self.compile(source, options = {})
self.new(options).compile(source)
end
# Initialize new context for Uglifier with given options
#
# options - Hash of options to override Uglifier::DEFAULTS
def initialize(options = {})
@options = DEFAULTS.merge(options)
@context = ExecJS.compile(File.open(ES5FallbackPath, "r:UTF-8").read + File.open(SourcePath, "r:UTF-8").read)
end
# Minifies JavaScript code
#
# source should be a String or IO object containing valid JavaScript.
#
# Returns minified code as String
def compile(source)
source = source.respond_to?(:read) ? source.read : source.to_s
js = []
js << "var result = '';"
js << "var source = #{MultiJson.dump(source)};"
js << "var ast = UglifyJS.parser.parse(source);"
if @options[:lift_vars]
js << "ast = UglifyJS.uglify.ast_lift_variables(ast);"
end
if @options[:copyright]
js << <<-JS
var comments = UglifyJS.parser.tokenizer(source)().comments_before;
for (var i = 0; i < comments.length; i++) {
var c = comments[i];
result += (c.type == "comment1") ? "//"+c.value+"\\n" : "/*"+c.value+"*/\\n";
}
JS
end
if @options[:mangle]
js << "ast = UglifyJS.uglify.ast_mangle(ast, #{MultiJson.dump(mangle_options)});"
end
if @options[:squeeze]
js << "ast = UglifyJS.uglify.ast_squeeze(ast, #{MultiJson.dump(squeeze_options)});"
end
if @options[:unsafe]
js << "ast = UglifyJS.uglify.ast_squeeze_more(ast);"
end
js << "result += UglifyJS.uglify.gen_code(ast, #{MultiJson.dump(gen_code_options)});"
if !@options[:beautify] && @options[:max_line_length]
js << "result = UglifyJS.uglify.split_lines(result, #{@options[:max_line_length].to_i})"
end
js << "return result + ';';"
@context.exec js.join("\n")
end
alias_method :compress, :compile
private
def mangle_options
{
"toplevel" => @options[:toplevel],
"defines" => {},
"except" => @options[:except],
"no_functions" => @options[:mangle] == :vars
}
end
def squeeze_options
{
"make_seqs" => @options[:seqs],
"dead_code" => @options[:dead_code],
"keep_comps" => !@options[:unsafe]
}
end
def gen_code_options
options = {
:ascii_only => @options[:ascii_only],
:inline_script => @options[:inline_script],
:quote_keys => @options[:quote_keys]
}
if @options[:beautify]
options.merge(:beautify => true).merge(@options[:beautify_options])
else
options
end
end
end
Jump to Line
Something went wrong with that request. Please try again.