reduce 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/README.markdown +32 -0
- data/Rakefile +20 -0
- data/VERSION +1 -0
- data/bin/reduce +33 -0
- data/lib/reduce.rb +35 -0
- data/reduce.gemspec +59 -0
- data/spec/files/facebox.css +99 -0
- data/spec/files/facebox.js +336 -0
- data/spec/files/paintcan.png +0 -0
- data/spec/files/test.gif +0 -0
- data/spec/reduce_spec.rb +33 -0
- data/spec/spec_helper.rb +23 -0
- data/vendor/README +135 -0
- data/vendor/yuicompressor-2.4.2.jar +0 -0
- metadata +79 -0
data/.gitignore
ADDED
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
|
data/spec/files/test.gif
ADDED
Binary file
|
data/spec/reduce_spec.rb
ADDED
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|