Skip to content

Commit

Permalink
Merge pull request #22 from jdeff/master
Browse files Browse the repository at this point in the history
Allow for multiple js files to be compiled
  • Loading branch information
jashkenas committed Nov 26, 2012
2 parents e9ebf39 + 434e9e1 commit 324311f
Show file tree
Hide file tree
Showing 10 changed files with 460 additions and 95 deletions.
14 changes: 12 additions & 2 deletions README.textile
Expand Up @@ -4,7 +4,7 @@ The *closure-compiler* gem is a svelte wrapper around the "Google Closure Compil

Latest Version: *"1.1.7":http://rubygems.org/gems/closure-compiler*

The Closure Compiler's *2012-07-25* JAR-file is included with the gem.
The Closure Compiler's *2012-09-17* JAR-file is included with the gem.

h2. Installation

Expand All @@ -14,13 +14,23 @@ sudo gem install closure-compiler

h2. Usage

The @Closure::Compiler@ has a single method, @compile@, which can be passed a string or an open @IO@ object, and returns the compiled JavaScript. The result is returned as a string, or, if a block is passed, yields as an @IO@ object for streaming writes.
The @Closure::Compiler@ has a @compile@ method, which can be passed a string or an open @IO@ object, and returns the compiled JavaScript. The result is returned as a string, or, if a block is passed, yields as an @IO@ object for streaming writes.

<pre>
require 'rubygems'
require 'closure-compiler'
Closure::Compiler.new.compile(File.open('underscore.js', 'r'))

=> "(function(){var j=this,m=j._;function i(a){......
</pre>

The @Closure::Compiler@ also has @compile_file@ and @compile_files@ methods, which can be passed a file path or an array of file paths respectively. The files are concatenated and compiled and, like the @compile@ method, the result is returned as a string or, if block is passed, yields an @IO@ object.

<pre>
require 'rubygems'
require 'closure-compiler'
Closure::Compiler.new.compile_files(['underscore.js', 'jasmine.js']))

=> "(function(){var j=this,m=j._;function i(a){......
</pre>

Expand Down
Binary file not shown.
2 changes: 1 addition & 1 deletion lib/closure-compiler.rb
Expand Up @@ -2,7 +2,7 @@ module Closure

VERSION = "1.1.7"

COMPILER_VERSION = "20120710"
COMPILER_VERSION = "20120917"

JAVA_COMMAND = 'java'

Expand Down
33 changes: 25 additions & 8 deletions lib/closure/compiler.rb
Expand Up @@ -9,14 +9,14 @@ class Error < StandardError; end
# The Closure::Compiler is a basic wrapper around the actual JAR. There's not
# much to see here.
class Compiler

DEFAULT_OPTIONS = {:warning_level => 'QUIET'}

# When you create a Compiler, pass in the flags and options.
def initialize(options={})
@java = options.delete(:java) || JAVA_COMMAND
@jar = options.delete(:jar_file) || COMPILER_JAR
@options = serialize_options(DEFAULT_OPTIONS.merge(options))
@options = DEFAULT_OPTIONS.merge(options)
end

# Can compile a JavaScript string or open IO object. Returns the compiled
Expand All @@ -34,21 +34,38 @@ def compile(io)
tempfile.flush

begin
result = `#{command} --js #{tempfile.path} 2>&1`
rescue Exception
raise Error, "compression failed: #{result}"
result = compile_files(tempfile.path)
rescue Exception => e
raise e
ensure
tempfile.close!
end

yield(StringIO.new(result)) if block_given?
result
end
alias_method :compress, :compile

# Takes an array of javascript file paths or a single path. Returns the
# resulting JavaScript as a string or yields an IO object containing the
# response to a block, for streaming.
def compile_files(files)
@options.merge!({js: files})

begin
result = `#{command} 2>&1`
rescue Exception
raise Error, "compression failed: #{result}"
end

unless $?.exitstatus.zero?
raise Error, result
end

yield(StringIO.new(result)) if block_given?
result
end
alias_method :compress, :compile

alias_method :compile_file, :compile_files

private

Expand All @@ -64,7 +81,7 @@ def serialize_options(options)
end

def command
[@java, '-jar', "\"#{@jar}\"", @options].flatten.join(' ')
[@java, '-jar', "\"#{@jar}\"", serialize_options(@options)].flatten.join(' ')
end

end
Expand Down
251 changes: 251 additions & 0 deletions test/fixtures/file1-file2-compiled.js

Large diffs are not rendered by default.

38 changes: 38 additions & 0 deletions test/fixtures/file1.js

Large diffs are not rendered by default.

38 changes: 38 additions & 0 deletions test/fixtures/file2.js

Large diffs are not rendered by default.

158 changes: 79 additions & 79 deletions test/fixtures/precompressed-compiled.js

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion test/test_helper.rb
@@ -1,4 +1,10 @@
if defined?(Gem) and Gem.available?('redgreen')
if begin
Gem::Specification::find_by_name 'redgreen'
rescue Gem::LoadError
false
rescue
Gem.available? 'redgreen'
end
require 'redgreen' if RUBY_VERSION < "1.9"
end
require 'test/unit'
Expand Down
13 changes: 9 additions & 4 deletions test/unit/closure_compiler_test.rb
Expand Up @@ -32,7 +32,7 @@ def test_block_syntax
end
assert result == COMPILED_ADVANCED
end

def test_jar_and_java_specifiation
jar = Dir['vendor/closure-compiler-*.jar'].first
unless java = ( `which java` rescue nil )
Expand All @@ -57,7 +57,6 @@ def test_exceptions

def test_stderr_reading
js = Compiler.new.compile(File.read('test/fixtures/precompressed.js'))
File.open('test/fixtures/precompressed-compiled.js', 'w+') {|f| f.write js }
assert js == File.read('test/fixtures/precompressed-compiled.js')
end

Expand All @@ -68,15 +67,21 @@ def test_permissions
def test_serialize_options
options = { 'externs' => 'library1.js', "compilation_level" => "ADVANCED_OPTIMIZATIONS" }
# ["--externs", "library1.js", "--compilation_level", "ADVANCED_OPTIMIZATIONS"]
# although Hash in 1.8 might change the order to :
# although Hash in 1.8 might change the order to :
# ["--compilation_level", "ADVANCED_OPTIMIZATIONS", "--externs", "library1.js"]
expected_options = options.to_a.map { |arr| [ "--#{arr[0]}", arr[1] ] }.flatten
assert_equal expected_options, Closure::Compiler.new.send(:serialize_options, options)
end

def test_serialize_options_for_arrays
compiler = Closure::Compiler.new('externs' => ['library1.js', "library2.js"])
assert_equal ["--externs", "library1.js", "--externs", "library2.js"], compiler.send(:serialize_options, 'externs' => ['library1.js', "library2.js"])
end

def test_compiling_array_of_file_paths
files = ['test/fixtures/file1.js', 'test/fixtures/file2.js']
result = Closure::Compiler.new().compile_files(files)

assert_equal result, File.read('test/fixtures/file1-file2-compiled.js')
end
end

0 comments on commit 324311f

Please sign in to comment.