[DRE-commits] [ruby-uglifier] 07/09: manually import github tarball 3.0.4
Praveen Arimbrathodiyil
praveen at moszumanska.debian.org
Sat Jan 28 20:20:53 UTC 2017
This is an automated email from the git hooks/post-receive script.
praveen pushed a commit to branch master
in repository ruby-uglifier.
commit 6f8e9c92a79a4f5e372e7b2b143822201b8dcf6a
Author: Pirate Praveen <praveen at debian.org>
Date: Sun Jan 29 01:31:06 2017 +0530
manually import github tarball 3.0.4
---
gemfiles/alaska | 4 +
gemfiles/rubyracer | 4 +
gemfiles/rubyrhino | 4 +
patches/es5-string-split.patch | 23 +++
spec/source_map_spec.rb | 226 ++++++++++++++++++++++
spec/spec_helper.rb | 32 ++++
spec/uglifier_spec.rb | 412 +++++++++++++++++++++++++++++++++++++++++
7 files changed, 705 insertions(+)
diff --git a/gemfiles/alaska b/gemfiles/alaska
new file mode 100644
index 0000000..455d547
--- /dev/null
+++ b/gemfiles/alaska
@@ -0,0 +1,4 @@
+source "https://rubygems.org"
+
+gemspec :path=> "../"
+gem "alaska", github: "mavenlink/alaska"
diff --git a/gemfiles/rubyracer b/gemfiles/rubyracer
new file mode 100644
index 0000000..3697faf
--- /dev/null
+++ b/gemfiles/rubyracer
@@ -0,0 +1,4 @@
+source "https://rubygems.org"
+
+gemspec :path=> "../"
+gem 'therubyracer'
diff --git a/gemfiles/rubyrhino b/gemfiles/rubyrhino
new file mode 100644
index 0000000..afb5a22
--- /dev/null
+++ b/gemfiles/rubyrhino
@@ -0,0 +1,4 @@
+source "https://rubygems.org"
+
+gemspec :path => "../"
+gem 'therubyrhino'
diff --git a/patches/es5-string-split.patch b/patches/es5-string-split.patch
new file mode 100644
index 0000000..402269f
--- /dev/null
+++ b/patches/es5-string-split.patch
@@ -0,0 +1,23 @@
+diff --git a/lib/split.js b/lib/split.js
+index 43d13a2..8cc2924 100644
+--- a/lib/split.js
++++ b/lib/split.js
+@@ -106,10 +106,11 @@ split = split || function (undef) {
+ return output.length > limit ? output.slice(0, limit) : output;
+ };
+
+- // For convenience
+- String.prototype.split = function (separator, limit) {
+- return self(this, separator, limit);
+- };
++ if ("\n".split(/\n/).length == 0) {
++ String.prototype.split = function (separator, limit) {
++ return self(this, separator, limit);
++ };
++ }
+
+ return self;
+
+--
+2.5.5
+
diff --git a/spec/source_map_spec.rb b/spec/source_map_spec.rb
new file mode 100644
index 0000000..47d60be
--- /dev/null
+++ b/spec/source_map_spec.rb
@@ -0,0 +1,226 @@
+# encoding: UTF-8
+require 'stringio'
+require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
+
+def expect_to_have_inline_source_map(minified, original)
+ options = { :source_map => { :sources_content => true } }
+ _, map = Uglifier.compile_with_map(minified, options)
+ expect(JSON.parse(map).fetch("sourcesContent", [])).to include(original)
+end
+
+describe "Uglifier" do
+ let(:source) do
+ <<-JS
+ function hello () {
+ function world () {
+ return 2;
+ };
+
+ return world() + world();
+ };
+ JS
+ end
+
+ it "generates source maps" do
+ source = File.open("lib/uglify.js", "r:UTF-8").read
+ minified, map = Uglifier.new.compile_with_map(source)
+ expect(minified.length).to be < source.length
+ expect(map.length).to be > 0
+ expect { JSON.parse(map) }.not_to raise_error
+ end
+
+ it "generates source maps with the correct meta-data" do
+ _, json = Uglifier.compile_with_map(
+ source,
+ :source_map => {
+ :filename => "ahoy.js",
+ :output_filename => "ahoy.min.js",
+ :root => "http://localhost/"
+ }
+ )
+
+ map = SourceMap::Map.from_json(json)
+ expect(map.filename).to eq("ahoy.min.js")
+ expect(map.sources).to eq(["ahoy.js"])
+ expect(map.names).to eq(%w(hello world))
+ expect(JSON.parse(json)["sourceRoot"]).to eq("http://localhost/")
+ expect(map[0].generated.line).to eq(1)
+ end
+
+ it "skips copyright lines in source maps" do
+ source = <<-JS
+ /* @copyright Conrad Irwin */
+ function hello () {
+ function world () {
+ return 2;
+ };
+
+ return world() + world();
+ };
+ JS
+
+ _, json = Uglifier.compile_with_map(
+ source,
+ :source_map => {
+ :filename => "ahoy.js",
+ :root => "http://localhost/"
+ }
+ )
+
+ map = SourceMap::Map.from_json(json)
+ expect(map[0].generated.line).to eq(2)
+ end
+
+ it "proceses an input source map" do
+ source = <<-JS
+ function hello () {
+ function world () {
+ return 2;
+ };
+
+ return world() + world();
+ };
+ JS
+
+ minified1, map1 = Uglifier.compile_with_map(
+ source,
+ :source_map => {
+ :filename => "ahoy.js",
+ :root => "http://localhost/"
+ },
+ :mangle => false
+ )
+
+ _, map2 = Uglifier.compile_with_map(
+ source,
+ :source_map => {
+ :input_source_map => map1
+ },
+ :mangle => true
+ )
+
+ expect(minified1.lines.to_a.length).to eq(1)
+
+ map = SourceMap::Map.from_json(map2)
+ expect(map.sources).to eq(["http://localhost/ahoy.js"])
+ expect(map[0].generated.line).to eq(1)
+ expect(map[-1].original.line).to eq(1)
+ end
+
+ it "handles empty string as input map sourceRoot" do
+ _, map1 = Uglifier.compile_with_map(
+ source,
+ :source_map => {
+ :filename => "ahoy.js",
+ :root => ""
+ },
+ :mangle => false
+ )
+
+ _, map = Uglifier.compile_with_map(
+ source,
+ :source_map => {
+ :input_source_map => map1
+ },
+ :mangle => true
+ )
+
+ expect(SourceMap::Map.from_json(map).sources).to eq(["ahoy.js"])
+ end
+
+ it "appends source map url to minified JS" do
+ minified, = Uglifier.compile_with_map(
+ source,
+ :source_map => {
+ :filename => "ahoy.js",
+ :output_filename => "ahoy.min.js",
+ :root => "http://localhost/",
+ :map_url => "http://example.com/map"
+ }
+ )
+ expect(minified).to include("\n//# sourceMappingURL=http://example.com/map")
+ end
+
+ it "appends source url to minified JS" do
+ minified, = Uglifier.compile_with_map(
+ source,
+ :source_map => {
+ :filename => "ahoy.js",
+ :output_filename => "ahoy.min.js",
+ :root => "http://localhost/",
+ :url => "http://example.com/source"
+ }
+ )
+ expect(minified).to include("\n//# sourceURL=http://example.com/source")
+ end
+
+ it "inlines source map" do
+ minified = Uglifier.compile(
+ source,
+ :source_map => {
+ :filename => "ahoy.js",
+ :output_filename => "ahoy.min.js",
+ :root => "http://localhost/",
+ :url => "http://example.com/source"
+ }
+ )
+ source_map_mime = "application/json;charset=utf-8;base64,"
+ expect(minified).to include("\n//# sourceMappingURL=data:#{source_map_mime}")
+ end
+
+ describe "inline source map parsing" do
+ let(:minified) do
+ Uglifier.compile(
+ source,
+ :source_map => {
+ :filename => "ahoy.js",
+ :sources_content => true
+ }
+ )
+ end
+
+ let(:code) { minified.split("\n")[0] }
+ let(:source_mapping_url) { minified.split("\n")[1][2..-1] }
+
+ it "parses inline source maps from line comments" do
+ minified = "#{code}\n//#{source_mapping_url}"
+ expect_to_have_inline_source_map(minified, source)
+ end
+
+ it "parses inline source maps with block comments" do
+ minified = "#{code}\n/*#{source_mapping_url}*/"
+ expect_to_have_inline_source_map(minified, source)
+ end
+
+ it "parses inline source maps with multi-line block comments" do
+ minified = "#{code}\n/*\n#{source_mapping_url}\n*/"
+ expect_to_have_inline_source_map(minified, source)
+ end
+
+ it "parses inline source maps from mixed comments" do
+ minified = "#{code}\n/*\n//#{source_mapping_url}\n*/"
+ expect_to_have_inline_source_map(minified, source)
+ end
+
+ it "only parses source maps at end of file" do
+ minified = "#{code}\n//#{source_mapping_url}\nhello();"
+ _, map = Uglifier.compile_with_map(minified)
+ expect(JSON.parse(map)["sourcesContent"]).to be_nil
+ end
+
+ it "handles other source map declarations at end of file" do
+ minified = "#{code}\n
+ //#{source_mapping_url}\n
+ //# sourceURL=http://example.com/source.js
+ //# sourceURL=http://example.com/source.js
+ "
+ expect_to_have_inline_source_map(minified, source)
+ end
+
+ it "does not explode when data URI is invalid" do
+ minified = "#{code}\n//# sourceMappingURL=data:application/javascript,foobar"
+ _, map = Uglifier.compile_with_map(minified)
+ expect(JSON.parse(map)["sourcesContent"]).to be_nil
+ end
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000..e878a68
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,32 @@
+# encoding: UTF-8
+require 'uglifier'
+require 'rspec'
+require 'sourcemap'
+
+# Requires supporting files with custom matchers and macros, etc,
+# in ./support/ and its subdirectories.
+Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
+
+if ENV["ALASKA"]
+ require 'alaska/runtime'
+ require 'tempfile'
+ ExecJS.runtime = Alaska::Runtime.new
+end
+
+RSpec.configure do |config|
+ config.mock_with :rspec do |mock|
+ mock.syntax = :expect
+ end
+ config.expect_with :rspec do |expect|
+ expect.syntax = :expect
+ end
+
+ if ENV['CI']
+ config.before(:example, :focus) { raise "Do not commit focused specs" }
+ else
+ config.filter_run_including :focus => true
+ config.run_all_when_everything_filtered = true
+ end
+
+ config.warnings = true
+end
diff --git a/spec/uglifier_spec.rb b/spec/uglifier_spec.rb
new file mode 100644
index 0000000..efbd9a3
--- /dev/null
+++ b/spec/uglifier_spec.rb
@@ -0,0 +1,412 @@
+# encoding: UTF-8
+require 'stringio'
+require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
+
+describe "Uglifier" do
+ it "minifies JS" do
+ source = File.open("lib/uglify.js", "r:UTF-8").read
+ minified = Uglifier.new.compile(source)
+ expect(minified.length).to be < source.length
+ expect { Uglifier.new.compile(minified) }.not_to raise_error
+ end
+
+ it "throws an exception when compilation fails" do
+ expect { Uglifier.new.compile(")(") }.to raise_error(Uglifier::Error)
+ end
+
+ it "throws an exception on invalid option" do
+ expect { Uglifier.new(:foo => true) }.to raise_error(ArgumentError)
+ end
+
+ it "doesn't omit null character in strings" do
+ expect(Uglifier.new.compile('var foo="\0bar"')).to include("\\0bar")
+ end
+
+ it "adds trailing semicolon to minified source" do
+ source = "(function id(i) {return i;}());"
+ expect(Uglifier.new.compile(source)[-1]).to eql(";"[0])
+ end
+
+ describe "property name mangling" do
+ let(:source) do
+ <<-JS
+ var obj = {
+ _hidden: false,
+ "name": 'value'
+ };
+
+ alert(object.name);
+ JS
+ end
+
+ it "does not mangle property names by default" do
+ expect(Uglifier.compile(source)).to include("object.name")
+ end
+
+ it "can be configured to mangle properties" do
+ expect(Uglifier.compile(source, :mangle_properties => true))
+ .not_to include("object.name")
+ end
+
+ it "can configure a regex for mangling" do
+ expect(Uglifier.compile(source, :mangle_properties => { :regex => /^_/ }))
+ .to include("object.name")
+ end
+
+ it "can be configured to ignore quotes properties" do
+ expect(Uglifier.compile(source, :mangle_properties => { :ignore_quoted => true }))
+ .to include("object.name")
+ end
+
+ it "can be configured to include debug in mangled properties" do
+ expect(Uglifier.compile(source, :mangle_properties => { :debug => true }))
+ .to include("_$name$_")
+ end
+ end
+
+ describe "argument name mangling" do
+ it "doesn't try to mangle $super by default to avoid breaking PrototypeJS" do
+ expect(Uglifier.compile('function foo($super) {return $super}')).to include("$super")
+ end
+
+ it "allows variables to be excluded from mangling" do
+ code = "function bar(foo) {return foo + 'bar'};"
+ expect(Uglifier.compile(code, :mangle => { :except => ["foo"] }))
+ .to include("(foo)")
+ end
+
+ it "skips mangling when set to false" do
+ code = "function bar(foo) {return foo + 'bar'};"
+ expect(Uglifier.compile(code, :mangle => false)).to include("(foo)")
+ end
+
+ it "mangles argument names by default" do
+ code = "function bar(foo) {return foo + 'bar'};"
+ expect(Uglifier.compile(code)).not_to include("(foo)")
+ end
+
+ it "mangles top-level names when explicitly instructed" do
+ code = "function bar(foo) {return foo + 'bar'};"
+ expect(Uglifier.compile(code, :mangle => { :toplevel => false }))
+ .to include("bar(")
+ expect(Uglifier.compile(code, :mangle => { :toplevel => true }))
+ .not_to include("bar(")
+ end
+
+ it "can be controlled with mangle option" do
+ code = "function bar(foo) {return foo + 'bar'};"
+ expect(Uglifier.compile(code, :mangle => false)).to include("(foo)")
+ end
+ end
+
+ describe "comment preservation" do
+ let(:source) do
+ <<-JS
+ /* @preserve Copyright Notice */
+ /* (c) 2011 */
+ // INCLUDED
+ //! BANG
+ function identity(p) { return p; }
+ /* Another Copyright */
+ /*! Another Bang */
+ // A comment!
+ function add(a, b) { return a + b; }
+ JS
+ end
+
+ it "handles copyright option" do
+ compiled = Uglifier.compile(source, :copyright => false)
+ expect(compiled).not_to match(/Copyright/)
+ end
+
+ describe ":copyright" do
+ subject { Uglifier.compile(source, :comments => :copyright) }
+
+ it "preserves comments with string Copyright" do
+ expect(subject).to match(/Copyright Notice/)
+ expect(subject).to match(/Another Copyright/)
+ end
+
+ it "preserves comments that start with a bang (!)" do
+ expect(subject).to match(/! BANG/)
+ expect(subject).to match(/! Another Bang/)
+ end
+
+ it "ignores other comments" do
+ expect(subject).not_to match(/INCLUDED/)
+ expect(subject).not_to match(/A comment!/)
+ end
+ end
+
+ describe ":jsdoc" do
+ subject { Uglifier.compile(source, :output => { :comments => :jsdoc }) }
+
+ it "preserves jsdoc license/preserve blocks" do
+ expect(subject).to match(/Copyright Notice/)
+ end
+
+ it "ignores other comments" do
+ expect(subject).not_to match(/Another Copyright/)
+ end
+ end
+
+ describe ":all" do
+ subject { Uglifier.compile(source, :comments => :all) }
+
+ it "preserves all comments" do
+ expect(subject).to match(/INCLUDED/)
+ expect(subject).to match(/2011/)
+ end
+ end
+
+ describe ":none" do
+ subject { Uglifier.compile(source, :comments => :none) }
+
+ it "omits all comments" do
+ expect(subject).not_to match(%r{//})
+ expect(subject).not_to match(%r{/\*})
+ end
+ end
+
+ describe "regular expression" do
+ subject { Uglifier.compile(source, :comments => /included/i) }
+
+ it "matches comment blocks with regex" do
+ expect(subject).to match(/INCLUDED/)
+ end
+
+ it "omits other blocks" do
+ expect(subject).not_to match(/2011/)
+ end
+ end
+ end
+
+ it "squeezes code only if squeeze is set to true" do
+ code = "function a(a){if(a) { return 0; } else { return 1; }}"
+ minified = Uglifier.compile(code, :squeeze => false)
+ squeezed = Uglifier.compile(code, :squeeze => true)
+ expect(minified.length).to be > squeezed.length
+ end
+
+ it "honors max line length" do
+ code = "var foo = 123;function bar() { return foo; }"
+ uglifier = Uglifier.new(:output => { :max_line_len => 20 }, :compress => false)
+ expect(uglifier.compile(code).split("\n").map(&:length)).to all(be < 28)
+ end
+
+ it "hoists vars to top of the scope" do
+ code = "function something() { var a = 1; a = 2; var b = 3; return a + b;}"
+ minified = Uglifier.compile(code, :compress => { :hoist_vars => true })
+ expect(minified).to match(/var \w,\w/)
+ end
+
+ describe "screw_ie8 option" do
+ let(:code) { "function something() { return g['switch']; }" }
+
+ it "defaults to not screw IE8" do
+ expect(Uglifier.compile(code)).to match(".switch")
+ end
+
+ it "forwards screw_ie8 option to UglifyJS" do
+ expect(Uglifier.compile(code, :mangle => false, :screw_ie8 => true)).to match(/g\.switch/)
+ expect(Uglifier.compile(code, :compress => false, :screw_ie8 => true)).to match(/g\.switch/)
+ end
+
+ it "supports legacy ie_proof output option as opposite for screw_ie8" do
+ minified = Uglifier.compile(code, :output => { :ie_proof => true })
+ expect(minified).to include('["switch"]')
+ end
+ end
+
+ it "can be configured to output only ASCII" do
+ code = "function emoji() { return '\\ud83c\\ude01'; }"
+ minified = Uglifier.compile(code, :output => { :ascii_only => true })
+ expect(minified).to include("\\ud83c\\ude01")
+ end
+
+ it "escapes </script when asked to" do
+ code = "function test() { return '</script>';}"
+ minified = Uglifier.compile(code, :output => { :inline_script => true })
+ expect(minified).not_to include("</script>")
+ end
+
+ it "quotes keys" do
+ code = "var a = {foo: 1}"
+ minified = Uglifier.compile(code, :output => { :quote_keys => true })
+ expect(minified).to include('"foo"')
+ end
+
+ it "quotes unsafe keys by default" do
+ code = 'var code = {"class": "", "\u200c":"A"}'
+ expect(Uglifier.compile(code)).to include('"class"')
+ expect(Uglifier.compile(code)).to include('"\u200c"')
+
+ uglifier = Uglifier.new(:output => { :ascii_only => false, :quote_keys => false })
+ expect(uglifier.compile(code)).to include(["200c".to_i(16)].pack("U*"))
+ end
+
+ it "handles constant definitions" do
+ code = "if (BOOL) { var a = STR; var b = NULL; var c = NUM; }"
+ defines = { "NUM" => 1234, "BOOL" => true, "NULL" => nil, "STR" => "str" }
+ processed = Uglifier.compile(code, :define => defines)
+ expect(processed).to include("a=\"str\"")
+ expect(processed).not_to include("if")
+ expect(processed).to include("b=null")
+ expect(processed).to include("c=1234")
+ end
+
+ it "can disable IIFE negation" do
+ code = "(function() { console.log('test')})();"
+ disabled_negation = Uglifier.compile(code, :compress => { :negate_iife => false })
+ expect(disabled_negation).not_to include("!")
+ negation = Uglifier.compile(code, :compress => { :negate_iife => true })
+ expect(negation).to include("!")
+ end
+
+ it "can drop console logging" do
+ code = "(function() { console.log('test')})();"
+ compiled = Uglifier.compile(code, :compress => { :drop_console => true })
+ expect(compiled).not_to include("console")
+ end
+
+ describe "collapse_vars option" do
+ let(:code) do
+ <<-JS
+ function a() {
+ var win = window;
+ return win.Handlebars;
+ }
+ JS
+ end
+
+ it "collapses vars when collapse_vars is enabled" do
+ compiled = Uglifier.compile(code, :compress => { :collapse_vars => true })
+ expect(compiled).to include("return window.Handlebars")
+ end
+
+ it "defaults to not collapsing variables" do
+ expect(Uglifier.compile(code)).not_to include("return window.Handlebars")
+ end
+ end
+
+ it "processes @ngInject annotations" do
+ code = <<-JS
+ /**
+ * @ngInject
+ */
+ var f = function(foo, bar) { return foo + bar};
+ JS
+ with_angular = Uglifier.compile(code, :compress => { :angular => true })
+ without_angular = Uglifier.compile(code, :compress => { :angular => false })
+ expect(with_angular).to include("f.$inject")
+ expect(without_angular).not_to include("f.$inject")
+ end
+
+ it "keeps unused function arguments when keep_fargs option is set" do
+ code = <<-JS
+ function plus(a, b, c) { return a + b};
+ plus(1, 2);
+ JS
+
+ options = lambda do |keep_fargs|
+ {
+ :mangle => false,
+ :compress => {
+ :keep_fargs => keep_fargs,
+ :unsafe => true
+ }
+ }
+ end
+
+ expect(Uglifier.compile(code, options.call(false))).not_to include("c)")
+ expect(Uglifier.compile(code, options.call(true))).to include("c)")
+ end
+
+ it "keeps function names in output when compressor keep_fnames is set" do
+ code = <<-JS
+ (function plus(a, b) { return a + b})(1, 2);
+ JS
+ expect(Uglifier.compile(code, :compress => true)).not_to include("plus")
+
+ keep_fnames = Uglifier.compile(code, :mangle => false, :compress => { :keep_fnames => true })
+ expect(keep_fnames).to include("plus")
+ end
+
+ it "does not mangle function names in output when mangler keep_fnames is set" do
+ code = <<-JS
+ (function() {
+ function plus(a, b) { return a + b}
+ plus(1, 2);
+ })();
+ JS
+ expect(Uglifier.compile(code, :mangle => true)).not_to include("plus")
+
+ keep_fnames = Uglifier.compile(code, :mangle => { :keep_fnames => true })
+ expect(keep_fnames).to include("plus")
+ end
+
+ it "sets sets both compress and mangle keep_fnames when toplevel keep_fnames is true" do
+ code = <<-JS
+ (function plus(a, b) { return a + b})(1, 2);
+ JS
+ expect(Uglifier.compile(code)).not_to include("plus")
+
+ keep_fnames = Uglifier.compile(code, :keep_fnames => true)
+ expect(keep_fnames).to include("plus")
+ end
+
+ describe "Input Formats" do
+ let(:code) { "function hello() { return 'hello world'; }" }
+
+ it "handles strings" do
+ expect(Uglifier.new.compile(code)).not_to be_empty
+ end
+
+ it "handles IO objects" do
+ expect(Uglifier.new.compile(StringIO.new(code))).not_to be_empty
+ end
+ end
+
+ describe "enclose" do
+ let(:code) { "$.foo()" }
+
+ it "encloses code with given arguments" do
+ minified = Uglifier.compile(code, :enclose => { 'window.jQuery' => '$' })
+ expect(minified).to match(/window.jQuery/)
+ end
+
+ it "handles multiple definitions" do
+ definitions = [%w(lol lulz), %w(foo bar)]
+ minified = Uglifier.compile(code, :enclose => definitions)
+ expect(minified).to match(/lol,foo/)
+ expect(minified).to match(/lulz,bar/)
+ end
+
+ it "wraps with function when given empty object" do
+ minified = Uglifier.compile(code, :enclose => {})
+ expect(minified).to match(/function\(/)
+ end
+ end
+
+ describe "wrap_iife option" do
+ let(:code) do
+ <<-JS
+ (function() {
+ return function() {
+ console.log('test')
+ };
+ })()();
+ JS
+ end
+
+ it "defaults to not wrap IIFEs" do
+ expect(Uglifier.compile(code))
+ .to match("!function(){return function(){console.log(\"test\")}}()();")
+ end
+
+ it "wraps IIFEs" do
+ expect(Uglifier.compile(code, :output => { :wrap_iife => true }))
+ .to match("(function(){return function(){console.log(\"test\")}})()();")
+ end
+ end
+end
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-uglifier.git
More information about the Pkg-ruby-extras-commits
mailing list