jammit 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -5,12 +5,14 @@ task :test do
5
5
  $LOAD_PATH.unshift(File.expand_path('test'))
6
6
  require 'redgreen' if Gem.available?('redgreen')
7
7
  require 'test/unit'
8
- Dir['test/**/test_*.rb'].each {|test| require test }
8
+ Dir.chdir('test')
9
+ Dir['./**/test_*.rb'].each {|test| require test }
9
10
  end
10
11
 
11
12
  desc 'Generate YARD Documentation'
12
13
  task :doc do
13
14
  sh "mv README TEMPME"
15
+ sh "rm -rf doc"
14
16
  sh "yardoc"
15
17
  sh "mv TEMPME README"
16
18
  end
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'jammit'
3
- s.version = '0.1.0' # Keep version in sync with jammit.rb
4
- s.date = '2009-11-06'
3
+ s.version = '0.1.1' # Keep version in sync with jammit.rb
4
+ s.date = '2009-11-16'
5
5
 
6
6
  s.homepage = "http://documentcloud.github.com/jammit/"
7
7
  s.summary = "Industrial Strength Asset Packaging for Rails"
@@ -4,7 +4,7 @@ $LOAD_PATH.push File.expand_path(File.dirname(__FILE__))
4
4
  # to all of the configuration options.
5
5
  module Jammit
6
6
 
7
- VERSION = "0.1.0"
7
+ VERSION = "0.1.1"
8
8
 
9
9
  ROOT = File.expand_path(File.dirname(__FILE__) + '/..')
10
10
 
@@ -96,6 +96,7 @@ end
96
96
  # Standard Library Dependencies:
97
97
  require 'zlib'
98
98
  require 'base64'
99
+ require 'pathname'
99
100
  require 'fileutils'
100
101
 
101
102
  # Gem Dependencies:
@@ -17,7 +17,8 @@ module Jammit
17
17
  }
18
18
 
19
19
  # Detect all image URLs that are inside of an "embed" folder.
20
- IMAGE_DETECTOR = /url\(['"]?(\/[^\s)]*embed\/[^\s)]+\.(png|jpg|jpeg|gif|tif|tiff))['"]?\)/
20
+ IMAGE_DETECTOR = /url\(['"]?([^\s)]*embed\/[^\s)]+\.(png|jpg|jpeg|gif|tif|tiff))['"]?\)/
21
+ IMAGE_REPLACER = /url\(__EMBED__([^\s)]+)\)/
21
22
 
22
23
  # MHTML file constants.
23
24
  MHTML_START = "/*\r\nContent-Type: multipart/related; boundary=\"JAMMIT_MHTML_SEPARATOR\"\r\n\r\n"
@@ -45,12 +46,11 @@ module Jammit
45
46
  # :datauri or :mhtml variant, post-processes the result to embed
46
47
  # referenced images.
47
48
  def compress_css(paths, variant=nil, asset_url=nil)
48
- compressed_css = @yui_css.compress(concatenate(paths))
49
- case variant
50
- when nil then compressed_css
51
- when :datauri then with_data_uris(compressed_css)
52
- when :mhtml then with_mhtml(compressed_css, asset_url)
53
- end
49
+ return @yui_css.compress(concatenate(paths)) if variant.nil?
50
+ compressed_css = @yui_css.compress(concatenate_and_tag_images(paths))
51
+ return with_data_uris(compressed_css) if variant == :datauri
52
+ return with_mhtml(compressed_css, asset_url) if variant == :mhtml
53
+ raise PackageNotFound, "\"#{variant}\" is not a valid stylesheet variant"
54
54
  end
55
55
 
56
56
  # Compiles a single JST file by writing out a javascript that adds
@@ -71,12 +71,25 @@ module Jammit
71
71
 
72
72
  private
73
73
 
74
+ # In order to support embedded images from relative paths, we need to
75
+ # expand the paths before contatenating the CSS together and losing the
76
+ # location of the original stylesheet path. Validate the images while we're
77
+ # at it.
78
+ def concatenate_and_tag_images(paths)
79
+ stylesheets = [paths].flatten.map do |css_path|
80
+ File.read(css_path).gsub(IMAGE_DETECTOR) do |url|
81
+ image_path = public_path($1, css_path)
82
+ valid_image(image_path) ? "url(__EMBED__#{image_path})" : url
83
+ end
84
+ end
85
+ stylesheets.join("\n")
86
+ end
87
+
74
88
  # Re-write all enabled image URLs in a stylesheet with their corresponding
75
89
  # Data-URI Base-64 encoded image contents.
76
90
  def with_data_uris(css)
77
- css.gsub(IMAGE_DETECTOR) do |url|
78
- image_path = "public#{$1}"
79
- valid_image(image_path) ? "url(\"data:#{mime_type(image_path)};base64,#{encoded_contents(image_path)}\")" : url
91
+ css.gsub(IMAGE_REPLACER) do |url|
92
+ "url(\"data:#{mime_type($1)};base64,#{encoded_contents($1)}\")"
80
93
  end
81
94
  end
82
95
 
@@ -84,25 +97,30 @@ module Jammit
84
97
  # The newlines ("\r\n") in the following method are critical. Without them
85
98
  # your MHTML will look identical, but won't work.
86
99
  def with_mhtml(css, asset_url)
87
- paths = {}
88
- css = css.gsub(IMAGE_DETECTOR) do |url|
89
- image_path = "public#{$1}"
90
- valid = valid_image(image_path)
91
- paths[$1] ||= image_path if valid
92
- valid ? "url(mhtml:#{asset_url}!#{$1})" : url
100
+ paths, index = {}, 0
101
+ css = css.gsub(IMAGE_REPLACER) do |url|
102
+ i = paths[$1] ||= "#{index += 1}-#{File.basename($1)}"
103
+ "url(mhtml:#{asset_url}!#{i})"
93
104
  end
94
- mhtml = paths.map do |identifier, path|
105
+ mhtml = paths.map do |path, identifier|
95
106
  mime, contents = mime_type(path), encoded_contents(path)
96
107
  [MHTML_SEPARATOR, "Content-Location: #{identifier}\r\n", "Content-Type: #{mime}\r\n", "Content-Transfer-Encoding: base64\r\n\r\n", contents, "\r\n"]
97
108
  end
98
109
  [MHTML_START, mhtml, MHTML_END, css].flatten.join('')
99
110
  end
100
111
 
112
+ # Get the site-absolute public path for an image file path that may or may
113
+ # not be relative, given the path of the stylesheet that contains it.
114
+ def public_path(image_path, css_path)
115
+ image_path, css_path = Pathname.new(image_path), Pathname.new(css_path)
116
+ (image_path.absolute? ? Pathname.new("public#{image_path}") : css_path.dirname + image_path).cleanpath
117
+ end
118
+
101
119
  # An image is valid if it exists, and is less than 32K.
102
120
  # IE does not support Data-URIs larger than 32K, and you probably shouldn't
103
121
  # be embedding images that large in any case.
104
122
  def valid_image(image_path)
105
- File.exists?(image_path) && File.size(image_path) < 32.kilobytes
123
+ image_path.exist? && image_path.size < 32.kilobytes
106
124
  end
107
125
 
108
126
  # Return the Base64-encoded contents of an image on a single line.
@@ -1 +1 @@
1
- var template = function(str){var fn = new Function('obj', 'var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push(\''+str.replace(/[\r\t\n]/g, " ").split("<%").join("\t").replace(/((^|%>)[^\t]*)'/g, "$1\r").replace(/\t=(.*?)%>/g, "',$1,'").split("\t").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');"); return fn;};
1
+ var template = function(str){var fn = new Function('obj', 'var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push(\''+str.replace(/[\r\t\n]/g, " ").split("<%").join("\t").replace(/((^|%>)[^\t]*)'/g, "$1\r").replace(/\t=(.*?)%>/g, "',$1,'").split("\t").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');"); return fn;};
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jammit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Ashkenas
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-06 00:00:00 -05:00
12
+ date: 2009-11-16 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency