ktheory-juicer 1.0.0.ktheory1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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.