Skip to content

Instantly share code, notes, and snippets.

@kurbmedia
Created April 18, 2011 22:20
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 kurbmedia/926358 to your computer and use it in GitHub Desktop.
Save kurbmedia/926358 to your computer and use it in GitHub Desktop.
JS Packaging, modeled after jammit but much lighter, and uses remote closure compiler.
module Packager
class Compressor
attr_accessor :templates, :javascripts
def initialize(config)
@templates = config['templates'] || {}
@javascripts = config['javascripts'] || {}
end
def compile_javascripts
compiled = @javascripts.keys.inject({}) do |hash, package|
hash.merge!(package => @javascripts[package].map{ |file| read_file("#{Rails.root}/app/javascripts/#{package}/#{file}") }.flatten)
hash
end
end
def compile_jst
namespace = "window.JST"
paths = Dir["#{Rails.root}/app/views/**/*.jst"]
compiled = paths.map do |path|
contents = read_file(path)
contents = contents.gsub(/\r?\n/, "").gsub("'", '\\\\\'').gsub("\t","")
name = template_name(path)
"#{namespace}.#{name} = _.template('#{contents}');"
end
setup_namespace = "#{namespace} = #{namespace} || {};"
package_namespaces = [@templates.keys].flatten.compact.map{ |ns| "#{namespace}.#{ns} = #{namespace}.#{ns} || {};" }
setup_namespace = [setup_namespace, package_namespaces]
create_closure([setup_namespace, compiled].flatten.join("\n"))
end
def compress!(data)
response = Net::HTTP.post_form(URI.parse('http://closure-compiler.appspot.com/compile'), {
'js_code' => data,
'compilation_level' => "SIMPLE_OPTIMIZATIONS",
'output_format' => 'text',
'output_info' => 'compiled_code'
})
response.body
end
def create_closure(content)
["(function(){", content, "})();"].flatten.join("\n")
end
def read_file(path)
File.open(path, 'rb') {|f| f.read }
end
def template_name(path)
path.gsub!("#{Rails.root}/app/views/", "")
@templates.each_pair do |namespace, files|
files = [files].flatten.compact
next if files.empty?
files.each do |fname|
next unless fname.to_s == path or fname.is_a?(Hash)
return "#{namespace}['#{File.basename(fname, ".jst")}']" unless fname.is_a?(Hash)
return "#{namespace}['#{fname.keys.first}']"
end
end
return "['#{File.basename(path, ".jst")}]'"
end
end
end
module PackageHelper
def include_javascripts(*args)
options = args.extract_options!
args.map!{ |file| "#{file}.min" } unless Rails.env.eql?('development')
javascript_include_tag(*args, options)
end
end
templates:
widgets:
- widgets/show.jst
# Use app/javascripts/packagename/ as the base dir.
javascripts:
core:
- jquery.js
- rails.js
- application.js
module Packager
class Processor
def initialize(app)
@app = app
end
def call(env)
return @app.call(env) unless env['PATH_INFO'].match(/javascripts/)
package = File.basename(env['PATH_INFO'], '.js')
contents = []
manifest = YAML::load(File.open("#{Rails.root}/config/packager.yml"))['javascripts']
jsfiles = manifest[package].map{ |filename| "#{Rails.root}/app/javascripts/#{package}/#{filename}" } || Dir["#{Rails.root}/app/javascripts/#{package}/*.js"]
jsfiles.each do |file|
lines = File.open(file,'r').map{ |line| line }
contents << lines
end
[200, {"Content-Type" => "application/javascript"}, [contents.compact.flatten.join("\n")]]
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment