crush 0.1.0 → 0.2.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/README.md +41 -1
- data/lib/crush.rb +47 -18
- data/lib/crush/closure.rb +4 -0
- data/lib/crush/cssmin.rb +4 -0
- data/lib/crush/engine.rb +11 -0
- data/lib/crush/jsmin.rb +4 -0
- data/lib/crush/version.rb +1 -1
- data/lib/crush/yui.rb +8 -0
- data/spec/crush/closure_spec.rb +2 -0
- data/spec/crush/cssmin_spec.rb +2 -0
- data/spec/crush/engine_spec.rb +6 -0
- data/spec/crush/jsmin_spec.rb +2 -0
- data/spec/crush/packr_spec.rb +2 -0
- data/spec/crush/rainpress_spec.rb +2 -0
- data/spec/crush/uglifier_spec.rb +2 -0
- data/spec/crush/yui_spec.rb +4 -0
- data/spec/crush_spec.rb +65 -21
- metadata +40 -3
data/README.md
CHANGED
@@ -32,10 +32,50 @@ Or you could use `Crush.prefer` to tell Crush which engine you'd like to use.
|
|
32
32
|
require "uglifier"
|
33
33
|
require "jsmin"
|
34
34
|
require "crush"
|
35
|
-
Crush.prefer(Crush::Uglifier)
|
35
|
+
Crush.prefer(Crush::Uglifier) # or Crush.prefer(:uglifier)
|
36
36
|
Crush.new("application.js").compress
|
37
37
|
```
|
38
38
|
|
39
|
+
API
|
40
|
+
---
|
41
|
+
|
42
|
+
There a few different ways to compress some data. The API, for the most part, follows the Tilt
|
43
|
+
API. So this is the standard way of compressing (reading the data from the file):
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
Crush.new("file.js", :mangle => true).compress
|
47
|
+
```
|
48
|
+
|
49
|
+
You can also pass the data using a block, like Tilt.
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
Crush.new(:uglifier, :mangle => true) { "some data to compress" }.compress
|
53
|
+
```
|
54
|
+
|
55
|
+
_Note how I declared which engine to use by its name (as a Symbol)._
|
56
|
+
|
57
|
+
I've also included a way to pass data that is more consistent with the other compression engines:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
Crush.new(:uglifier, :mangle => true).compress("some data to compress")
|
61
|
+
```
|
62
|
+
|
63
|
+
Engines
|
64
|
+
-------
|
65
|
+
|
66
|
+
Support fo these compression engines are included:
|
67
|
+
|
68
|
+
ENGINES FILE EXTENSIONS NAME REQUIRED LIBRARIES
|
69
|
+
-------------------------- ------------------ ---------- ------------------
|
70
|
+
JSMin .js, .min.js jsmin jsmin
|
71
|
+
Packr .js, .pack.js packr packr
|
72
|
+
YUI::JavaScriptCompressor .js, .yui.js yui_js yui/compressor
|
73
|
+
Closure::Compiler .js, .closure.js closure closure-compiler
|
74
|
+
Uglifier .js, .ugly.js uglifier uglifier
|
75
|
+
CSSMin .css, .min.css cssmin cssmin
|
76
|
+
Rainpress .css, .rain.css rainpress rainpress
|
77
|
+
YUI::CssCompressor .css, .yui.css yui_css yui/compressor
|
78
|
+
|
39
79
|
Copyright
|
40
80
|
---------
|
41
81
|
|
data/lib/crush.rb
CHANGED
@@ -10,9 +10,12 @@ module Crush
|
|
10
10
|
|
11
11
|
class EngineNotFound < StandardError; end
|
12
12
|
|
13
|
+
@preferred_engines = {}
|
14
|
+
@engine_mappings = Hash.new { |h, k| h[k] = [] }
|
15
|
+
|
13
16
|
# Hash of registered compression engines.
|
14
17
|
def self.mappings
|
15
|
-
@
|
18
|
+
@engine_mappings
|
16
19
|
end
|
17
20
|
|
18
21
|
# Ensures the extension doesn't include the "."
|
@@ -36,37 +39,63 @@ module Crush
|
|
36
39
|
|
37
40
|
# Make the given compression engine preferred. Which means,
|
38
41
|
# it will reordered the beginning of its mapping.
|
39
|
-
def self.prefer(
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
42
|
+
def self.prefer(engine_or_name, *extensions)
|
43
|
+
engine = find_by_name(engine_or_name) unless engine_or_name.is_a?(Class)
|
44
|
+
|
45
|
+
if extensions.empty?
|
46
|
+
mappings.each do |ext, engines|
|
47
|
+
@preferred_engines[ext] = engine if engines.include?(engine)
|
48
|
+
end
|
49
|
+
else
|
50
|
+
register(engine, *extensions)
|
51
|
+
extensions.each do |ext|
|
52
|
+
ext = normalize(ext)
|
53
|
+
@preferred_engines[ext] = engine
|
44
54
|
end
|
45
55
|
end
|
46
56
|
end
|
47
57
|
|
58
|
+
# Looks for a compression engine. When given a Symbol, it will look for an engine
|
59
|
+
# by name. When given a String, it will look for a compression engine by filename
|
60
|
+
# or file extension.
|
61
|
+
def self.[](path_or_name)
|
62
|
+
path_or_name.is_a?(Symbol) ? find_by_name(path_or_name) : find_by_path(path_or_name)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Create a new compression engine. The first argument is used to determine
|
66
|
+
# which engine to use. This can be either an engine name (as a Symbol) or a path
|
67
|
+
# to a file (as a String). If a path is given, the engine is initialized with
|
68
|
+
# a reference to that path.
|
69
|
+
def self.new(path_or_name, options = {}, &block)
|
70
|
+
if engine = self[path_or_name]
|
71
|
+
path = path_or_name.is_a?(Symbol) ? nil : path_or_name
|
72
|
+
engine.new(path, options, &block)
|
73
|
+
else
|
74
|
+
raise EngineNotFound.new("No compression engine registered for '#{path}'")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Look for a compression engine with the given engine name.
|
79
|
+
# Return nil when no engine is found.
|
80
|
+
def self.find_by_name(engine_name)
|
81
|
+
mappings.values.flatten.detect { |engine| engine.engine_name == engine_name.to_s }
|
82
|
+
end
|
83
|
+
|
48
84
|
# Look for a compression engine for the given filename or file
|
49
85
|
# extension. Return nil when no engine is found.
|
50
|
-
def self.
|
86
|
+
def self.find_by_path(path)
|
51
87
|
pattern = File.basename(path.to_s).downcase
|
52
88
|
until pattern.empty? || registered?(pattern)
|
53
89
|
pattern.sub! /^[^.]*\.?/, ""
|
54
90
|
end
|
55
|
-
|
56
91
|
pattern = normalize(pattern)
|
92
|
+
|
93
|
+
preferred_engine = @preferred_engines[pattern]
|
94
|
+
return preferred_engine unless preferred_engine.nil?
|
95
|
+
|
57
96
|
mappings[pattern].detect(&:engine_initialized?) || mappings[pattern].first
|
58
97
|
end
|
59
98
|
|
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
99
|
register Crush::JSMin, "js", "min.js"
|
71
100
|
register Crush::Packr, "js", "pack.js"
|
72
101
|
register Crush::YUI::JavaScriptCompressor, "js", "yui.js"
|
data/lib/crush/closure.rb
CHANGED
data/lib/crush/cssmin.rb
CHANGED
data/lib/crush/engine.rb
CHANGED
@@ -16,6 +16,17 @@ module Crush
|
|
16
16
|
class << self
|
17
17
|
attr_accessor :engine_initialized
|
18
18
|
alias :engine_initialized? :engine_initialized
|
19
|
+
|
20
|
+
# Returns a lowercase, underscored name for the engine.
|
21
|
+
def engine_name
|
22
|
+
engine_name = name.to_s.dup
|
23
|
+
engine_name.sub! /^.*::/ , ""
|
24
|
+
engine_name.gsub! /([A-Z]+)([A-Z][a-z])/, '\1_\2'
|
25
|
+
engine_name.gsub! /([a-z\d])([A-Z])/, '\1_\2'
|
26
|
+
engine_name.tr! "-", "_"
|
27
|
+
engine_name.downcase!
|
28
|
+
engine_name
|
29
|
+
end
|
19
30
|
end
|
20
31
|
|
21
32
|
# Create a new engine with the file and options specified. By
|
data/lib/crush/jsmin.rb
CHANGED
data/lib/crush/version.rb
CHANGED
data/lib/crush/yui.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
module Crush
|
2
2
|
module YUI
|
3
3
|
class JavaScriptCompressor < Crush::Engine
|
4
|
+
def self.engine_name
|
5
|
+
"yui_js"
|
6
|
+
end
|
7
|
+
|
4
8
|
def self.engine_initialized?
|
5
9
|
!!(defined? ::YUI) && !!(defined? ::YUI::JavaScriptCompressor)
|
6
10
|
end
|
@@ -19,6 +23,10 @@ module Crush
|
|
19
23
|
end
|
20
24
|
|
21
25
|
class CssCompressor < Crush::Engine
|
26
|
+
def self.engine_name
|
27
|
+
"yui_css"
|
28
|
+
end
|
29
|
+
|
22
30
|
def self.engine_initialized?
|
23
31
|
!!(defined? ::YUI) && !!(defined? ::YUI::CssCompressor)
|
24
32
|
end
|
data/spec/crush/closure_spec.rb
CHANGED
@@ -2,6 +2,8 @@ require "spec_helper"
|
|
2
2
|
require "closure-compiler"
|
3
3
|
|
4
4
|
describe Crush::Closure::Compiler do
|
5
|
+
specify { Crush::Closure::Compiler.engine_name.should == "closure" }
|
6
|
+
|
5
7
|
it "is registered for '.js' files" do
|
6
8
|
Crush.mappings["js"].should include(Crush::Closure::Compiler)
|
7
9
|
end
|
data/spec/crush/cssmin_spec.rb
CHANGED
data/spec/crush/engine_spec.rb
CHANGED
@@ -4,6 +4,12 @@ describe Crush::Engine do
|
|
4
4
|
class MockEngine < Crush::Engine
|
5
5
|
end
|
6
6
|
|
7
|
+
describe ".engine_name" do
|
8
|
+
it "returns an undescored version of the class name" do
|
9
|
+
MockEngine.engine_name.should == "mock_engine"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
7
13
|
describe "#file" do
|
8
14
|
it "returns the file the engine was initialized with" do
|
9
15
|
engine = MockEngine.new("application.js") {}
|
data/spec/crush/jsmin_spec.rb
CHANGED
data/spec/crush/packr_spec.rb
CHANGED
data/spec/crush/uglifier_spec.rb
CHANGED
data/spec/crush/yui_spec.rb
CHANGED
@@ -2,6 +2,8 @@ require "spec_helper"
|
|
2
2
|
require "yui/compressor"
|
3
3
|
|
4
4
|
describe Crush::YUI::JavaScriptCompressor do
|
5
|
+
specify { Crush::YUI::JavaScriptCompressor.engine_name.should == "yui_js" }
|
6
|
+
|
5
7
|
it "is registered for '.js' files" do
|
6
8
|
Crush.mappings["js"].should include(Crush::YUI::JavaScriptCompressor)
|
7
9
|
end
|
@@ -22,6 +24,8 @@ describe Crush::YUI::JavaScriptCompressor do
|
|
22
24
|
end
|
23
25
|
|
24
26
|
describe Crush::YUI::CssCompressor do
|
27
|
+
specify { Crush::YUI::CssCompressor.engine_name.should == "yui_css" }
|
28
|
+
|
25
29
|
it "is registered for '.js' files" do
|
26
30
|
Crush.mappings["css"].should include(Crush::YUI::CssCompressor)
|
27
31
|
end
|
data/spec/crush_spec.rb
CHANGED
@@ -2,6 +2,10 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Crush do
|
4
4
|
class MockCompressor
|
5
|
+
def self.engine_name
|
6
|
+
"mock"
|
7
|
+
end
|
8
|
+
|
5
9
|
def self.engine_initialized?
|
6
10
|
true
|
7
11
|
end
|
@@ -14,6 +18,10 @@ describe Crush do
|
|
14
18
|
end
|
15
19
|
|
16
20
|
class MockCompressor2 < MockCompressor
|
21
|
+
def self.engine_name
|
22
|
+
"mock2"
|
23
|
+
end
|
24
|
+
|
17
25
|
def self.engine_initialized?
|
18
26
|
false
|
19
27
|
end
|
@@ -21,8 +29,8 @@ describe Crush do
|
|
21
29
|
|
22
30
|
before(:all) do
|
23
31
|
Crush.register(MockCompressor, "mock", ".mck", "file.txt")
|
24
|
-
Crush.register(MockCompressor, "mult")
|
25
|
-
Crush.register(MockCompressor2, "mult")
|
32
|
+
Crush.register(MockCompressor, "mult", "mlt")
|
33
|
+
Crush.register(MockCompressor2, "mult", "mlt")
|
26
34
|
end
|
27
35
|
|
28
36
|
describe ".mappings" do
|
@@ -55,36 +63,34 @@ describe Crush do
|
|
55
63
|
end
|
56
64
|
|
57
65
|
describe ".[]" do
|
58
|
-
it "returns
|
59
|
-
Crush["none"].should be_nil
|
60
|
-
end
|
61
|
-
|
62
|
-
it "returns engines matching exact extension names" do
|
66
|
+
it "returns engines found by path when given strings" do
|
63
67
|
Crush["mock"].should == MockCompressor
|
64
|
-
|
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
|
68
|
+
Crush["application.js.mock"].should == MockCompressor
|
75
69
|
Crush["some/path/file.txt"].should == MockCompressor
|
76
70
|
end
|
77
71
|
|
78
|
-
it "returns engines
|
79
|
-
Crush[
|
72
|
+
it "returns engines found by name when given symbols" do
|
73
|
+
Crush[:mock].should == MockCompressor
|
74
|
+
Crush[:mock2].should == MockCompressor2
|
80
75
|
end
|
81
76
|
end
|
82
77
|
|
83
78
|
describe ".prefer" do
|
84
|
-
it "reorders the engine
|
79
|
+
it "reorders the engine engines so the given engine is returned" do
|
85
80
|
Crush.prefer(MockCompressor)
|
86
81
|
Crush["mult"].should == MockCompressor
|
87
82
|
end
|
83
|
+
|
84
|
+
it "accepts symbol names of the various engines" do
|
85
|
+
Crush.prefer(:mock2)
|
86
|
+
Crush["mult"].should == MockCompressor2
|
87
|
+
end
|
88
|
+
|
89
|
+
it "limits the preference to the given extensions" do
|
90
|
+
Crush.prefer(:mock, "mlt")
|
91
|
+
Crush["mult"].should == MockCompressor2
|
92
|
+
Crush["mlt"].should == MockCompressor
|
93
|
+
end
|
88
94
|
end
|
89
95
|
|
90
96
|
describe ".new" do
|
@@ -98,4 +104,42 @@ describe Crush do
|
|
98
104
|
expect { Crush.new("file.php") }.to raise_error(Crush::EngineNotFound)
|
99
105
|
end
|
100
106
|
end
|
107
|
+
|
108
|
+
describe ".find_by_name" do
|
109
|
+
it "returns nil if the engine could not be found" do
|
110
|
+
Crush.find_by_name("none").should be_nil
|
111
|
+
end
|
112
|
+
|
113
|
+
it "returns the registered engine with the given name" do
|
114
|
+
Crush.find_by_name("mock").should == MockCompressor
|
115
|
+
Crush.find_by_name("mock2").should == MockCompressor2
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe ".find_by_path" do
|
120
|
+
it "returns nil when no engines are found" do
|
121
|
+
Crush.find_by_path("none").should be_nil
|
122
|
+
end
|
123
|
+
|
124
|
+
it "returns engines matching exact extension names" do
|
125
|
+
Crush.find_by_path("mock").should == MockCompressor
|
126
|
+
end
|
127
|
+
|
128
|
+
it "returns engines matching exact file extensions" do
|
129
|
+
Crush.find_by_path(".MOCK").should == MockCompressor
|
130
|
+
end
|
131
|
+
|
132
|
+
it "returns engines matching multiple file extensions" do
|
133
|
+
Crush.find_by_path("application.js.Mock").should == MockCompressor
|
134
|
+
end
|
135
|
+
|
136
|
+
it "returns engines matching filenames" do
|
137
|
+
Crush.find_by_path("some/path/file.txt").should == MockCompressor
|
138
|
+
end
|
139
|
+
|
140
|
+
it "returns engines that are already initialized" do
|
141
|
+
Crush.instance_variable_get("@preferred_engines").delete("mult")
|
142
|
+
Crush.find_by_path("mult").should == MockCompressor
|
143
|
+
end
|
144
|
+
end
|
101
145
|
end
|
metadata
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crush
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
4
5
|
prerelease:
|
5
|
-
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
6
11
|
platform: ruby
|
7
12
|
authors:
|
8
13
|
- Pete
|
@@ -11,7 +16,7 @@ autorequire:
|
|
11
16
|
bindir: bin
|
12
17
|
cert_chain: []
|
13
18
|
|
14
|
-
date: 2011-06-
|
19
|
+
date: 2011-06-06 00:00:00 Z
|
15
20
|
dependencies:
|
16
21
|
- !ruby/object:Gem::Dependency
|
17
22
|
name: rspec
|
@@ -21,6 +26,11 @@ dependencies:
|
|
21
26
|
requirements:
|
22
27
|
- - ~>
|
23
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 23
|
30
|
+
segments:
|
31
|
+
- 2
|
32
|
+
- 6
|
33
|
+
- 0
|
24
34
|
version: 2.6.0
|
25
35
|
type: :development
|
26
36
|
version_requirements: *id001
|
@@ -32,6 +42,9 @@ dependencies:
|
|
32
42
|
requirements:
|
33
43
|
- - ">="
|
34
44
|
- !ruby/object:Gem::Version
|
45
|
+
hash: 3
|
46
|
+
segments:
|
47
|
+
- 0
|
35
48
|
version: "0"
|
36
49
|
type: :development
|
37
50
|
version_requirements: *id002
|
@@ -43,6 +56,9 @@ dependencies:
|
|
43
56
|
requirements:
|
44
57
|
- - ">="
|
45
58
|
- !ruby/object:Gem::Version
|
59
|
+
hash: 3
|
60
|
+
segments:
|
61
|
+
- 0
|
46
62
|
version: "0"
|
47
63
|
type: :development
|
48
64
|
version_requirements: *id003
|
@@ -54,6 +70,9 @@ dependencies:
|
|
54
70
|
requirements:
|
55
71
|
- - ">="
|
56
72
|
- !ruby/object:Gem::Version
|
73
|
+
hash: 3
|
74
|
+
segments:
|
75
|
+
- 0
|
57
76
|
version: "0"
|
58
77
|
type: :development
|
59
78
|
version_requirements: *id004
|
@@ -65,6 +84,9 @@ dependencies:
|
|
65
84
|
requirements:
|
66
85
|
- - ">="
|
67
86
|
- !ruby/object:Gem::Version
|
87
|
+
hash: 3
|
88
|
+
segments:
|
89
|
+
- 0
|
68
90
|
version: "0"
|
69
91
|
type: :development
|
70
92
|
version_requirements: *id005
|
@@ -76,6 +98,9 @@ dependencies:
|
|
76
98
|
requirements:
|
77
99
|
- - ">="
|
78
100
|
- !ruby/object:Gem::Version
|
101
|
+
hash: 3
|
102
|
+
segments:
|
103
|
+
- 0
|
79
104
|
version: "0"
|
80
105
|
type: :development
|
81
106
|
version_requirements: *id006
|
@@ -87,6 +112,9 @@ dependencies:
|
|
87
112
|
requirements:
|
88
113
|
- - ">="
|
89
114
|
- !ruby/object:Gem::Version
|
115
|
+
hash: 3
|
116
|
+
segments:
|
117
|
+
- 0
|
90
118
|
version: "0"
|
91
119
|
type: :development
|
92
120
|
version_requirements: *id007
|
@@ -98,6 +126,9 @@ dependencies:
|
|
98
126
|
requirements:
|
99
127
|
- - ">="
|
100
128
|
- !ruby/object:Gem::Version
|
129
|
+
hash: 3
|
130
|
+
segments:
|
131
|
+
- 0
|
101
132
|
version: "0"
|
102
133
|
type: :development
|
103
134
|
version_requirements: *id008
|
@@ -149,17 +180,23 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
149
180
|
requirements:
|
150
181
|
- - ">="
|
151
182
|
- !ruby/object:Gem::Version
|
183
|
+
hash: 3
|
184
|
+
segments:
|
185
|
+
- 0
|
152
186
|
version: "0"
|
153
187
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
188
|
none: false
|
155
189
|
requirements:
|
156
190
|
- - ">="
|
157
191
|
- !ruby/object:Gem::Version
|
192
|
+
hash: 3
|
193
|
+
segments:
|
194
|
+
- 0
|
158
195
|
version: "0"
|
159
196
|
requirements: []
|
160
197
|
|
161
198
|
rubyforge_project: crush
|
162
|
-
rubygems_version: 1.7.
|
199
|
+
rubygems_version: 1.7.1
|
163
200
|
signing_key:
|
164
201
|
specification_version: 3
|
165
202
|
summary: A generic interface to multiple Ruby compression engines.
|