ghazel-jammit 0.4.4.3 → 0.6.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/jammit.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'ghazel-jammit'
3
- s.version = '0.4.4.3' # Keep version in sync with jammit.rb
4
- s.date = '2010-2-6'
3
+ s.version = '0.6.0.1' # Keep version in sync with jammit.rb
4
+ s.date = '2010-11-8'
5
5
 
6
6
  s.homepage = "http://documentcloud.github.com/jammit/"
7
7
  s.summary = "Industrial Strength Asset Packaging for Rails"
@@ -27,9 +27,8 @@ Gem::Specification.new do |s|
27
27
  '--main' << 'README' <<
28
28
  '--all'
29
29
 
30
- s.add_dependency 'rails', ['>= 2.0.0']
31
- s.add_dependency 'yui-compressor', ['>= 0.9.1']
32
- s.add_dependency 'ghazel-closure-compiler', ['>= 0.2.0.2']
30
+ s.add_dependency 'ghazel-yui-compressor', ['>= 0.9.4.2']
31
+ s.add_dependency 'closure-compiler', ['>= 0.1.0']
33
32
 
34
- s.files = Dir['lib/**/*', 'bin/*', 'jammit.gemspec', 'LICENSE', 'README']
35
- end
33
+ s.files = Dir['lib/**/*', 'bin/*', 'rails/*', 'jammit.gemspec', 'LICENSE', 'README']
34
+ end
@@ -26,9 +26,7 @@ Options:
26
26
  def initialize
27
27
  parse_options
28
28
  ensure_configuration_file
29
- Jammit.load_configuration(@options[:config_path])
30
- Jammit.packager.force = @options[:force]
31
- Jammit.packager.precache_all(@options[:output_folder], @options[:base_url])
29
+ Jammit.package!(@options)
32
30
  end
33
31
 
34
32
 
@@ -16,25 +16,26 @@ module Jammit
16
16
  '.tif' => 'image/tiff',
17
17
  '.tiff' => 'image/tiff',
18
18
  '.ttf' => 'font/truetype',
19
- '.otf' => 'font/opentype'
19
+ '.otf' => 'font/opentype',
20
+ '.woff' => 'font/woff'
20
21
  }
21
22
 
22
23
  # Font extensions for which we allow embedding:
23
24
  EMBED_EXTS = EMBED_MIME_TYPES.keys
24
- EMBED_FONTS = ['.ttf', '.otf']
25
+ EMBED_FONTS = ['.ttf', '.otf', '.woff']
25
26
 
26
- # 32k maximum size for embeddable images (an IE8 limitation).
27
- MAX_IMAGE_SIZE = 32768
27
+ # (32k - padding) maximum length for data-uri assets (an IE8 limitation).
28
+ MAX_IMAGE_SIZE = 32700
28
29
 
29
30
  # CSS asset-embedding regexes for URL rewriting.
30
31
  EMBED_DETECTOR = /url\(['"]?([^\s)]+\.[a-z]+)(\?\d+)?['"]?\)/
31
32
  EMBEDDABLE = /[\A\/]embed\//
32
- EMBED_REPLACER = /url\(__EMBED__([^\s)]+)(\?\d+)?\)/
33
+ EMBED_REPLACER = /url\(__EMBED__(.+?)(\?\d+)?\)/
33
34
 
34
35
  # MHTML file constants.
35
- MHTML_START = "/*\r\nContent-Type: multipart/related; boundary=\"JAMMIT_MHTML_SEPARATOR\"\r\n\r\n"
36
- MHTML_SEPARATOR = "--JAMMIT_MHTML_SEPARATOR\r\n"
37
- MHTML_END = "*/\r\n"
36
+ MHTML_START = "/*\r\nContent-Type: multipart/related; boundary=\"MHTML_MARK\"\r\n\r\n"
37
+ MHTML_SEPARATOR = "--MHTML_MARK\r\n"
38
+ MHTML_END = "\r\n--MHTML_MARK--\r\n*/\r\n"
38
39
 
39
40
  # JST file constants.
40
41
  JST_START = "(function(){"
@@ -61,9 +62,13 @@ module Jammit
61
62
  end
62
63
 
63
64
  # Concatenate together a list of JavaScript paths, and pass them through the
64
- # YUI Compressor (with munging enabled).
65
+ # YUI Compressor (with munging enabled). JST can optionally be included.
65
66
  def compress_js(paths)
66
- js = concatenate(paths)
67
+ if (jst_paths = paths.grep(Jammit.template_extension_matcher)).empty?
68
+ js = concatenate(paths)
69
+ else
70
+ js = concatenate(paths - jst_paths) + compile_jst(jst_paths)
71
+ end
67
72
  Jammit.compress_assets ? @js_compressor.compress(js) : js
68
73
  end
69
74
 
@@ -71,6 +76,7 @@ module Jammit
71
76
  # :datauri or :mhtml variant, post-processes the result to embed
72
77
  # referenced assets.
73
78
  def compress_css(paths, variant=nil, asset_url=nil)
79
+ @asset_contents = {}
74
80
  css = concatenate_and_tag_assets(paths, variant)
75
81
  css = @css_compressor.compress(css) if Jammit.compress_assets
76
82
  case variant
@@ -87,13 +93,16 @@ module Jammit
87
93
  # specified your own preferred function, or turned it off.
88
94
  # JST templates are named with the basename of their file.
89
95
  def compile_jst(paths)
90
- namespace = Jammit.template_namespace
91
- compiled = paths.map do |path|
92
- template_name = File.basename(path, File.extname(path))
93
- contents = File.read(path).gsub(/\n/, '').gsub("'", '\\\\\'')
94
- "#{namespace}.#{template_name} = #{Jammit.template_function}('#{contents}');"
96
+ namespace = Jammit.template_namespace
97
+ paths = paths.grep(Jammit.template_extension_matcher).sort
98
+ base_path = find_base_path(paths)
99
+ compiled = paths.map do |path|
100
+ contents = read_binary_file(path)
101
+ contents = contents.gsub(/\n/, '').gsub("'", '\\\\\'')
102
+ name = template_name(path, base_path)
103
+ "#{namespace}['#{name}'] = #{Jammit.template_function}('#{contents}');"
95
104
  end
96
- compiler = Jammit.include_jst_script ? File.read(DEFAULT_JST_SCRIPT) : '';
105
+ compiler = Jammit.include_jst_script ? read_binary_file(DEFAULT_JST_SCRIPT) : '';
97
106
  setup_namespace = "#{namespace} = #{namespace} || {};"
98
107
  [JST_START, setup_namespace, compiler, compiled, JST_END].flatten.join("\n")
99
108
  end
@@ -101,13 +110,35 @@ module Jammit
101
110
 
102
111
  private
103
112
 
113
+ # Given a set of paths, find a common prefix path.
114
+ def find_base_path(paths)
115
+ return nil if paths.length <= 1
116
+ paths.sort!
117
+ first = paths.first.split('/')
118
+ last = paths.last.split('/')
119
+ i = 0
120
+ while first[i] == last[i] && i <= first.length
121
+ i += 1
122
+ end
123
+ res = first.slice(0, i).join('/')
124
+ res.empty? ? nil : res
125
+ end
126
+
127
+ # Determine the name of a JS template. If there's a common base path, use
128
+ # the namespaced prefix. Otherwise, simply use the filename.
129
+ def template_name(path, base_path)
130
+ return File.basename(path, ".#{Jammit.template_extension}") unless base_path
131
+ path.gsub(/\A#{Regexp.escape(base_path)}\/(.*)\.#{Jammit.template_extension}\Z/, '\1')
132
+ end
133
+
104
134
  # In order to support embedded assets from relative paths, we need to
105
135
  # expand the paths before contatenating the CSS together and losing the
106
136
  # location of the original stylesheet path. Validate the assets while we're
107
137
  # at it.
108
138
  def concatenate_and_tag_assets(paths, variant=nil)
109
139
  stylesheets = [paths].flatten.map do |css_path|
110
- File.read(css_path).gsub(EMBED_DETECTOR) do |url|
140
+ contents = read_binary_file(css_path)
141
+ contents.gsub(EMBED_DETECTOR) do |url|
111
142
  ipath, cpath = Pathname.new($1), Pathname.new(File.expand_path(css_path))
112
143
  is_url = URI.parse($1).absolute?
113
144
  is_url ? url : "url(#{construct_asset_path(ipath, cpath, variant)})"
@@ -168,7 +199,7 @@ module Jammit
168
199
  # append the RAILS_ASSET_ID cache-buster to URLs, if it's defined.
169
200
  def rewrite_asset_path(path, file_path)
170
201
  asset_id = rails_asset_id(file_path)
171
- asset_id.blank? ? path : "#{path}?#{asset_id}"
202
+ (!asset_id || asset_id == '') ? path : "#{path}?#{asset_id}"
172
203
  end
173
204
 
174
205
  # Similar to the AssetTagHelper's method of the same name, this will
@@ -180,23 +211,25 @@ module Jammit
180
211
  end
181
212
 
182
213
  # An asset is valid for embedding if it exists, is less than 32K, and is
183
- # stored somewhere inside of a folder named "embed".
184
- # IE does not support Data-URIs larger than 32K, and you probably shouldn't
185
- # be embedding assets that large in any case.
214
+ # stored somewhere inside of a folder named "embed". IE does not support
215
+ # Data-URIs larger than 32K, and you probably shouldn't be embedding assets
216
+ # that large in any case. Because we need to check the base64 length here,
217
+ # save it so that we don't have to compute it again later.
186
218
  def embeddable?(asset_path, variant)
187
219
  font = EMBED_FONTS.include?(asset_path.extname)
188
220
  return false unless variant
189
221
  return false unless asset_path.to_s.match(EMBEDDABLE) && asset_path.exist?
190
222
  return false unless EMBED_EXTS.include?(asset_path.extname)
191
- return false unless font || asset_path.size < MAX_IMAGE_SIZE
223
+ return false unless font || encoded_contents(asset_path).length < MAX_IMAGE_SIZE
192
224
  return false if font && variant == :mhtml
193
- true
225
+ return true
194
226
  end
195
227
 
196
228
  # Return the Base64-encoded contents of an asset on a single line.
197
229
  def encoded_contents(asset_path)
198
- data = File.open(asset_path, 'rb'){|f| f.read }
199
- Base64.encode64(data).gsub(/\n/, '')
230
+ return @asset_contents[asset_path] if @asset_contents[asset_path]
231
+ data = read_binary_file(asset_path)
232
+ @asset_contents[asset_path] = Base64.encode64(data).gsub(/\n/, '')
200
233
  end
201
234
 
202
235
  # Grab the mime-type of an asset, by filename.
@@ -206,9 +239,13 @@ module Jammit
206
239
 
207
240
  # Concatenate together a list of asset files.
208
241
  def concatenate(paths)
209
- [paths].flatten.map {|p| File.read(p) }.join("\n")
242
+ [paths].flatten.map {|p| read_binary_file(p) }.join("\n")
210
243
  end
211
244
 
245
+ # `File.read`, but in "binary" mode.
246
+ def read_binary_file(path)
247
+ File.open(path, 'rb') {|f| f.read }
248
+ end
212
249
  end
213
250
 
214
251
  end
@@ -5,7 +5,7 @@ module Jammit
5
5
  # missing or uncached asset packages.
6
6
  class Controller < ActionController::Base
7
7
 
8
- VALID_FORMATS = [:css, :js, :jst]
8
+ VALID_FORMATS = [:css, :js]
9
9
 
10
10
  SUFFIX_STRIPPER = /-(datauri|mhtml)\Z/
11
11
 
@@ -15,12 +15,16 @@ module Jammit
15
15
  # yet been cached. The package will be built, cached, and gzipped.
16
16
  def package
17
17
  parse_request
18
+ template_ext = Jammit.template_extension.to_sym
18
19
  case @extension
19
- when :js then render :js => (@contents = Jammit.packager.pack_javascripts(@package))
20
- when :css then render :text => generate_stylesheets, :content_type => 'text/css'
21
- when :jst then render :js => (@contents = Jammit.packager.pack_templates(@package))
20
+ when :js
21
+ render :js => (@contents = Jammit.packager.pack_javascripts(@package))
22
+ when template_ext
23
+ render :js => (@contents = Jammit.packager.pack_templates(@package))
24
+ when :css
25
+ render :text => generate_stylesheets, :content_type => 'text/css'
22
26
  end
23
- cache_package if perform_caching
27
+ cache_package if perform_caching && (@extension != template_ext)
24
28
  rescue Jammit::PackageNotFound
25
29
  package_not_found
26
30
  end
@@ -50,19 +54,19 @@ module Jammit
50
54
  def generate_stylesheets
51
55
  return @contents = Jammit.packager.pack_stylesheets(@package, @variant) unless @variant == :mhtml
52
56
  @mtime = Time.now
53
- request_url = prefix_url(request.request_uri)
57
+ request_url = prefix_url(request.fullpath)
54
58
  cached_url = prefix_url(Jammit.asset_url(@package, @extension, @variant, @mtime))
55
59
  css = Jammit.packager.pack_stylesheets(@package, @variant, request_url)
56
60
  @contents = css.gsub(request_url, cached_url) if perform_caching
57
61
  css
58
62
  end
59
63
 
60
- # Extracts the package name, extension (:css, :js, :jst), and variant
61
- # (:datauri, :mhtml) from the incoming URL.
64
+ # Extracts the package name, extension (:css, :js), and variant (:datauri,
65
+ # :mhtml) from the incoming URL.
62
66
  def parse_request
63
67
  pack = params[:package]
64
68
  @extension = params[:extension].to_sym
65
- raise PackageNotFound unless VALID_FORMATS.include?(@extension)
69
+ raise PackageNotFound unless (VALID_FORMATS + [Jammit.template_extension.to_sym]).include?(@extension)
66
70
  if Jammit.embed_assets
67
71
  suffix_match = pack.match(SUFFIX_STRIPPER)
68
72
  @variant = Jammit.embed_assets && suffix_match && suffix_match[1].to_sym
@@ -84,7 +88,7 @@ end
84
88
  # Make the Jammit::Controller available to Rails as a top-level controller.
85
89
  ::JammitController = Jammit::Controller
86
90
 
87
- if Rails.env.development?
91
+ if defined?(Rails) && Rails.env.development?
88
92
  ActionController::Base.class_eval do
89
93
  append_before_filter { Jammit.reload! }
90
94
  end
@@ -2,20 +2,17 @@
2
2
  require 'uri'
3
3
  require 'erb'
4
4
  require 'zlib'
5
+ require 'yaml'
5
6
  require 'base64'
6
7
  require 'pathname'
7
8
  require 'fileutils'
8
9
 
9
10
  # Gem Dependencies:
10
- require 'rubygems'
11
- gem 'rails', '~> 2.0'
12
11
  require 'yui/compressor'
13
12
  require 'closure-compiler'
14
- require 'active_support'
15
- require 'active_support/core_ext/hash'
16
13
 
17
14
  # Load initial configuration before the rest of Jammit.
18
- Jammit.load_configuration(Jammit::DEFAULT_CONFIG_PATH) if defined?(Rails)
15
+ Jammit.load_configuration(Jammit::DEFAULT_CONFIG_PATH, true) if defined?(Rails)
19
16
 
20
17
  # Jammit Core:
21
18
  require 'jammit/compressor'
@@ -23,6 +20,9 @@ require 'jammit/packager'
23
20
 
24
21
  # Jammit Rails Integration:
25
22
  if defined?(Rails)
26
- require 'jammit/controller' # Rails will auto-load 'jammit/helper' for us.
23
+ require 'jammit/controller'
24
+ require 'jammit/helper'
25
+ require 'jammit/railtie'
27
26
  require 'jammit/routes'
28
- end
27
+ end
28
+
data/lib/jammit/helper.rb CHANGED
@@ -6,40 +6,48 @@ module Jammit
6
6
  # to the cached packages.
7
7
  module Helper
8
8
 
9
- DATA_URI_START = "<!--[if (!IE)|(gte IE 8)]><!-->"
10
- DATA_URI_END = "<!--<![endif]-->"
11
- MHTML_START = "<!--[if lte IE 7]>"
12
- MHTML_END = "<![endif]-->"
9
+ DATA_URI_START = "<!--[if (!IE)|(gte IE 8)]><!-->" unless defined?(DATA_URI_START)
10
+ DATA_URI_END = "<!--<![endif]-->" unless defined?(DATA_URI_END)
11
+ MHTML_START = "<!--[if lte IE 7]>" unless defined?(MHTML_START)
12
+ MHTML_END = "<![endif]-->" unless defined?(MHTML_END)
13
13
 
14
14
  # If embed_assets is turned on, writes out links to the Data-URI and MHTML
15
15
  # versions of the stylesheet package, otherwise the package is regular
16
16
  # compressed CSS, and in development the stylesheet URLs are passed verbatim.
17
17
  def include_stylesheets(*packages)
18
18
  options = packages.extract_options!
19
- return individual_stylesheets(packages, options) unless Jammit.package_assets
19
+ return individual_stylesheets(packages, options) unless should_package?
20
20
  disabled = (options.delete(:embed_assets) == false) || (options.delete(:embed_images) == false)
21
- return packaged_stylesheets(packages, options) if disabled || !Jammit.embed_assets
22
- return embedded_image_stylesheets(packages, options)
21
+ return html_safe(packaged_stylesheets(packages, options)) if disabled || !Jammit.embed_assets
22
+ return html_safe(embedded_image_stylesheets(packages, options))
23
23
  end
24
24
 
25
25
  # Writes out the URL to the bundled and compressed javascript package,
26
26
  # except in development, where it references the individual scripts.
27
27
  def include_javascripts(*packages)
28
28
  tags = packages.map do |pack|
29
- Jammit.package_assets ? Jammit.asset_url(pack, :js) : Jammit.packager.individual_urls(pack.to_sym, :js)
29
+ should_package? ? Jammit.asset_url(pack, :js) : Jammit.packager.individual_urls(pack.to_sym, :js)
30
30
  end
31
- javascript_include_tag(tags.flatten)
31
+ html_safe(javascript_include_tag(tags.flatten))
32
32
  end
33
33
 
34
34
  # Writes out the URL to the concatenated and compiled JST file -- we always
35
35
  # have to pre-process it, even in development.
36
36
  def include_templates(*packages)
37
- javascript_include_tag(packages.map {|pack| Jammit.asset_url(pack, :jst) })
37
+ raise DeprecationError, "Jammit 0.5+ no longer supports separate packages for templates.\nYou can include your JST alongside your JS, and use include_javascripts."
38
38
  end
39
39
 
40
40
 
41
41
  private
42
42
 
43
+ def should_package?
44
+ Jammit.package_assets && !(Jammit.allow_debugging && params[:debug_assets])
45
+ end
46
+
47
+ def html_safe(string)
48
+ string.respond_to?(:html_safe) ? string.html_safe : string
49
+ end
50
+
43
51
  # HTML tags, in order, for all of the individual stylesheets.
44
52
  def individual_stylesheets(packages, options)
45
53
  tags_with_options(packages, options) {|p| Jammit.packager.individual_urls(p.to_sym, :css) }
@@ -21,14 +21,12 @@ module Jammit
21
21
  @compressor = Compressor.new
22
22
  @force = false
23
23
  @config = {
24
- :css => (Jammit.configuration[:stylesheets] || {}).symbolize_keys,
25
- :js => (Jammit.configuration[:javascripts] || {}).symbolize_keys,
26
- :jst => (Jammit.configuration[:templates] || {}).symbolize_keys
24
+ :css => (Jammit.configuration[:stylesheets] || {}),
25
+ :js => (Jammit.configuration[:javascripts] || {})
27
26
  }
28
27
  @packages = {
29
28
  :css => create_packages(@config[:css]),
30
- :js => create_packages(@config[:js]),
31
- :jst => create_packages(@config[:jst])
29
+ :js => create_packages(@config[:js])
32
30
  }
33
31
  end
34
32
 
@@ -40,7 +38,6 @@ module Jammit
40
38
  def precache_all(output_dir=nil, base_url=nil)
41
39
  output_dir ||= File.join(PUBLIC_ROOT, Jammit.package_path)
42
40
  cacheable(:js, output_dir).each {|p| cache(p, 'js', pack_javascripts(p), output_dir) }
43
- cacheable(:jst, output_dir).each {|p| cache(p, 'jst', pack_templates(p), output_dir) }
44
41
  cacheable(:css, output_dir).each do |p|
45
42
  cache(p, 'css', pack_stylesheets(p), output_dir)
46
43
  if Jammit.embed_assets
@@ -87,10 +84,9 @@ module Jammit
87
84
 
88
85
  # Return the compiled contents of a JST package.
89
86
  def pack_templates(package)
90
- @compressor.compile_jst(package_for(package, :jst)[:paths])
87
+ @compressor.compile_jst(package_for(package, :js)[:paths])
91
88
  end
92
89
 
93
-
94
90
  private
95
91
 
96
92
  # Look up a package asset list by name, raising an exception if the
@@ -110,30 +106,48 @@ module Jammit
110
106
  end
111
107
 
112
108
  # Return a list of all of the packages that should be cached. If "force" is
113
- # true, this is all of them -- otherwise only the packages whose source
114
- # files have changed since the last package build.
109
+ # true, this is all of them -- otherwise only the packages that are missing
110
+ # or whose source files have changed since the last package build.
115
111
  def cacheable(extension, output_dir)
116
112
  names = @packages[extension].keys
117
113
  return names if @force
114
+ config_mtime = File.mtime(Jammit.config_path)
118
115
  return names.select do |name|
119
- pack = package_for(name, extension)
120
- cached = File.join(output_dir, Jammit.filename(name, extension))
121
- since = File.exists?(cached) && File.mtime(cached)
122
- !since || pack[:paths].any? {|src| File.mtime(src) > since }
116
+ pack = package_for(name, extension)
117
+ cached = [Jammit.filename(name, extension)]
118
+ cached.push Jammit.filename(name, extension, :datauri) if Jammit.embed_assets
119
+ cached.push Jammit.filename(name, extension, :mhtml) if Jammit.mhtml_enabled
120
+ cached.map! {|file| File.join(output_dir, file) }
121
+ if cached.any? {|file| !File.exists?(file) }
122
+ true
123
+ else
124
+ since = cached.map {|file| File.mtime(file) }.min
125
+ config_mtime > since || pack[:paths].any? {|src| File.mtime(src) > since }
126
+ end
123
127
  end
124
128
  end
125
129
 
126
- # Compiles the list of assets that goes into each package. Runs an ordered
127
- # list of Dir.globs, taking the merged unique result.
130
+ # Compiles the list of assets that goes into each package. Runs an
131
+ # ordered list of Dir.globs, taking the merged unique result.
132
+ # If there are JST files in this package we need to add an extra
133
+ # path for when package_assets is off (e.g. in a dev environment).
134
+ # This package (e.g. /assets/package-name.jst) will never exist as
135
+ # an actual file but will be dynamically generated by Jammit on
136
+ # every request.
128
137
  def create_packages(config)
129
138
  packages = {}
130
139
  return packages if !config
131
140
  config.each do |name, globs|
132
141
  globs ||= []
133
142
  packages[name] = {}
134
- paths = globs.map {|glob| glob_files(glob) }.flatten.uniq
143
+ paths = globs.flatten.uniq.map {|glob| glob_files(glob) }.flatten.uniq
135
144
  packages[name][:paths] = paths
136
- packages[name][:urls] = paths.map {|path| path.sub(PATH_TO_URL, '') }
145
+ if !paths.grep(Jammit.template_extension_matcher).empty?
146
+ packages[name][:urls] = paths.grep(JS_EXTENSION).map {|path| path.sub(PATH_TO_URL, '') }
147
+ packages[name][:urls] += [Jammit.asset_url(name, Jammit.template_extension)]
148
+ else
149
+ packages[name][:urls] = paths.map {|path| path.sub(PATH_TO_URL, '') }
150
+ end
137
151
  end
138
152
  packages
139
153
  end
@@ -145,4 +159,4 @@ module Jammit
145
159
 
146
160
  end
147
161
 
148
- end
162
+ end
@@ -0,0 +1,14 @@
1
+ # Rails 3 configuration via Railtie
2
+
3
+ if defined?(Rails::Railtie)
4
+ module Jammit
5
+ class Railtie < Rails::Railtie
6
+
7
+ initializer :jammit_routes do |app|
8
+ # Add a Jammit route for the reloader.
9
+ app.routes_reloader.paths << File.join(File.dirname(__FILE__), "..", "..", "rails", "routes.rb")
10
+ end
11
+
12
+ end
13
+ end
14
+ end
data/lib/jammit/routes.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Jammit
2
2
 
3
- # Rails 2.x routing module.
3
+ # Rails 2.x routing module. Rails 3.x routes are in rails/routes.rb.
4
4
  module Routes
5
5
 
6
6
  # Jammit uses a single route in order to slow down Rails' routing speed
@@ -8,18 +8,16 @@ module Jammit
8
8
  # Jammit::Routes.draw(map)
9
9
  # Passing in the routing "map" object.
10
10
  def self.draw(map)
11
- map.jammit "/#{Jammit.package_path}/:package.:extension",
12
- :controller => 'jammit', :action => 'package'
11
+ map.jammit "/#{Jammit.package_path}/:package.:extension", {
12
+ :controller => 'jammit',
13
+ :action => 'package',
14
+ :requirements => {
15
+ # A hack to allow extension to include "."
16
+ :extension => /.+/
17
+ }
18
+ }
13
19
  end
14
20
 
15
21
  end
16
22
 
17
- end
18
-
19
- # Rails 3.x routes.
20
- if defined?(Jammit::Railtie)
21
- Jammit::Railtie.routes do
22
- match "/#{Jammit.package_path}/:package.:extension",
23
- :to => 'jammit#package', :as => 'jammit'
24
- end
25
23
  end
data/lib/jammit.rb CHANGED
@@ -4,13 +4,13 @@ $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.4.4"
7
+ VERSION = "0.6.0.1"
8
8
 
9
9
  ROOT = File.expand_path(File.dirname(__FILE__) + '/..')
10
10
 
11
- ASSET_ROOT = File.expand_path(defined?(Rails) ? Rails.root : ".") unless defined?(ASSET_ROOT)
11
+ ASSET_ROOT = File.expand_path((defined?(Rails) && Rails.root.to_s.length > 0) ? Rails.root : ".") unless defined?(ASSET_ROOT)
12
12
 
13
- PUBLIC_ROOT = defined?(Rails) ? Rails.public_path : File.join(ASSET_ROOT, 'public')
13
+ PUBLIC_ROOT = (defined?(Rails) && Rails.public_path.to_s.length > 0) ? Rails.public_path : File.join(ASSET_ROOT, 'public') unless defined?(PUBLIC_ROOT)
14
14
 
15
15
  DEFAULT_CONFIG_PATH = File.join(ASSET_ROOT, 'config', 'assets.yml')
16
16
 
@@ -26,6 +26,10 @@ module Jammit
26
26
 
27
27
  DEFAULT_COMPRESSOR = :yui
28
28
 
29
+ # Extension matchers for JavaScript and JST, which need to be disambiguated.
30
+ JS_EXTENSION = /\.js\Z/
31
+ DEFAULT_JST_EXTENSION = "jst"
32
+
29
33
  # Jammit raises a @PackageNotFound@ exception when a non-existent package is
30
34
  # requested by a browser -- rendering a 404.
31
35
  class PackageNotFound < NameError; end
@@ -38,11 +42,15 @@ module Jammit
38
42
  # cached packages is locked.
39
43
  class OutputNotWritable < StandardError; end
40
44
 
45
+ # Jammit raises a DeprecationError if you try to use an outdated feature.
46
+ class DeprecationError < StandardError; end
47
+
41
48
  class << self
42
49
  attr_reader :configuration, :template_function, :template_namespace,
43
50
  :embed_assets, :package_assets, :compress_assets, :gzip_assets,
44
- :package_path, :mhtml_enabled, :include_jst_script,
45
- :javascript_compressor, :compressor_options, :css_compressor_options
51
+ :package_path, :mhtml_enabled, :include_jst_script, :config_path,
52
+ :javascript_compressor, :compressor_options, :css_compressor_options,
53
+ :template_extension, :template_extension_matcher, :allow_debugging
46
54
  end
47
55
 
48
56
  # The minimal required configuration.
@@ -50,24 +58,31 @@ module Jammit
50
58
  @package_path = DEFAULT_PACKAGE_PATH
51
59
 
52
60
  # Load the complete asset configuration from the specified @config_path@.
53
- def self.load_configuration(config_path)
61
+ # If we're loading softly, don't let missing configuration error out.
62
+ def self.load_configuration(config_path, soft=false)
54
63
  exists = config_path && File.exists?(config_path)
64
+ return false if soft && !exists
55
65
  raise ConfigurationNotFound, "could not find the \"#{config_path}\" configuration file" unless exists
56
66
  conf = YAML.load(ERB.new(File.read(config_path)).result)
57
67
  @config_path = config_path
58
- @configuration = conf = conf.symbolize_keys
68
+ @configuration = symbolize_keys(conf)
59
69
  @package_path = conf[:package_path] || DEFAULT_PACKAGE_PATH
60
70
  @embed_assets = conf[:embed_assets] || conf[:embed_images]
61
71
  @compress_assets = !(conf[:compress_assets] == false)
62
72
  @gzip_assets = !(conf[:gzip_assets] == false)
73
+ @allow_debugging = !(conf[:allow_debugging] == false)
63
74
  @mhtml_enabled = @embed_assets && @embed_assets != "datauri"
64
- @compressor_options = (conf[:compressor_options] || {}).symbolize_keys
65
- @css_compressor_options = (conf[:css_compressor_options] || {}).symbolize_keys
75
+ @compressor_options = symbolize_keys(conf[:compressor_options] || {})
76
+ @css_compressor_options = symbolize_keys(conf[:css_compressor_options] || {})
66
77
  set_javascript_compressor(conf[:javascript_compressor])
67
78
  set_package_assets(conf[:package_assets])
68
79
  set_template_function(conf[:template_function])
69
80
  set_template_namespace(conf[:template_namespace])
81
+ set_template_extension(conf[:template_extension])
82
+ symbolize_keys(conf[:stylesheets]) if conf[:stylesheets]
83
+ symbolize_keys(conf[:javascripts]) if conf[:javascripts]
70
84
  check_java_version
85
+ check_for_deprecations
71
86
  self
72
87
  end
73
88
 
@@ -96,6 +111,18 @@ module Jammit
96
111
  "/#{package_path}/#{filename(package, extension, suffix)}#{timestamp}"
97
112
  end
98
113
 
114
+ # Convenience method for packaging up Jammit, using the default options.
115
+ def self.package!(options={})
116
+ options = {
117
+ :config_path => Jammit::DEFAULT_CONFIG_PATH,
118
+ :output_folder => nil,
119
+ :base_url => nil,
120
+ :force => false
121
+ }.merge(options)
122
+ load_configuration(options[:config_path])
123
+ packager.force = options[:force]
124
+ packager.precache_all(options[:output_folder], options[:base_url])
125
+ end
99
126
 
100
127
  private
101
128
 
@@ -107,7 +134,7 @@ module Jammit
107
134
 
108
135
  # Turn asset packaging on or off, depending on configuration and environment.
109
136
  def self.set_package_assets(value)
110
- package_env = !defined?(Rails) || !Rails.env.development?
137
+ package_env = !defined?(Rails) || (!Rails.env.development? && !Rails.env.test?)
111
138
  @package_assets = value == true || value.nil? ? package_env :
112
139
  value == 'always' ? true : false
113
140
  end
@@ -124,6 +151,12 @@ module Jammit
124
151
  @template_namespace = value == true || value.nil? ? DEFAULT_JST_NAMESPACE : value.to_s
125
152
  end
126
153
 
154
+ # Set the extension for JS templates.
155
+ def self.set_template_extension(value)
156
+ @template_extension = (value == true || value.nil? ? DEFAULT_JST_EXTENSION : value.to_s).gsub(/\A\.?(.*)\Z/, '\1')
157
+ @template_extension_matcher = /\.#{Regexp.escape(@template_extension)}\Z/
158
+ end
159
+
127
160
  # The YUI Compressor requires Java > 1.4, and Closure requires Java > 1.6.
128
161
  def self.check_java_version
129
162
  return true if @checked_java_version
@@ -143,11 +176,23 @@ module Jammit
143
176
  warn("Asset compression disabled -- Java unavailable.")
144
177
  end
145
178
 
179
+ # Jammit 0.5+ no longer supports separate template packages.
180
+ def self.check_for_deprecations
181
+ raise DeprecationError, "Jammit 0.5+ no longer supports separate packages for templates.\nPlease fold your templates into the appropriate 'javascripts' package instead." if @configuration[:templates]
182
+ end
183
+
146
184
  def self.warn(message)
147
185
  message = "Jammit Warning: #{message}"
148
- @logger ||= (defined?(Rails) && Rails.logger ? Rails.logger :
149
- defined?(RAILS_DEFAULT_LOGGER) ? RAILS_DEFAULT_LOGGER : nil)
150
- @logger ? @logger.warn(message) : STDERR.puts(message)
186
+ $stderr.puts message
187
+ end
188
+
189
+ # Clone of active_support's symbolize_keys, so that we don't have to depend
190
+ # on active_support in any fashion. Converts a hash's keys to all symbols.
191
+ def self.symbolize_keys(hash)
192
+ hash.keys.each do |key|
193
+ hash[(key.to_sym rescue key) || key] = hash.delete(key)
194
+ end
195
+ hash
151
196
  end
152
197
 
153
198
  end
data/rails/routes.rb ADDED
@@ -0,0 +1,10 @@
1
+ if defined?(Rails::Application)
2
+ # Rails3 routes
3
+ Rails.application.routes.draw do
4
+ match "/#{Jammit.package_path}/:package.:extension",
5
+ :to => 'jammit#package', :as => :jammit, :constraints => {
6
+ # A hack to allow extension to include "."
7
+ :extension => /.+/
8
+ }
9
+ end
10
+ end
metadata CHANGED
@@ -1,7 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ghazel-jammit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4.3
4
+ hash: 125
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 6
9
+ - 0
10
+ - 1
11
+ version: 0.6.0.1
5
12
  platform: ruby
6
13
  authors:
7
14
  - Jeremy Ashkenas
@@ -9,39 +16,42 @@ autorequire:
9
16
  bindir: bin
10
17
  cert_chain: []
11
18
 
12
- date: 2010-02-06 00:00:00 -08:00
19
+ date: 2010-11-08 00:00:00 -08:00
13
20
  default_executable:
14
21
  dependencies:
15
22
  - !ruby/object:Gem::Dependency
16
- name: rails
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
23
+ name: ghazel-yui-compressor
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
20
27
  requirements:
21
28
  - - ">="
22
29
  - !ruby/object:Gem::Version
23
- version: 2.0.0
24
- version:
25
- - !ruby/object:Gem::Dependency
26
- name: yui-compressor
30
+ hash: 19
31
+ segments:
32
+ - 0
33
+ - 9
34
+ - 4
35
+ - 2
36
+ version: 0.9.4.2
27
37
  type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 0.9.1
34
- version:
38
+ version_requirements: *id001
35
39
  - !ruby/object:Gem::Dependency
36
- name: ghazel-closure-compiler
37
- type: :runtime
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
40
+ name: closure-compiler
41
+ prerelease: false
42
+ requirement: &id002 !ruby/object:Gem::Requirement
43
+ none: false
40
44
  requirements:
41
45
  - - ">="
42
46
  - !ruby/object:Gem::Version
43
- version: 0.2.0.2
44
- version:
47
+ hash: 27
48
+ segments:
49
+ - 0
50
+ - 1
51
+ - 0
52
+ version: 0.1.0
53
+ type: :runtime
54
+ version_requirements: *id002
45
55
  description: " Jammit is an industrial strength asset packaging library for Rails,\n providing both the CSS and JavaScript concatenation and compression that\n you'd expect, as well as YUI Compressor and Closure Compiler compatibility,\n ahead-of-time gzipping, built-in JavaScript template support, and optional\n Data-URI / MHTML image embedding.\n"
46
56
  email: jeremy@documentcloud.org
47
57
  executables:
@@ -58,9 +68,11 @@ files:
58
68
  - lib/jammit/helper.rb
59
69
  - lib/jammit/jst.js
60
70
  - lib/jammit/packager.rb
71
+ - lib/jammit/railtie.rb
61
72
  - lib/jammit/routes.rb
62
73
  - lib/jammit.rb
63
74
  - bin/jammit
75
+ - rails/routes.rb
64
76
  - jammit.gemspec
65
77
  - LICENSE
66
78
  - README
@@ -80,21 +92,27 @@ rdoc_options:
80
92
  require_paths:
81
93
  - lib
82
94
  required_ruby_version: !ruby/object:Gem::Requirement
95
+ none: false
83
96
  requirements:
84
97
  - - ">="
85
98
  - !ruby/object:Gem::Version
99
+ hash: 3
100
+ segments:
101
+ - 0
86
102
  version: "0"
87
- version:
88
103
  required_rubygems_version: !ruby/object:Gem::Requirement
104
+ none: false
89
105
  requirements:
90
106
  - - ">="
91
107
  - !ruby/object:Gem::Version
108
+ hash: 3
109
+ segments:
110
+ - 0
92
111
  version: "0"
93
- version:
94
112
  requirements: []
95
113
 
96
114
  rubyforge_project: jammit
97
- rubygems_version: 1.3.5
115
+ rubygems_version: 1.4.2
98
116
  signing_key:
99
117
  specification_version: 3
100
118
  summary: Industrial Strength Asset Packaging for Rails