secobarbital-jammit 0.5.0.1 → 0.6.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/jammit.gemspec +6 -7
- data/lib/jammit.rb +47 -15
- data/lib/jammit/command_line.rb +1 -3
- data/lib/jammit/compressor.rb +58 -25
- data/lib/jammit/controller.rb +14 -10
- data/lib/jammit/dependencies.rb +7 -7
- data/lib/jammit/helper.rb +17 -9
- data/lib/jammit/packager.rb +27 -16
- data/lib/jammit/railtie.rb +14 -0
- data/lib/jammit/routes.rb +9 -11
- data/rails/routes.rb +10 -0
- metadata +18 -23
data/jammit.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'secobarbital-jammit'
|
3
|
-
s.version = '0.
|
4
|
-
s.date = '
|
3
|
+
s.version = '0.6.0.1' # Keep version in sync with jammit.rb
|
4
|
+
s.date = '2011-3-4'
|
5
5
|
|
6
6
|
s.homepage = "http://documentcloud.github.com/jammit/"
|
7
7
|
s.summary = "Industrial Strength Asset Packaging for Rails"
|
@@ -14,7 +14,7 @@ Gem::Specification.new do |s|
|
|
14
14
|
EOS
|
15
15
|
|
16
16
|
s.authors = ['Jeremy Ashkenas', 'Seggy Umboh']
|
17
|
-
s.email = ['jeremy@documentcloud.org', '
|
17
|
+
s.email = ['jeremy@documentcloud.org', 'seggy.umboh@gmail.com']
|
18
18
|
s.rubyforge_project = 'jammit'
|
19
19
|
|
20
20
|
s.require_paths = ['lib']
|
@@ -27,8 +27,7 @@ Gem::Specification.new do |s|
|
|
27
27
|
'--main' << 'README' <<
|
28
28
|
'--all'
|
29
29
|
|
30
|
-
s.add_dependency '
|
31
|
-
s.add_dependency 'yui-compressor', ['>= 0.9.1']
|
30
|
+
s.add_dependency 'yui-compressor', ['>= 0.9.3']
|
32
31
|
|
33
|
-
s.files = Dir['lib/**/*', 'bin/*', 'jammit.gemspec', 'LICENSE', 'README']
|
34
|
-
end
|
32
|
+
s.files = Dir['lib/**/*', 'bin/*', 'rails/*', 'jammit.gemspec', 'LICENSE', 'README']
|
33
|
+
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.
|
7
|
+
VERSION = "0.6.0"
|
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
|
|
@@ -27,8 +27,8 @@ module Jammit
|
|
27
27
|
DEFAULT_COMPRESSOR = :yui
|
28
28
|
|
29
29
|
# Extension matchers for JavaScript and JST, which need to be disambiguated.
|
30
|
-
|
31
|
-
|
30
|
+
JS_EXTENSION = /\.js\Z/
|
31
|
+
DEFAULT_JST_EXTENSION = "jst"
|
32
32
|
|
33
33
|
# Jammit raises a @PackageNotFound@ exception when a non-existent package is
|
34
34
|
# requested by a browser -- rendering a 404.
|
@@ -48,8 +48,9 @@ module Jammit
|
|
48
48
|
class << self
|
49
49
|
attr_reader :configuration, :template_function, :template_namespace,
|
50
50
|
:embed_assets, :package_assets, :compress_assets, :gzip_assets,
|
51
|
-
:package_path, :mhtml_enabled, :include_jst_script,
|
52
|
-
: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
|
53
54
|
end
|
54
55
|
|
55
56
|
# The minimal required configuration.
|
@@ -57,23 +58,29 @@ module Jammit
|
|
57
58
|
@package_path = DEFAULT_PACKAGE_PATH
|
58
59
|
|
59
60
|
# Load the complete asset configuration from the specified @config_path@.
|
60
|
-
|
61
|
+
# If we're loading softly, don't let missing configuration error out.
|
62
|
+
def self.load_configuration(config_path, soft=false)
|
61
63
|
exists = config_path && File.exists?(config_path)
|
64
|
+
return false if soft && !exists
|
62
65
|
raise ConfigurationNotFound, "could not find the \"#{config_path}\" configuration file" unless exists
|
63
66
|
conf = YAML.load(ERB.new(File.read(config_path)).result)
|
64
67
|
@config_path = config_path
|
65
|
-
@configuration = conf
|
68
|
+
@configuration = symbolize_keys(conf)
|
66
69
|
@package_path = conf[:package_path] || DEFAULT_PACKAGE_PATH
|
67
70
|
@embed_assets = conf[:embed_assets] || conf[:embed_images]
|
68
71
|
@compress_assets = !(conf[:compress_assets] == false)
|
69
72
|
@gzip_assets = !(conf[:gzip_assets] == false)
|
73
|
+
@allow_debugging = !(conf[:allow_debugging] == false)
|
70
74
|
@mhtml_enabled = @embed_assets && @embed_assets != "datauri"
|
71
|
-
@compressor_options = (conf[:compressor_options] || {})
|
72
|
-
@css_compressor_options = (conf[:css_compressor_options] || {})
|
75
|
+
@compressor_options = symbolize_keys(conf[:compressor_options] || {})
|
76
|
+
@css_compressor_options = symbolize_keys(conf[:css_compressor_options] || {})
|
73
77
|
set_javascript_compressor(conf[:javascript_compressor])
|
74
78
|
set_package_assets(conf[:package_assets])
|
75
79
|
set_template_function(conf[:template_function])
|
76
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]
|
77
84
|
check_java_version
|
78
85
|
check_for_deprecations
|
79
86
|
self
|
@@ -104,6 +111,18 @@ module Jammit
|
|
104
111
|
"/#{package_path}/#{filename(package, extension, suffix)}#{timestamp}"
|
105
112
|
end
|
106
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
|
107
126
|
|
108
127
|
private
|
109
128
|
|
@@ -115,7 +134,7 @@ module Jammit
|
|
115
134
|
|
116
135
|
# Turn asset packaging on or off, depending on configuration and environment.
|
117
136
|
def self.set_package_assets(value)
|
118
|
-
package_env = !defined?(Rails) || !Rails.env.development?
|
137
|
+
package_env = !defined?(Rails) || (!Rails.env.development? && !Rails.env.test?)
|
119
138
|
@package_assets = value == true || value.nil? ? package_env :
|
120
139
|
value == 'always' ? true : false
|
121
140
|
end
|
@@ -132,6 +151,12 @@ module Jammit
|
|
132
151
|
@template_namespace = value == true || value.nil? ? DEFAULT_JST_NAMESPACE : value.to_s
|
133
152
|
end
|
134
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
|
+
|
135
160
|
# The YUI Compressor requires Java > 1.4, and Closure requires Java > 1.6.
|
136
161
|
def self.check_java_version
|
137
162
|
return true if @checked_java_version
|
@@ -157,9 +182,16 @@ module Jammit
|
|
157
182
|
|
158
183
|
def self.warn(message)
|
159
184
|
message = "Jammit Warning: #{message}"
|
160
|
-
|
161
|
-
|
162
|
-
|
185
|
+
$stderr.puts message
|
186
|
+
end
|
187
|
+
|
188
|
+
# Clone of active_support's symbolize_keys, so that we don't have to depend
|
189
|
+
# on active_support in any fashion. Converts a hash's keys to all symbols.
|
190
|
+
def self.symbolize_keys(hash)
|
191
|
+
hash.keys.each do |key|
|
192
|
+
hash[(key.to_sym rescue key) || key] = hash.delete(key)
|
193
|
+
end
|
194
|
+
hash
|
163
195
|
end
|
164
196
|
|
165
197
|
end
|
data/lib/jammit/command_line.rb
CHANGED
@@ -26,9 +26,7 @@ Options:
|
|
26
26
|
def initialize
|
27
27
|
parse_options
|
28
28
|
ensure_configuration_file
|
29
|
-
Jammit.
|
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
|
|
data/lib/jammit/compressor.rb
CHANGED
@@ -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
|
27
|
-
MAX_IMAGE_SIZE =
|
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__(
|
33
|
+
EMBED_REPLACER = /url\(__EMBED__(.+?)(\?\d+)?\)/
|
33
34
|
|
34
35
|
# MHTML file constants.
|
35
|
-
MHTML_START = "/*\r\nContent-Type: multipart/related; boundary=\"
|
36
|
-
MHTML_SEPARATOR = "--
|
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(){"
|
@@ -60,7 +61,7 @@ module Jammit
|
|
60
61
|
# Concatenate together a list of JavaScript paths, and pass them through the
|
61
62
|
# YUI Compressor (with munging enabled). JST can optionally be included.
|
62
63
|
def compress_js(paths)
|
63
|
-
if (jst_paths = paths.grep(
|
64
|
+
if (jst_paths = paths.grep(Jammit.template_extension_matcher)).empty?
|
64
65
|
js = concatenate(paths)
|
65
66
|
else
|
66
67
|
js = concatenate(paths - jst_paths) + compile_jst(jst_paths)
|
@@ -72,6 +73,7 @@ module Jammit
|
|
72
73
|
# :datauri or :mhtml variant, post-processes the result to embed
|
73
74
|
# referenced assets.
|
74
75
|
def compress_css(paths, variant=nil, asset_url=nil)
|
76
|
+
@asset_contents = {}
|
75
77
|
css = concatenate_and_tag_assets(paths, variant)
|
76
78
|
css = @css_compressor.compress(css) if Jammit.compress_assets
|
77
79
|
case variant
|
@@ -88,13 +90,16 @@ module Jammit
|
|
88
90
|
# specified your own preferred function, or turned it off.
|
89
91
|
# JST templates are named with the basename of their file.
|
90
92
|
def compile_jst(paths)
|
91
|
-
namespace
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
93
|
+
namespace = Jammit.template_namespace
|
94
|
+
paths = paths.grep(Jammit.template_extension_matcher).sort
|
95
|
+
base_path = find_base_path(paths)
|
96
|
+
compiled = paths.map do |path|
|
97
|
+
contents = read_binary_file(path)
|
98
|
+
contents = contents.gsub(/\n/, '').gsub("'", '\\\\\'')
|
99
|
+
name = template_name(path, base_path)
|
100
|
+
"#{namespace}['#{name}'] = #{Jammit.template_function}('#{contents}');"
|
96
101
|
end
|
97
|
-
compiler = Jammit.include_jst_script ?
|
102
|
+
compiler = Jammit.include_jst_script ? read_binary_file(DEFAULT_JST_SCRIPT) : '';
|
98
103
|
setup_namespace = "#{namespace} = #{namespace} || {};"
|
99
104
|
[JST_START, setup_namespace, compiler, compiled, JST_END].flatten.join("\n")
|
100
105
|
end
|
@@ -102,13 +107,35 @@ module Jammit
|
|
102
107
|
|
103
108
|
private
|
104
109
|
|
110
|
+
# Given a set of paths, find a common prefix path.
|
111
|
+
def find_base_path(paths)
|
112
|
+
return nil if paths.length <= 1
|
113
|
+
paths.sort!
|
114
|
+
first = paths.first.split('/')
|
115
|
+
last = paths.last.split('/')
|
116
|
+
i = 0
|
117
|
+
while first[i] == last[i] && i <= first.length
|
118
|
+
i += 1
|
119
|
+
end
|
120
|
+
res = first.slice(0, i).join('/')
|
121
|
+
res.empty? ? nil : res
|
122
|
+
end
|
123
|
+
|
124
|
+
# Determine the name of a JS template. If there's a common base path, use
|
125
|
+
# the namespaced prefix. Otherwise, simply use the filename.
|
126
|
+
def template_name(path, base_path)
|
127
|
+
return File.basename(path, ".#{Jammit.template_extension}") unless base_path
|
128
|
+
path.gsub(/\A#{Regexp.escape(base_path)}\/(.*)\.#{Jammit.template_extension}\Z/, '\1')
|
129
|
+
end
|
130
|
+
|
105
131
|
# In order to support embedded assets from relative paths, we need to
|
106
132
|
# expand the paths before contatenating the CSS together and losing the
|
107
133
|
# location of the original stylesheet path. Validate the assets while we're
|
108
134
|
# at it.
|
109
135
|
def concatenate_and_tag_assets(paths, variant=nil)
|
110
136
|
stylesheets = [paths].flatten.map do |css_path|
|
111
|
-
|
137
|
+
contents = read_binary_file(css_path)
|
138
|
+
contents.gsub(EMBED_DETECTOR) do |url|
|
112
139
|
ipath, cpath = Pathname.new($1), Pathname.new(File.expand_path(css_path))
|
113
140
|
is_url = URI.parse($1).absolute?
|
114
141
|
is_url ? url : "url(#{construct_asset_path(ipath, cpath, variant)})"
|
@@ -169,7 +196,7 @@ module Jammit
|
|
169
196
|
# append the RAILS_ASSET_ID cache-buster to URLs, if it's defined.
|
170
197
|
def rewrite_asset_path(path, file_path)
|
171
198
|
asset_id = rails_asset_id(file_path)
|
172
|
-
asset_id
|
199
|
+
(!asset_id || asset_id == '') ? path : "#{path}?#{asset_id}"
|
173
200
|
end
|
174
201
|
|
175
202
|
# Similar to the AssetTagHelper's method of the same name, this will
|
@@ -181,23 +208,25 @@ module Jammit
|
|
181
208
|
end
|
182
209
|
|
183
210
|
# An asset is valid for embedding if it exists, is less than 32K, and is
|
184
|
-
# stored somewhere inside of a folder named "embed".
|
185
|
-
#
|
186
|
-
#
|
211
|
+
# stored somewhere inside of a folder named "embed". IE does not support
|
212
|
+
# Data-URIs larger than 32K, and you probably shouldn't be embedding assets
|
213
|
+
# that large in any case. Because we need to check the base64 length here,
|
214
|
+
# save it so that we don't have to compute it again later.
|
187
215
|
def embeddable?(asset_path, variant)
|
188
216
|
font = EMBED_FONTS.include?(asset_path.extname)
|
189
217
|
return false unless variant
|
190
218
|
return false unless asset_path.to_s.match(EMBEDDABLE) && asset_path.exist?
|
191
219
|
return false unless EMBED_EXTS.include?(asset_path.extname)
|
192
|
-
return false unless font || asset_path.
|
220
|
+
return false unless font || encoded_contents(asset_path).length < MAX_IMAGE_SIZE
|
193
221
|
return false if font && variant == :mhtml
|
194
|
-
true
|
222
|
+
return true
|
195
223
|
end
|
196
224
|
|
197
225
|
# Return the Base64-encoded contents of an asset on a single line.
|
198
226
|
def encoded_contents(asset_path)
|
199
|
-
|
200
|
-
|
227
|
+
return @asset_contents[asset_path] if @asset_contents[asset_path]
|
228
|
+
data = read_binary_file(asset_path)
|
229
|
+
@asset_contents[asset_path] = Base64.encode64(data).gsub(/\n/, '')
|
201
230
|
end
|
202
231
|
|
203
232
|
# Grab the mime-type of an asset, by filename.
|
@@ -207,9 +236,13 @@ module Jammit
|
|
207
236
|
|
208
237
|
# Concatenate together a list of asset files.
|
209
238
|
def concatenate(paths)
|
210
|
-
[paths].flatten.map {|p|
|
239
|
+
[paths].flatten.map {|p| read_binary_file(p) }.join("\n")
|
211
240
|
end
|
212
241
|
|
242
|
+
# `File.read`, but in "binary" mode.
|
243
|
+
def read_binary_file(path)
|
244
|
+
File.open(path, 'rb') {|f| f.read }
|
245
|
+
end
|
213
246
|
end
|
214
247
|
|
215
248
|
end
|
data/lib/jammit/controller.rb
CHANGED
@@ -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
|
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
|
20
|
-
|
21
|
-
when
|
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.
|
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
|
61
|
-
#
|
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
|
data/lib/jammit/dependencies.rb
CHANGED
@@ -2,19 +2,16 @@
|
|
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
|
-
require 'active_support'
|
14
|
-
require 'active_support/core_ext/hash'
|
15
12
|
|
16
13
|
# Load initial configuration before the rest of Jammit.
|
17
|
-
Jammit.load_configuration(Jammit::DEFAULT_CONFIG_PATH) if defined?(Rails)
|
14
|
+
Jammit.load_configuration(Jammit::DEFAULT_CONFIG_PATH, true) if defined?(Rails)
|
18
15
|
|
19
16
|
# Jammit Core:
|
20
17
|
require 'jammit/compressor'
|
@@ -22,6 +19,9 @@ require 'jammit/packager'
|
|
22
19
|
|
23
20
|
# Jammit Rails Integration:
|
24
21
|
if defined?(Rails)
|
25
|
-
require 'jammit/controller'
|
22
|
+
require 'jammit/controller'
|
23
|
+
require 'jammit/helper'
|
24
|
+
require 'jammit/railtie'
|
26
25
|
require 'jammit/routes'
|
27
|
-
end
|
26
|
+
end
|
27
|
+
|
data/lib/jammit/helper.rb
CHANGED
@@ -6,29 +6,29 @@ 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
|
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
|
-
|
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
|
@@ -40,6 +40,14 @@ module Jammit
|
|
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) }
|
data/lib/jammit/packager.rb
CHANGED
@@ -21,8 +21,8 @@ module Jammit
|
|
21
21
|
@compressor = Compressor.new
|
22
22
|
@force = false
|
23
23
|
@config = {
|
24
|
-
:css => (Jammit.configuration[:stylesheets] || {})
|
25
|
-
:js => (Jammit.configuration[:javascripts] || {})
|
24
|
+
:css => (Jammit.configuration[:stylesheets] || {}),
|
25
|
+
:js => (Jammit.configuration[:javascripts] || {})
|
26
26
|
}
|
27
27
|
@packages = {
|
28
28
|
:css => create_packages(@config[:css]),
|
@@ -84,17 +84,15 @@ module Jammit
|
|
84
84
|
|
85
85
|
# Return the compiled contents of a JST package.
|
86
86
|
def pack_templates(package)
|
87
|
-
@compressor.compile_jst(package_for(package, :
|
87
|
+
@compressor.compile_jst(package_for(package, :js)[:paths])
|
88
88
|
end
|
89
89
|
|
90
|
-
|
91
90
|
private
|
92
91
|
|
93
92
|
# Look up a package asset list by name, raising an exception if the
|
94
93
|
# package has gone missing.
|
95
94
|
def package_for(package, extension)
|
96
95
|
pack = @packages[extension] && @packages[extension][package]
|
97
|
-
pack ||= @packages[:js] && @packages[:js][package] if extension == :jst
|
98
96
|
pack || not_found(package, extension)
|
99
97
|
end
|
100
98
|
|
@@ -108,21 +106,34 @@ module Jammit
|
|
108
106
|
end
|
109
107
|
|
110
108
|
# Return a list of all of the packages that should be cached. If "force" is
|
111
|
-
# true, this is all of them -- otherwise only the packages
|
112
|
-
# 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.
|
113
111
|
def cacheable(extension, output_dir)
|
114
112
|
names = @packages[extension].keys
|
115
113
|
return names if @force
|
114
|
+
config_mtime = File.mtime(Jammit.config_path)
|
116
115
|
return names.select do |name|
|
117
|
-
pack
|
118
|
-
cached
|
119
|
-
|
120
|
-
|
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
|
121
127
|
end
|
122
128
|
end
|
123
129
|
|
124
|
-
# Compiles the list of assets that goes into each package. Runs an
|
125
|
-
# 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.
|
126
137
|
def create_packages(config)
|
127
138
|
packages = {}
|
128
139
|
return packages if !config
|
@@ -131,9 +142,9 @@ module Jammit
|
|
131
142
|
packages[name] = {}
|
132
143
|
paths = globs.flatten.uniq.map {|glob| glob_files(glob) }.flatten.uniq
|
133
144
|
packages[name][:paths] = paths
|
134
|
-
if !paths.grep(
|
135
|
-
packages[name][:urls] = paths.grep(
|
136
|
-
packages[name][:urls] += [Jammit.asset_url(name,
|
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)]
|
137
148
|
else
|
138
149
|
packages[name][:urls] = paths.map {|path| path.sub(PATH_TO_URL, '') }
|
139
150
|
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
|
-
|
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/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,13 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: secobarbital-jammit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 125
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
|
-
-
|
8
|
+
- 6
|
8
9
|
- 0
|
9
10
|
- 1
|
10
|
-
version: 0.
|
11
|
+
version: 0.6.0.1
|
11
12
|
platform: ruby
|
12
13
|
authors:
|
13
14
|
- Jeremy Ashkenas
|
@@ -16,41 +17,29 @@ autorequire:
|
|
16
17
|
bindir: bin
|
17
18
|
cert_chain: []
|
18
19
|
|
19
|
-
date:
|
20
|
+
date: 2011-03-04 00:00:00 -08:00
|
20
21
|
default_executable:
|
21
22
|
dependencies:
|
22
|
-
- !ruby/object:Gem::Dependency
|
23
|
-
name: rails
|
24
|
-
prerelease: false
|
25
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
-
requirements:
|
27
|
-
- - ">="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
segments:
|
30
|
-
- 2
|
31
|
-
- 0
|
32
|
-
- 0
|
33
|
-
version: 2.0.0
|
34
|
-
type: :runtime
|
35
|
-
version_requirements: *id001
|
36
23
|
- !ruby/object:Gem::Dependency
|
37
24
|
name: yui-compressor
|
38
25
|
prerelease: false
|
39
|
-
requirement: &
|
26
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
27
|
+
none: false
|
40
28
|
requirements:
|
41
29
|
- - ">="
|
42
30
|
- !ruby/object:Gem::Version
|
31
|
+
hash: 61
|
43
32
|
segments:
|
44
33
|
- 0
|
45
34
|
- 9
|
46
|
-
-
|
47
|
-
version: 0.9.
|
35
|
+
- 3
|
36
|
+
version: 0.9.3
|
48
37
|
type: :runtime
|
49
|
-
version_requirements: *
|
38
|
+
version_requirements: *id001
|
50
39
|
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"
|
51
40
|
email:
|
52
41
|
- jeremy@documentcloud.org
|
53
|
-
-
|
42
|
+
- seggy.umboh@gmail.com
|
54
43
|
executables:
|
55
44
|
- jammit
|
56
45
|
extensions: []
|
@@ -65,9 +54,11 @@ files:
|
|
65
54
|
- lib/jammit/helper.rb
|
66
55
|
- lib/jammit/jst.js
|
67
56
|
- lib/jammit/packager.rb
|
57
|
+
- lib/jammit/railtie.rb
|
68
58
|
- lib/jammit/routes.rb
|
69
59
|
- lib/jammit.rb
|
70
60
|
- bin/jammit
|
61
|
+
- rails/routes.rb
|
71
62
|
- jammit.gemspec
|
72
63
|
- LICENSE
|
73
64
|
- README
|
@@ -87,23 +78,27 @@ rdoc_options:
|
|
87
78
|
require_paths:
|
88
79
|
- lib
|
89
80
|
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
90
82
|
requirements:
|
91
83
|
- - ">="
|
92
84
|
- !ruby/object:Gem::Version
|
85
|
+
hash: 3
|
93
86
|
segments:
|
94
87
|
- 0
|
95
88
|
version: "0"
|
96
89
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
97
91
|
requirements:
|
98
92
|
- - ">="
|
99
93
|
- !ruby/object:Gem::Version
|
94
|
+
hash: 3
|
100
95
|
segments:
|
101
96
|
- 0
|
102
97
|
version: "0"
|
103
98
|
requirements: []
|
104
99
|
|
105
100
|
rubyforge_project: jammit
|
106
|
-
rubygems_version: 1.3.
|
101
|
+
rubygems_version: 1.3.7
|
107
102
|
signing_key:
|
108
103
|
specification_version: 3
|
109
104
|
summary: Industrial Strength Asset Packaging for Rails
|