reduce 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ pkg
2
+ spec/files/*.min
data/README.markdown ADDED
@@ -0,0 +1,32 @@
1
+ Lossless reduction for js, css, jpg, png, gif
2
+
3
+ Install
4
+ =======
5
+ install ruby + rubygems
6
+ sudo gem install reduce
7
+
8
+ Usage
9
+ =====
10
+ reduce -o public/image.gif
11
+ reduce public/javascripts/application.js > public/javascripts/application.min.js
12
+
13
+ Options
14
+ =======
15
+ -o, --overwrite overwrite file
16
+ -v, --version Show Version
17
+ -h, --help Show this.
18
+
19
+ Ruby
20
+ ====
21
+ reduced_data = Reduce.reduce('files/bla.js')
22
+
23
+ How does it work?
24
+ =================
25
+ - uses web-based lossless image reduction service [Smush.it](http://smush.it) / [PunyPng](http://www.gracepointafterfive.com/punypng) through [smusher](http://github.com/grosser/smusher)
26
+ - uses YUI compressor to minify css/js
27
+
28
+ Author
29
+ ======
30
+ Michael Grosser
31
+ grosser.michael@gmail.com
32
+ Hereby placed under public domain, do what you want, just do not hold me accountable...
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ task :default => :spec
2
+ require 'spec/rake/spectask'
3
+ Spec::Rake::SpecTask.new {|t| t.spec_opts = ['--color']}
4
+
5
+ begin
6
+ require 'jeweler'
7
+ project_name = 'reduce'
8
+ Jeweler::Tasks.new do |gem|
9
+ gem.name = "reduce"
10
+ gem.summary = "Reduce your assets: minify javascript + stylesheets, optimize images lossless"
11
+ gem.email = "grosser.michael@gmail.com"
12
+ gem.homepage = "http://github.com/grosser/#{project_name}"
13
+ gem.authors = ["Michael Grosser"]
14
+ gem.add_dependency ['smusher']
15
+ end
16
+
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
20
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
data/bin/reduce ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'optparse'
4
+ require 'reduce'
5
+
6
+ options = {}
7
+ OptionParser.new do |opts|
8
+ opts.banner = <<BANNER
9
+ Lossless optimize js, css, jpg, png, gif
10
+
11
+ Usage:
12
+ reduce -o public/image.gif
13
+ reduce public/javascripts/application.js > public/javascripts/application.min.js
14
+
15
+ Options are:
16
+ BANNER
17
+ opts.on("-o", "--overwrite", "overwrite file") { options[:overwrite]=true }
18
+ opts.on('-v', '--version', 'Show Version'){ puts Reduce::VERSION; exit}
19
+ opts.on("-h", "--help", "Show this.") { puts opts; exit }
20
+ end.parse!
21
+
22
+ file = ARGV.first
23
+ if file.to_s.empty? or not File.exist?(file)
24
+ puts "Usage instructions: reduce --help"
25
+ exit
26
+ else
27
+ data = Reduce.reduce(file)
28
+ if options[:overwrite]
29
+ File.open(file, 'w'){|f| f.print data}
30
+ else
31
+ print data
32
+ end
33
+ end
data/lib/reduce.rb ADDED
@@ -0,0 +1,35 @@
1
+ require 'smusher'
2
+ raise "please install a newer version of smusher" if Smusher::VERSION < '0.4.0'
3
+
4
+ module Reduce
5
+ extend self
6
+
7
+ VERSION = File.read( File.join(File.dirname(__FILE__),'..','VERSION') ).strip
8
+
9
+ def reduce(file)
10
+ extension = File.extname(file).downcase.sub('.','')
11
+ case extension
12
+ when 'js','css'
13
+ compressor = File.join(File.dirname(__FILE__),'..','vendor','yuicompressor*.jar')
14
+ `java -jar #{compressor} --type #{extension} #{file}`
15
+ when 'jpg', 'jpeg', 'png', 'gif'
16
+ reduce_image file
17
+ else
18
+ raise "reduce does not know how to handle a .#{extension} file (#{file})"
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def reduce_image(input)
25
+ output = input+'.temp'
26
+ FileUtils.cp(input, output)
27
+
28
+ service = (input.downcase =~ /\.gif$/ ? 'PunyPng' : 'SmushIt')
29
+ Smusher.optimize_image(output, :quiet=>true, :service => service)
30
+
31
+ data = File.read(output)
32
+ FileUtils.rm(output)
33
+ data
34
+ end
35
+ end
data/reduce.gemspec ADDED
@@ -0,0 +1,59 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{reduce}
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Michael Grosser"]
12
+ s.date = %q{2009-11-22}
13
+ s.default_executable = %q{reduce}
14
+ s.email = %q{grosser.michael@gmail.com}
15
+ s.executables = ["reduce"]
16
+ s.extra_rdoc_files = [
17
+ "README.markdown"
18
+ ]
19
+ s.files = [
20
+ ".gitignore",
21
+ "README.markdown",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "bin/reduce",
25
+ "lib/reduce.rb",
26
+ "reduce.gemspec",
27
+ "spec/files/facebox.css",
28
+ "spec/files/facebox.js",
29
+ "spec/files/paintcan.png",
30
+ "spec/files/test.gif",
31
+ "spec/reduce_spec.rb",
32
+ "spec/spec_helper.rb",
33
+ "vendor/README",
34
+ "vendor/yuicompressor-2.4.2.jar"
35
+ ]
36
+ s.homepage = %q{http://github.com/grosser/reduce}
37
+ s.rdoc_options = ["--charset=UTF-8"]
38
+ s.require_paths = ["lib"]
39
+ s.rubygems_version = %q{1.3.5}
40
+ s.summary = %q{Reduce your assets: minify javascript + stylesheets, optimize images lossless}
41
+ s.test_files = [
42
+ "spec/spec_helper.rb",
43
+ "spec/reduce_spec.rb"
44
+ ]
45
+
46
+ if s.respond_to? :specification_version then
47
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
48
+ s.specification_version = 3
49
+
50
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
51
+ s.add_runtime_dependency(%q<smusher>, [">= 0"])
52
+ else
53
+ s.add_dependency(%q<smusher>, [">= 0"])
54
+ end
55
+ else
56
+ s.add_dependency(%q<smusher>, [">= 0"])
57
+ end
58
+ end
59
+
@@ -0,0 +1,99 @@
1
+ #facebox .b {
2
+ background:url(/images/facebox/b.png);
3
+ }
4
+
5
+ #facebox .tl {
6
+ background:url(/images/facebox/tl.png);
7
+ }
8
+
9
+ #facebox .tr {
10
+ background:url(/images/facebox/tr.png);
11
+ }
12
+
13
+ #facebox .bl {
14
+ background:url(/images/facebox/bl.png);
15
+ }
16
+
17
+ #facebox .br {
18
+ background:url(/images/facebox/br.png);
19
+ }
20
+
21
+ #facebox {
22
+ position: absolute;
23
+ top: 0;
24
+ left: 0;
25
+ z-index: 100;
26
+ text-align: left;
27
+ }
28
+
29
+ #facebox .popup {
30
+ position: relative;
31
+ }
32
+
33
+ #facebox table {
34
+ border-collapse: collapse;
35
+ }
36
+
37
+ #facebox td {
38
+ border-bottom: 0;
39
+ padding: 0;
40
+ }
41
+
42
+ #facebox .body {
43
+ padding: 10px;
44
+ background: #fff;
45
+ width: 370px;
46
+ }
47
+
48
+ #facebox .loading {
49
+ text-align: center;
50
+ }
51
+
52
+ #facebox .image {
53
+ text-align: center;
54
+ }
55
+
56
+ #facebox img {
57
+ border: 0;
58
+ margin: 0;
59
+ }
60
+
61
+ #facebox .footer {
62
+ border-top: 1px solid #DDDDDD;
63
+ padding-top: 5px;
64
+ margin-top: 10px;
65
+ text-align: right;
66
+ }
67
+
68
+ #facebox .footer img {
69
+ vertical-align: middle;
70
+ }
71
+
72
+ #facebox .tl, #facebox .tr, #facebox .bl, #facebox .br {
73
+ height: 10px;
74
+ width: 10px;
75
+ overflow: hidden;
76
+ padding: 0;
77
+ }
78
+
79
+ #facebox_overlay {
80
+ position: fixed;
81
+ top: 0px;
82
+ left: 0px;
83
+ height:100%;
84
+ width:100%;
85
+ }
86
+
87
+ .facebox_hide {
88
+ z-index:-100;
89
+ }
90
+
91
+ .facebox_overlayBG {
92
+ background-color: #000;
93
+ z-index: 99;
94
+ }
95
+
96
+ * html #facebox_overlay { /* ie6 hack */
97
+ position: absolute;
98
+ height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');
99
+ }
@@ -0,0 +1,336 @@
1
+ /*
2
+ * Facebox (for jQuery)
3
+ * version: 1.2 (05/05/2008)
4
+ * @requires jQuery v1.2 or later
5
+ *
6
+ * Examples at http://famspam.com/facebox/
7
+ *
8
+ * Licensed under the MIT:
9
+ * http://www.opensource.org/licenses/mit-license.php
10
+ *
11
+ * Copyright 2007, 2008 Chris Wanstrath [ chris@ozmm.org ]
12
+ *
13
+ * Usage:
14
+ *
15
+ * jQuery(document).ready(function() {
16
+ * jQuery('a[rel*=facebox]').facebox()
17
+ * })
18
+ *
19
+ * <a href="#terms" rel="facebox">Terms</a>
20
+ * Loads the #terms div in the box
21
+ *
22
+ * <a href="terms.html" rel="facebox">Terms</a>
23
+ * Loads the terms.html page in the box
24
+ *
25
+ * <a href="terms.png" rel="facebox">Terms</a>
26
+ * Loads the terms.png image in the box
27
+ *
28
+ *
29
+ * You can also use it programmatically:
30
+ *
31
+ * jQuery.facebox('some html')
32
+ * jQuery.facebox('some html', 'my-groovy-style')
33
+ *
34
+ * The above will open a facebox with "some html" as the content.
35
+ *
36
+ * jQuery.facebox(function($) {
37
+ * $.get('blah.html', function(data) { $.facebox(data) })
38
+ * })
39
+ *
40
+ * The above will show a loading screen before the passed function is called,
41
+ * allowing for a better ajaxy experience.
42
+ *
43
+ * The facebox function can also display an ajax page, an image, or the contents of a div:
44
+ *
45
+ * jQuery.facebox({ ajax: 'remote.html' })
46
+ * jQuery.facebox({ ajax: 'remote.html' }, 'my-groovy-style')
47
+ * jQuery.facebox({ image: 'stairs.jpg' })
48
+ * jQuery.facebox({ image: 'stairs.jpg' }, 'my-groovy-style')
49
+ * jQuery.facebox({ div: '#box' })
50
+ * jQuery.facebox({ div: '#box' }, 'my-groovy-style')
51
+ *
52
+ * Want to close the facebox? Trigger the 'close.facebox' document event:
53
+ *
54
+ * jQuery(document).trigger('close.facebox')
55
+ *
56
+ * Facebox also has a bunch of other hooks:
57
+ *
58
+ * loading.facebox
59
+ * beforeReveal.facebox
60
+ * reveal.facebox (aliased as 'afterReveal.facebox')
61
+ * init.facebox
62
+ *
63
+ * Simply bind a function to any of these hooks:
64
+ *
65
+ * $(document).bind('reveal.facebox', function() { ...stuff to do after the facebox and contents are revealed... })
66
+ *
67
+ */
68
+ (function($) {
69
+ $.facebox = function(data, klass) {
70
+ $.facebox.loading()
71
+
72
+ if (data.ajax) fillFaceboxFromAjax(data.ajax, klass)
73
+ else if (data.image) fillFaceboxFromImage(data.image, klass)
74
+ else if (data.div) fillFaceboxFromHref(data.div, klass)
75
+ else if ($.isFunction(data)) data.call($)
76
+ else $.facebox.reveal(data, klass)
77
+ }
78
+
79
+ /*
80
+ * Public, $.facebox methods
81
+ */
82
+
83
+ $.extend($.facebox, {
84
+ //possible option: noAutoload --- will build facebox only when it is needed
85
+ settings: {
86
+ opacity : 0,
87
+ overlay : true,
88
+ imagePath : '/images/facebox/',
89
+ loadingImage : 'loading.gif',
90
+ closeImage : 'closelabel.gif',
91
+ imageTypes : [ 'png', 'jpg', 'jpeg', 'gif' ]
92
+ },
93
+
94
+ html : function(){
95
+ return '\
96
+ <div id="facebox" style="display:none;"> \
97
+ <div class="popup"> \
98
+ <table> \
99
+ <tbody> \
100
+ <tr> \
101
+ <td class="tl"/><td class="b"/><td class="tr"/> \
102
+ </tr> \
103
+ <tr> \
104
+ <td class="b"/> \
105
+ <td class="body"> \
106
+ <div class="content"> \
107
+ </div> \
108
+ <div class="footer"> \
109
+ <a href="#" class="close"> \
110
+ <img src="'+$.facebox.settings.imagePath+$.facebox.settings.closeImage+'" title="close" class="close_image" /> \
111
+ </a> \
112
+ </div> \
113
+ </td> \
114
+ <td class="b"/> \
115
+ </tr> \
116
+ <tr> \
117
+ <td class="bl"/><td class="b"/><td class="br"/> \
118
+ </tr> \
119
+ </tbody> \
120
+ </table> \
121
+ </div> \
122
+ </div>'
123
+ },
124
+
125
+ loading: function() {
126
+ init()
127
+ var $f = $('#facebox')
128
+ if ($f.find('.loading').length == 1) return true
129
+ showOverlay()
130
+
131
+ $f.find('.content').empty()
132
+ $f.find('.body').children().hide().end().
133
+ append('<div class="loading"><img src="'+$.facebox.settings.imagePath+$.facebox.settings.loadingImage+'"/></div>')
134
+
135
+ $f.css({
136
+ top: getPageScroll()[1] + (getPageHeight() / 10),
137
+ left: $(window).width() / 2 - 205
138
+ }).show()
139
+
140
+ $(document).bind('keydown.facebox', function(e) {
141
+ if (e.keyCode == 27) $.facebox.close()
142
+ return true
143
+ })
144
+ $(document).trigger('loading.facebox')
145
+ },
146
+
147
+ reveal: function(data, klass) {
148
+ $(document).trigger('beforeReveal.facebox')
149
+ var $f = $('#facebox')
150
+ if (klass) $('#facebox .content').addClass(klass)
151
+ $f.find('.content').append(data)
152
+ $f.find('.loading').remove()
153
+ $f.find('.body').children().fadeIn('normal')
154
+ $f.css('left', $(window).width() / 2 - ($('#facebox table').width() / 2))
155
+ $(document).trigger('reveal.facebox').trigger('afterReveal.facebox')
156
+ },
157
+
158
+ close: function() {
159
+ $(document).trigger('close.facebox')
160
+ return false
161
+ }
162
+ })
163
+
164
+ /*
165
+ * Public, $.fn methods
166
+ */
167
+
168
+ $.fn.facebox = function(settings) {
169
+ merge_settings(settings)
170
+ if(!settings.noAutoload)init()
171
+
172
+ return this.bind('click.facebox',function(){
173
+ $.facebox.loading()
174
+
175
+ // support for rel="facebox.inline_popup" syntax, to add a class
176
+ // also supports deprecated "facebox[.inline_popup]" syntax
177
+ var klass = this.rel.match(/facebox\[?\.(\w+)\]?/)
178
+ if (klass) klass = klass[1]
179
+
180
+ fillFaceboxFromHref(this.href, klass)
181
+ return false
182
+ })
183
+ }
184
+
185
+ /*
186
+ * Private methods
187
+ */
188
+
189
+ function merge_settings(settings){
190
+ $.extend($.facebox.settings, settings)
191
+ }
192
+
193
+ // called one time to setup facebox on this page
194
+ function init() {
195
+ if ($.facebox.settings.inited) return
196
+ else $.facebox.settings.inited = true
197
+
198
+ $(document).trigger('init.facebox')
199
+ makeCompatible()
200
+
201
+ var imageTypes = $.facebox.settings.imageTypes.join('|')
202
+ $.facebox.settings.imageTypesRegexp = new RegExp('\.(' + imageTypes + ')$', 'i')
203
+
204
+ $('body').append($.facebox.html())
205
+ if(! $.facebox.settings.noAutoload)preloadImages()
206
+ $('#facebox .close').click($.facebox.close)
207
+ }
208
+
209
+ function preloadImages(){
210
+ var preload = [ new Image(), new Image() ]
211
+ var path = $.facebox.settings.imagePath
212
+ preload[0].src = path + $.facebox.settings.closeImage
213
+ preload[1].src = path + $.facebox.settings.loadingImage
214
+
215
+ $('#facebox').find('.b:first, .bl, .br, .tl, .tr').each(function() {
216
+ preload.push(new Image())
217
+ preload.slice(-1).src = $(this).css('background-image').replace(/url\((.+)\)/, '$1')
218
+ })
219
+ }
220
+
221
+ // getPageScroll() by quirksmode.com
222
+ function getPageScroll() {
223
+ var xScroll, yScroll;
224
+ if (self.pageYOffset) {
225
+ yScroll = self.pageYOffset;
226
+ xScroll = self.pageXOffset;
227
+ } else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict
228
+ yScroll = document.documentElement.scrollTop;
229
+ xScroll = document.documentElement.scrollLeft;
230
+ } else if (document.body) {// all other Explorers
231
+ yScroll = document.body.scrollTop;
232
+ xScroll = document.body.scrollLeft;
233
+ }
234
+ return new Array(xScroll,yScroll)
235
+ }
236
+
237
+ // Adapted from getPageSize() by quirksmode.com
238
+ function getPageHeight() {
239
+ var windowHeight
240
+ if (self.innerHeight) { // all except Explorer
241
+ windowHeight = self.innerHeight;
242
+ } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
243
+ windowHeight = document.documentElement.clientHeight;
244
+ } else if (document.body) { // other Explorers
245
+ windowHeight = document.body.clientHeight;
246
+ }
247
+ return windowHeight
248
+ }
249
+
250
+ // Backwards compatibility
251
+ function makeCompatible() {
252
+ var $s = $.facebox.settings
253
+
254
+ $s.loadingImage = $s.loading_image || $s.loadingImage
255
+ $s.closeImage = $s.close_image || $s.closeImage
256
+ $s.imageTypes = $s.image_types || $s.imageTypes
257
+ $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml
258
+ }
259
+
260
+ // Figures out what you want to display and displays it
261
+ // formats are:
262
+ // div: #id
263
+ // image: blah.extension
264
+ // ajax: anything else
265
+ function fillFaceboxFromHref(href, klass) {
266
+ // div
267
+ if (href.match(/#/)) {
268
+ var url = window.location.href.split('#')[0]
269
+ var target = href.replace(url,'')
270
+ $.facebox.reveal($(target).show().replaceWith("<div id='facebox_moved'></div>"), klass)
271
+
272
+ // image
273
+ } else if (href.match($.facebox.settings.imageTypesRegexp)) {
274
+ fillFaceboxFromImage(href, klass)
275
+ // ajax
276
+ } else {
277
+ fillFaceboxFromAjax(href, klass)
278
+ }
279
+ }
280
+
281
+ function fillFaceboxFromImage(href, klass) {
282
+ var image = new Image()
283
+ image.onload = function() {
284
+ $.facebox.reveal('<div class="image"><img src="' + image.src + '" /></div>', klass)
285
+ }
286
+ image.src = href
287
+ }
288
+
289
+ function fillFaceboxFromAjax(href, klass) {
290
+ $.get(href, function(data) { $.facebox.reveal(data, klass) })
291
+ }
292
+
293
+ function skipOverlay() {
294
+ return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null
295
+ }
296
+
297
+ function showOverlay() {
298
+ if (skipOverlay()) return
299
+
300
+ if ($('#facebox_overlay').length == 0)
301
+ $("body").append('<div id="facebox_overlay" class="facebox_hide"></div>')
302
+
303
+ $('#facebox_overlay').hide().addClass("facebox_overlayBG")
304
+ .css('opacity', $.facebox.settings.opacity)
305
+ .click(function() { $(document).trigger('close.facebox') })
306
+ .fadeIn(200)
307
+ return false
308
+ }
309
+
310
+ function hideOverlay() {
311
+ if (skipOverlay()) return
312
+
313
+ $('#facebox_overlay').fadeOut(200, function(){
314
+ $("#facebox_overlay").removeClass("facebox_overlayBG").
315
+ addClass("facebox_hide").
316
+ remove()
317
+ })
318
+
319
+ return false
320
+ }
321
+
322
+ /*
323
+ * Bindings
324
+ */
325
+
326
+ $(document).bind('close.facebox', function() {
327
+ $(document).unbind('keydown.facebox')
328
+ $('#facebox').fadeOut(function() {
329
+ if ($('#facebox_moved').length == 0) $('#facebox .content').removeClass().addClass('content')
330
+ else $('#facebox_moved').replaceWith($('#facebox .content').children().hide())
331
+ hideOverlay()
332
+ $('#facebox .loading').remove()
333
+ })
334
+ })
335
+
336
+ })(jQuery);
Binary file
Binary file
@@ -0,0 +1,33 @@
1
+ require File.expand_path("spec_helper", File.dirname(__FILE__))
2
+ files = File.join(File.dirname(__FILE__),'files')
3
+
4
+ def cleanup(files)
5
+ Dir[files+'/*.min.*', files+'/*.temp'].each{|f| FileUtils.rm(f)}
6
+ end
7
+
8
+ describe Reduce do
9
+ after(:all){ cleanup(files) }
10
+
11
+ cleanup(files)
12
+ Dir[files+'/*.*'].each do |file|
13
+ extension = File.extname(file)
14
+ it "reduces #{File.extname(file)} and returns the content" do
15
+ data = Reduce.reduce(file)
16
+ data.length.should < File.size(file)
17
+ end
18
+ end
19
+
20
+ it "uses PunyPng for gifs" do
21
+ Smusher.should_receive(:optimize_image).with(anything, hash_including(:service => 'PunyPng'))
22
+ Reduce.reduce(File.join(files, 'test.gif'))
23
+ end
24
+
25
+ it "uses SmushIt for other images" do
26
+ Smusher.should_receive(:optimize_image).with(anything, hash_including(:service => 'SmushIt'))
27
+ Reduce.reduce(File.join(files, 'paintcan.png'))
28
+ end
29
+
30
+ it "has a VERSION" do
31
+ Reduce::VERSION.should =~ /^\d+\.\d+\.\d+$/
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ # ---- requirements
2
+ require 'rubygems'
3
+
4
+ $LOAD_PATH << File.expand_path("../lib", File.dirname(__FILE__))
5
+ require 'reduce'
6
+
7
+ # ---- bugfix
8
+ #`exit?': undefined method `run?' for Test::Unit:Module (NoMethodError)
9
+ #can be solved with require test/unit but this will result in extra test-output
10
+ module Test
11
+ module Unit
12
+ def self.run?
13
+ true
14
+ end
15
+ end
16
+ end
17
+
18
+ # ---- Helpers
19
+ def pending_it(text,&block)
20
+ it text do
21
+ pending(&block)
22
+ end
23
+ end
data/vendor/README ADDED
@@ -0,0 +1,135 @@
1
+ ==============================================================================
2
+ YUI Compressor
3
+ ==============================================================================
4
+
5
+ NAME
6
+
7
+ YUI Compressor - The Yahoo! JavaScript and CSS Compressor
8
+
9
+ SYNOPSIS
10
+
11
+ Usage: java -jar yuicompressor-x.y.z.jar [options] [input file]
12
+
13
+ Global Options
14
+ -h, --help Displays this information
15
+ --type <js|css> Specifies the type of the input file
16
+ --charset <charset> Read the input file using <charset>
17
+ --line-break <column> Insert a line break after the specified column number
18
+ -v, --verbose Display informational messages and warnings
19
+ -o <file> Place the output into <file>. Defaults to stdout.
20
+
21
+ JavaScript Options
22
+ --nomunge Minify only, do not obfuscate
23
+ --preserve-semi Preserve all semicolons
24
+ --disable-optimizations Disable all micro optimizations
25
+
26
+ DESCRIPTION
27
+
28
+ The YUI Compressor is a JavaScript compressor which, in addition to removing
29
+ comments and white-spaces, obfuscates local variables using the smallest
30
+ possible variable name. This obfuscation is safe, even when using constructs
31
+ such as 'eval' or 'with' (although the compression is not optimal is those
32
+ cases) Compared to jsmin, the average savings is around 20%.
33
+
34
+ The YUI Compressor is also able to safely compress CSS files. The decision
35
+ on which compressor is being used is made on the file extension (js or css)
36
+
37
+ GLOBAL OPTIONS
38
+
39
+ -h, --help
40
+ Prints help on how to use the YUI Compressor
41
+
42
+ --line-break
43
+ Some source control tools don't like files containing lines longer than,
44
+ say 8000 characters. The linebreak option is used in that case to split
45
+ long lines after a specific column. It can also be used to make the code
46
+ more readable, easier to debug (especially with the MS Script Debugger)
47
+ Specify 0 to get a line break after each semi-colon in JavaScript, and
48
+ after each rule in CSS.
49
+
50
+ --type js|css
51
+ The type of compressor (JavaScript or CSS) is chosen based on the
52
+ extension of the input file name (.js or .css) This option is required
53
+ if no input file has been specified. Otherwise, this option is only
54
+ required if the input file extension is neither 'js' nor 'css'.
55
+
56
+ --charset character-set
57
+ If a supported character set is specified, the YUI Compressor will use it
58
+ to read the input file. Otherwise, it will assume that the platform's
59
+ default character set is being used. The output file is encoded using
60
+ the same character set.
61
+
62
+ -o outfile
63
+ Place output in file outfile. If not specified, the YUI Compressor will
64
+ default to the standard output, which you can redirect to a file.
65
+
66
+ -v, --verbose
67
+ Display informational messages and warnings.
68
+
69
+ JAVASCRIPT ONLY OPTIONS
70
+
71
+ --nomunge
72
+ Minify only. Do not obfuscate local symbols.
73
+
74
+ --preserve-semi
75
+ Preserve unnecessary semicolons (such as right before a '}') This option
76
+ is useful when compressed code has to be run through JSLint (which is the
77
+ case of YUI for example)
78
+
79
+ --disable-optimizations
80
+ Disable all the built-in micro optimizations.
81
+
82
+ NOTES
83
+
84
+ + If no input file is specified, it defaults to stdin.
85
+
86
+ + The YUI Compressor requires Java version >= 1.4.
87
+
88
+ + It is possible to prevent a local variable, nested function or function
89
+ argument from being obfuscated by using "hints". A hint is a string that
90
+ is located at the very beginning of a function body like so:
91
+
92
+ function fn (arg1, arg2, arg3) {
93
+ "arg2:nomunge, localVar:nomunge, nestedFn:nomunge";
94
+
95
+ ...
96
+ var localVar;
97
+ ...
98
+
99
+ function nestedFn () {
100
+ ....
101
+ }
102
+
103
+ ...
104
+ }
105
+
106
+ The hint itself disappears from the compressed file.
107
+
108
+ + C-style comments starting with /*! are preserved. This is useful with
109
+ comments containing copyright/license information. For example:
110
+
111
+ /*!
112
+ * TERMS OF USE - EASING EQUATIONS
113
+ * Open source under the BSD License.
114
+ * Copyright 2001 Robert Penner All rights reserved.
115
+ */
116
+
117
+ becomes:
118
+
119
+ /*
120
+ * TERMS OF USE - EASING EQUATIONS
121
+ * Open source under the BSD License.
122
+ * Copyright 2001 Robert Penner All rights reserved.
123
+ */
124
+
125
+ AUTHOR
126
+
127
+ The YUI Compressor was written and is maintained by:
128
+ Julien Lecomte <jlecomte@yahoo-inc.com>
129
+ The CSS portion is a port of Isaac Schlueter's cssmin utility.
130
+
131
+ COPYRIGHT
132
+
133
+ Copyright (c) 2007, Yahoo! Inc. All rights reserved.
134
+ Code licensed under the BSD License:
135
+ http://developer.yahoo.net/yui/license.txt
Binary file
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: reduce
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Michael Grosser
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-22 00:00:00 +01:00
13
+ default_executable: reduce
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: smusher
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description:
26
+ email: grosser.michael@gmail.com
27
+ executables:
28
+ - reduce
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.markdown
33
+ files:
34
+ - .gitignore
35
+ - README.markdown
36
+ - Rakefile
37
+ - VERSION
38
+ - bin/reduce
39
+ - lib/reduce.rb
40
+ - reduce.gemspec
41
+ - spec/files/facebox.css
42
+ - spec/files/facebox.js
43
+ - spec/files/paintcan.png
44
+ - spec/files/test.gif
45
+ - spec/reduce_spec.rb
46
+ - spec/spec_helper.rb
47
+ - vendor/README
48
+ - vendor/yuicompressor-2.4.2.jar
49
+ has_rdoc: true
50
+ homepage: http://github.com/grosser/reduce
51
+ licenses: []
52
+
53
+ post_install_message:
54
+ rdoc_options:
55
+ - --charset=UTF-8
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ requirements: []
71
+
72
+ rubyforge_project:
73
+ rubygems_version: 1.3.5
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: "Reduce your assets: minify javascript + stylesheets, optimize images lossless"
77
+ test_files:
78
+ - spec/spec_helper.rb
79
+ - spec/reduce_spec.rb