lib/uglifier.rb in uglifier-4.1.20 vs lib/uglifier.rb in uglifier-4.2.0

- old
+ new

@@ -96,10 +96,11 @@ :define => {}, # Define values for symbol replacement :keep_fnames => false, # Generate code safe for the poor souls relying on Function.prototype.name at run-time. Sets both compress and mangle keep_fanems to true. :toplevel => false, :ie8 => true, # Generate safe code for IE8 :source_map => false, # Generate source map + :error_context_lines => 8, # How many lines surrounding the error line :harmony => false # Enable ES6/Harmony mode (experimental). Disabling mangling and compressing is recommended with Harmony mode. } EXTRA_OPTIONS = [:comments, :mangle_properties] @@ -147,13 +148,10 @@ def initialize(options = {}) (options.keys - DEFAULTS.keys - EXTRA_OPTIONS)[0..1].each do |missing| raise ArgumentError, "Invalid option: #{missing}" end @options = options - - source = harmony? ? source_with(HarmonySourcePath) : source_with(SourcePath) - @context = ExecJS.compile(source) end # Minifies JavaScript code # # @param source [IO, String] valid JS source code. @@ -178,10 +176,17 @@ run_uglifyjs(source, true) end private + def context + @context ||= begin + source = harmony? ? source_with(HarmonySourcePath) : source_with(SourcePath) + ExecJS.compile(source) + end + end + def source_map_comments return '' unless @options[:source_map].respond_to?(:[]) suffix = '' if @options[:source_map][:map_url] @@ -211,28 +216,80 @@ :parse => parse_options, :sourceMap => source_map_options(input_map), :ie8 => ie8? } - parse_result(@context.call("uglifier", options), generate_map) + parse_result(context.call("uglifier", options), generate_map, options) end def harmony? @options[:harmony] end - def error_message(result) - result['error']['message'] + - if result['error']['message'].start_with?("Unexpected token") && !harmony? - ". To use ES6 syntax, harmony mode must be enabled with " \ - "Uglifier.new(:harmony => true)." + def harmony_error_message(message) + if message.start_with?("Unexpected token") + ". To use ES6 syntax, harmony mode must be enabled with " \ + "Uglifier.new(:harmony => true)." + else + "" + end + end + + def error_context_lines + @options.fetch(:error_context_lines, DEFAULTS[:error_context_lines]).to_i + end + + def error_context_format_options(low, high, line_index, column) + line_width = high.to_s.size + { + :line_index => line_index, + :base_index => low, + :line_width => line_width, + :line_format => "\e[36m%#{line_width + 1}d\e[0m ", # cyan + :col => column + } + end + + def format_error_line(line, options) + # light red + indicator = ' => '.rjust(options[:line_width] + 2) + colored_line = "#{line[0...options[:col]]}\e[91m#{line[options[:col]..-1]}" + "\e[91m#{indicator}\e[0m#{colored_line}\e[0m" + end + + def format_lines(lines, options) + lines.map.with_index do |line, index| + if options[:base_index] + index == options[:line_index] + format_error_line(line, options) else - "" + "#{options[:line_format] % (options[:base_index] + index + 1)}#{line}" end + end end - def parse_result(result, generate_map) - raise Error, error_message(result) if result.has_key?('error') + def context_lines_message(source, line_number, column) + return if line_number.nil? + + line_index = line_number - 1 + lines = source.split("\n") + + first_line = [line_index - error_context_lines, 0].max + last_line = [line_number + error_context_lines, lines.size].min + options = error_context_format_options(first_line, last_line, line_index, column) + context_lines = lines[first_line...last_line] + + "--\n#{format_lines(context_lines, options).join("\n")}\n==" + end + + def error_message(result, options) + err = result['error'] + harmony_msg = harmony? ? '' : harmony_error_message(err['message'].to_s) + src_ctx = context_lines_message(options[:source], err['line'], err['col']) + "#{err['message']}#{harmony_msg}\n#{src_ctx}" + end + + def parse_result(result, generate_map, options) + raise Error, error_message(result, options) if result.has_key?('error') if generate_map [result['code'] + source_map_comments, result['map']] else result['code'] + source_map_comments