The Jammit::Packager resolves the configuration file into lists of real assets that get merged into individual asset packages. Given the compiled contents of an asset package, the Packager knows how to cache that package with the correct timestamps.
Creating a new Packager will rebuild the list of assets from the Jammit.configuration. When assets.yml is being changed on the fly, create a new Packager.
# File lib/jammit/packager.rb, line 16 def initialize @compressor = Compressor.new @force = false @package_names = nil @config = { :css => (Jammit.configuration[:stylesheets] || {}), :js => (Jammit.configuration[:javascripts] || {}) } @packages = { :css => create_packages(@config[:css]), :js => create_packages(@config[:js]) } end
Caches a single prebuilt asset package and gzips it at the highest compression level. Ensures that the modification time of both both variants is identical, for web server caching modules, as well as MHTML.
# File lib/jammit/packager.rb, line 55 def cache(package, extension, contents, output_dir, suffix=nil, mtime=nil) FileUtils.mkdir_p(output_dir) unless File.exists?(output_dir) raise OutputNotWritable, "Jammit doesn't have permission to write to \"#{output_dir}\"" unless File.writable?(output_dir) mtime ||= latest_mtime package_for(package, extension.to_sym)[:paths] files = [] files << file_name = File.join(output_dir, Jammit.filename(package, extension, suffix)) File.open(file_name, 'wb+') {|f| f.write(contents) } if Jammit.gzip_assets files << zip_name = "#{file_name}.gz" Zlib::GzipWriter.open(zip_name, Zlib::BEST_COMPRESSION) {|f| f.write(contents) } end File.utime(mtime, mtime, *files) end
Get the list of individual assets for a package.
# File lib/jammit/packager.rb, line 70 def individual_urls(package, extension) package_for(package, extension)[:urls] end
Return the compressed contents of a javascript package.
# File lib/jammit/packager.rb, line 80 def pack_javascripts(package) @compressor.compress_js(package_for(package, :js)[:paths]) end
Return the compressed contents of a stylesheet package.
# File lib/jammit/packager.rb, line 75 def pack_stylesheets(package, variant=nil, asset_url=nil) @compressor.compress_css(package_for(package, :css)[:paths], variant, asset_url) end
Return the compiled contents of a JST package.
# File lib/jammit/packager.rb, line 85 def pack_templates(package) @compressor.compile_jst(package_for(package, :js)[:paths]) end
Ask the packager to precache all defined assets, along with their gzip'd versions. In order to prebuild the MHTML stylesheets, we need to know the base_url, because IE only supports MHTML with absolute references. Unless forced, will only rebuild assets whose source files have been changed since their last package build.
# File lib/jammit/packager.rb, line 35 def precache_all(output_dir=nil, base_url=nil) output_dir ||= File.join(Jammit.public_root, Jammit.package_path) cacheable(:js, output_dir).each {|p| cache(p, 'js', pack_javascripts(p), output_dir) } cacheable(:css, output_dir).each do |p| cache(p, 'css', pack_stylesheets(p), output_dir) if Jammit.embed_assets cache(p, 'css', pack_stylesheets(p, :datauri), output_dir, :datauri) if Jammit.mhtml_enabled raise MissingConfiguration, "A --base-url option is required in order to generate MHTML." unless base_url mtime = latest_mtime package_for(p, :css)[:paths] asset_url = "#{base_url}#{Jammit.asset_url(p, :css, :mhtml, mtime)}" cache(p, 'css', pack_stylesheets(p, :mhtml, asset_url), output_dir, :mhtml, mtime) end end end end
Return a list of all of the packages that should be cached. If "force" is true, this is all of them -- otherwise only the packages that are missing or whose source files have changed since the last package build.
# File lib/jammit/packager.rb, line 122 def cacheable(extension, output_dir) names = @packages[extension].keys names = names.select {|n| @package_names.include? n } if @package_names config_mtime = File.mtime(Jammit.config_path) return names if @force return names.select do |name| pack = package_for(name, extension) cached = [Jammit.filename(name, extension)] if extension == :css cached.push Jammit.filename(name, extension, :datauri) if Jammit.embed_assets cached.push Jammit.filename(name, extension, :mhtml) if Jammit.mhtml_enabled end cached.map! {|file| File.join(output_dir, file) } if cached.any? {|file| !File.exists?(file) } true else since = cached.map {|file| File.mtime(file) }.min config_mtime > since || pack[:paths].any? {|src| File.mtime(src) > since } end end end
Compiles the list of assets that goes into each package. Runs an ordered list of Dir.globs, taking the merged unique result. If there are JST files in this package we need to add an extra path for when package_assets is off (e.g. in a dev environment). This package (e.g. /assets/package-name.jst) will never exist as an actual file but will be dynamically generated by Jammit on every request.
# File lib/jammit/packager.rb, line 151 def create_packages(config) packages = {} return packages if !config config.each do |name, globs| globs ||= [] packages[name] = {} paths = globs.flatten.uniq.map {|glob| glob_files(glob) }.flatten.uniq packages[name][:paths] = paths if !paths.grep(Jammit.template_extension_matcher).empty? packages[name][:urls] = paths.grep(JS_EXTENSION).map {|path| path.sub(path_to_url, '') } packages[name][:urls] += [Jammit.asset_url(name, Jammit.template_extension)] else packages[name][:urls] = paths.map {|path| path.sub(path_to_url, '') } end end packages end
Absolute globs are absolute -- relative globs are relative to ASSET_ROOT. Print a warning if no files were found that match the glob.
# File lib/jammit/packager.rb, line 101 def glob_files(glob) absolute = Pathname.new(glob).absolute? paths = Dir[absolute ? glob : File.join(ASSET_ROOT, glob)].sort Jammit.warn("No assets match '#{glob}'") if paths.empty? paths end
Get the latest mtime of a list of files (plus the config path).
# File lib/jammit/packager.rb, line 114 def latest_mtime(paths) paths += [Jammit.config_path] paths.map {|p| File.mtime(p) }.max || Time.now end
Raise a PackageNotFound exception for missing packages...
# File lib/jammit/packager.rb, line 170 def not_found(package, extension) raise PackageNotFound, "assets.yml does not contain a \"#{package}\" #{extension.to_s.upcase} package" end
Look up a package asset list by name, raising an exception if the package has gone missing.
# File lib/jammit/packager.rb, line 94 def package_for(package, extension) pack = @packages[extension] && @packages[extension][package] pack || not_found(package, extension) end
Generated with the Darkfish Rdoc Generator 2.