juicer 0.2.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/History.txt +28 -0
  2. data/Rakefile +84 -36
  3. data/Readme.rdoc +192 -23
  4. data/VERSION +1 -0
  5. data/bin/juicer +2 -4
  6. data/lib/juicer.rb +9 -10
  7. data/lib/juicer/asset/path.rb +275 -0
  8. data/lib/juicer/asset/path_resolver.rb +79 -0
  9. data/lib/juicer/binary.rb +3 -5
  10. data/lib/juicer/cache_buster.rb +112 -27
  11. data/lib/juicer/command/install.rb +4 -2
  12. data/lib/juicer/command/list.rb +16 -9
  13. data/lib/juicer/command/merge.rb +30 -14
  14. data/lib/juicer/command/verify.rb +1 -1
  15. data/lib/juicer/css_cache_buster.rb +31 -47
  16. data/lib/juicer/datafy/datafy.rb +20 -0
  17. data/lib/juicer/dependency_resolver/css_dependency_resolver.rb +29 -0
  18. data/lib/juicer/dependency_resolver/dependency_resolver.rb +101 -0
  19. data/lib/juicer/dependency_resolver/javascript_dependency_resolver.rb +23 -0
  20. data/lib/juicer/ext/logger.rb +5 -0
  21. data/lib/juicer/ext/string.rb +47 -0
  22. data/lib/juicer/ext/symbol.rb +15 -0
  23. data/lib/juicer/image_embed.rb +129 -0
  24. data/lib/juicer/install/base.rb +2 -2
  25. data/lib/juicer/install/closure_compiler_installer.rb +69 -0
  26. data/lib/juicer/install/jslint_installer.rb +3 -3
  27. data/lib/juicer/install/rhino_installer.rb +3 -2
  28. data/lib/juicer/install/yui_compressor_installer.rb +3 -2
  29. data/lib/juicer/jslint.rb +1 -1
  30. data/lib/juicer/merger/base.rb +1 -1
  31. data/lib/juicer/merger/javascript_merger.rb +3 -4
  32. data/lib/juicer/merger/stylesheet_merger.rb +13 -15
  33. data/lib/juicer/minifyer/closure_compiler.rb +90 -0
  34. data/lib/juicer/minifyer/java_base.rb +77 -0
  35. data/lib/juicer/minifyer/yui_compressor.rb +15 -48
  36. data/test/bin/jslint-1.0.js +523 -0
  37. data/test/bin/jslint.js +523 -0
  38. data/test/bin/rhino1_7R1.zip +0 -0
  39. data/test/bin/rhino1_7R2-RC1.jar +0 -0
  40. data/test/bin/rhino1_7R2-RC1.zip +0 -0
  41. data/test/bin/yuicompressor +0 -0
  42. data/test/bin/yuicompressor-2.3.5.zip +0 -0
  43. data/test/bin/yuicompressor-2.4.2.jar +0 -0
  44. data/test/bin/yuicompressor-2.4.2.zip +0 -0
  45. data/test/data/Changelog.txt +10 -0
  46. data/test/data/a.css +3 -0
  47. data/test/data/a.js +5 -0
  48. data/test/data/a1.css +5 -0
  49. data/test/data/b.css +1 -0
  50. data/test/data/b.js +5 -0
  51. data/test/data/b1.css +5 -0
  52. data/test/data/c1.css +3 -0
  53. data/test/data/css/2.gif +1 -0
  54. data/test/data/css/test.css +11 -0
  55. data/test/data/css/test2.css +1 -0
  56. data/test/data/d1.css +3 -0
  57. data/test/data/images/1.png +1 -0
  58. data/test/data/my_app.js +2 -0
  59. data/test/data/not-ok.js +2 -0
  60. data/test/data/ok.js +3 -0
  61. data/test/data/path_test.css +5 -0
  62. data/test/data/path_test2.css +14 -0
  63. data/test/data/pkg/module/moda.js +2 -0
  64. data/test/data/pkg/module/modb.js +3 -0
  65. data/test/data/pkg/pkg.js +1 -0
  66. data/test/fixtures/yui-download.html +425 -0
  67. data/test/test_helper.rb +36 -7
  68. data/test/unit/juicer/asset/path_resolver_test.rb +76 -0
  69. data/test/unit/juicer/asset/path_test.rb +370 -0
  70. data/test/unit/juicer/cache_buster_test.rb +104 -0
  71. data/test/{juicer/test_chainable.rb → unit/juicer/chainable_test.rb} +1 -1
  72. data/test/unit/juicer/command/install_test.rb +58 -0
  73. data/test/{juicer/command/test_list.rb → unit/juicer/command/list_test.rb} +26 -14
  74. data/test/unit/juicer/command/merge_test.rb +162 -0
  75. data/test/{juicer/command/test_util.rb → unit/juicer/command/util_test.rb} +10 -6
  76. data/test/unit/juicer/command/verify_test.rb +48 -0
  77. data/test/{juicer/test_css_cache_buster.rb → unit/juicer/css_cache_buster_test.rb} +10 -30
  78. data/test/unit/juicer/datafy_test.rb +37 -0
  79. data/test/{juicer/merger/test_css_dependency_resolver.rb → unit/juicer/dependency_resolver/css_dependency_resolver_test.rb} +2 -2
  80. data/test/{juicer/merger/test_javascript_dependency_resolver.rb → unit/juicer/dependency_resolver/javascript_dependency_resolver_test.rb} +13 -2
  81. data/test/unit/juicer/ext/{#string_test.rb# → string_test.rb} +0 -7
  82. data/test/unit/juicer/ext/symbol_test.rb +27 -0
  83. data/test/unit/juicer/image_embed_test.rb +271 -0
  84. data/test/unit/juicer/install/installer_base_test.rb +214 -0
  85. data/test/{juicer/install/test_jslint_installer.rb → unit/juicer/install/jslint_installer_test.rb} +1 -1
  86. data/test/{juicer/install/test_rhino_installer.rb → unit/juicer/install/rhino_installer_test.rb} +1 -1
  87. data/test/{juicer/install/test_yui_compressor_installer.rb → unit/juicer/install/yui_compressor_test.rb} +16 -16
  88. data/test/unit/juicer/jslint_test.rb +60 -0
  89. data/test/{juicer/merger/test_base.rb → unit/juicer/merger/base_test.rb} +1 -1
  90. data/test/{juicer/merger/test_javascript_merger.rb → unit/juicer/merger/javascript_merger_test.rb} +2 -2
  91. data/test/{juicer/merger/test_stylesheet_merger.rb → unit/juicer/merger/stylesheet_merger_test.rb} +15 -13
  92. data/test/unit/juicer/minifyer/closure_compressor_test.rb +107 -0
  93. data/test/{integration → unit}/juicer/minifyer/yui_compressor_test.rb +30 -47
  94. data/test/unit/juicer_test.rb +1 -0
  95. metadata +207 -113
  96. data/lib/juicer/core.rb +0 -61
  97. data/lib/juicer/merger/css_dependency_resolver.rb +0 -25
  98. data/lib/juicer/merger/dependency_resolver.rb +0 -82
  99. data/lib/juicer/merger/javascript_dependency_resolver.rb +0 -21
  100. data/tasks/ann.rake +0 -80
  101. data/tasks/bones.rake +0 -20
  102. data/tasks/gem.rake +0 -201
  103. data/tasks/git.rake +0 -40
  104. data/tasks/notes.rake +0 -27
  105. data/tasks/post_load.rake +0 -34
  106. data/tasks/rdoc.rake +0 -51
  107. data/tasks/rubyforge.rake +0 -55
  108. data/tasks/setup.rb +0 -292
  109. data/tasks/spec.rake +0 -54
  110. data/tasks/svn.rake +0 -47
  111. data/tasks/test.rake +0 -40
  112. data/tasks/test/setup.rake +0 -35
  113. data/tasks/zentest.rake +0 -36
  114. data/test/juicer/command/test_install.rb +0 -53
  115. data/test/juicer/command/test_merge.rb +0 -160
  116. data/test/juicer/command/test_verify.rb +0 -33
  117. data/test/juicer/install/test_installer_base.rb +0 -195
  118. data/test/juicer/minifyer/test_yui_compressor.rb +0 -159
  119. data/test/juicer/test_cache_buster.rb +0 -58
  120. data/test/juicer/test_core.rb +0 -47
  121. data/test/juicer/test_jslint.rb +0 -33
  122. data/test/test_juicer.rb +0 -4
data/History.txt CHANGED
@@ -1,3 +1,31 @@
1
+ == 1.0.0 / 2010-02-24
2
+ * Make sure @import rules with url is removed when files are merged
3
+ * Dependency resolver supports depending on directories
4
+ * Constant refefined warnings fixed in installer module (Aaron Suggs)
5
+ * Ruby 1.9 compatibility
6
+ * Google Closure Compiler support for `juicer merge` (Pavel Valodzka)
7
+ * Fix bug in `juicer list` for files with no dependencies (Daniel Stockman)
8
+ * Image embedder to embed images using data uris (Morgan Roderick)
9
+ * YUI Compressor --arguments now works (Daniel Stockman)
10
+ * Download Rhino over HTTP rather than FTP to avoid certain corporate
11
+ firewall restraints
12
+ * Development improvements:
13
+ Use Jeweler to package gem
14
+ Less obtrusive Ruby core extensions (Pavel Valodzka)
15
+ Switched from Hpricot to Nokogiri
16
+ New AssetPath interface for resolving URLs in CSS files
17
+ Refactor web_root -> document_root
18
+ Tests are considerably sped up
19
+ Reorganized tests in unit/ directory
20
+ Use shoulda for tests
21
+ Use mocha in tests
22
+ Use FakeFS for certain file operations in tests
23
+ Bundling binaries needed to run tests
24
+ * Refactored/moved dependency resolver classes. They now live in
25
+ Juicer::CssDependencyResolver and
26
+ Juicer::JavaScriptDependencyResolver
27
+ Dependency resolvers include Enumerable
28
+
1
29
  == 0.2.6 / 2009-07-20
2
30
  * New installation paths for YUI Compressor
3
31
  Patch by http://github.com/craveytrain
data/Rakefile CHANGED
@@ -1,48 +1,96 @@
1
- # Look in the tasks/setup.rb file for the various options that can be
2
- # configured in this Rakefile. The .rake files in the tasks directory
3
- # are where the options are used.
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
4
5
 
5
6
  begin
6
- require 'bones'
7
- Bones.setup
8
- rescue LoadError
9
- begin
10
- load 'tasks/setup.rb'
11
- rescue LoadError
12
- raise RuntimeError, '### please install the "bones" gem ###'
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |gem|
9
+ gem.name = "juicer"
10
+ gem.summary = "Command line tool for CSS and JavaScript developers"
11
+ gem.description = "Resolve dependencies, merge and minify CSS and JavaScript files with Juicer - the command line tool for frontend engineers"
12
+ gem.email = "christian@cjohansen.no"
13
+ gem.homepage = "http://github.com/cjohansen/juicer"
14
+ gem.authors = ["Christian Johansen"]
15
+ gem.rubyforge_project = "juicer"
16
+ gem.add_development_dependency "shoulda", ">= 2.10.2"
17
+ gem.add_development_dependency "mocha", ">= 0.9.8"
18
+ gem.add_development_dependency "fakefs", ">= 0.2.1"
19
+ gem.add_development_dependency "jeweler", ">= 0.2.1"
20
+ gem.add_development_dependency "redgreen", ">= 1.2.2" if RUBY_VERSION < "1.9"
21
+ gem.add_dependency "cmdparse"
22
+ gem.add_dependency "nokogiri"
23
+ gem.add_dependency "rubyzip"
24
+ gem.executables = ["juicer"]
25
+ gem.post_install_message = <<-MSG
26
+ Juicer does not ship with third party libraries. You probably want to install
27
+ Yui Compressor and JsLint now:
28
+
29
+ juicer install yui_compressor
30
+ juicer install jslint
31
+
32
+ Happy juicing!
33
+ MSG
34
+ gem.files = FileList["[A-Z]*", "{bin,generators,lib,test}/**/*"]
13
35
  end
14
- end
15
36
 
16
- ensure_in_path 'lib'
17
- require 'juicer'
18
- load 'tasks/test/setup.rake'
37
+ Jeweler::GemcutterTasks.new
38
+ Jeweler::RubyforgeTasks.new do |rubyforge|
39
+ rubyforge.doc_task = "rdoc"
40
+ end
41
+ rescue LoadError => err
42
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
43
+ puts err.message
44
+ end
19
45
 
20
- task :default => 'test:run'
46
+ Rake::TestTask.new("test:units") do |test|
47
+ test.libs << 'test'
48
+ test.pattern = 'test/unit/**/*_test.rb'
49
+ test.verbose = true
50
+ end
21
51
 
22
- PROJ.name = 'juicer'
23
- PROJ.authors = 'Christian Johansen'
24
- PROJ.email = 'christian@cjohansen.no'
25
- PROJ.url = 'http://www.cjohansen.no/en/projects/juicer'
26
- PROJ.version = Juicer::VERSION
27
- PROJ.rubyforge.name = 'juicer'
28
- PROJ.readme_file = 'Readme.rdoc'
29
- PROJ.exclude = %w(tmp$ bak$ ~$ CVS \.svn ^pkg ^doc \.git ^rcov ^test\/data gemspec ^test\/bin)
30
- PROJ.rdoc.remote_dir = 'juicer'
52
+ Rake::TestTask.new("test:integration") do |test|
53
+ test.libs << 'test'
54
+ test.pattern = 'test/integration/**/*_test.rb'
55
+ test.verbose = true
56
+ end
31
57
 
32
- PROJ.spec.opts << '--color'
58
+ task :test => ["check_dependencies:development", "test:units", "test:integration"]
33
59
 
34
- PROJ.gem.extras[:post_install_message] = <<-MSG
35
- Juicer does not ship with third party libraries. You probably want to install
36
- Yui Compressor and JsLint now:
60
+ task :default => "test:units"
37
61
 
38
- juicer install yui_compressor
39
- juicer install jslint
62
+ # lib/tasks/cruise.rake
63
+ desc 'Continuous build target'
64
+ task :cruise do
65
+ out = ENV['CC_BUILD_ARTIFACTS']
66
+ mkdir_p out unless File.directory? out if out
67
+
68
+ Rake::Task["rcov"].invoke
69
+ mv 'coverage/', "#{out}/" if out
70
+ end
40
71
 
41
- Happy juicing!
42
- MSG
72
+ begin
73
+ require 'rcov/rcovtask'
74
+ Rcov::RcovTask.new do |test|
75
+ test.libs << 'test'
76
+ test.pattern = 'test/**/*_test.rb'
77
+ test.verbose = true
78
+ end
79
+ rescue LoadError
80
+ task :rcov do
81
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
82
+ end
83
+ end
43
84
 
44
- CLOBBER.include "test/data"
85
+ Rake::RDocTask.new do |rdoc|
86
+ if File.exist?('VERSION')
87
+ version = File.read('VERSION')
88
+ else
89
+ version = ""
90
+ end
45
91
 
46
- depend_on 'cmdparse'
47
- depend_on 'hpricot'
48
- depend_on 'rubyzip'
92
+ rdoc.rdoc_dir = 'rdoc'
93
+ rdoc.title = "jstdutil #{version}"
94
+ rdoc.rdoc_files.include('README*')
95
+ rdoc.rdoc_files.include('lib/**/*.rb')
96
+ end
data/Readme.rdoc CHANGED
@@ -1,6 +1,12 @@
1
1
  = Juicer
2
2
  Official URL: http://github.com/cjohansen/juicer/tree/master
3
- Christian Johansen (http://www.cjohansen.no)
3
+
4
+ Christian Johansen (http://www.cjohansen.no) and contributors:
5
+
6
+ * Morgan Roderick (http://roderick.dk)
7
+ * Pavel Valodzka (http://github.com/valodzka)
8
+ * Daniel Stockman (http://evocateur.org/)
9
+ * Aaron Suggs (http://ktheory.com)
4
10
 
5
11
  == DESCRIPTION:
6
12
 
@@ -10,12 +16,13 @@ High level overview; Juicer can
10
16
 
11
17
  * figure out which files depend on each other and merge them together, reducing
12
18
  the number of http requests per page view, thus improving performance
13
- * use YUI Compressor to compress code, thus improving performance
19
+ * use YUI Compressor or Google Closure Compiler to compress code, thus improving performance
14
20
  * verify that your JavaScript is safe to minify/compress by running JsLint on it
15
21
  * cycle asset hosts in CSS files
16
22
  * add "cache busters" to URLs in CSS files
17
23
  * recalculate relative URLs in CSS files, as well as convert them to absolute
18
24
  (or convert absolute URLs to relative URLs)
25
+ * embed images into stylesheets using data-uris
19
26
 
20
27
  == FEATURES:
21
28
 
@@ -23,7 +30,7 @@ High level overview; Juicer can
23
30
 
24
31
  Juicer can read @import statements in CSS files and use them to combine all your
25
32
  stylesheets into a single file. This file may be minified using the YUI
26
- Compressor. Eventually it will support other minifying tools too.
33
+ Compressor or Google Closure Compiler. Eventually it will support other minifying tools too.
27
34
 
28
35
  Juicer can treat your JavaScript files much the same way too, parsing a comment
29
36
  switch @depend, as this example shows:
@@ -31,14 +38,14 @@ switch @depend, as this example shows:
31
38
  /**
32
39
  * My script file
33
40
  *
34
- * @depend jquery-1.2.0.js
41
+ * @depend jquery-1.4.1.js
35
42
  */
36
43
  var myNS = {
37
44
  myObject = {}
38
45
  };
39
46
 
40
47
  Running <tt>juicer merge</tt> on this file will result in a minified file
41
- <tt>filename.min.js</tt> containing the file jquery-1.2.0.js (located in the
48
+ <tt>filename.min.js</tt> containing the file jquery-1.4.1.js (located in the
42
49
  same directory) and the code above.
43
50
 
44
51
  You can use @import (CSS files) and @depend (JavaScript) recursively, effectively
@@ -50,10 +57,10 @@ When merging CSS files, you may want to merge CSS files in different directories
50
57
  You may also want the resulting CSS file to end up in another directory as well.
51
58
  Juicer automatically recalculates referenced URLs to reflect this change.
52
59
 
53
- Absolute URLs are not changed by default, but if you provide juicer merge with
54
- --document-root [DIR] and --relative-urls then absolute URLs are converted to
55
- URLs relative to output directory. You can also use --absolute-urls to convert
56
- all URLs to absolute ones.
60
+ Absolute URLs are not changed by default, but if you provide juicer merge
61
+ with <code>--document-root [DIR]</code> and <code>--relative-urls</code> then
62
+ absolute URLs are converted to URLs relative to output directory. You can also
63
+ use <code>--absolute-urls</code> to convert all URLs to absolute ones.
57
64
 
58
65
  === Cache busters
59
66
 
@@ -69,20 +76,170 @@ Unfortunately, the popular web proxy Squid shipped for some time with a default
69
76
  configuration which would not treat a URL as a "new" URL if the only thing changed
70
77
  was the GET parameters. For this reason Juicer provides hard cache busters.
71
78
 
72
- Hard cache busters result in URLs such as http://assets/images/1-cb1234567890.png,
79
+ Hard cache busters result in URLs such as: http://assets/images/1-cb1234567890.png,
73
80
  ie URLs that require either renaming of files, or (more conveniently) a web
74
81
  server configuration that will forward URLs to the right files anyway.
75
82
 
76
- == PLANNED FEATURES:
83
+ === Embed images in stylesheets
84
+
85
+ Juicer supports embedding images into stylesheets using data uri's.
86
+
87
+ In order to be as unobtrusive as possible, you must indicate for each image that it
88
+ can be embedded in the stylesheet by using the embed url suffix.
89
+
90
+ Example:
91
+
92
+ h1 { background: url(/somepath/someimage.png?embed=true); }
93
+
94
+ When merging the stylesheets, you must specify which type of embedding you want,
95
+ currently only 'none' and 'data_uri' are supported.
96
+
97
+ $ juicer merge my-stylesheet.css -o my-stylesheet.merged.css --embed-images data_uri
98
+
99
+ The result will look similar to this:
100
+
101
+ h1 { background: url(data:image/png;base64,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); }
102
+
103
+ Embedding images in stylesheets should be used very carefully, as they will bloat
104
+ your css files considerably, and you will loose some of the fine grained control
105
+ over caching of images.
106
+
107
+ Before using Juicer to embed images into your stylesheets, you should have control
108
+ over cache expiration of stylesheets.
109
+
110
+ You should also have gzip enabled, as base64 encoded images take up about 30% more
111
+ space than serving them normally. With gzip enabled this is reduced to about 5-10% bloat.
112
+
113
+ ==== Usage scenario: Modern browsers and IE7, IE6 support
114
+
115
+ As all of the major browsers in their later incarnations support the data uri scheme,
116
+ it is possible to just create two merged stylesheets, although you can create as many
117
+ as you want really.
118
+
119
+ Let's assume you have the following files:
120
+
121
+ * reset.css
122
+ * layout.css
123
+ * typography.css
124
+
125
+ /* layout.css */
126
+ body { background: url( /images/my-body-background.png?embed=true); }
127
+
128
+ And let's assume that you want to merge these, and embed the flagged images in
129
+ layout.css into the stylesheet.
130
+
131
+ To do this, you would have a master stylesheet that imports the other stylesheets using
132
+ the @import statemet. It could look like this:
133
+
134
+ /* master.css */
135
+ @import url(reset.css)
136
+ @import url(layout.css)
137
+ @import url(typography.css)
138
+
139
+ Now, in order to create the two versions of the stylesheet, you would simply run
140
+ Juicer with and without the option to embed images
141
+
142
+ $ juicer merge master.css -o master.embedded.css --embed-images data_uri
143
+ $ juicer merge master.css -o master.normal.css
144
+
145
+ In order to only load the relevant stylesheet to supporting browsers, and preventing
146
+ doubling the effective payload of the background images, you would reference the
147
+ stylesheets like this:
148
+
149
+ <head>
150
+ ...
151
+ <!--[if !IE]>-->
152
+ <link rel="stylesheet" type="text/css" href="master.embedded.css" />
153
+ <!--<![endif]-->
154
+ <!--[if gte IE 8]>
155
+ <link rel="stylesheet" type="text/css" href="master.embedded.css" />
156
+ <![endif]-->
157
+ <!--[if lte IE 7]>
158
+ <link rel="stylesheet" type="text/css" href="master.normal.css" />
159
+ <![endif]-->
160
+ ...
161
+ </head>
162
+
163
+ The first conditional comemnt allows only non-IE browsers to fetch the
164
+ <code>master.embedded.css</code> stylesheet.
165
+
166
+ The second conditional comment allows only IE8+ browsers to fetch the
167
+ <code>master.embedded.css</code> stylesheet.
77
168
 
78
- Juicer 0.2.0 is the first usable release. Work will continue from here. Improving
79
- documentation and APIs is one concern, but there are also new features planned:
169
+ The last conditional comment allows only IE7 and lower to fetch the
170
+ <code>master.normal.css</code> stylesheet.
171
+
172
+ Unfortunately, you will need to use three conditional comments, or you will end
173
+ up with an unsightly "-->" displayed at the top of your pages in IE.
174
+
175
+ ==== Browser support
176
+ Windows Vista, Windows 2003, Windows 7
177
+ Tests needed
178
+
179
+ Windows XP
180
+ * IE8 - up to 32kb IS supported
181
+ * Firefox 3.5.2 - OK
182
+ * Opera 9.64 - OK
183
+ * Chrome 3 - OK
184
+ * Safari 4 - OK
185
+
186
+ OS X 10.6.1
187
+ * Firefox 3.5 - OK
188
+ * Firefox 2.0.20 - OK
189
+ * Safari 4 - OK
190
+ * Opera 10 - OK
191
+ * Opera 9.27 - OK
192
+ * Opera 8.0 - OK
193
+ * Camino 1.6.10 - OK
194
+
195
+ Debian
196
+ * Opera 10 - OK
197
+
198
+ Android
199
+ * WebKit - OK
200
+
201
+ iPhone
202
+ * Safari - OK
203
+
204
+ The test used is located at http://roderick.dk/experiments/data-uri-limits/
205
+
206
+ The test used tests loading of styles using the href attribute, it is ASSUMED
207
+ that loading images from data-uri in css has similar support.
208
+ Soon[tm] there will be a testpage with images as well.
209
+
210
+ If you have funky browser / OS combinations not listed above, please visit the
211
+ test and send a screenshot and details about browser and OS to morgan@roderick.dk
212
+
213
+
214
+ ==== Support for really old user-agents
215
+ If you plan to support user-agents that do understand conditional comments and
216
+ does not support the data uri scheme, you will have to do some kind of detection
217
+ of support. These user-agents would be very rare, as our browser testing shows,
218
+ most modern user agents support data-uris.
219
+
220
+ * http://weston.ruter.net/2009/05/07/detecting-support-for-data-uris/
221
+
222
+ Please note that image embedding is NOT a silver bullet, but can help reduce
223
+ the amount of HTTP connections needed for a page.
224
+
225
+
226
+ ==== MHTML Support
227
+
228
+ Due to MHTML being very awkward in it's implementation (having the absolute url
229
+ including protocol inside the stylesheet itself), it was decided to be of very
230
+ little real value and attempts at supporting it has been dropped.
231
+
232
+
233
+ ==== Further reading
234
+
235
+ * http://www.websiteoptimization.com/speed/tweak/inline-images/
236
+ * http://en.wikipedia.org/wiki/Data_URI_scheme
237
+
238
+
239
+ == PLANNED FEATURES:
80
240
 
81
241
  * Support more minifiers, JsMin (Ruby port), Packer and possibly others
82
242
  * Add support for CssTidy to compress CSS files
83
- * juicer build, a command that can build several files in one swoop using a
84
- configuration file
85
- * juicer doc, a command that produces documentation using YUI Doc or JsDoc
86
243
 
87
244
  If you have any ideas, feature requests, want to contribute or whatever, fork
88
245
  the project on github, or get in touch through christian (at) cjohansen.no.
@@ -99,30 +256,42 @@ the project on github, or get in touch through christian (at) cjohansen.no.
99
256
 
100
257
  == REQUIREMENTS:
101
258
 
102
- In order to use YUI Compressor and JsMin (requires Rhino) you need Java
259
+ In order to use YUI Compressor, Closure Compiler or JsMin (requires Rhino) you need Java
103
260
  installed and the java executable available on your path.
104
261
 
105
262
  == INSTALL:
106
263
 
107
264
  $ gem install juicer
108
265
  $ juicer install yui_compressor
266
+ $ juicer install closure_compiler
109
267
  $ juicer install jslint
110
268
 
111
269
  You need Java installed and available on your PATH. During gem installation,
112
- Juicer will download and install YUI Compressor, JsLint and Rhino for you.
270
+ Juicer will download and install YUI Compressor, Closure Compiler, JsLint and Rhino for you.
271
+
272
+ rake check_dependencies:development
273
+
274
+ Will tell you about other dependencies that might be missing on your system.
113
275
 
114
- == For developers
115
276
 
116
- Before running tests you should run
117
- rake test:setup
277
+ == Contributors
118
278
 
119
- which brings in third party libraries (ie, requires a working network connection)
279
+ * Morgan Roderick (http://roderick.dk)
280
+ Added support for embedding graphics using data-uri
281
+ Several small fixes and optimizations
282
+ * Pavel Valodzka (http://github.com/valodzka)
283
+ Added Google Closure Compiler support
284
+ * Daniel Stockman (http://evocateur.org/)
285
+ Fixed `juicer list` when running it against files with no dependencies
286
+ * Aaron Suggs (http://ktheory.com)
287
+ Added support for depending on directories
288
+ Fixed installers on 1.0 branch
120
289
 
121
290
  == LICENSE:
122
291
 
123
292
  (The MIT License)
124
293
 
125
- Copyright (c) 2008-2009 Christian Johansen
294
+ Copyright (c) 2008-2010 Christian Johansen
126
295
 
127
296
  Permission is hereby granted, free of charge, to any person obtaining
128
297
  a copy of this software and associated documentation files (the