juicer 0.2.6 → 1.0.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/History.txt +28 -0
- data/Rakefile +84 -36
- data/Readme.rdoc +192 -23
- data/VERSION +1 -0
- data/bin/juicer +2 -4
- data/lib/juicer.rb +9 -10
- data/lib/juicer/asset/path.rb +275 -0
- data/lib/juicer/asset/path_resolver.rb +79 -0
- data/lib/juicer/binary.rb +3 -5
- data/lib/juicer/cache_buster.rb +112 -27
- data/lib/juicer/command/install.rb +4 -2
- data/lib/juicer/command/list.rb +16 -9
- data/lib/juicer/command/merge.rb +30 -14
- data/lib/juicer/command/verify.rb +1 -1
- data/lib/juicer/css_cache_buster.rb +31 -47
- data/lib/juicer/datafy/datafy.rb +20 -0
- data/lib/juicer/dependency_resolver/css_dependency_resolver.rb +29 -0
- data/lib/juicer/dependency_resolver/dependency_resolver.rb +101 -0
- data/lib/juicer/dependency_resolver/javascript_dependency_resolver.rb +23 -0
- data/lib/juicer/ext/logger.rb +5 -0
- data/lib/juicer/ext/string.rb +47 -0
- data/lib/juicer/ext/symbol.rb +15 -0
- data/lib/juicer/image_embed.rb +129 -0
- data/lib/juicer/install/base.rb +2 -2
- data/lib/juicer/install/closure_compiler_installer.rb +69 -0
- data/lib/juicer/install/jslint_installer.rb +3 -3
- data/lib/juicer/install/rhino_installer.rb +3 -2
- data/lib/juicer/install/yui_compressor_installer.rb +3 -2
- data/lib/juicer/jslint.rb +1 -1
- data/lib/juicer/merger/base.rb +1 -1
- data/lib/juicer/merger/javascript_merger.rb +3 -4
- data/lib/juicer/merger/stylesheet_merger.rb +13 -15
- data/lib/juicer/minifyer/closure_compiler.rb +90 -0
- data/lib/juicer/minifyer/java_base.rb +77 -0
- data/lib/juicer/minifyer/yui_compressor.rb +15 -48
- data/test/bin/jslint-1.0.js +523 -0
- data/test/bin/jslint.js +523 -0
- data/test/bin/rhino1_7R1.zip +0 -0
- data/test/bin/rhino1_7R2-RC1.jar +0 -0
- data/test/bin/rhino1_7R2-RC1.zip +0 -0
- data/test/bin/yuicompressor +0 -0
- data/test/bin/yuicompressor-2.3.5.zip +0 -0
- data/test/bin/yuicompressor-2.4.2.jar +0 -0
- data/test/bin/yuicompressor-2.4.2.zip +0 -0
- data/test/data/Changelog.txt +10 -0
- data/test/data/a.css +3 -0
- data/test/data/a.js +5 -0
- data/test/data/a1.css +5 -0
- data/test/data/b.css +1 -0
- data/test/data/b.js +5 -0
- data/test/data/b1.css +5 -0
- data/test/data/c1.css +3 -0
- data/test/data/css/2.gif +1 -0
- data/test/data/css/test.css +11 -0
- data/test/data/css/test2.css +1 -0
- data/test/data/d1.css +3 -0
- data/test/data/images/1.png +1 -0
- data/test/data/my_app.js +2 -0
- data/test/data/not-ok.js +2 -0
- data/test/data/ok.js +3 -0
- data/test/data/path_test.css +5 -0
- data/test/data/path_test2.css +14 -0
- data/test/data/pkg/module/moda.js +2 -0
- data/test/data/pkg/module/modb.js +3 -0
- data/test/data/pkg/pkg.js +1 -0
- data/test/fixtures/yui-download.html +425 -0
- data/test/test_helper.rb +36 -7
- data/test/unit/juicer/asset/path_resolver_test.rb +76 -0
- data/test/unit/juicer/asset/path_test.rb +370 -0
- data/test/unit/juicer/cache_buster_test.rb +104 -0
- data/test/{juicer/test_chainable.rb → unit/juicer/chainable_test.rb} +1 -1
- data/test/unit/juicer/command/install_test.rb +58 -0
- data/test/{juicer/command/test_list.rb → unit/juicer/command/list_test.rb} +26 -14
- data/test/unit/juicer/command/merge_test.rb +162 -0
- data/test/{juicer/command/test_util.rb → unit/juicer/command/util_test.rb} +10 -6
- data/test/unit/juicer/command/verify_test.rb +48 -0
- data/test/{juicer/test_css_cache_buster.rb → unit/juicer/css_cache_buster_test.rb} +10 -30
- data/test/unit/juicer/datafy_test.rb +37 -0
- data/test/{juicer/merger/test_css_dependency_resolver.rb → unit/juicer/dependency_resolver/css_dependency_resolver_test.rb} +2 -2
- data/test/{juicer/merger/test_javascript_dependency_resolver.rb → unit/juicer/dependency_resolver/javascript_dependency_resolver_test.rb} +13 -2
- data/test/unit/juicer/ext/{#string_test.rb# → string_test.rb} +0 -7
- data/test/unit/juicer/ext/symbol_test.rb +27 -0
- data/test/unit/juicer/image_embed_test.rb +271 -0
- data/test/unit/juicer/install/installer_base_test.rb +214 -0
- data/test/{juicer/install/test_jslint_installer.rb → unit/juicer/install/jslint_installer_test.rb} +1 -1
- data/test/{juicer/install/test_rhino_installer.rb → unit/juicer/install/rhino_installer_test.rb} +1 -1
- data/test/{juicer/install/test_yui_compressor_installer.rb → unit/juicer/install/yui_compressor_test.rb} +16 -16
- data/test/unit/juicer/jslint_test.rb +60 -0
- data/test/{juicer/merger/test_base.rb → unit/juicer/merger/base_test.rb} +1 -1
- data/test/{juicer/merger/test_javascript_merger.rb → unit/juicer/merger/javascript_merger_test.rb} +2 -2
- data/test/{juicer/merger/test_stylesheet_merger.rb → unit/juicer/merger/stylesheet_merger_test.rb} +15 -13
- data/test/unit/juicer/minifyer/closure_compressor_test.rb +107 -0
- data/test/{integration → unit}/juicer/minifyer/yui_compressor_test.rb +30 -47
- data/test/unit/juicer_test.rb +1 -0
- metadata +207 -113
- data/lib/juicer/core.rb +0 -61
- data/lib/juicer/merger/css_dependency_resolver.rb +0 -25
- data/lib/juicer/merger/dependency_resolver.rb +0 -82
- data/lib/juicer/merger/javascript_dependency_resolver.rb +0 -21
- data/tasks/ann.rake +0 -80
- data/tasks/bones.rake +0 -20
- data/tasks/gem.rake +0 -201
- data/tasks/git.rake +0 -40
- data/tasks/notes.rake +0 -27
- data/tasks/post_load.rake +0 -34
- data/tasks/rdoc.rake +0 -51
- data/tasks/rubyforge.rake +0 -55
- data/tasks/setup.rb +0 -292
- data/tasks/spec.rake +0 -54
- data/tasks/svn.rake +0 -47
- data/tasks/test.rake +0 -40
- data/tasks/test/setup.rake +0 -35
- data/tasks/zentest.rake +0 -36
- data/test/juicer/command/test_install.rb +0 -53
- data/test/juicer/command/test_merge.rb +0 -160
- data/test/juicer/command/test_verify.rb +0 -33
- data/test/juicer/install/test_installer_base.rb +0 -195
- data/test/juicer/minifyer/test_yui_compressor.rb +0 -159
- data/test/juicer/test_cache_buster.rb +0 -58
- data/test/juicer/test_core.rb +0 -47
- data/test/juicer/test_jslint.rb +0 -33
- 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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'rake'
|
|
3
|
+
require 'rake/testtask'
|
|
4
|
+
require 'rake/rdoctask'
|
|
4
5
|
|
|
5
6
|
begin
|
|
6
|
-
require '
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
58
|
+
task :test => ["check_dependencies:development", "test:units", "test:integration"]
|
|
33
59
|
|
|
34
|
-
|
|
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
|
-
|
|
39
|
-
|
|
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
|
-
|
|
42
|
-
|
|
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
|
-
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
|
54
|
-
|
|
55
|
-
URLs relative to output directory. You can also
|
|
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
|
-
|
|
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,iVBORw0KGgoAAAANSUhEUgAAAHsAAAA8CAYAAABGmsWrAAAJhElEQVR42u1cf2hVVRz/rMXgwWAwGAyEgbAYLBaTl4uFYRiLwWKhGIuNhVEoQmIURZEYiaIYE8UoejSSpJEoSpI0lCJxKOlGkTQajYSHj0ajoTQ2ejhef5zPZWfH8733PHfv87nOF+4fO/e8e8/5fs731+ecu4pCoQAv/w95yKvAg+3Fg+3Fg+3Fg+2lvORh6UZFRUWS720BcAPArIfAXZZbOZXasjsB/A3gFwD/ANgLoDKG524AULBc7WWC003L2A6vZDfeBOBrALVa23sAtsfw7GmhvVw8x4ylbX4lg/0agCpL+1veQa88sFcV2b6S5Pb/DezxItu9PMBgHxNW+CEPw30uvRKQSQBPAjjK7HkSwB4Axy1900ISlvWQPRhgBy77GYd+lwCkjLY9AN73kD04dbarzJZxGeXBjlnmPdjl4cZXMabWA5gCkAPwM4AFS996AHUArrPGbrH0yTIe1wBoZJutHm8wYvltxn1XaYIidPL8XVg5tBpLyZ9AJoRF12wJO7Ps7yJ1nHseioC5kQjahULBegkTugQ7LfkngA+g6NCtAA4CGOW9/fx9jfDbLbzfJdyXrm+0sbUIfdZDUbK3jPY5AJ8TVJscFp7XKvT/0dL3kpGDmPcHOPffLPcuUx9OWLleLmBXUmH/FglGwRHsngTBvhPxjFuw8+e7hf5NAtjnLX3PR4BdjO5iAdslZh+F4rCrEmKRkozFUZssNVB8vcni5YvIJaS55WMY/zsAdpYqQetFPBsV5Sx1AD5b5oLNJzi+gyHhJlawdwsT7gPwCIA1AAZDfp9l8uYiWQA7AGwTrH2I97YBeBfAcBHzXAAwFgJWp+HOSw1qFvadsSBZfS/pBE2Kg5stjzlp6Xfa9jrL1WXpd8vSL8zDSGOdg9ptCzLlagBfCH11694u9JHky4icQorZp1llBLJZyI3mAKSSjNltQnw9Y2k/5vj7UsvzAD7SYu0sgFdZCpqyscRjGwSwCUsp4FMCS5iCopgTc+N1lrYpoZ621ZPVZQD2lOCKP7G012p1filEOnAxJLS3Jwn2jJC9QlCU62TKQS6GkCn3W7IkqmIfWxjYPwvW3uboAq+XMdg3QkqxcpAZR4OKDeyrAh35JYAOuul6AK8IteCJMgZ7PiTzxX0or1zGl1ruQ6O48fcJri6NBjtkk3EmGytJqkr4rpoiavzY6uyhIuvZYFX2CYncgyISq5cqwbtTQnyeShpsAHgBwLkilLSpCCLlfllWFGhSclmKbH29MNeJUoA9C+A5B7d8AsBj9+AJ4Oiy6ku4cCTFSrVuZYxjeENo/37Zs3bc4uyBnQE6z0y8zvV1cGPQbNt+oyHPlRi0lpCYaOvfq4F3y3L/JpYyXpVQO1NRu3I2Bu0OFB2tL5S9wrP+CMPK9XI9vNBvaTsE4M0ESyNzOzHNZHGYbrgLQKaIEFOMLPC5vUb7KgC/ArjCGLoB937uvRLqDMA7TGjrjIWkSyaOSbmCbYtVYwnGrTGozQlTeg0AMstQtE101u+YBeygT0fM+UM6oub+KI4XuZ5Bs9V92xPMTs8mnARVOyyCC7HEyeUnl32Iac/fFewLlrZ1jKM9juxOdRE15dWYEr3UMsAGgJcdS56pCICrBYuNktdj0kNRYO9hnDKlGcBXWPwMd0BIuMJcp9T+EoARx6w9VcRCQkhCabZnATwhzD3ILZ6FfdcvFQH2iyHueZIV0JE43VmF9IG38TF+NxMJ152X67SKMWPytkRvBPL3XpVcPJ0kGvK0ogmoL0mCerhBiPEXYOfBpf7jIQtsA5PGVrrVi3z+PNR+QavF2oNwtMXiys+yz2r+thmLX70MS5VTkqVXLYDvcG+H5eYiEg8vMWHleoVZdiWAHxibpSwxF1LLgkzaGv+P9cpDwsDeDHXcyKw/38TdX2Q2s2a0HVl6tFAojK9duxYsWY4yNg4zAZmmi9/NcNFA93/AcGeNUIfv2uneD/H+Z+x7Sou7NxkPdR7gB7roXSH6eIOhppVuuo8LuonkSRt1cAXA23S59RqBMs2xH6IxVPO9p/juS1CnZ84aRMo6AE/z7za2pRm2hjjm+WvXriWWoHUJidoR3E1njjPhmBDiY5AsnWTs2kPwUrwuMyeYpyKaAXwL9cEBqPyfGDdHmK23U5lpI7Hq5Tv6jeSvFeEHAE4ywVyAOjLUyDDWxqqjk55qnKzhTyRUqjiGBc7lLSarjXx/2iBLzI8TVmvxvpsLYjUX60UuwNNJkyo2NmcignWyMV95zfprSIQc0TLNnZys/pVmLRU8wJV9mIpbg8U99gZhjFtojau4YF1q9k56pSP0NkEGXUWrTQF4SsvKO6Co4oNQJ10BdTbvAOf5I4CPoTaRTKllBfMUlu6RV9Lr3Yb6tHlaI5gm4gA7zLJnHa1dL1tsp1iymvXPcOV/pS2KLk56n4U1qiYI66E2WiYtz9UlzYWzi8/od9RDwJTts8y/nQvmioVw2Shk9Ge4IGwl3ifMcwYsZWyDUWUAwIdxkUwPRZRPpvRDfUHRRcUGbqqHWXutBehJrSZ+nIrooRvsoLVP4e6TIEHJ1BICrm18C1TOGY7ThfCpJ7jTFiuU3p2jxVeHkCy1gl53QB1x3mip8XPamEa1qz9JsI/DfhSnm65tFGrnZpSW2iKsYhPATVAf5KcYkwOXa25hBl7iewLY6kBJ9hO0/VpOsNlBD5MErckCaF4oIVvpPWweMPgiU/rKdJD61eN3TrPwwLNk6MLTiOFYVBjYExGZa5RcxdL/l1LPOBbcy3NCQ/QQn2qsUzsU956lyxzmItMtocOyCGtpVWmCNw91Ri5KguO7A5qlNvN5Z5ktb9X67+biPiF4l24CGnZaZxsBbtf0PcKQkqZujtEQZuKgTaPo0g9JWxZLxJ8j3Zc34ulWqL3Z32mJQyxLBqmgOajPfy/zN318xjYq4zR//zfuPuS4heN8XLsy9BBNWiI2ynLIZPF20e3/BbWN+SvB3sF3fwq1x/0Py8wxwxh2kkz6ggs0ylDmmcDNGgvgNud/mXpaxxJy2WfQXLY4jzP+dXPVdgh8do6lwiDsu0XnyCP30npOYXGD5VXtHUGdndFiZY6Z+Gu0hBx/P6W5uhbWvrryMvQWDbSSlKZoU/Zx/D1a/0n2XUNPo9fZGW0xZ7RwMKbNP8V7I9pYx41krg+LJ2DGjXdNUp8XS8mN26RF43tzCNkd8gxamTNoXlae+P837sH24sH24sH24sH24sH24sH2krj8B1XycbZeOGbwAAAAAElFTkSuQmCCCg==); }
|
|
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
|
-
|
|
79
|
-
|
|
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
|
|
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
|
-
|
|
117
|
-
rake test:setup
|
|
277
|
+
== Contributors
|
|
118
278
|
|
|
119
|
-
|
|
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-
|
|
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
|