ghazel-yui-compressor 0.9.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require "rubygems"
2
+ require "rake/gempackagetask"
3
+ require "rake/rdoctask"
4
+ require "rake/testtask"
5
+
6
+ task :default => :test
7
+
8
+ Rake::TestTask.new do |t|
9
+ t.libs += ["lib", "test"]
10
+ t.test_files = FileList["test/*_test.rb"]
11
+ t.verbose = true
12
+ end
13
+
14
+ Rake::RDocTask.new do |t|
15
+ t.rdoc_files.include("README.rdoc", "lib/**/*.rb")
16
+ end
17
+
18
+ Rake::GemPackageTask.new(eval(IO.read(File.join(File.dirname(__FILE__), "yui-compressor.gemspec")))) do |pkg|
19
+ pkg.need_zip = true
20
+ pkg.need_tar = true
21
+ end
@@ -0,0 +1,204 @@
1
+ require "open3"
2
+ require "stringio"
3
+
4
+ module YUI #:nodoc:
5
+ class Compressor
6
+ VERSION = "0.9.4"
7
+
8
+ class Error < StandardError; end
9
+ class OptionError < Error; end
10
+ class RuntimeError < Error; end
11
+
12
+ attr_reader :options, :command
13
+
14
+ def self.default_options #:nodoc:
15
+ { :charset => "utf-8", :line_break => nil }
16
+ end
17
+
18
+ def self.compressor_type #:nodoc:
19
+ raise Error, "create a CssCompressor or JavaScriptCompressor instead"
20
+ end
21
+
22
+ def initialize(options = {}) #:nodoc:
23
+ @options = self.class.default_options.merge(options)
24
+ @command = [path_to_java, "-jar", path_to_jar_file, *(command_option_for_type + command_options)]
25
+ @command = @command.flatten.join(' ') if ENV['OS'] == 'Windows_NT'
26
+ end
27
+
28
+ # Compress a stream or string of code with YUI Compressor. (A stream is
29
+ # any object that responds to +read+ and +close+ like an IO.) If a block
30
+ # is given, you can read the compressed code from the block's argument.
31
+ # Otherwise, +compress+ returns a string of compressed code.
32
+ #
33
+ # ==== Example: Compress CSS
34
+ # compressor = YUI::CssCompressor.new
35
+ # compressor.compress(<<-END_CSS)
36
+ # div.error {
37
+ # color: red;
38
+ # }
39
+ # div.warning {
40
+ # display: none;
41
+ # }
42
+ # END_CSS
43
+ # # => "div.error{color:red;}div.warning{display:none;}"
44
+ #
45
+ # ==== Example: Compress JavaScript
46
+ # compressor = YUI::JavaScriptCompressor.new
47
+ # compressor.compress('(function () { var foo = {}; foo["bar"] = "baz"; })()')
48
+ # # => "(function(){var foo={};foo.bar=\"baz\"})();"
49
+ #
50
+ # ==== Example: Compress and gzip a file on disk
51
+ # File.open("my.js", "r") do |source|
52
+ # Zlib::GzipWriter.open("my.js.gz", "w") do |gzip|
53
+ # compressor.compress(source) do |compressed|
54
+ # while buffer = compressed.read(4096)
55
+ # gzip.write(buffer)
56
+ # end
57
+ # end
58
+ # end
59
+ # end
60
+ #
61
+ def compress(stream_or_string)
62
+ streamify(stream_or_string) do |stream|
63
+ Open3.popen3(*command) do |stdin, stdout, stderr|
64
+ begin
65
+ stdin.binmode
66
+ transfer(stream, stdin)
67
+
68
+ if block_given?
69
+ yield stdout
70
+ else
71
+ stdout.read
72
+ end
73
+
74
+ rescue Exception => e
75
+ raise RuntimeError, "compression failed"
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ private
82
+ def command_options
83
+ options.inject([]) do |command_options, (name, argument)|
84
+ method = begin
85
+ method(:"command_option_for_#{name}")
86
+ rescue NameError
87
+ raise OptionError, "undefined option #{name.inspect}"
88
+ end
89
+
90
+ command_options.concat(method.call(argument))
91
+ end
92
+ end
93
+
94
+ def path_to_java
95
+ options.delete(:java) || "java"
96
+ end
97
+
98
+ def path_to_jar_file
99
+ options.delete(:jar_file) || File.join(File.dirname(__FILE__), *%w".. yuicompressor-2.4.4.jar")
100
+ end
101
+
102
+ def streamify(stream_or_string)
103
+ if stream_or_string.respond_to?(:read)
104
+ yield stream_or_string
105
+ else
106
+ yield StringIO.new(stream_or_string.to_s)
107
+ end
108
+ end
109
+
110
+ def transfer(from_stream, to_stream)
111
+ while buffer = from_stream.read(4096)
112
+ to_stream.write(buffer)
113
+ end
114
+ to_stream.close
115
+ end
116
+
117
+ def command_option_for_type
118
+ ["--type", self.class.compressor_type.to_s]
119
+ end
120
+
121
+ def command_option_for_charset(charset)
122
+ ["--charset", charset.to_s]
123
+ end
124
+
125
+ def command_option_for_line_break(line_break)
126
+ line_break ? ["--line-break", line_break.to_s] : []
127
+ end
128
+ end
129
+
130
+ class CssCompressor < Compressor
131
+ def self.compressor_type #:nodoc:
132
+ "css"
133
+ end
134
+
135
+ # Creates a new YUI::CssCompressor for minifying CSS code.
136
+ #
137
+ # Options are:
138
+ #
139
+ # <tt>:charset</tt>:: Specifies the character encoding to use. Defaults to
140
+ # <tt>"utf-8"</tt>.
141
+ # <tt>:line_break</tt>:: By default, CSS will be compressed onto a single
142
+ # line. Use this option to specify the maximum
143
+ # number of characters in each line before a newline
144
+ # is added. If <tt>:line_break</tt> is 0, a newline
145
+ # is added after each CSS rule.
146
+ #
147
+ def initialize(options = {})
148
+ super
149
+ end
150
+ end
151
+
152
+ class JavaScriptCompressor < Compressor
153
+ def self.compressor_type #:nodoc:
154
+ "js"
155
+ end
156
+
157
+ def self.default_options #:nodoc:
158
+ super.merge(
159
+ :munge => false,
160
+ :optimize => true,
161
+ :preserve_semicolons => false
162
+ )
163
+ end
164
+
165
+ # Creates a new YUI::JavaScriptCompressor for minifying JavaScript code.
166
+ #
167
+ # Options are:
168
+ #
169
+ # <tt>:charset</tt>:: Specifies the character encoding to use. Defaults to
170
+ # <tt>"utf-8"</tt>.
171
+ # <tt>:line_break</tt>:: By default, JavaScript will be compressed onto a
172
+ # single line. Use this option to specify the
173
+ # maximum number of characters in each line before a
174
+ # newline is added. If <tt>:line_break</tt> is 0, a
175
+ # newline is added after each JavaScript statement.
176
+ # <tt>:munge</tt>:: Specifies whether YUI Compressor should shorten local
177
+ # variable names when possible. Defaults to +false+.
178
+ # <tt>:optimize</tt>:: Specifies whether YUI Compressor should optimize
179
+ # JavaScript object property access and object literal
180
+ # declarations to use as few characters as possible.
181
+ # Defaults to +true+.
182
+ # <tt>:preserve_semicolons</tt>:: Defaults to +false+. If +true+, YUI
183
+ # Compressor will ensure semicolons exist
184
+ # after each statement to appease tools like
185
+ # JSLint.
186
+ #
187
+ def initialize(options = {})
188
+ super
189
+ end
190
+
191
+ private
192
+ def command_option_for_munge(munge)
193
+ munge ? [] : ["--nomunge"]
194
+ end
195
+
196
+ def command_option_for_optimize(optimize)
197
+ optimize ? [] : ["--disable-optimizations"]
198
+ end
199
+
200
+ def command_option_for_preserve_semicolons(preserve_semicolons)
201
+ preserve_semicolons ? ["--preserve-semi"] : []
202
+ end
203
+ end
204
+ end
Binary file
@@ -0,0 +1,99 @@
1
+ require "test/unit"
2
+ require "yui/compressor"
3
+
4
+ module YUI
5
+ class CompressorTest < Test::Unit::TestCase
6
+ FIXTURE_CSS = <<-END_CSS
7
+ div.warning {
8
+ display: none;
9
+ }
10
+
11
+ div.error {
12
+ background: red;
13
+ color: white;
14
+ }
15
+
16
+ @media screen and (max-device-width: 640px) {
17
+ body { font-size: 90%; }
18
+ }
19
+ END_CSS
20
+
21
+ FIXTURE_JS = <<-END_JS
22
+ // here's a comment
23
+ var Foo = { "a": 1 };
24
+ Foo["bar"] = (function(baz) {
25
+ /* here's a
26
+ multiline comment */
27
+ if (false) {
28
+ doSomething();
29
+ } else {
30
+ for (var index = 0; index < baz.length; index++) {
31
+ doSomething(baz[index]);
32
+ }
33
+ }
34
+ })("hello");
35
+ END_JS
36
+
37
+ def test_compressor_should_raise_when_instantiated
38
+ assert_raises YUI::Compressor::Error do
39
+ YUI::Compressor.new
40
+ end
41
+ end
42
+
43
+ def test_css_should_be_compressed
44
+ @compressor = YUI::CssCompressor.new
45
+ assert_equal "div.warning{display:none}div.error{background:red;color:white}@media screen and (max-device-width:640px){body{font-size:90%}}", @compressor.compress(FIXTURE_CSS)
46
+ end
47
+
48
+ def test_js_should_be_compressed
49
+ @compressor = YUI::JavaScriptCompressor.new
50
+ assert_equal "var Foo={a:1};Foo.bar=(function(baz){if(false){doSomething()}else{for(var index=0;index<baz.length;index++){doSomething(baz[index])}}})(\"hello\");", @compressor.compress(FIXTURE_JS)
51
+ end
52
+
53
+ def test_compress_should_raise_when_an_unknown_option_is_specified
54
+ assert_raises YUI::Compressor::OptionError do
55
+ @compressor = YUI::CssCompressor.new(:foo => "bar")
56
+ @compressor.compress(FIXTURE_JS)
57
+ end
58
+ end
59
+
60
+ def test_compress_should_accept_an_io_argument
61
+ @compressor = YUI::CssCompressor.new
62
+ assert_equal "div.warning{display:none}div.error{background:red;color:white}@media screen and (max-device-width:640px){body{font-size:90%}}", @compressor.compress(StringIO.new(FIXTURE_CSS))
63
+ end
64
+
65
+ def test_compress_should_accept_a_block_and_yield_an_io
66
+ @compressor = YUI::CssCompressor.new
67
+ @compressor.compress(FIXTURE_CSS) do |stream|
68
+ assert_kind_of IO, stream
69
+ assert_equal "div.warning{display:none}div.error{background:red;color:white}@media screen and (max-device-width:640px){body{font-size:90%}}", stream.read
70
+ end
71
+ end
72
+
73
+ def test_line_break_option_should_insert_line_breaks_in_css
74
+ @compressor = YUI::CssCompressor.new(:line_break => 0)
75
+ assert_equal "div.warning{display:none}\ndiv.error{background:red;color:white}\n@media screen and (max-device-width:640px){body{font-size:90%}\n}", @compressor.compress(FIXTURE_CSS)
76
+
77
+ end
78
+
79
+ def test_line_break_option_should_insert_line_breaks_in_js
80
+ @compressor = YUI::JavaScriptCompressor.new(:line_break => 0)
81
+ assert_equal "var Foo={a:1};\nFoo.bar=(function(baz){if(false){doSomething()\n}else{for(var index=0;\nindex<baz.length;\nindex++){doSomething(baz[index])\n}}})(\"hello\");", @compressor.compress(FIXTURE_JS)
82
+ end
83
+
84
+ def test_munge_option_should_munge_local_variable_names
85
+ @compressor = YUI::JavaScriptCompressor.new(:munge => true)
86
+ assert_equal "var Foo={a:1};Foo.bar=(function(b){if(false){doSomething()}else{for(var a=0;a<b.length;a++){doSomething(b[a])}}})(\"hello\");", @compressor.compress(FIXTURE_JS)
87
+ end
88
+
89
+ def test_optimize_option_should_not_modify_property_accesses_or_object_literal_keys_when_false
90
+ @compressor = YUI::JavaScriptCompressor.new(:optimize => false)
91
+ assert_equal "var Foo={\"a\":1};Foo[\"bar\"]=(function(baz){if(false){doSomething()}else{for(var index=0;index<baz.length;index++){doSomething(baz[index])}}})(\"hello\");", @compressor.compress(FIXTURE_JS)
92
+ end
93
+
94
+ def test_preserve_semicolons_option_should_preserve_semicolons
95
+ @compressor = YUI::JavaScriptCompressor.new(:preserve_semicolons => true)
96
+ assert_equal "var Foo={a:1};Foo.bar=(function(baz){if(false){doSomething();}else{for(var index=0;index<baz.length;index++){doSomething(baz[index]);}}})(\"hello\");", @compressor.compress(FIXTURE_JS)
97
+ end
98
+ end
99
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ghazel-yui-compressor
3
+ version: !ruby/object:Gem::Version
4
+ hash: 21
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 9
9
+ - 4
10
+ - 1
11
+ version: 0.9.4.1
12
+ platform: ruby
13
+ authors:
14
+ - Sam Stephenson
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-02-20 00:00:00 -08:00
20
+ default_executable:
21
+ dependencies: []
22
+
23
+ description: A Ruby interface to YUI Compressor for minifying JavaScript and CSS assets.
24
+ email: sstephenson@gmail.com
25
+ executables: []
26
+
27
+ extensions: []
28
+
29
+ extra_rdoc_files: []
30
+
31
+ files:
32
+ - Rakefile
33
+ - lib/yui/compressor.rb
34
+ - lib/yuicompressor-2.4.4.jar
35
+ - test/compressor_test.rb
36
+ has_rdoc: true
37
+ homepage: http://github.com/sstephenson/ruby-yui-compressor/
38
+ licenses: []
39
+
40
+ post_install_message:
41
+ rdoc_options: []
42
+
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ hash: 3
51
+ segments:
52
+ - 0
53
+ version: "0"
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ requirements: []
64
+
65
+ rubyforge_project: yui
66
+ rubygems_version: 1.4.2
67
+ signing_key:
68
+ specification_version: 3
69
+ summary: JavaScript and CSS minification library
70
+ test_files:
71
+ - test/compressor_test.rb