crush 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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