Class: Jammit::Compressor
- Inherits:
- Object
- Defined in:
- lib/jammit/compressor.rb
Overview
Uses the YUI Compressor or Closure Compiler to compress JavaScript. Always uses YUI to compress CSS (Which means that Java must be installed.) Also knows how to create a concatenated JST file. If “embed_images” is turned on, creates “mhtml” and “datauri” versions of all stylesheets, with all enabled images inlined into the css.
Constant Summary
- IMAGE_MIME_TYPES = Mapping from extension to mime-type of all embeddable images.
{ '.png' => 'image/png', '.jpg' => 'image/jpeg', '.jpeg' => 'image/jpeg', '.gif' => 'image/gif', '.tif' => 'image/tiff', '.tiff' => 'image/tiff' }
- IMAGE_DETECTOR =
/url\(['"]?([^\s)]+\.(png|jpg|jpeg|gif|tif|tiff))['"]?\)/
- IMAGE_EMBED =
/[\A\/]embed\//
- IMAGE_REPLACER =
/url\(__EMBED__([^\s)]+)\)/
- MHTML_START = MHTML file constants.
"/*\r\nContent-Type: multipart/related; boundary=\"JAMMIT_MHTML_SEPARATOR\"\r\n\r\n"
- MHTML_SEPARATOR =
"--JAMMIT_MHTML_SEPARATOR\r\n"
- MHTML_END =
"*/\r\n"
- JST_START = JST file constants.
"(function(){window.JST = window.JST || {};"
- JST_END =
"})();"
- DEFAULT_OPTIONS =
{ :yui => {:munge => true}, :closure => {} }
Method Summary
- - (Object) compile_jst(paths) Compiles a single JST file by writing out a javascript that adds template properties to a top-level “window.JST” object.
- - (Object) compress_css(paths, variant = nil, asset_url = nil) Concatenate and compress a list of CSS stylesheets.
- - (Object) compress_js(paths) Concatenate together a list of JavaScript paths, and pass them through the YUI Compressor (with munging enabled).
- - (Compressor) initialize Creating a compressor initializes the internal YUI Compressor from the “yui-compressor” gem, or the internal Closure Compiler from the “closure-compiler” gem.
- - (Object) absolute_path(image_pathname, css_pathname) private Get the site-absolute public path for an image file path that may or may not be relative, given the path of the stylesheet that contains it.
- - (Object) concatenate(paths) private Concatenate together a list of asset files.
- - (Object) concatenate_and_tag_images(paths, variant = nil) private In order to support embedded images from relative paths, we need to expand the paths before contatenating the CSS together and losing the location of the original stylesheet path.
- - (Object) embeddable?(image_path) private An image is valid for embedding if it exists, is less than 32K, and is stored somewhere inside of a folder named “embed”.
- - (Object) encoded_contents(image_path) private Return the Base64-encoded contents of an image on a single line.
- - (Object) mime_type(image_path) private Grab the mime-type of an image, by filename.
- - (Object) relative_path(absolute_path) private CSS images that are referenced by relative paths, and are not being embedded, must be rewritten relative to the newly-merged stylesheet path.
- - (Object) rewrite_image_path(image_path, css_path, embed = false) private Return a rewritten image URL for a new stylesheet — the image should be tagged for embedding if embeddable, and referenced at the correct level if relative.
- - (Object) with_data_uris(css) private Re-write all enabled image URLs in a stylesheet with their corresponding Data-URI Base-64 encoded image contents.
- - (Object) with_mhtml(css, asset_url) private Re-write all enabled image URLs in a stylesheet with the MHTML equivalent.
Constructor Details
- (Compressor) initialize
Creating a compressor initializes the internal YUI Compressor from the “yui-compressor” gem, or the internal Closure Compiler from the “closure-compiler” gem.
42 43 44 45 46 47 48 49 |
# File 'lib/jammit/compressor.rb', line 42 def initialize @css_compressor = YUI::CssCompressor.new flavor = Jammit.javascript_compressor = DEFAULT_OPTIONS[flavor].merge(Jammit.) @js_compressor = flavor == :closure ? Closure::Compiler.new() : YUI::JavaScriptCompressor.new() end |
Method Details
- (Object) compile_jst(paths)
Compiles a single JST file by writing out a javascript that adds template properties to a top-level “window.JST” object. Adds a JST-compilation function to the top of the package, unless you’ve specified your own preferred function, or turned it off. JST templates are named with the basename of their file.
75 76 77 78 79 80 81 82 83 |
# File 'lib/jammit/compressor.rb', line 75 def compile_jst(paths) compiled = paths.map do |path| template_name = File.basename(path, File.extname(path)) contents = File.read(path).gsub(/\n/, '').gsub("'", '\\\\\'') "window.JST.#{template_name} = #{Jammit.template_function}('#{contents}');" end compiler = Jammit.include_jst_script ? File.read(DEFAULT_JST_SCRIPT) : ''; [JST_START, compiler, compiled, JST_END].flatten.join("\n") end |
- (Object) compress_css(paths, variant = nil, asset_url = nil)
Concatenate and compress a list of CSS stylesheets. When compressing a :datauri or :mhtml variant, post-processes the result to embed referenced images.
60 61 62 63 64 65 66 67 68 |
# File 'lib/jammit/compressor.rb', line 60 def compress_css(paths, variant=nil, asset_url=nil) compressed_css = @css_compressor.compress(concatenate_and_tag_images(paths, variant)) case variant when nil then return compressed_css when :datauri then return with_data_uris(compressed_css) when :mhtml then return with_mhtml(compressed_css, asset_url) else raise PackageNotFound, "\"#{variant}\" is not a valid stylesheet variant" end end |
- (Object) compress_js(paths)
Concatenate together a list of JavaScript paths, and pass them through the YUI Compressor (with munging enabled).
53 54 55 |
# File 'lib/jammit/compressor.rb', line 53 def compress_js(paths) @js_compressor.compress(concatenate(paths)) end |
- (Object) absolute_path(image_pathname, css_pathname) (private)
Get the site-absolute public path for an image file path that may or may not be relative, given the path of the stylesheet that contains it.
138 139 140 141 142 |
# File 'lib/jammit/compressor.rb', line 138 def absolute_path(image_pathname, css_pathname) (image_pathname.absolute? ? Pathname.new(File.join(PUBLIC_ROOT, image_pathname)) : css_pathname.dirname + image_pathname).cleanpath end |
- (Object) concatenate(paths) (private)
Concatenate together a list of asset files.
169 170 171 |
# File 'lib/jammit/compressor.rb', line 169 def concatenate(paths) [paths].flatten.map {|p| File.read(p) }.join("\n") end |
- (Object) concatenate_and_tag_images(paths, variant = nil) (private)
In order to support embedded images from relative paths, we need to expand the paths before contatenating the CSS together and losing the location of the original stylesheet path. Validate the images while we’re at it.
92 93 94 95 96 97 98 99 100 101 |
# File 'lib/jammit/compressor.rb', line 92 def concatenate_and_tag_images(paths, variant=nil) stylesheets = [paths].flatten.map do |css_path| File.read(css_path).gsub(IMAGE_DETECTOR) do |url| ipath, cpath = Pathname.new($1), Pathname.new(File.(css_path)) is_url = URI.parse($1).absolute? is_url ? url : "url(#{rewrite_image_path(ipath, cpath, !!variant)})" end end stylesheets.join("\n") end |
- (Object) embeddable?(image_path) (private)
An image is valid for embedding if it exists, is less than 32K, and is stored somewhere inside of a folder named “embed”. IE does not support Data-URIs larger than 32K, and you probably shouldn’t be embedding images that large in any case.
154 155 156 |
# File 'lib/jammit/compressor.rb', line 154 def (image_path) image_path.to_s.match(IMAGE_EMBED) && image_path.exist? && image_path.size < 32.kilobytes end |
- (Object) encoded_contents(image_path) (private)
Return the Base64-encoded contents of an image on a single line.
159 160 161 |
# File 'lib/jammit/compressor.rb', line 159 def encoded_contents(image_path) Base64.encode64(File.read(image_path)).gsub(/\n/, '') end |
- (Object) mime_type(image_path) (private)
Grab the mime-type of an image, by filename.
164 165 166 |
# File 'lib/jammit/compressor.rb', line 164 def mime_type(image_path) IMAGE_MIME_TYPES[File.extname(image_path)] end |
- (Object) relative_path(absolute_path) (private)
CSS images that are referenced by relative paths, and are not being embedded, must be rewritten relative to the newly-merged stylesheet path.
146 147 148 |
# File 'lib/jammit/compressor.rb', line 146 def relative_path(absolute_path) File.join('../', absolute_path.sub(PUBLIC_ROOT, '')) end |
- (Object) rewrite_image_path(image_path, css_path, embed = false) (private)
Return a rewritten image URL for a new stylesheet — the image should be tagged for embedding if embeddable, and referenced at the correct level if relative.
130 131 132 133 134 |
# File 'lib/jammit/compressor.rb', line 130 def rewrite_image_path(image_path, css_path, =false) public_path = absolute_path(image_path, css_path) return "__EMBED__#{public_path}" if && (public_path) image_path.absolute? ? image_path.to_s : relative_path(public_path) end |
- (Object) with_data_uris(css) (private)
Re-write all enabled image URLs in a stylesheet with their corresponding Data-URI Base-64 encoded image contents.
105 106 107 108 109 |
# File 'lib/jammit/compressor.rb', line 105 def with_data_uris(css) css.gsub(IMAGE_REPLACER) do |url| "url(\"data:#{mime_type($1)};base64,#{encoded_contents($1)}\")" end end |
- (Object) with_mhtml(css, asset_url) (private)
Re-write all enabled image URLs in a stylesheet with the MHTML equivalent. The newlines (“\r\n”) in the following method are critical. Without them your MHTML will look identical, but won’t work.
114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/jammit/compressor.rb', line 114 def with_mhtml(css, asset_url) paths, index = {}, 0 css = css.gsub(IMAGE_REPLACER) do |url| i = paths[$1] ||= "#{index += 1}-#{File.basename($1)}" "url(mhtml:#{asset_url}!#{i})" end mhtml = paths.map do |path, identifier| mime, contents = mime_type(path), encoded_contents(path) [MHTML_SEPARATOR, "Content-Location: #{identifier}\r\n", "Content-Type: #{mime}\r\n", "Content-Transfer-Encoding: base64\r\n\r\n", contents, "\r\n"] end [MHTML_START, mhtml, MHTML_END, css].flatten.join('') end |