Created
January 20, 2013 14:09
-
-
Save SomeHats/4578938 to your computer and use it in GitHub Desktop.
A drop in plugin for converting from various preprocessors (Stylus, Sass, LESS & CoffeeScript), as well as minify-ing the whole lot, using YUICompressor for CSS and Google's Closure Compiler for Javascript. It also automatically optimises images using optipng and jpegtran. Drop convert-compress.rb into your _plugins directory, and install the de…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rubygems' | |
require 'yuicompressor' | |
require 'stylus' | |
require 'less' | |
require 'sass' | |
require 'closure-compiler' | |
require 'coffee-script' | |
require 'optipng' | |
require 'jpegtran' | |
module Jekyll | |
module CompileCompress | |
class CompileCompressFile < Jekyll::StaticFile | |
# Generic convert/compress thingy | |
# +dest+ is the String path to the destination dir | |
# | |
# Returns false if the file was not modified since last time (no-op). | |
def write(dest) | |
dest_path = File.join(dest, @dir, @name) | |
type = File.extname(@name) | |
return false if File.exist? dest and !modified? | |
@@mtimes[path] = mtime | |
FileUtils.mkdir_p(File.dirname(dest_path)) | |
begin | |
content = File.read(path) | |
case type | |
when ".css" | |
# Compress CSS | |
content = compressCss(content) | |
when ".styl" | |
# Convert Stylus to css | |
begin | |
print "Converting #{@name} to css... " | |
Stylus.use :nib | |
content = Stylus.compile(content) | |
print "done.\n" | |
rescue => e | |
puts "error.\nStylus: #{e.message}" | |
else | |
# compress & rename | |
content = compressCss(content) | |
dest_path = dest_path.gsub(/\.styl$/, ".css") | |
end | |
when ".less" | |
# Convert less to css | |
begin | |
print "Converting #{@name} to css... " | |
content = ::Less::Parser.new({:paths => [File.dirname(path)]}).parse(content).to_css | |
print "done.\n" | |
rescue => e | |
puts "error.\nLess: #{e.message}" | |
else | |
# compress & rename | |
content = compressCss(content) | |
dest_path = dest_path.gsub(/\.less$/, ".css") | |
end | |
when ".sass" | |
# Convert sass to css | |
begin | |
print "Converting #{@name} to css... " | |
content = ::Sass::Engine.new(content, :syntax => :sass, :load_paths => [File.dirname(path)]).render | |
print "done.\n" | |
rescue => e | |
puts "error.\nSass: #{e.message}" | |
else | |
# compress & rename | |
content = compressCss(content) | |
dest_path = dest_path.gsub(/\.sass$/, ".css") | |
end | |
when ".scss" | |
# Convert scss to css | |
begin | |
print "Converting #{@name} to css... " | |
content = ::Sass::Engine.new(content, :syntax => :scss, :load_paths => [File.dirname(path)]).render | |
print "done.\n" | |
rescue => e | |
puts "error.\nSass: #{e.message}" | |
else | |
# compress & rename | |
content = compressCss(content) | |
dest_path = dest_path.gsub(/\.scss$/, ".css") | |
end | |
when ".js" | |
# Compress JS | |
content = compressJs(content) | |
when ".coffee" | |
# Convert coffeescript to javascript | |
begin | |
print "Converting #{@name} to js... " | |
content = CoffeeScript.compile content | |
print "done.\n" | |
rescue => e | |
puts "error.\nCoffee: #{e.message}" | |
else | |
# compress & rename | |
content = compressJs(content) | |
dest_path = dest_path.gsub(/\.coffee$/, ".js") | |
end | |
end | |
File.open(dest_path, 'w') do |f| | |
f.write(content) | |
end | |
# Images have to be optimised after they've been written | |
case type | |
when '.png' | |
print "Optimising #{@name}... " | |
result = Optipng.optimize([dest_path], { :level => 7}).succeed | |
print "#{result.shift()[1] * -1}% reduction.\n" | |
when '.jpg', '.jpeg' | |
print "Optimising #{@name}... " | |
reduction = IO.popen("du #{dest_path}").readlines.first.to_f | |
Jpegtran.optimize(dest_path, { :progressive => true, :optimise => true }) | |
reduction = IO.popen("du #{dest_path}").readlines.first.to_f / reduction | |
print "#{(100 - reduction * 100).to_s[0,5]}% reduction.\n" | |
end | |
end | |
true | |
end | |
def compressCss(content) | |
print "Compressing #{@name}... " | |
size = content.bytesize.to_f | |
content = YUICompressor.compress_css(content) | |
size = content.bytesize.to_f / size; | |
print "#{(100 - size * 100).to_s[0,5]}% reduction.\n" | |
content | |
end | |
def compressJs(content) | |
print "Compressing #{@name}... " | |
size = content.bytesize.to_f | |
content = Closure::Compiler.new.compile(content) | |
size = content.bytesize.to_f / size; | |
print "#{(100 - size * 100).to_s[0,5]}% reduction.\n" | |
content | |
end | |
end | |
class CompCompGenerator < Jekyll::Generator | |
safe true | |
# Jekyll will have already added the *.js files as Jekyll::StaticFile | |
# objects to the static_files array. We can replace them with our | |
# CompileCompressFile objects to hijack what gets written, and where to. | |
def generate(site) | |
use = [".css", ".styl", ".less", ".sass", ".scss", ".js", ".coffee", | |
".png", ".jpg", ".jpeg"] | |
site.static_files.clone.each do |sf| | |
type = File.extname(sf.path) | |
if use.include? type | |
site.static_files.delete(sf) | |
name = File.basename(sf.path); | |
dest = File.dirname(sf.path).sub(site.source, '') | |
site.static_files << CompileCompressFile.new(site, site.source, dest, name) | |
end | |
end | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
yuicompressor stylus tilt less therubyracer sass closure-compiler coffee-script json optipng jpegtran |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment