juicer 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.
Files changed (71) hide show
  1. data/History.txt +10 -0
  2. data/Manifest.txt +58 -0
  3. data/Rakefile +44 -0
  4. data/Readme.rdoc +143 -0
  5. data/bin/juicer +8 -0
  6. data/lib/juicer.rb +70 -0
  7. data/lib/juicer/binary.rb +173 -0
  8. data/lib/juicer/cache_buster.rb +45 -0
  9. data/lib/juicer/chainable.rb +106 -0
  10. data/lib/juicer/cli.rb +56 -0
  11. data/lib/juicer/command/install.rb +59 -0
  12. data/lib/juicer/command/list.rb +50 -0
  13. data/lib/juicer/command/merge.rb +185 -0
  14. data/lib/juicer/command/util.rb +32 -0
  15. data/lib/juicer/command/verify.rb +60 -0
  16. data/lib/juicer/core.rb +59 -0
  17. data/lib/juicer/css_cache_buster.rb +99 -0
  18. data/lib/juicer/install/base.rb +186 -0
  19. data/lib/juicer/install/jslint_installer.rb +51 -0
  20. data/lib/juicer/install/rhino_installer.rb +52 -0
  21. data/lib/juicer/install/yui_compressor_installer.rb +66 -0
  22. data/lib/juicer/jslint.rb +90 -0
  23. data/lib/juicer/merger/base.rb +74 -0
  24. data/lib/juicer/merger/css_dependency_resolver.rb +25 -0
  25. data/lib/juicer/merger/dependency_resolver.rb +82 -0
  26. data/lib/juicer/merger/javascript_dependency_resolver.rb +21 -0
  27. data/lib/juicer/merger/javascript_merger.rb +30 -0
  28. data/lib/juicer/merger/stylesheet_merger.rb +112 -0
  29. data/lib/juicer/minifyer/yui_compressor.rb +129 -0
  30. data/tasks/ann.rake +80 -0
  31. data/tasks/bones.rake +20 -0
  32. data/tasks/gem.rake +201 -0
  33. data/tasks/git.rake +40 -0
  34. data/tasks/notes.rake +27 -0
  35. data/tasks/post_load.rake +34 -0
  36. data/tasks/rdoc.rake +50 -0
  37. data/tasks/rubyforge.rake +55 -0
  38. data/tasks/setup.rb +300 -0
  39. data/tasks/spec.rake +54 -0
  40. data/tasks/svn.rake +47 -0
  41. data/tasks/test.rake +40 -0
  42. data/tasks/test/setup.rake +35 -0
  43. data/test/bin/jslint.js +474 -0
  44. data/test/bin/rhino1_7R1.zip +0 -0
  45. data/test/bin/rhino1_7R2-RC1.zip +0 -0
  46. data/test/bin/yuicompressor +238 -0
  47. data/test/bin/yuicompressor-2.3.5.zip +0 -0
  48. data/test/bin/yuicompressor-2.4.2.zip +0 -0
  49. data/test/juicer/command/test_install.rb +53 -0
  50. data/test/juicer/command/test_list.rb +69 -0
  51. data/test/juicer/command/test_merge.rb +155 -0
  52. data/test/juicer/command/test_util.rb +54 -0
  53. data/test/juicer/command/test_verify.rb +33 -0
  54. data/test/juicer/install/test_installer_base.rb +195 -0
  55. data/test/juicer/install/test_jslint_installer.rb +54 -0
  56. data/test/juicer/install/test_rhino_installer.rb +57 -0
  57. data/test/juicer/install/test_yui_compressor_installer.rb +56 -0
  58. data/test/juicer/merger/test_base.rb +122 -0
  59. data/test/juicer/merger/test_css_dependency_resolver.rb +36 -0
  60. data/test/juicer/merger/test_javascript_dependency_resolver.rb +39 -0
  61. data/test/juicer/merger/test_javascript_merger.rb +74 -0
  62. data/test/juicer/merger/test_stylesheet_merger.rb +178 -0
  63. data/test/juicer/minifyer/test_yui_compressor.rb +159 -0
  64. data/test/juicer/test_cache_buster.rb +58 -0
  65. data/test/juicer/test_chainable.rb +94 -0
  66. data/test/juicer/test_core.rb +47 -0
  67. data/test/juicer/test_css_cache_buster.rb +72 -0
  68. data/test/juicer/test_jslint.rb +33 -0
  69. data/test/test_helper.rb +146 -0
  70. data/test/test_juicer.rb +4 -0
  71. metadata +194 -0
@@ -0,0 +1,122 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[.. .. test_helper])) unless defined?(Juicer)
2
+
3
+ class TestMergerBase < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @file_merger = Juicer::Merger::Base.new
7
+ Juicer::Test::FileSetup.new.create
8
+ end
9
+
10
+ def teardown
11
+ file = path('test_out.css')
12
+ File.delete(file) if File.exists?(file)
13
+ end
14
+
15
+ def test_constructor
16
+ files = ['a.css', 'b.css'].collect { |file| path(file) }
17
+ file_merger = Juicer::Merger::Base.new files
18
+ assert_equal 2, file_merger.files.length
19
+ end
20
+
21
+ def test_append_duplicate_files
22
+ @file_merger.append ['a.css', 'b.css'].collect { |file| path(file) }
23
+ assert_equal 2, @file_merger.files.length,
24
+ "b.css should not be included twice even when a.css imports it and it is manually added"
25
+ end
26
+
27
+ def test_append_duplicate
28
+ @file_merger.append ['a.css', 'b.css'].collect { |file| path(file) }
29
+ assert_equal 2, @file_merger.files.length
30
+
31
+ @file_merger.append path('a.css')
32
+ assert_equal 2, @file_merger.files.length
33
+
34
+ @file_merger.append path('version.txt')
35
+ assert_equal 3, @file_merger.files.length
36
+ end
37
+
38
+ def test_append_alias
39
+ @file_merger << ['a.css', 'b.css'].collect { |file| path(file) }
40
+ assert_equal 2, @file_merger.files.length
41
+ end
42
+
43
+ def test_save_to_stream
44
+ a_css = path('a.css')
45
+ a_css_contents = IO.read(a_css) + "\n"
46
+ ios = StringIO.new
47
+ @file_merger << a_css
48
+ @file_merger.save ios
49
+ assert_equal a_css_contents, ios.string
50
+ end
51
+
52
+ def test_save_to_file
53
+ a_css = path('a.css')
54
+ output_file = path('test_out.css')
55
+ @file_merger << a_css
56
+ @file_merger.save(output_file)
57
+
58
+ assert_equal IO.read(a_css) + "\n", IO.read(output_file)
59
+ end
60
+
61
+ def test_save_merged_to_stream
62
+ a_css = path('a.css')
63
+ b_css = path('b.css')
64
+ ios = StringIO.new
65
+
66
+ @file_merger << a_css
67
+ @file_merger << b_css
68
+ @file_merger.save(ios)
69
+
70
+ assert_equal "#{IO.read(a_css)}\n#{IO.read(b_css)}\n", ios.string
71
+ end
72
+
73
+ def test_save_merged_to_file
74
+ a_css = path('a.css')
75
+ b_css = path('b.css')
76
+ a_contents = IO.read(a_css) + "\n"
77
+ b_contents = IO.read(b_css) + "\n"
78
+ output_file = path('test_out.css')
79
+
80
+ @file_merger << a_css
81
+ @file_merger << b_css
82
+ @file_merger.save(output_file)
83
+
84
+ assert_equal "#{IO.read(a_css)}\n#{IO.read(b_css)}\n", IO.read(output_file)
85
+ end
86
+
87
+ def test_resolve_dependencies
88
+ Juicer::Merger::Base.publicize_methods do
89
+ @file_merger.dependency_resolver = MockImportResolver.new
90
+
91
+ @file_merger.resolve_dependencies('a.css')
92
+ assert_equal 1, @file_merger.files.length
93
+
94
+ @file_merger.resolve_dependencies('a.css')
95
+ assert_equal 1, @file_merger.files.length
96
+ end
97
+ end
98
+
99
+ def test_merge
100
+ Juicer::Merger::Base.publicize_methods do
101
+ a_content = <<EOF
102
+ @import 'b.css';
103
+
104
+ /* Dette er a.css */
105
+
106
+ EOF
107
+
108
+ content = @file_merger.merge(path('a.css'))
109
+ assert_equal a_content, content
110
+ end
111
+ end
112
+
113
+ def test_attributes
114
+ assert_not_nil @file_merger.files
115
+ end
116
+ end
117
+
118
+ class MockImportResolver
119
+ def resolve(file)
120
+ [file]
121
+ end
122
+ end
@@ -0,0 +1,36 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[.. .. test_helper])) unless defined?(Juicer)
2
+
3
+ class TestCssDependencyResolver < Test::Unit::TestCase
4
+ def setup
5
+ @resolver = Juicer::Merger::CssDependencyResolver.new
6
+ Juicer::Test::FileSetup.new.create
7
+ end
8
+
9
+ def test_init
10
+ assert_equal [], @resolver.files
11
+ end
12
+
13
+ def test_resolve
14
+ b_file = path('b.css')
15
+ a_file = path('a.css')
16
+
17
+ files = @resolver.resolve(path('a.css')) do |file|
18
+ assert b_file == file || a_file == file
19
+ b_file != file
20
+ end
21
+
22
+ assert_equal [a_file], files
23
+
24
+ files = @resolver.resolve(path('a.css')) do |file|
25
+ assert b_file == file || a_file == file
26
+ true
27
+ end
28
+
29
+ assert_equal [a_file, b_file], files.sort
30
+ end
31
+
32
+ def test_load_order
33
+ files = @resolver.resolve(path("a1.css")).collect { |file| file.split("/").pop }
34
+ assert_equal "d1.cssb1.cssc1.cssa1.css", files.join
35
+ end
36
+ end
@@ -0,0 +1,39 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[.. .. test_helper])) unless defined?(Juicer)
2
+
3
+ class TestJavaScriptDependencyResolver < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @resolver = Juicer::Merger::JavaScriptDependencyResolver.new
7
+ Juicer::Test::FileSetup.new.create
8
+ end
9
+
10
+ def test_init
11
+ assert_equal [], @resolver.files
12
+ end
13
+
14
+ def test_resolve
15
+ b_file = path('b.js')
16
+ a_file = path('a.js')
17
+
18
+ files = @resolver.resolve(a_file) do |file|
19
+ assert b_file == file || a_file == file, file
20
+ b_file != file
21
+ end
22
+
23
+ assert_equal [a_file], files
24
+
25
+ files = @resolver.resolve(a_file) do |file|
26
+ assert b_file == file || a_file == file
27
+ true
28
+ end
29
+
30
+ assert_equal [a_file, b_file], files.sort
31
+
32
+ files = @resolver.resolve(b_file) do |file|
33
+ assert b_file == file || a_file == file
34
+ true
35
+ end
36
+
37
+ assert_equal [a_file, b_file], files.sort
38
+ end
39
+ end
@@ -0,0 +1,74 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[.. .. test_helper])) unless defined?(Juicer)
2
+
3
+ class TestJavaScriptMerger < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @file_merger = Juicer::Merger::JavaScriptMerger.new
7
+ Juicer::Test::FileSetup.new.create
8
+ end
9
+
10
+ def teardown
11
+ file = path('test_out.js')
12
+ File.delete(file) if File.exists?(file)
13
+ end
14
+
15
+ def test_init
16
+ Juicer::Merger::JavaScriptMerger.publicize_methods do
17
+ assert_equal Juicer::Merger::JavaScriptDependencyResolver, @file_merger.dependency_resolver.class
18
+ end
19
+ end
20
+
21
+ def test_merge
22
+ Juicer::Merger::JavaScriptMerger.publicize_methods do
23
+ a_content = <<EOF
24
+ /**
25
+ * @depend b.js
26
+ */
27
+
28
+ /* Dette er a.js */
29
+
30
+ EOF
31
+ content = @file_merger.merge(path('a.js'))
32
+ assert_equal a_content, content
33
+ end
34
+ end
35
+
36
+ def test_constructor
37
+ file_merger = Juicer::Merger::JavaScriptMerger.new(path('a.js'))
38
+ assert_equal 2, file_merger.files.length
39
+ end
40
+
41
+ def test_append
42
+ @file_merger << path('a.js')
43
+ assert_equal 2, @file_merger.files.length
44
+ end
45
+
46
+ def test_save
47
+ a_js = path('a.js')
48
+ b_js = path('b.js')
49
+ merged = <<EOF
50
+ /**
51
+ * @depends a.js
52
+ */
53
+
54
+ /* Dette er b.css */
55
+
56
+ /**
57
+ * @depend b.js
58
+ */
59
+
60
+ /* Dette er a.js */
61
+
62
+ EOF
63
+
64
+ @file_merger << a_js
65
+ ios = StringIO.new
66
+ @file_merger.save(ios)
67
+ assert_equal merged, ios.string
68
+
69
+ output_file = path('test_out.js')
70
+ @file_merger.save(output_file)
71
+
72
+ assert_equal merged, IO.read(output_file)
73
+ end
74
+ end
@@ -0,0 +1,178 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[.. .. test_helper])) unless defined?(Juicer)
2
+
3
+ class TestStylesheetMerger < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @file_merger = Juicer::Merger::StylesheetMerger.new
7
+ Juicer::Test::FileSetup.new.create
8
+ Dir.chdir path("")
9
+ end
10
+
11
+ def teardown
12
+ file = path('test_out.css')
13
+ File.delete(file) if File.exists?(file)
14
+ end
15
+
16
+ def test_init
17
+ Juicer::Merger::StylesheetMerger.publicize_methods do
18
+ assert_equal Juicer::Merger::CssDependencyResolver, @file_merger.dependency_resolver.class
19
+ end
20
+ end
21
+
22
+ def test_merge
23
+ Juicer::Merger::StylesheetMerger.publicize_methods do
24
+ a_content = "\n\n/* Dette er a.css */\n"
25
+ content = @file_merger.merge(path('a.css'))
26
+ assert_equal a_content + "\n", content
27
+ end
28
+ end
29
+
30
+ def test_constructor
31
+ file_merger = Juicer::Merger::StylesheetMerger.new(path('a.css'))
32
+ assert_equal 2, file_merger.files.length
33
+ end
34
+
35
+ def test_append
36
+ @file_merger << path('a.css')
37
+ assert_equal 2, @file_merger.files.length
38
+ end
39
+
40
+ def test_save
41
+ a_css = path('a.css')
42
+ b_css = path('b.css')
43
+ merged = <<EOF
44
+ /* Dette er b.css */
45
+
46
+
47
+
48
+ /* Dette er a.css */
49
+
50
+ EOF
51
+
52
+ @file_merger << a_css
53
+ ios = StringIO.new
54
+ @file_merger.save(ios)
55
+ assert_equal merged, ios.string
56
+
57
+ output_file = path('test_out.css')
58
+ @file_merger.save(output_file)
59
+
60
+ assert_equal merged, IO.read(output_file)
61
+ end
62
+
63
+ def test_included_files_should_have_referenced_relative_urls_rereferenced
64
+ @file_merger << path("path_test.css")
65
+ ios = StringIO.new
66
+ @file_merger.save(ios)
67
+ files = ios.string.scan(/url\(([^\)]*)\)/).collect { |f| f.first }.uniq.sort
68
+
69
+ assert_equal "a1.css::css/2.gif::images/1.png", files.join("::")
70
+ end
71
+
72
+ def test_resolve_path_should_leave_absolute_urls
73
+ merger = Juicer::Merger::StylesheetMerger.new
74
+ url = "/some/url"
75
+
76
+ Juicer::Merger::StylesheetMerger.publicize_methods do
77
+ assert_equal url, merger.resolve_path(url, nil)
78
+ end
79
+ end
80
+
81
+ def test_resolve_path_error_when_relative_missing_web_root
82
+ merger = Juicer::Merger::StylesheetMerger.new [], :relative_urls => true
83
+
84
+ Juicer::Merger::StylesheetMerger.publicize_methods do
85
+ assert_raise ArgumentError do
86
+ merger.resolve_path("/some/url", nil)
87
+ end
88
+ end
89
+ end
90
+
91
+ def test_resolve_path_should_make_absolute_urls_relative
92
+ merger = Juicer::Merger::StylesheetMerger.new [], :relative_urls => true, :web_root => "/home/usr"
93
+
94
+ Juicer::Merger::StylesheetMerger.publicize_methods do
95
+ merger.instance_eval { @root = Pathname.new "/home/usr/design" }
96
+ assert_equal "../some/url", merger.resolve_path("/some/url", nil)
97
+ end
98
+ end
99
+
100
+ def test_resolve_path_should_leave_full_urls
101
+ merger = Juicer::Merger::StylesheetMerger.new []
102
+ url = "http://test.com"
103
+
104
+ Juicer::Merger::StylesheetMerger.publicize_methods do
105
+ merger.instance_eval { @root = Pathname.new "/home/usr/design" }
106
+ assert_equal url, merger.resolve_path(url, nil)
107
+ end
108
+ end
109
+
110
+ def test_resolve_path_error_when_missing_absolute_web_root
111
+ merger = Juicer::Merger::StylesheetMerger.new [], :absolute_urls => true
112
+
113
+ Juicer::Merger::StylesheetMerger.publicize_methods do
114
+ assert_raise ArgumentError do
115
+ merger.resolve_path("../some/url", nil)
116
+ end
117
+ end
118
+ end
119
+
120
+ def test_resolve_path_should_make_relative_urls_absolute
121
+ merger = Juicer::Merger::StylesheetMerger.new [], :absolute_urls => true, :web_root => "/home/usr"
122
+
123
+ Juicer::Merger::StylesheetMerger.publicize_methods do
124
+ merger.instance_eval { @root = Pathname.new "/home/usr/design" }
125
+ assert_equal "/design/images/1.png", merger.resolve_path("../images/1.png", "/home/usr/design/css")
126
+ end
127
+ end
128
+
129
+ def test_resolve_path_should_redefine_relative_urls
130
+ merger = Juicer::Merger::StylesheetMerger.new [], :relative_urls => true
131
+
132
+ Juicer::Merger::StylesheetMerger.publicize_methods do
133
+ merger.instance_eval { @root = Pathname.new "/home/usr/design2/css" }
134
+ assert_equal "../../design/images/1.png", merger.resolve_path("../images/1.png", "/home/usr/design/css")
135
+ end
136
+ end
137
+
138
+ def test_resolve_path_should_redefine_absolute_urls
139
+ merger = Juicer::Merger::StylesheetMerger.new [], :relative_urls => true, :web_root => "/home/usr"
140
+
141
+ Juicer::Merger::StylesheetMerger.publicize_methods do
142
+ merger.instance_eval { @root = Pathname.new "/home/usr/design2/css" }
143
+ assert_equal "../../images/1.png", merger.resolve_path("/images/1.png", "/home/usr/design/css")
144
+ end
145
+ end
146
+
147
+ def test_resolve_path_with_hosts_should_cycle_asset_hosts
148
+ merger = Juicer::Merger::StylesheetMerger.new [], :hosts => ["http://assets1", "http://assets2", "http://assets3"]
149
+
150
+ Juicer::Merger::StylesheetMerger.publicize_methods do
151
+ merger.instance_eval { @root = Pathname.new "/home/usr/design2/css" }
152
+ assert_equal "http://assets1/images/1.png", merger.resolve_path("/images/1.png", nil)
153
+ assert_equal "http://assets2/images/1.png", merger.resolve_path("/images/1.png", nil)
154
+ assert_equal "http://assets3/images/1.png", merger.resolve_path("/images/1.png", nil)
155
+ assert_equal "http://assets1/images/1.png", merger.resolve_path("/images/1.png", nil)
156
+ end
157
+ end
158
+
159
+ def test_resolve_paths_should_handle_relative_web_roots
160
+ merger = Juicer::Merger::StylesheetMerger.new [], :web_root => "test/data", :relative_urls => true
161
+ merger << File.expand_path("css/test2.css")
162
+
163
+ Juicer::Merger::StylesheetMerger.publicize_methods do
164
+ merger.instance_eval { @root = Pathname.new File.expand_path("test/data/css") }
165
+ assert_equal "../images/1.png", merger.resolve_path("/images/1.png", nil)
166
+ end
167
+ end
168
+
169
+ def test_cycle_asset_hosts_should_use_same_host_for_same_url
170
+ @file_merger = Juicer::Merger::StylesheetMerger.new nil, :hosts => ["http://assets1", "http://assets2", "http://assets3"]
171
+ @file_merger << path("path_test2.css")
172
+ ios = StringIO.new
173
+ @file_merger.save(ios)
174
+ files = ios.string.scan(/url\(([^\)]*)\)/).collect { |f| f.first }
175
+
176
+ assert_equal "1/images/1.png::2/css/2.gif::3/a1.css::2/css/2.gif::1/a2.css".gsub(/(\d\/)/, 'http://assets\1'), files.join("::")
177
+ end
178
+ end