ktheory-juicer 1.0.0.ktheory1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +30 -0
- data/Manifest.txt +58 -0
- data/Rakefile +96 -0
- data/Readme.rdoc +312 -0
- data/VERSION +1 -0
- data/bin/juicer +8 -0
- data/lib/juicer.rb +70 -0
- data/lib/juicer/asset/path.rb +275 -0
- data/lib/juicer/asset/path_resolver.rb +79 -0
- data/lib/juicer/binary.rb +171 -0
- data/lib/juicer/cache_buster.rb +130 -0
- data/lib/juicer/chainable.rb +106 -0
- data/lib/juicer/cli.rb +56 -0
- data/lib/juicer/command/install.rb +61 -0
- data/lib/juicer/command/list.rb +57 -0
- data/lib/juicer/command/merge.rb +205 -0
- data/lib/juicer/command/util.rb +32 -0
- data/lib/juicer/command/verify.rb +60 -0
- data/lib/juicer/css_cache_buster.rb +80 -0
- 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 +136 -0
- data/lib/juicer/install/base.rb +186 -0
- data/lib/juicer/install/closure_compiler_installer.rb +69 -0
- data/lib/juicer/install/jslint_installer.rb +51 -0
- data/lib/juicer/install/rhino_installer.rb +53 -0
- data/lib/juicer/install/yui_compressor_installer.rb +67 -0
- data/lib/juicer/jslint.rb +90 -0
- data/lib/juicer/merger/base.rb +74 -0
- data/lib/juicer/merger/javascript_merger.rb +29 -0
- data/lib/juicer/merger/stylesheet_merger.rb +110 -0
- 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 +96 -0
- 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/test_helper.rb +169 -0
- 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/unit/juicer/chainable_test.rb +94 -0
- data/test/unit/juicer/command/install_test.rb +58 -0
- data/test/unit/juicer/command/list_test.rb +81 -0
- data/test/unit/juicer/command/merge_test.rb +162 -0
- data/test/unit/juicer/command/util_test.rb +58 -0
- data/test/unit/juicer/command/verify_test.rb +48 -0
- data/test/unit/juicer/css_cache_buster_test.rb +71 -0
- data/test/unit/juicer/datafy_test.rb +37 -0
- data/test/unit/juicer/dependency_resolver/css_dependency_resolver_test.rb +36 -0
- data/test/unit/juicer/dependency_resolver/javascript_dependency_resolver_test.rb +50 -0
- data/test/unit/juicer/ext/string_test.rb +59 -0
- 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/unit/juicer/install/jslint_installer_test.rb +54 -0
- data/test/unit/juicer/install/rhino_installer_test.rb +57 -0
- data/test/unit/juicer/install/yui_compressor_test.rb +56 -0
- data/test/unit/juicer/jslint_test.rb +60 -0
- data/test/unit/juicer/merger/base_test.rb +122 -0
- data/test/unit/juicer/merger/javascript_merger_test.rb +74 -0
- data/test/unit/juicer/merger/stylesheet_merger_test.rb +180 -0
- data/test/unit/juicer/minifyer/closure_compressor_test.rb +107 -0
- data/test/unit/juicer/minifyer/yui_compressor_test.rb +116 -0
- data/test/unit/juicer_test.rb +1 -0
- metadata +265 -0
data/History.txt
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
== 0.2.6 / 2009-07-20
|
2
|
+
* New installation paths for YUI Compressor
|
3
|
+
Patch by http://github.com/craveytrain
|
4
|
+
|
5
|
+
== 0.2.5 / 2009-05-22
|
6
|
+
* Fixed a bug with the stylesheet merger where url( <url> ); (ie URL surrounded
|
7
|
+
by spaces) resolved wrong.
|
8
|
+
|
9
|
+
== 0.2.4 / 2009-04-29
|
10
|
+
|
11
|
+
* More robust pattern checking for url() references in CSS files
|
12
|
+
* Allow skipping verification
|
13
|
+
* Bug fix: Skip cache buster if type=none
|
14
|
+
* Bug fix: Quote JsLint command parts to allow for spaces in jar file paths
|
15
|
+
* Bug fix: cache buster type wasn't carried all the way (ie had no effect)
|
16
|
+
|
17
|
+
== 0.2.3 / 2009-03-03
|
18
|
+
|
19
|
+
* Cache busters in CSS files should only be appended once to each URL
|
20
|
+
* Output to merge target should accept directories as well as files (in case of
|
21
|
+
directories, file name is generated)
|
22
|
+
* Tests should not ship with 3rd party libraries
|
23
|
+
|
24
|
+
== 0.2.0 / 2009-02-25
|
25
|
+
|
26
|
+
* First usable release; merge, verify, install targets
|
27
|
+
|
28
|
+
== 0.1.0 / 2008-12-17
|
29
|
+
|
30
|
+
* Dug up old project and set it up with Mr Bones
|
data/Manifest.txt
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
Rakefile
|
4
|
+
Readme.rdoc
|
5
|
+
bin/juicer
|
6
|
+
lib/juicer.rb
|
7
|
+
lib/juicer/binary.rb
|
8
|
+
lib/juicer/cache_buster.rb
|
9
|
+
lib/juicer/chainable.rb
|
10
|
+
lib/juicer/cli.rb
|
11
|
+
lib/juicer/command/install.rb
|
12
|
+
lib/juicer/command/list.rb
|
13
|
+
lib/juicer/command/merge.rb
|
14
|
+
lib/juicer/command/util.rb
|
15
|
+
lib/juicer/command/verify.rb
|
16
|
+
lib/juicer/core.rb
|
17
|
+
lib/juicer/css_cache_buster.rb
|
18
|
+
lib/juicer/install/base.rb
|
19
|
+
lib/juicer/install/jslint_installer.rb
|
20
|
+
lib/juicer/install/rhino_installer.rb
|
21
|
+
lib/juicer/install/yui_compressor_installer.rb
|
22
|
+
lib/juicer/jslint.rb
|
23
|
+
lib/juicer/merger/base.rb
|
24
|
+
lib/juicer/merger/css_dependency_resolver.rb
|
25
|
+
lib/juicer/merger/dependency_resolver.rb
|
26
|
+
lib/juicer/merger/javascript_dependency_resolver.rb
|
27
|
+
lib/juicer/merger/javascript_merger.rb
|
28
|
+
lib/juicer/merger/stylesheet_merger.rb
|
29
|
+
lib/juicer/minifyer/yui_compressor.rb
|
30
|
+
tasks/test/setup.rake
|
31
|
+
test/bin/jslint.js
|
32
|
+
test/bin/rhino1_7R1.zip
|
33
|
+
test/bin/rhino1_7R2-RC1.zip
|
34
|
+
test/bin/yuicompressor
|
35
|
+
test/bin/yuicompressor-2.3.5.zip
|
36
|
+
test/bin/yuicompressor-2.4.2.zip
|
37
|
+
test/juicer/command/test_install.rb
|
38
|
+
test/juicer/command/test_list.rb
|
39
|
+
test/juicer/command/test_merge.rb
|
40
|
+
test/juicer/command/test_util.rb
|
41
|
+
test/juicer/command/test_verify.rb
|
42
|
+
test/juicer/install/test_installer_base.rb
|
43
|
+
test/juicer/install/test_jslint_installer.rb
|
44
|
+
test/juicer/install/test_rhino_installer.rb
|
45
|
+
test/juicer/install/test_yui_compressor_installer.rb
|
46
|
+
test/juicer/merger/test_base.rb
|
47
|
+
test/juicer/merger/test_css_dependency_resolver.rb
|
48
|
+
test/juicer/merger/test_javascript_dependency_resolver.rb
|
49
|
+
test/juicer/merger/test_javascript_merger.rb
|
50
|
+
test/juicer/merger/test_stylesheet_merger.rb
|
51
|
+
test/juicer/minifyer/test_yui_compressor.rb
|
52
|
+
test/juicer/test_cache_buster.rb
|
53
|
+
test/juicer/test_chainable.rb
|
54
|
+
test/juicer/test_core.rb
|
55
|
+
test/juicer/test_css_cache_buster.rb
|
56
|
+
test/juicer/test_jslint.rb
|
57
|
+
test/test_helper.rb
|
58
|
+
test/test_juicer.rb
|
data/Rakefile
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'jeweler'
|
8
|
+
Jeweler::Tasks.new do |gem|
|
9
|
+
gem.name = "ktheory-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"
|
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}/**/*"]
|
35
|
+
end
|
36
|
+
|
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
|
45
|
+
|
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
|
51
|
+
|
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
|
57
|
+
|
58
|
+
task :test => ["check_dependencies:development", "test:units", "test:integration"]
|
59
|
+
|
60
|
+
task :default => "test:units"
|
61
|
+
|
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
|
71
|
+
|
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
|
84
|
+
|
85
|
+
Rake::RDocTask.new do |rdoc|
|
86
|
+
if File.exist?('VERSION')
|
87
|
+
version = File.read('VERSION')
|
88
|
+
else
|
89
|
+
version = ""
|
90
|
+
end
|
91
|
+
|
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
ADDED
@@ -0,0 +1,312 @@
|
|
1
|
+
= Juicer
|
2
|
+
Official URL: http://github.com/cjohansen/juicer/tree/master
|
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)
|
10
|
+
|
11
|
+
== DESCRIPTION:
|
12
|
+
|
13
|
+
Juicer is a command line tool that helps you ship frontend code for production.
|
14
|
+
|
15
|
+
High level overview; Juicer can
|
16
|
+
|
17
|
+
* figure out which files depend on each other and merge them together, reducing
|
18
|
+
the number of http requests per page view, thus improving performance
|
19
|
+
* use YUI Compressor or Google Closure Compiler to compress code, thus improving performance
|
20
|
+
* verify that your JavaScript is safe to minify/compress by running JsLint on it
|
21
|
+
* cycle asset hosts in CSS files
|
22
|
+
* add "cache busters" to URLs in CSS files
|
23
|
+
* recalculate relative URLs in CSS files, as well as convert them to absolute
|
24
|
+
(or convert absolute URLs to relative URLs)
|
25
|
+
* embed images into stylesheets using data-uris
|
26
|
+
|
27
|
+
== FEATURES:
|
28
|
+
|
29
|
+
=== Merging and minifying
|
30
|
+
|
31
|
+
Juicer can read @import statements in CSS files and use them to combine all your
|
32
|
+
stylesheets into a single file. This file may be minified using the YUI
|
33
|
+
Compressor or Google Closure Compiler. Eventually it will support other minifying tools too.
|
34
|
+
|
35
|
+
Juicer can treat your JavaScript files much the same way too, parsing a comment
|
36
|
+
switch @depend, as this example shows:
|
37
|
+
|
38
|
+
/**
|
39
|
+
* My script file
|
40
|
+
*
|
41
|
+
* @depend jquery-1.2.0.js
|
42
|
+
*/
|
43
|
+
var myNS = {
|
44
|
+
myObject = {}
|
45
|
+
};
|
46
|
+
|
47
|
+
Running <tt>juicer merge</tt> on this file will result in a minified file
|
48
|
+
<tt>filename.min.js</tt> containing the file jquery-1.2.0.js (located in the
|
49
|
+
same directory) and the code above.
|
50
|
+
|
51
|
+
You can use @import (CSS files) and @depend (JavaScript) recursively, effectively
|
52
|
+
creating a dependency chain for Juicer to climb and merge.
|
53
|
+
|
54
|
+
=== Paths
|
55
|
+
|
56
|
+
When merging CSS files, you may want to merge CSS files in different directories.
|
57
|
+
You may also want the resulting CSS file to end up in another directory as well.
|
58
|
+
Juicer automatically recalculates referenced URLs to reflect this change.
|
59
|
+
|
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.
|
64
|
+
|
65
|
+
=== Cache busters
|
66
|
+
|
67
|
+
Juicer supports so-called cache busters. A cache buster is a pattern in a path
|
68
|
+
whose only purpose is to "trick" browsers to redownload a file when it has
|
69
|
+
changed in cases where a far future expires header is used.
|
70
|
+
|
71
|
+
There are two types of cache busters; soft ones add a parameter to the URL, like
|
72
|
+
so: http://assets/images/1.png?cb1234567890, ie the letters "cb" (as in cache
|
73
|
+
buster) and then the timestamp of the files mtime.
|
74
|
+
|
75
|
+
Unfortunately, the popular web proxy Squid shipped for some time with a default
|
76
|
+
configuration which would not treat a URL as a "new" URL if the only thing changed
|
77
|
+
was the GET parameters. For this reason Juicer provides hard cache busters.
|
78
|
+
|
79
|
+
Hard cache busters result in URLs such as: http://assets/images/1-cb1234567890.png,
|
80
|
+
ie URLs that require either renaming of files, or (more conveniently) a web
|
81
|
+
server configuration that will forward URLs to the right files anyway.
|
82
|
+
|
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.
|
168
|
+
|
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:
|
240
|
+
|
241
|
+
* Support more minifiers, JsMin (Ruby port), Packer and possibly others
|
242
|
+
* Add support for CssTidy to compress CSS files
|
243
|
+
|
244
|
+
If you have any ideas, feature requests, want to contribute or whatever, fork
|
245
|
+
the project on github, or get in touch through christian (at) cjohansen.no.
|
246
|
+
|
247
|
+
== SYNOPSIS:
|
248
|
+
|
249
|
+
juicer merge myfile.css
|
250
|
+
-> Produces myfile.min.css which may contain several CSS files, minified
|
251
|
+
|
252
|
+
juicer merge myfile.js
|
253
|
+
-> Produces myfile.min.js, minified and combined
|
254
|
+
|
255
|
+
juicer help
|
256
|
+
|
257
|
+
== REQUIREMENTS:
|
258
|
+
|
259
|
+
In order to use YUI Compressor, Closure Compiler or JsMin (requires Rhino) you need Java
|
260
|
+
installed and the java executable available on your path.
|
261
|
+
|
262
|
+
== INSTALL:
|
263
|
+
|
264
|
+
$ gem install juicer
|
265
|
+
$ juicer install yui_compressor
|
266
|
+
$ juicer install closure_compiler
|
267
|
+
$ juicer install jslint
|
268
|
+
|
269
|
+
You need Java installed and available on your PATH. During gem installation,
|
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.
|
275
|
+
|
276
|
+
|
277
|
+
== Contributors
|
278
|
+
|
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
|
+
Fixed installers on 1.0 branch
|
288
|
+
|
289
|
+
== LICENSE:
|
290
|
+
|
291
|
+
(The MIT License)
|
292
|
+
|
293
|
+
Copyright (c) 2008-2009 Christian Johansen
|
294
|
+
|
295
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
296
|
+
a copy of this software and associated documentation files (the
|
297
|
+
'Software'), to deal in the Software without restriction, including
|
298
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
299
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
300
|
+
permit persons to whom the Software is furnished to do so, subject to
|
301
|
+
the following conditions:
|
302
|
+
|
303
|
+
The above copyright notice and this permission notice shall be
|
304
|
+
included in all copies or substantial portions of the Software.
|
305
|
+
|
306
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
307
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
308
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
309
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
310
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
311
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
312
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|