require 'jsmin'
require File.join(File.dirname(__FILE__), 'js', 'vendors')
module AssetHat
# Methods for minifying JavaScript.
module JS
# A list of supported minification
# engine names.
ENGINES = [:weak, :jsmin]
# A list of supported
# 3rd-party JavaScript plugin/vendor names.
VENDORS = Vendors::VENDORS
# Returns the expected path for the minified version of a JS asset:
#
# AssetHat::JS.min_filepath('public/javascripts/bundles/application.js')
# # => 'public/javascripts/bundles/application.min.js'
def self.min_filepath(filepath)
AssetHat.min_filepath(filepath, 'js')
end
# Accepts a string of JS, and returns that JS minified. Options:
#
# [engine] Default is :jsmin
; see
# Engines.jsmin.
# Allowed values are in ENGINES.
def self.minify(input_string, options={})
options.reverse_merge!(:engine => :jsmin)
engine = options[:engine].to_sym
unless ENGINES.include?(engine)
raise %Q{
Unknown JS minification engine '#{engine}'.
Allowed: #{ENGINES.map{ |e| "'#{e}'" }.join(', ')}
}.strip.gsub(/\s+/, ' ') and return
end
AssetHat::JS::Engines.send(engine, input_string)
end
# Swappable JavaScript minification engines.
module Engines
# Barebones JavaScript minification engine that:
# - Skips leading/trailing whitespace for each line, excluding line
# breaks; and
# - Removes one-line comments that had no actual code on that line.
def self.weak(input_string)
input = StringIO.new(input_string)
output = StringIO.new
input.each do |line|
# Remove indentation and trailing whitespace
line.strip!
next if line.blank?
# Skip single-line comments
next if !(line =~ /^\/\//).nil?
# TODO: Also skip single-line comments that began mid-line, but not
# inside a string or regex
# TODO: Skip multi-line comments
# - Should not strip from within a string or regex
# - Should not strip comments that begin with `/*!` (e.g., licenses)
output.write(line + "\n")
end
output.rewind
output.read
end
# JavaScript minification engine that simply uses the JSMin gem, a Ruby
# port of Crockford's JSMin.
#
# Sources:
# - http://github.com/rgrove/jsmin
# - http://rubygems.org/gems/jsmin
def self.jsmin(input_string)
JSMin.minify(input_string)
end
end # module Engines
end
end