diff --git a/.gitignore b/.gitignore index 34e54fd..b2782e9 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -spec/*.min +pkg +spec/files/*.min diff --git a/README.markdown b/README.markdown new file mode 100644 index 0000000..d01dfb6 --- /dev/null +++ b/README.markdown @@ -0,0 +1,28 @@ +Problem +======= + - javascript / stylesheets minification is complicated + - lossless image reduction requires endless libaries + +Solution +======== + - ALL IN ONE reduction simple as pie! + +Install +======= + install ruby + rubygems + curl + sudo gem install grosser-smusher grosser-reduce -s http://gems.github.com/ + +Usage +===== + #with JS + CSS + JPG + PNG + GIF + #in ruby + Reduce.reduce('files/bla.js','files/bla.min.js') + + #from command line + reduce files/input.js > files/input.min.js + +Author +====== +Michael Grosser +grosser.michael@gmail.com +Hereby placed under public domain, do what you want, just do not hold me accountable... \ No newline at end of file diff --git a/Rakefile b/Rakefile index 7dc71a2..e05fe02 100644 --- a/Rakefile +++ b/Rakefile @@ -14,6 +14,7 @@ begin gem.homepage = "http://github.com/grosser/reduce" gem.authors = ["Michael Grosser"] gem.add_dependency ['grosser-smusher'] + gem.files += FileList["vendor/**/*"] end rescue LoadError puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com" diff --git a/bin/reduce b/bin/reduce new file mode 100644 index 0000000..abef2f8 --- /dev/null +++ b/bin/reduce @@ -0,0 +1,12 @@ +#!/usr/bin/env ruby +require 'rubygems' +require 'reduce' + +path = ARGV[0] +if ARGV.length != 1 or not File.exist?(path) + puts "reduce FILE_TO_OPTIMIZE(js,css,jpg,png,gif)" + puts "reduce files/xxx.js" + exit +end + +print Reduce.reduce(path) \ No newline at end of file diff --git a/lib/reduce.rb b/lib/reduce.rb index e6c695c..8e160d5 100644 --- a/lib/reduce.rb +++ b/lib/reduce.rb @@ -3,17 +3,36 @@ module Reduce extend self + def reduce(input,output=nil) extension = File.extname(input).downcase.sub('.','') case extension when 'js','css' compressor = File.join(File.dirname(__FILE__),'..','vendor','yuicompressor*.jar') - `java -jar #{compressor} --type #{extension} #{input} > #{output}` + if output + `java -jar #{compressor} --type #{extension} #{input} > #{output}` + else + `java -jar #{compressor} --type #{extension} #{input}` + end when 'jpg','jpeg','png' - FileUtils.cp(input,output) - Smusher.optimize_image(output,:quiet=>true) + if output + reduce_image(input,output) + else + output = input+'.temp' + reduce_image(input,output) + data = File.read(output) + FileUtils.rm(output) + data + end else raise "WTF? a .#{extension} file...." end end + +private + + def reduce_image(input,output) + FileUtils.cp(input,output) + Smusher.optimize_image(output,:quiet=>true) + end end \ No newline at end of file diff --git a/reduce.gemspec b/reduce.gemspec new file mode 100644 index 0000000..f18cacb --- /dev/null +++ b/reduce.gemspec @@ -0,0 +1,33 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{reduce} + s.version = "0.1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Michael Grosser"] + s.date = %q{2009-02-11} + s.default_executable = %q{reduce} + s.email = %q{grosser.michael@gmail.com} + s.executables = ["reduce"] + s.files = ["vendor/yuicompressor-2.4.2.jar", "bin/reduce"] + s.has_rdoc = true + s.homepage = %q{http://github.com/grosser/reduce} + s.rdoc_options = ["--inline-source", "--charset=UTF-8"] + s.require_paths = ["lib"] + s.rubygems_version = %q{1.3.1} + s.summary = %q{Reduce your assets: minify javascript + stylesheets, optimize images lossless} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 0"]) + else + s.add_dependency(%q, [">= 0"]) + end + else + s.add_dependency(%q, [">= 0"]) + end +end diff --git a/spec/reduce_spec.rb b/spec/reduce_spec.rb index 7ca0864..9753f16 100644 --- a/spec/reduce_spec.rb +++ b/spec/reduce_spec.rb @@ -4,10 +4,14 @@ describe Reduce do Dir[files+'/*.min'].each{|f|FileUtils.rm(f)} Dir[files+'/*.*'].each do |file| - it "reduces #{File.extname(file)}" do + it "reduces #{File.extname(file)} and stores in output" do out = file+'.min' Reduce.reduce(file,out) File.size(out).should < File.size(file) end + it "reduces #{File.extname(file)} and returns the content" do + data = Reduce.reduce(file) + data.length.should < File.size(file) + end end end \ No newline at end of file diff --git a/vendor/README b/vendor/README new file mode 100644 index 0000000..8da3c6c --- /dev/null +++ b/vendor/README @@ -0,0 +1,135 @@ +============================================================================== +YUI Compressor +============================================================================== + +NAME + + YUI Compressor - The Yahoo! JavaScript and CSS Compressor + +SYNOPSIS + + Usage: java -jar yuicompressor-x.y.z.jar [options] [input file] + + Global Options + -h, --help Displays this information + --type Specifies the type of the input file + --charset Read the input file using + --line-break Insert a line break after the specified column number + -v, --verbose Display informational messages and warnings + -o Place the output into . Defaults to stdout. + + JavaScript Options + --nomunge Minify only, do not obfuscate + --preserve-semi Preserve all semicolons + --disable-optimizations Disable all micro optimizations + +DESCRIPTION + + The YUI Compressor is a JavaScript compressor which, in addition to removing + comments and white-spaces, obfuscates local variables using the smallest + possible variable name. This obfuscation is safe, even when using constructs + such as 'eval' or 'with' (although the compression is not optimal is those + cases) Compared to jsmin, the average savings is around 20%. + + The YUI Compressor is also able to safely compress CSS files. The decision + on which compressor is being used is made on the file extension (js or css) + +GLOBAL OPTIONS + + -h, --help + Prints help on how to use the YUI Compressor + + --line-break + Some source control tools don't like files containing lines longer than, + say 8000 characters. The linebreak option is used in that case to split + long lines after a specific column. It can also be used to make the code + more readable, easier to debug (especially with the MS Script Debugger) + Specify 0 to get a line break after each semi-colon in JavaScript, and + after each rule in CSS. + + --type js|css + The type of compressor (JavaScript or CSS) is chosen based on the + extension of the input file name (.js or .css) This option is required + if no input file has been specified. Otherwise, this option is only + required if the input file extension is neither 'js' nor 'css'. + + --charset character-set + If a supported character set is specified, the YUI Compressor will use it + to read the input file. Otherwise, it will assume that the platform's + default character set is being used. The output file is encoded using + the same character set. + + -o outfile + Place output in file outfile. If not specified, the YUI Compressor will + default to the standard output, which you can redirect to a file. + + -v, --verbose + Display informational messages and warnings. + +JAVASCRIPT ONLY OPTIONS + + --nomunge + Minify only. Do not obfuscate local symbols. + + --preserve-semi + Preserve unnecessary semicolons (such as right before a '}') This option + is useful when compressed code has to be run through JSLint (which is the + case of YUI for example) + + --disable-optimizations + Disable all the built-in micro optimizations. + +NOTES + + + If no input file is specified, it defaults to stdin. + + + The YUI Compressor requires Java version >= 1.4. + + + It is possible to prevent a local variable, nested function or function + argument from being obfuscated by using "hints". A hint is a string that + is located at the very beginning of a function body like so: + + function fn (arg1, arg2, arg3) { + "arg2:nomunge, localVar:nomunge, nestedFn:nomunge"; + + ... + var localVar; + ... + + function nestedFn () { + .... + } + + ... + } + + The hint itself disappears from the compressed file. + + + C-style comments starting with /*! are preserved. This is useful with + comments containing copyright/license information. For example: + + /*! + * TERMS OF USE - EASING EQUATIONS + * Open source under the BSD License. + * Copyright 2001 Robert Penner All rights reserved. + */ + + becomes: + + /* + * TERMS OF USE - EASING EQUATIONS + * Open source under the BSD License. + * Copyright 2001 Robert Penner All rights reserved. + */ + +AUTHOR + + The YUI Compressor was written and is maintained by: + Julien Lecomte + The CSS portion is a port of Isaac Schlueter's cssmin utility. + +COPYRIGHT + + Copyright (c) 2007, Yahoo! Inc. All rights reserved. + Code licensed under the BSD License: + http://developer.yahoo.net/yui/license.txt