ktheory-juicer 1.0.0.ktheory1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/History.txt +30 -0
  2. data/Manifest.txt +58 -0
  3. data/Rakefile +96 -0
  4. data/Readme.rdoc +312 -0
  5. data/VERSION +1 -0
  6. data/bin/juicer +8 -0
  7. data/lib/juicer.rb +70 -0
  8. data/lib/juicer/asset/path.rb +275 -0
  9. data/lib/juicer/asset/path_resolver.rb +79 -0
  10. data/lib/juicer/binary.rb +171 -0
  11. data/lib/juicer/cache_buster.rb +130 -0
  12. data/lib/juicer/chainable.rb +106 -0
  13. data/lib/juicer/cli.rb +56 -0
  14. data/lib/juicer/command/install.rb +61 -0
  15. data/lib/juicer/command/list.rb +57 -0
  16. data/lib/juicer/command/merge.rb +205 -0
  17. data/lib/juicer/command/util.rb +32 -0
  18. data/lib/juicer/command/verify.rb +60 -0
  19. data/lib/juicer/css_cache_buster.rb +80 -0
  20. data/lib/juicer/datafy/datafy.rb +20 -0
  21. data/lib/juicer/dependency_resolver/css_dependency_resolver.rb +29 -0
  22. data/lib/juicer/dependency_resolver/dependency_resolver.rb +101 -0
  23. data/lib/juicer/dependency_resolver/javascript_dependency_resolver.rb +23 -0
  24. data/lib/juicer/ext/logger.rb +5 -0
  25. data/lib/juicer/ext/string.rb +47 -0
  26. data/lib/juicer/ext/symbol.rb +15 -0
  27. data/lib/juicer/image_embed.rb +136 -0
  28. data/lib/juicer/install/base.rb +186 -0
  29. data/lib/juicer/install/closure_compiler_installer.rb +69 -0
  30. data/lib/juicer/install/jslint_installer.rb +51 -0
  31. data/lib/juicer/install/rhino_installer.rb +53 -0
  32. data/lib/juicer/install/yui_compressor_installer.rb +67 -0
  33. data/lib/juicer/jslint.rb +90 -0
  34. data/lib/juicer/merger/base.rb +74 -0
  35. data/lib/juicer/merger/javascript_merger.rb +29 -0
  36. data/lib/juicer/merger/stylesheet_merger.rb +110 -0
  37. data/lib/juicer/minifyer/closure_compiler.rb +90 -0
  38. data/lib/juicer/minifyer/java_base.rb +77 -0
  39. data/lib/juicer/minifyer/yui_compressor.rb +96 -0
  40. data/test/bin/jslint-1.0.js +523 -0
  41. data/test/bin/jslint.js +523 -0
  42. data/test/bin/rhino1_7R1.zip +0 -0
  43. data/test/bin/rhino1_7R2-RC1.jar +0 -0
  44. data/test/bin/rhino1_7R2-RC1.zip +0 -0
  45. data/test/bin/yuicompressor +0 -0
  46. data/test/bin/yuicompressor-2.3.5.zip +0 -0
  47. data/test/bin/yuicompressor-2.4.2.jar +0 -0
  48. data/test/bin/yuicompressor-2.4.2.zip +0 -0
  49. data/test/data/Changelog.txt +10 -0
  50. data/test/data/a.css +3 -0
  51. data/test/data/a.js +5 -0
  52. data/test/data/a1.css +5 -0
  53. data/test/data/b.css +1 -0
  54. data/test/data/b.js +5 -0
  55. data/test/data/b1.css +5 -0
  56. data/test/data/c1.css +3 -0
  57. data/test/data/css/2.gif +1 -0
  58. data/test/data/css/test.css +11 -0
  59. data/test/data/css/test2.css +1 -0
  60. data/test/data/d1.css +3 -0
  61. data/test/data/images/1.png +1 -0
  62. data/test/data/my_app.js +2 -0
  63. data/test/data/not-ok.js +2 -0
  64. data/test/data/ok.js +3 -0
  65. data/test/data/path_test.css +5 -0
  66. data/test/data/path_test2.css +14 -0
  67. data/test/data/pkg/module/moda.js +2 -0
  68. data/test/data/pkg/module/modb.js +3 -0
  69. data/test/data/pkg/pkg.js +1 -0
  70. data/test/test_helper.rb +169 -0
  71. data/test/unit/juicer/asset/path_resolver_test.rb +76 -0
  72. data/test/unit/juicer/asset/path_test.rb +370 -0
  73. data/test/unit/juicer/cache_buster_test.rb +104 -0
  74. data/test/unit/juicer/chainable_test.rb +94 -0
  75. data/test/unit/juicer/command/install_test.rb +58 -0
  76. data/test/unit/juicer/command/list_test.rb +81 -0
  77. data/test/unit/juicer/command/merge_test.rb +162 -0
  78. data/test/unit/juicer/command/util_test.rb +58 -0
  79. data/test/unit/juicer/command/verify_test.rb +48 -0
  80. data/test/unit/juicer/css_cache_buster_test.rb +71 -0
  81. data/test/unit/juicer/datafy_test.rb +37 -0
  82. data/test/unit/juicer/dependency_resolver/css_dependency_resolver_test.rb +36 -0
  83. data/test/unit/juicer/dependency_resolver/javascript_dependency_resolver_test.rb +50 -0
  84. data/test/unit/juicer/ext/string_test.rb +59 -0
  85. data/test/unit/juicer/ext/symbol_test.rb +27 -0
  86. data/test/unit/juicer/image_embed_test.rb +271 -0
  87. data/test/unit/juicer/install/installer_base_test.rb +214 -0
  88. data/test/unit/juicer/install/jslint_installer_test.rb +54 -0
  89. data/test/unit/juicer/install/rhino_installer_test.rb +57 -0
  90. data/test/unit/juicer/install/yui_compressor_test.rb +56 -0
  91. data/test/unit/juicer/jslint_test.rb +60 -0
  92. data/test/unit/juicer/merger/base_test.rb +122 -0
  93. data/test/unit/juicer/merger/javascript_merger_test.rb +74 -0
  94. data/test/unit/juicer/merger/stylesheet_merger_test.rb +180 -0
  95. data/test/unit/juicer/minifyer/closure_compressor_test.rb +107 -0
  96. data/test/unit/juicer/minifyer/yui_compressor_test.rb +116 -0
  97. data/test/unit/juicer_test.rb +1 -0
  98. 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.