Skip to content

Instantly share code, notes, and snippets.

@arnklint
Forked from kares/javascript.rake
Created May 24, 2010 16:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arnklint/412058 to your computer and use it in GitHub Desktop.
Save arnklint/412058 to your computer and use it in GitHub Desktop.
# configure these defaults based on Your needs :
JS_FILES_DIR = 'public/javascripts' # the javascripts base directory
EXCLUDED_JS_FILES = %W{ cache/* test/* } # excluded from compilation
OUT_FILE_JS_EXT_PREFIX = ".min" # override with `rake ... OUT_EXT=_pack`
COMPILER_JAR = "lib/jars/build/compiler.jar" # adjust the jar path !
# only required if running under JRuby - will compile multiple files
# faster as it does not need to run system `java -jar ...` commands.
COMPILER_MAIN_CLASS = "com.google.javascript.jscomp.CommandLineRunner"
COMPILER_DOWNLOAD_URI = 'http://closure-compiler.googlecode.com/files/compiler-latest.zip'
#
# a javascript compile rake task (uses google's closure compiler).
#
# @see http://code.google.com/closure/compiler/
#
namespace :javascript do
desc "js compilation - minifies a single file (specify FILE=some.js)"
task :compile do
js_file = ENV['FILE']
raise "no FILE given" if js_file.blank?
options = build_options(js_file)
compile_js_if_necessary(js_file, options)
end
desc "js compilation - minifies all /javascripts/**/*.js files"
task :compile_all do
js_files = Dir[ File.join(JS_FILES_DIR, "**/*[^#{output_ext_prefix}].js") ]
js_files = filter_excluded_js_files(js_files)
puts "matched #{js_files.size} .js file(s)"
if ENV['OUT_FILE'].blank?
js_files.each do |js_file|
options = build_options(js_file)
compile_js_if_necessary(js_file, options)
end
else
options = build_options.merge! :force => true
compile_js_if_necessary(js_files, options)
end
end
desc "deletes all (compiled) /javascripts/**/*#{OUT_FILE_JS_EXT_PREFIX}.js files"
task :clean_compiled do
js_files = Dir[ File.join(JS_FILES_DIR, "**/*#{output_ext_prefix}.js") ]
puts "removing #{js_files.size} file(s)"
FileUtils.rm js_files
end
desc "downloads (and extracts) the latest closure compiler.jar into #{COMPILER_JAR}"
task :download_jar do
require 'uri'; require 'net/http'; require 'tempfile'
uri = URI.parse(COMPILER_DOWNLOAD_URI)
response = Net::HTTP.start(uri.host, uri.port) do |http|
http.get(uri.path)
end
case response
when Net::HTTPSuccess
file_data, content_type = response.body, response.content_type
raise "no data returned from #{uri}" if file_data.nil? || file_data.size == 0
else
raise "download from #{uri} failed with response: #{response}"
end
filename = uri.path.split('/')[-1]
Tempfile.open(filename) do |tmpfile|
tmpfile << file_data
filename = tmpfile.path
end
if content_type =~ /application\/(x-)?zip/
# compiler-latest.zip with 3 entries :
# - compiler.jar
# - COPYING
# - README
extract_path = File.dirname(COMPILER_JAR)
unless File.exist?(extract_path)
FileUtils.mkdir_p(extract_path)
end
# -u update files, create if necessary :
system "unzip -u #{filename} -d #{extract_path}"
else
raise "unexpected content-type: #{content_type}"
end
end
#========================================================================
def build_options(js_file = nil)
options = {}
options[:force] = false
if force = ENV['FORCE']
options[:force] = (force.to_s == true.to_s)
end
if out_file = ENV['OUT_FILE']
options[:output] = out_file
else
options[:output] = output_filename(js_file)
end
options
end
def filter_excluded_js_files(js_files)
return js_files if EXCLUDED_JS_FILES.blank?
js_files.map do |js_file|
excluded = EXCLUDED_JS_FILES.find do |excluded_pattern|
expanded_pattern = File.join(JS_FILES_DIR, excluded_pattern)
File.fnmatch(expanded_pattern, js_file)
end
excluded ? nil : js_file
end.compact
end
def output_ext_prefix
ENV['OUT_EXT'].blank? ? OUT_FILE_JS_EXT_PREFIX : ENV['OUT_EXT']
end
# /javascript/application.js => /javascript/application.min.js
def output_filename(js_file)
output_file = File.basename(js_file, File.extname(js_file))
output_file = File.join(File.dirname(js_file), output_file)
return output_file + output_ext_prefix + File.extname(js_file)
end
def compile_js_if_necessary(js_file, options)
output_file = options[:output]
File.delete(output_file) if options[:force]
if ! File.exist?(output_file) ||
File.mtime(js_file) > File.mtime(output_file)
compile_js(js_file, options)
else
nil # no need to compile otherwise ...
end
end
def compile_js(files, options)
files = [ files ] unless files.is_a?(Array)
compiler_options = {}
compiler_options['--js'] = files.join(' ')
compiler_options['--js_output_file'] = options[:output]
compiler_options['--compilation_level'] = 'SIMPLE_OPTIMIZATIONS'
puts "compiling #{files.size} javascript file(s) into #{options[:output]}"
verify_compiler_jar_exist
if RUBY_PLATFORM == 'java' # JRuby style :
require 'ant'; require COMPILER_JAR
ant.java :classname => COMPILER_MAIN_CLASS do
compiler_options.to_a.flatten.each { |value| arg :value => value }
end
else
system "java -jar #{COMPILER_JAR} #{compiler_options.to_a.join(' ')}"
end
end
def verify_compiler_jar_exist
return if File.exist?(COMPILER_JAR)
puts "#{COMPILER_JAR} not found !"
raise "run `rake javascript:download_jar` to download the closure compiler.jar"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment