crush 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,4 +1,2 @@
1
- source "http://rubygems.org"
2
-
3
- # Specify your gem's dependencies in crush.gemspec
1
+ source :rubygems
4
2
  gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Peter Browne
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,42 @@
1
+ Crush
2
+ =====
3
+
4
+ Crush is a generic interface, like Tilt, for the various compression engines in Ruby.
5
+ It is useful for asset libraries that support multiple javascript and stylesheet compression engines.
6
+
7
+ Basic Usage
8
+ -----------
9
+
10
+ ```ruby
11
+ require "uglifier"
12
+ require "crush"
13
+ Crush.new("application.js").compress
14
+ ```
15
+
16
+ This would automatically compress the data found in the `application.js` file using Uglifier.
17
+ Crush favors engines whose libraries have already been loaded.
18
+
19
+ If you have multiple compression libraries loaded, and you want to control which one to use,
20
+ you can initialize the engine directly.
21
+
22
+ ```ruby
23
+ require "uglifier"
24
+ require "jsmin"
25
+ require "crush"
26
+ Crush::Uglifier.new("application.js").compress
27
+ ```
28
+
29
+ Or you could use `Crush.prefer` to tell Crush which engine you'd like to use.
30
+
31
+ ```ruby
32
+ require "uglifier"
33
+ require "jsmin"
34
+ require "crush"
35
+ Crush.prefer(Crush::Uglifier)
36
+ Crush.new("application.js").compress
37
+ ```
38
+
39
+ Copyright
40
+ ---------
41
+
42
+ Copyright (c) 2011 [Peter Browne](http://petebrowne.com). See LICENSE for details.
data/Rakefile CHANGED
@@ -1 +1,6 @@
1
+ task :default => :spec
2
+
1
3
  require "bundler/gem_tasks"
4
+
5
+ require "rspec/core/rake_task"
6
+ RSpec::Core::RakeTask.new
@@ -12,6 +12,15 @@ Gem::Specification.new do |s|
12
12
  s.description = "Crush is a generic interface, like Tilt, for the various compression engines in Ruby."
13
13
 
14
14
  s.rubyforge_project = "crush"
15
+
16
+ s.add_development_dependency "rspec", "~> 2.6.0"
17
+ s.add_development_dependency "jsmin"
18
+ s.add_development_dependency "packr"
19
+ s.add_development_dependency "uglifier"
20
+ s.add_development_dependency "closure-compiler"
21
+ s.add_development_dependency "yui-compressor"
22
+ s.add_development_dependency "cssmin"
23
+ s.add_development_dependency "rainpress"
15
24
 
16
25
  s.files = `git ls-files`.split("\n")
17
26
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -1,2 +1,79 @@
1
1
  module Crush
2
+ autoload :Closure, "crush/closure"
3
+ autoload :CSSMin, "crush/cssmin"
4
+ autoload :Engine, "crush/engine"
5
+ autoload :JSMin, "crush/jsmin"
6
+ autoload :Packr, "crush/packr"
7
+ autoload :Rainpress, "crush/rainpress"
8
+ autoload :Uglifier, "crush/uglifier"
9
+ autoload :YUI, "crush/yui"
10
+
11
+ class EngineNotFound < StandardError; end
12
+
13
+ # Hash of registered compression engines.
14
+ def self.mappings
15
+ @mappings ||= Hash.new { |h, k| h[k] = [] }
16
+ end
17
+
18
+ # Ensures the extension doesn't include the "."
19
+ def self.normalize(ext)
20
+ ext.to_s.downcase.sub /^\./, ""
21
+ end
22
+
23
+ # Registers a compression engine for the given file extension(s).
24
+ def self.register(engine, *extensions)
25
+ extensions.each do |ext|
26
+ ext = normalize(ext)
27
+ mappings[ext].unshift(engine).uniq!
28
+ end
29
+ end
30
+
31
+ # Returns true when an engine exists for the given file extension.
32
+ def self.registered?(ext)
33
+ ext = normalize(ext)
34
+ mappings.key?(ext) && !mappings[ext].empty?
35
+ end
36
+
37
+ # Make the given compression engine preferred. Which means,
38
+ # it will reordered the beginning of its mapping.
39
+ def self.prefer(engine)
40
+ mappings.each do |ext, engines|
41
+ if engines.include?(engine)
42
+ engines.delete(engine)
43
+ engines.unshift(engine)
44
+ end
45
+ end
46
+ end
47
+
48
+ # Look for a compression engine for the given filename or file
49
+ # extension. Return nil when no engine is found.
50
+ def self.[](path)
51
+ pattern = File.basename(path.to_s).downcase
52
+ until pattern.empty? || registered?(pattern)
53
+ pattern.sub! /^[^.]*\.?/, ""
54
+ end
55
+
56
+ pattern = normalize(pattern)
57
+ mappings[pattern].detect(&:engine_initialized?) || mappings[pattern].first
58
+ end
59
+
60
+ # Create a new compression engine for the given file using the file's extension
61
+ # to determine the the engine mapping.
62
+ def self.new(path, options = {}, &block)
63
+ if engine = self[path]
64
+ engine.new path, options, &block
65
+ else
66
+ raise EngineNotFound.new("No compression engine registered for '#{path}'")
67
+ end
68
+ end
69
+
70
+ register Crush::JSMin, "js", "min.js"
71
+ register Crush::Packr, "js", "pack.js"
72
+ register Crush::YUI::JavaScriptCompressor, "js", "yui.js"
73
+ register Crush::Closure::Compiler, "js", "closure.js"
74
+ register Crush::Uglifier, "js", "ugly.js"
75
+
76
+ register Crush::CSSMin, "css", "min.css"
77
+ register Crush::Rainpress, "css", "rain.css"
78
+ register Crush::YUI::CssCompressor, "css", "yui.css"
2
79
  end
@@ -0,0 +1,21 @@
1
+ module Crush
2
+ module Closure
3
+ class Compiler < Crush::Engine
4
+ def self.engine_initialized?
5
+ !!(defined? ::Closure) && !!(defined? ::Closure::Compiler)
6
+ end
7
+
8
+ def initialize_engine
9
+ require_template_library "closure-compiler"
10
+ end
11
+
12
+ def prepare
13
+ @engine = ::Closure::Compiler.new(options)
14
+ end
15
+
16
+ def evaluate
17
+ @engine.compile(data)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ module Crush
2
+ class CSSMin < Engine
3
+ def self.engine_initialized?
4
+ !!(defined? ::CSSMin)
5
+ end
6
+
7
+ def initialize_engine
8
+ require_template_library "cssmin"
9
+ end
10
+
11
+ def evaluate
12
+ ::CSSMin.minify(data)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,89 @@
1
+ module Crush
2
+ class Engine
3
+ # The name of the file to be compressed
4
+ attr_reader :file
5
+
6
+ # A Hash of compression engine specific options. This is passed directly
7
+ # to the underlying engine and is not used by the generic interface.
8
+ attr_reader :options
9
+
10
+ # The data to cmopress; loaded from a file or given directly.
11
+ attr_reader :data
12
+
13
+ # Used to determine if this class's initialize_engine method has
14
+ # been called yet.
15
+ @engine_initialized = false
16
+ class << self
17
+ attr_accessor :engine_initialized
18
+ alias :engine_initialized? :engine_initialized
19
+ end
20
+
21
+ # Create a new engine with the file and options specified. By
22
+ # default, the data to compress is read from the file. When a block is given,
23
+ # it should read data and return as a String.
24
+ #
25
+ # All arguments are optional.
26
+ def initialize(file = nil, options = nil)
27
+ if file.respond_to?(:to_hash)
28
+ @options = file.to_hash
29
+ else
30
+ @file = file
31
+ @options = options || {}
32
+ end
33
+
34
+ unless self.class.engine_initialized?
35
+ initialize_engine
36
+ self.class.engine_initialized = true
37
+ end
38
+
39
+ @data = if block_given?
40
+ yield
41
+ elsif @file
42
+ File.respond_to?(:binread) ? File.binread(@file) : File.read(@file)
43
+ end
44
+
45
+ prepare
46
+ end
47
+
48
+ # Compresses the data. Data can be read through the file or the block
49
+ # given at initialization, or through passing it here directly.
50
+ def render(data = nil)
51
+ @data = data unless data.nil?
52
+ evaluate
53
+ end
54
+ alias :compress :render
55
+ alias :compile :render
56
+
57
+ protected
58
+
59
+ # Called once and only once for each template subclass the first time
60
+ # the engine class is initialized. This should be used to require the
61
+ # underlying engine library and perform any initial setup.
62
+ def initialize_engine
63
+
64
+ end
65
+
66
+ # Do whatever preparation is necessary to setup the underlying compression
67
+ # engine. Called immediately after template data is loaded. Instance
68
+ # variables set in this method are available when #compress is called.
69
+ def prepare
70
+
71
+ end
72
+
73
+ # Called when it's time to compress. Return the compressed data
74
+ # from this method.
75
+ def evaluate
76
+
77
+ end
78
+
79
+ # Like Kernel::require but issues a warning urging a manual require when
80
+ # running under a threaded environment.
81
+ def require_template_library(name)
82
+ if Thread.list.size > 1
83
+ warn "WARN: crush autoloading '#{name}' in a non thread-safe way; " +
84
+ "explicit require '#{name}' suggested."
85
+ end
86
+ require name
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,15 @@
1
+ module Crush
2
+ class JSMin < Engine
3
+ def self.engine_initialized?
4
+ !!(defined? ::JSMin)
5
+ end
6
+
7
+ def initialize_engine
8
+ require_template_library "jsmin"
9
+ end
10
+
11
+ def evaluate
12
+ ::JSMin.minify(data)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Crush
2
+ class Packr < Engine
3
+ def self.engine_initialized?
4
+ !!(defined? ::Packr)
5
+ end
6
+
7
+ def initialize_engine
8
+ require_template_library "packr"
9
+ end
10
+
11
+ def evaluate
12
+ ::Packr.pack(data, options)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Crush
2
+ class Rainpress < Engine
3
+ def self.engine_initialized?
4
+ !!(defined? ::Rainpress)
5
+ end
6
+
7
+ def initialize_engine
8
+ require_template_library "rainpress"
9
+ end
10
+
11
+ def evaluate
12
+ ::Rainpress.compress(data, options)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ module Crush
2
+ class Uglifier < Engine
3
+ def self.engine_initialized?
4
+ !!(defined? ::Uglifier)
5
+ end
6
+
7
+ def initialize_engine
8
+ require_template_library "uglifier"
9
+ end
10
+
11
+ def prepare
12
+ @engine = ::Uglifier.new(options)
13
+ end
14
+
15
+ def evaluate
16
+ @engine.compile(data)
17
+ end
18
+ end
19
+ end
@@ -1,3 +1,3 @@
1
1
  module Crush
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,39 @@
1
+ module Crush
2
+ module YUI
3
+ class JavaScriptCompressor < Crush::Engine
4
+ def self.engine_initialized?
5
+ !!(defined? ::YUI) && !!(defined? ::YUI::JavaScriptCompressor)
6
+ end
7
+
8
+ def initialize_engine
9
+ require_template_library "yui/compressor"
10
+ end
11
+
12
+ def prepare
13
+ @engine = ::YUI::JavaScriptCompressor.new(options)
14
+ end
15
+
16
+ def evaluate
17
+ @engine.compress(data)
18
+ end
19
+ end
20
+
21
+ class CssCompressor < Crush::Engine
22
+ def self.engine_initialized?
23
+ !!(defined? ::YUI) && !!(defined? ::YUI::CssCompressor)
24
+ end
25
+
26
+ def initialize_engine
27
+ require_template_library "yui/compressor"
28
+ end
29
+
30
+ def prepare
31
+ @engine = ::YUI::CssCompressor.new(options)
32
+ end
33
+
34
+ def evaluate
35
+ @engine.compress(data)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,22 @@
1
+ require "spec_helper"
2
+ require "closure-compiler"
3
+
4
+ describe Crush::Closure::Compiler do
5
+ it "is registered for '.js' files" do
6
+ Crush.mappings["js"].should include(Crush::Closure::Compiler)
7
+ end
8
+
9
+ it "minifies using Closure::Compiler" do
10
+ compressor = mock(:compressor)
11
+ ::Closure::Compiler.should_receive(:new).with({}).and_return(compressor)
12
+ compressor.should_receive(:compile).with("hello").and_return("world")
13
+ Crush::Closure::Compiler.new.compress("hello").should == "world"
14
+ end
15
+
16
+ it "sends options to Closure::Compiler" do
17
+ compressor = mock(:compressor)
18
+ ::Closure::Compiler.should_receive(:new).with(:foo => "bar").and_return(compressor)
19
+ compressor.should_receive(:compile).with("hello").and_return("world")
20
+ Crush::Closure::Compiler.new(:foo => "bar").compress("hello")
21
+ end
22
+ end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+ require "cssmin"
3
+
4
+ describe Crush::CSSMin do
5
+ it "is registered for '.js' files" do
6
+ Crush.mappings["css"].should include(Crush::CSSMin)
7
+ end
8
+
9
+ it "minifies using CSSMin" do
10
+ ::CSSMin.should_receive(:minify).with("hello").and_return("world")
11
+ Crush::CSSMin.new.compress("hello").should == "world"
12
+ end
13
+ end
@@ -0,0 +1,104 @@
1
+ require "spec_helper"
2
+
3
+ describe Crush::Engine do
4
+ class MockEngine < Crush::Engine
5
+ end
6
+
7
+ describe "#file" do
8
+ it "returns the file the engine was initialized with" do
9
+ engine = MockEngine.new("application.js") {}
10
+ engine.file.should == "application.js"
11
+ end
12
+ end
13
+
14
+ describe "#options" do
15
+ it "returns the options passed to the engine" do
16
+ engine = MockEngine.new(nil, :foo => "bar") {}
17
+ engine.options[:foo].should == "bar"
18
+ engine = MockEngine.new(:bar => "foo") {}
19
+ engine.options[:bar].should == "foo"
20
+ end
21
+ end
22
+
23
+ describe "#data" do
24
+ it "returns the data from the file" do
25
+ File.stub(:binread => "Hello", :read => "Hello")
26
+ engine = MockEngine.new("application.js")
27
+ engine.data.should == "Hello"
28
+ end
29
+
30
+ it "returns the data from the given block" do
31
+ engine = MockEngine.new("application.js") { "Hello" }
32
+ engine.data.should == "Hello"
33
+ end
34
+ end
35
+
36
+ class InitializingMockEngine < Crush::Engine
37
+ class << self
38
+ attr_accessor :initialized_count
39
+ end
40
+
41
+ def initialize_engine
42
+ self.class.initialized_count += 1
43
+ end
44
+ end
45
+
46
+ describe "#initialize_engine" do
47
+ it "is called one time to require the library" do
48
+ InitializingMockEngine.initialized_count = 0
49
+ InitializingMockEngine.new
50
+ InitializingMockEngine.initialized_count.should == 1
51
+ InitializingMockEngine.new
52
+ InitializingMockEngine.initialized_count.should == 1
53
+ end
54
+ end
55
+
56
+ class InitializedMockEngine < Crush::Engine
57
+ end
58
+
59
+ describe ".engine_initialized?" do
60
+ it "returns false before the engine has been initialized" do
61
+ InitializedMockEngine.engine_initialized?.should be_false
62
+ end
63
+
64
+ it "returns true once the engine has been initialized" do
65
+ InitializedMockEngine.new
66
+ InitializedMockEngine.engine_initialized?.should be_true
67
+ end
68
+ end
69
+
70
+ class PreparingMockEngine < Crush::Engine
71
+ class << self
72
+ attr_accessor :prepared_count
73
+ end
74
+
75
+ def prepare
76
+ self.class.prepared_count += 1
77
+ end
78
+ end
79
+
80
+ describe "#prepare" do
81
+ it "is called each time an engine is created" do
82
+ PreparingMockEngine.prepared_count = 0
83
+ PreparingMockEngine.new
84
+ PreparingMockEngine.prepared_count.should == 1
85
+ PreparingMockEngine.new
86
+ PreparingMockEngine.prepared_count.should == 2
87
+ end
88
+ end
89
+
90
+ class SimpleMockEngine < Crush::Engine
91
+ def evaluate
92
+ @data.strip
93
+ end
94
+ end
95
+
96
+ describe "#compress" do
97
+ it "compresses the data using the engine" do
98
+ File.stub(:binread => " hello ", :read => " hello ")
99
+ SimpleMockEngine.new("file.txt").compile.should == "hello"
100
+ SimpleMockEngine.new { " hello " }.render.should == "hello"
101
+ SimpleMockEngine.new.compress(" hello ").should == "hello"
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+ require "jsmin"
3
+
4
+ describe Crush::JSMin do
5
+ it "is registered for '.js' files" do
6
+ Crush.mappings["js"].should include(Crush::JSMin)
7
+ end
8
+
9
+ it "minifies using JSMin" do
10
+ ::JSMin.should_receive(:minify).with("hello").and_return("world")
11
+ Crush::JSMin.new.compress("hello").should == "world"
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+ require "packr"
3
+
4
+ describe Crush::Packr do
5
+ it "is registered for '.js' files" do
6
+ Crush.mappings["js"].should include(Crush::Packr)
7
+ end
8
+
9
+ it "minifies using Packr" do
10
+ ::Packr.should_receive(:pack).with("hello", {}).and_return("world")
11
+ Crush::Packr.new.compress("hello").should == "world"
12
+ end
13
+
14
+ it "sends options to Packr" do
15
+ ::Packr.should_receive(:pack).with("hello", :foo => "bar")
16
+ Crush::Packr.new(:foo => "bar").compress("hello")
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+ require "rainpress"
3
+
4
+ describe Crush::Rainpress do
5
+ it "is registered for '.js' files" do
6
+ Crush.mappings["css"].should include(Crush::Rainpress)
7
+ end
8
+
9
+ it "minifies using Rainpress" do
10
+ ::Rainpress.should_receive(:compress).with("hello", {}).and_return("world")
11
+ Crush::Rainpress.new.compress("hello").should == "world"
12
+ end
13
+
14
+ it "sends options to Rainpress" do
15
+ ::Rainpress.should_receive(:compress).with("hello", :foo => "bar")
16
+ Crush::Rainpress.new(:foo => "bar").compress("hello")
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ require "spec_helper"
2
+ require "uglifier"
3
+
4
+ describe Crush::Uglifier do
5
+ it "is registered for '.js' files" do
6
+ Crush.mappings["js"].should include(Crush::Uglifier)
7
+ end
8
+
9
+ it "minifies using Uglifier" do
10
+ compressor = mock(:compressor)
11
+ ::Uglifier.should_receive(:new).with({}).and_return(compressor)
12
+ compressor.should_receive(:compile).with("hello").and_return("world")
13
+ Crush::Uglifier.new.compress("hello").should == "world"
14
+ end
15
+
16
+ it "sends options to Uglifier" do
17
+ compressor = mock(:compressor)
18
+ ::Uglifier.should_receive(:new).with(:foo => "bar").and_return(compressor)
19
+ compressor.should_receive(:compile).with("hello").and_return("world")
20
+ Crush::Uglifier.new(:foo => "bar").compress("hello")
21
+ end
22
+ end
@@ -0,0 +1,42 @@
1
+ require "spec_helper"
2
+ require "yui/compressor"
3
+
4
+ describe Crush::YUI::JavaScriptCompressor do
5
+ it "is registered for '.js' files" do
6
+ Crush.mappings["js"].should include(Crush::YUI::JavaScriptCompressor)
7
+ end
8
+
9
+ it "minifies using YUI::JavaScriptCompressor" do
10
+ compressor = mock(:compressor)
11
+ ::YUI::JavaScriptCompressor.should_receive(:new).with({}).and_return(compressor)
12
+ compressor.should_receive(:compress).with("hello").and_return("world")
13
+ Crush::YUI::JavaScriptCompressor.new.compress("hello").should == "world"
14
+ end
15
+
16
+ it "sends options to YUI::JavaScriptCompressor" do
17
+ compressor = mock(:compressor)
18
+ ::YUI::JavaScriptCompressor.should_receive(:new).with(:foo => "bar").and_return(compressor)
19
+ compressor.should_receive(:compress).with("hello").and_return("world")
20
+ Crush::YUI::JavaScriptCompressor.new(:foo => "bar").compress("hello")
21
+ end
22
+ end
23
+
24
+ describe Crush::YUI::CssCompressor do
25
+ it "is registered for '.js' files" do
26
+ Crush.mappings["css"].should include(Crush::YUI::CssCompressor)
27
+ end
28
+
29
+ it "minifies using YUI::CssCompressor" do
30
+ compressor = mock(:compressor)
31
+ ::YUI::CssCompressor.should_receive(:new).with({}).and_return(compressor)
32
+ compressor.should_receive(:compress).with("hello").and_return("world")
33
+ Crush::YUI::CssCompressor.new.compress("hello").should == "world"
34
+ end
35
+
36
+ it "sends options to YUI::CssCompressor" do
37
+ compressor = mock(:compressor)
38
+ ::YUI::CssCompressor.should_receive(:new).with(:foo => "bar").and_return(compressor)
39
+ compressor.should_receive(:compress).with("hello").and_return("world")
40
+ Crush::YUI::CssCompressor.new(:foo => "bar").compress("hello")
41
+ end
42
+ end
@@ -0,0 +1,101 @@
1
+ require "spec_helper"
2
+
3
+ describe Crush do
4
+ class MockCompressor
5
+ def self.engine_initialized?
6
+ true
7
+ end
8
+
9
+ attr_reader :args, :block
10
+ def initialize(*args, &block)
11
+ @args = args
12
+ @block = block
13
+ end
14
+ end
15
+
16
+ class MockCompressor2 < MockCompressor
17
+ def self.engine_initialized?
18
+ false
19
+ end
20
+ end
21
+
22
+ before(:all) do
23
+ Crush.register(MockCompressor, "mock", ".mck", "file.txt")
24
+ Crush.register(MockCompressor, "mult")
25
+ Crush.register(MockCompressor2, "mult")
26
+ end
27
+
28
+ describe ".mappings" do
29
+ it "always returns an array" do
30
+ Crush.mappings["none"].should == []
31
+ end
32
+ end
33
+
34
+ describe ".register" do
35
+ it "stores engines" do
36
+ Crush.mappings["mock"].should include(MockCompressor)
37
+ Crush.mappings["mck"].should include(MockCompressor)
38
+ Crush.mappings["file.txt"].should include(MockCompressor)
39
+ end
40
+
41
+ it "prefers the latest registered engines" do
42
+ Crush.mappings["mult"].first.should == MockCompressor2
43
+ end
44
+ end
45
+
46
+ describe ".registered?" do
47
+ it "returns false if the extension is not registered" do
48
+ Crush.registered?("none").should be_false
49
+ end
50
+
51
+ it "returns true if the given extension is registered" do
52
+ Crush.registered?("mock").should be_true
53
+ Crush.registered?(".mock").should be_true
54
+ end
55
+ end
56
+
57
+ describe ".[]" do
58
+ it "returns nil when no engines are found" do
59
+ Crush["none"].should be_nil
60
+ end
61
+
62
+ it "returns engines matching exact extension names" do
63
+ Crush["mock"].should == MockCompressor
64
+ end
65
+
66
+ it "returns engines matching exact file extensions" do
67
+ Crush[".MOCK"].should == MockCompressor
68
+ end
69
+
70
+ it "returns engines matching multiple file extensions" do
71
+ Crush["application.js.Mock"].should == MockCompressor
72
+ end
73
+
74
+ it "returns engines matching filenames" do
75
+ Crush["some/path/file.txt"].should == MockCompressor
76
+ end
77
+
78
+ it "returns engines that are already initialized" do
79
+ Crush["mult"].should == MockCompressor
80
+ end
81
+ end
82
+
83
+ describe ".prefer" do
84
+ it "reorders the engine mappings so the given engine is returned" do
85
+ Crush.prefer(MockCompressor)
86
+ Crush["mult"].should == MockCompressor
87
+ end
88
+ end
89
+
90
+ describe ".new" do
91
+ it "creates a new engine if found" do
92
+ compressor = Crush.new("application.mock", :key => "value") { "Hello World" }
93
+ compressor.args.should =~ [ "application.mock", { :key => "value" } ]
94
+ compressor.block.call.should == "Hello World"
95
+ end
96
+
97
+ it "raises an error if no engine is found" do
98
+ expect { Crush.new("file.php") }.to raise_error(Crush::EngineNotFound)
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,7 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+ Bundler.require
4
+
5
+ RSpec.configure do |config|
6
+
7
+ end
metadata CHANGED
@@ -1,13 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crush
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
5
4
  prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 1
10
- version: 0.0.1
5
+ version: 0.1.0
11
6
  platform: ruby
12
7
  authors:
13
8
  - Pete
@@ -16,9 +11,96 @@ autorequire:
16
11
  bindir: bin
17
12
  cert_chain: []
18
13
 
19
- date: 2011-05-31 00:00:00 Z
20
- dependencies: []
21
-
14
+ date: 2011-06-05 00:00:00 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rspec
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ~>
23
+ - !ruby/object:Gem::Version
24
+ version: 2.6.0
25
+ type: :development
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: jsmin
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: "0"
36
+ type: :development
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: packr
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: uglifier
51
+ prerelease: false
52
+ requirement: &id004 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ type: :development
59
+ version_requirements: *id004
60
+ - !ruby/object:Gem::Dependency
61
+ name: closure-compiler
62
+ prerelease: false
63
+ requirement: &id005 !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ type: :development
70
+ version_requirements: *id005
71
+ - !ruby/object:Gem::Dependency
72
+ name: yui-compressor
73
+ prerelease: false
74
+ requirement: &id006 !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: "0"
80
+ type: :development
81
+ version_requirements: *id006
82
+ - !ruby/object:Gem::Dependency
83
+ name: cssmin
84
+ prerelease: false
85
+ requirement: &id007 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: "0"
91
+ type: :development
92
+ version_requirements: *id007
93
+ - !ruby/object:Gem::Dependency
94
+ name: rainpress
95
+ prerelease: false
96
+ requirement: &id008 !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: "0"
102
+ type: :development
103
+ version_requirements: *id008
22
104
  description: Crush is a generic interface, like Tilt, for the various compression engines in Ruby.
23
105
  email: me@petebrowne.com
24
106
  executables: []
@@ -30,10 +112,30 @@ extra_rdoc_files: []
30
112
  files:
31
113
  - .gitignore
32
114
  - Gemfile
115
+ - LICENSE
116
+ - README.md
33
117
  - Rakefile
34
118
  - crush.gemspec
35
119
  - lib/crush.rb
120
+ - lib/crush/closure.rb
121
+ - lib/crush/cssmin.rb
122
+ - lib/crush/engine.rb
123
+ - lib/crush/jsmin.rb
124
+ - lib/crush/packr.rb
125
+ - lib/crush/rainpress.rb
126
+ - lib/crush/uglifier.rb
36
127
  - lib/crush/version.rb
128
+ - lib/crush/yui.rb
129
+ - spec/crush/closure_spec.rb
130
+ - spec/crush/cssmin_spec.rb
131
+ - spec/crush/engine_spec.rb
132
+ - spec/crush/jsmin_spec.rb
133
+ - spec/crush/packr_spec.rb
134
+ - spec/crush/rainpress_spec.rb
135
+ - spec/crush/uglifier_spec.rb
136
+ - spec/crush/yui_spec.rb
137
+ - spec/crush_spec.rb
138
+ - spec/spec_helper.rb
37
139
  homepage: http://github.com/petebrowne/crush
38
140
  licenses: []
39
141
 
@@ -47,25 +149,28 @@ required_ruby_version: !ruby/object:Gem::Requirement
47
149
  requirements:
48
150
  - - ">="
49
151
  - !ruby/object:Gem::Version
50
- hash: 3
51
- segments:
52
- - 0
53
152
  version: "0"
54
153
  required_rubygems_version: !ruby/object:Gem::Requirement
55
154
  none: false
56
155
  requirements:
57
156
  - - ">="
58
157
  - !ruby/object:Gem::Version
59
- hash: 3
60
- segments:
61
- - 0
62
158
  version: "0"
63
159
  requirements: []
64
160
 
65
161
  rubyforge_project: crush
66
- rubygems_version: 1.7.1
162
+ rubygems_version: 1.7.2
67
163
  signing_key:
68
164
  specification_version: 3
69
165
  summary: A generic interface to multiple Ruby compression engines.
70
- test_files: []
71
-
166
+ test_files:
167
+ - spec/crush/closure_spec.rb
168
+ - spec/crush/cssmin_spec.rb
169
+ - spec/crush/engine_spec.rb
170
+ - spec/crush/jsmin_spec.rb
171
+ - spec/crush/packr_spec.rb
172
+ - spec/crush/rainpress_spec.rb
173
+ - spec/crush/uglifier_spec.rb
174
+ - spec/crush/yui_spec.rb
175
+ - spec/crush_spec.rb
176
+ - spec/spec_helper.rb