sprockets 2.2.3 → 2.12.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +135 -4
- data/bin/sprockets +8 -0
- data/lib/rake/sprocketstask.rb +24 -13
- data/lib/sprockets.rb +52 -8
- data/lib/sprockets/asset.rb +17 -8
- data/lib/sprockets/asset_attributes.rb +15 -4
- data/lib/sprockets/base.rb +155 -15
- data/lib/sprockets/bundled_asset.rb +5 -6
- data/lib/sprockets/caching.rb +39 -39
- data/lib/sprockets/closure_compressor.rb +22 -0
- data/lib/sprockets/compressing.rb +73 -0
- data/lib/sprockets/context.rb +57 -3
- data/lib/sprockets/directive_processor.rb +3 -1
- data/lib/sprockets/engines.rb +4 -4
- data/lib/sprockets/environment.rb +12 -15
- data/lib/sprockets/errors.rb +1 -0
- data/lib/sprockets/index.rb +1 -0
- data/lib/sprockets/jst_processor.rb +2 -6
- data/lib/sprockets/manifest.rb +77 -19
- data/lib/sprockets/mime.rb +5 -4
- data/lib/sprockets/{trail.rb → paths.rb} +5 -37
- data/lib/sprockets/processed_asset.rb +1 -1
- data/lib/sprockets/processing.rb +3 -77
- data/lib/sprockets/processor.rb +1 -1
- data/lib/sprockets/sass_cache_store.rb +29 -0
- data/lib/sprockets/sass_compressor.rb +27 -0
- data/lib/sprockets/sass_functions.rb +70 -0
- data/lib/sprockets/sass_importer.rb +30 -0
- data/lib/sprockets/sass_template.rb +66 -0
- data/lib/sprockets/scss_template.rb +13 -0
- data/lib/sprockets/server.rb +1 -1
- data/lib/sprockets/static_asset.rb +4 -1
- data/lib/sprockets/uglifier_compressor.rb +29 -0
- data/lib/sprockets/version.rb +1 -1
- data/lib/sprockets/yui_compressor.rb +27 -0
- metadata +88 -7
data/lib/sprockets/context.rb
CHANGED
@@ -53,7 +53,7 @@ module Sprockets
|
|
53
53
|
# # => 'application'
|
54
54
|
#
|
55
55
|
def logical_path
|
56
|
-
@logical_path
|
56
|
+
@logical_path.chomp(File.extname(@logical_path))
|
57
57
|
end
|
58
58
|
|
59
59
|
# Returns content type of file
|
@@ -81,7 +81,11 @@ module Sprockets
|
|
81
81
|
attributes = environment.attributes_for(pathname)
|
82
82
|
|
83
83
|
if pathname.absolute?
|
84
|
-
pathname
|
84
|
+
if environment.stat(pathname)
|
85
|
+
pathname
|
86
|
+
else
|
87
|
+
raise FileNotFound, "couldn't find file '#{pathname}'"
|
88
|
+
end
|
85
89
|
|
86
90
|
elsif content_type = options[:content_type]
|
87
91
|
content_type = self.content_type if content_type == :self
|
@@ -101,7 +105,7 @@ module Sprockets
|
|
101
105
|
|
102
106
|
raise FileNotFound, "couldn't find file '#{path}'"
|
103
107
|
else
|
104
|
-
environment.resolve(path, :base_path => self.pathname.dirname, &block)
|
108
|
+
environment.resolve(path, {:base_path => self.pathname.dirname}.merge(options), &block)
|
105
109
|
end
|
106
110
|
end
|
107
111
|
|
@@ -217,6 +221,56 @@ module Sprockets
|
|
217
221
|
"data:#{asset.content_type};base64,#{Rack::Utils.escape(base64)}"
|
218
222
|
end
|
219
223
|
|
224
|
+
# Expands logical path to full url to asset.
|
225
|
+
#
|
226
|
+
# NOTE: This helper is currently not implemented and should be
|
227
|
+
# customized by the application. Though, in the future, some
|
228
|
+
# basics implemention may be provided with different methods that
|
229
|
+
# are required to be overridden.
|
230
|
+
def asset_path(path, options = {})
|
231
|
+
message = <<-EOS
|
232
|
+
Custom asset_path helper is not implemented
|
233
|
+
|
234
|
+
Extend your environment context with a custom method.
|
235
|
+
|
236
|
+
environment.context_class.class_eval do
|
237
|
+
def asset_path(path, options = {})
|
238
|
+
end
|
239
|
+
end
|
240
|
+
EOS
|
241
|
+
raise NotImplementedError, message
|
242
|
+
end
|
243
|
+
|
244
|
+
# Expand logical image asset path.
|
245
|
+
def image_path(path)
|
246
|
+
asset_path(path, :type => :image)
|
247
|
+
end
|
248
|
+
|
249
|
+
# Expand logical video asset path.
|
250
|
+
def video_path(path)
|
251
|
+
asset_path(path, :type => :video)
|
252
|
+
end
|
253
|
+
|
254
|
+
# Expand logical audio asset path.
|
255
|
+
def audio_path(path)
|
256
|
+
asset_path(path, :type => :audio)
|
257
|
+
end
|
258
|
+
|
259
|
+
# Expand logical font asset path.
|
260
|
+
def font_path(path)
|
261
|
+
asset_path(path, :type => :font)
|
262
|
+
end
|
263
|
+
|
264
|
+
# Expand logical javascript asset path.
|
265
|
+
def javascript_path(path)
|
266
|
+
asset_path(path, :type => :javascript)
|
267
|
+
end
|
268
|
+
|
269
|
+
# Expand logical stylesheet asset path.
|
270
|
+
def stylesheet_path(path)
|
271
|
+
asset_path(path, :type => :stylesheet)
|
272
|
+
end
|
273
|
+
|
220
274
|
private
|
221
275
|
# Annotates exception backtrace with the original template that
|
222
276
|
# the exception was raised in.
|
@@ -65,7 +65,7 @@ module Sprockets
|
|
65
65
|
# //= require "foo"
|
66
66
|
#
|
67
67
|
DIRECTIVE_PATTERN = /
|
68
|
-
^
|
68
|
+
^ \W* = \s* (\w+.*?) (\*\/)? $
|
69
69
|
/x
|
70
70
|
|
71
71
|
attr_reader :pathname
|
@@ -92,6 +92,8 @@ module Sprockets
|
|
92
92
|
@context = context
|
93
93
|
|
94
94
|
@result = ""
|
95
|
+
@result.force_encoding(body.encoding) if body.respond_to?(:encoding)
|
96
|
+
|
95
97
|
@has_written_body = false
|
96
98
|
|
97
99
|
process_directives
|
data/lib/sprockets/engines.rb
CHANGED
@@ -28,12 +28,12 @@ module Sprockets
|
|
28
28
|
# Sprockets.register_engine '.sass', SassTemplate
|
29
29
|
#
|
30
30
|
module Engines
|
31
|
-
# Returns
|
32
|
-
#
|
33
|
-
#
|
31
|
+
# Returns a `Hash` of `Engine`s registered on the `Environment`.
|
32
|
+
# If an `ext` argument is supplied, the `Engine` associated with
|
33
|
+
# that extension will be returned.
|
34
34
|
#
|
35
35
|
# environment.engines
|
36
|
-
# # =>
|
36
|
+
# # => {".coffee" => CoffeeScriptTemplate, ".sass" => SassTemplate, ...}
|
37
37
|
#
|
38
38
|
# environment.engines('.coffee')
|
39
39
|
# # => CoffeeScriptTemplate
|
@@ -1,9 +1,6 @@
|
|
1
1
|
require 'sprockets/base'
|
2
|
-
require 'sprockets/charset_normalizer'
|
3
2
|
require 'sprockets/context'
|
4
|
-
require 'sprockets/directive_processor'
|
5
3
|
require 'sprockets/index'
|
6
|
-
require 'sprockets/safety_colons'
|
7
4
|
|
8
5
|
require 'hike'
|
9
6
|
require 'logger'
|
@@ -35,24 +32,24 @@ module Sprockets
|
|
35
32
|
@digest_class = ::Digest::MD5
|
36
33
|
@version = ''
|
37
34
|
|
38
|
-
@mime_types =
|
35
|
+
@mime_types = Sprockets.registered_mime_types
|
39
36
|
@engines = Sprockets.engines
|
40
|
-
@preprocessors =
|
41
|
-
@postprocessors =
|
42
|
-
@bundle_processors =
|
37
|
+
@preprocessors = Sprockets.preprocessors
|
38
|
+
@postprocessors = Sprockets.postprocessors
|
39
|
+
@bundle_processors = Sprockets.bundle_processors
|
40
|
+
@compressors = Sprockets.compressors
|
41
|
+
|
42
|
+
Sprockets.paths.each do |path|
|
43
|
+
append_path(path)
|
44
|
+
end
|
43
45
|
|
44
46
|
@engines.each do |ext, klass|
|
45
47
|
add_engine_to_trail(ext, klass)
|
46
48
|
end
|
47
49
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
register_preprocessor 'text/css', DirectiveProcessor
|
52
|
-
register_preprocessor 'application/javascript', DirectiveProcessor
|
53
|
-
|
54
|
-
register_postprocessor 'application/javascript', SafetyColons
|
55
|
-
register_bundle_processor 'text/css', CharsetNormalizer
|
50
|
+
@mime_types.each do |ext, type|
|
51
|
+
@trail.append_extension(ext)
|
52
|
+
end
|
56
53
|
|
57
54
|
expire_index!
|
58
55
|
|
data/lib/sprockets/errors.rb
CHANGED
data/lib/sprockets/index.rb
CHANGED
@@ -2,9 +2,7 @@ require 'tilt'
|
|
2
2
|
|
3
3
|
module Sprockets
|
4
4
|
class JstProcessor < Tilt::Template
|
5
|
-
|
6
|
-
'application/javascript'
|
7
|
-
end
|
5
|
+
self.default_mime_type = 'application/javascript'
|
8
6
|
|
9
7
|
def self.default_namespace
|
10
8
|
'this.JST'
|
@@ -18,9 +16,7 @@ module Sprockets
|
|
18
16
|
|
19
17
|
def evaluate(scope, locals, &block)
|
20
18
|
<<-JST
|
21
|
-
(function() {
|
22
|
-
#{namespace} || (#{namespace} = {});
|
23
|
-
#{namespace}[#{scope.logical_path.inspect}] = #{indent(data)};
|
19
|
+
(function() { #{namespace} || (#{namespace} = {}); #{namespace}[#{scope.logical_path.inspect}] = #{indent(data)};
|
24
20
|
}).call(this);
|
25
21
|
JST
|
26
22
|
end
|
data/lib/sprockets/manifest.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'multi_json'
|
2
|
+
require 'securerandom'
|
2
3
|
require 'time'
|
3
4
|
|
4
5
|
module Sprockets
|
@@ -18,26 +19,50 @@ module Sprockets
|
|
18
19
|
# a full path to the manifest json file. The file may or may not
|
19
20
|
# already exist. The dirname of the `path` will be used to write
|
20
21
|
# compiled assets to. Otherwise, if the path is a directory, the
|
21
|
-
# filename will default
|
22
|
+
# filename will default a random "manifest-123.json" file in that
|
23
|
+
# directory.
|
22
24
|
#
|
23
25
|
# Manifest.new(environment, "./public/assets/manifest.json")
|
24
26
|
#
|
25
|
-
def initialize(
|
26
|
-
|
27
|
+
def initialize(*args)
|
28
|
+
if args.first.is_a?(Base) || args.first.nil?
|
29
|
+
@environment = args.shift
|
30
|
+
end
|
27
31
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
@dir, @path = args[0], args[1]
|
33
|
+
|
34
|
+
# Expand paths
|
35
|
+
@dir = File.expand_path(@dir) if @dir
|
36
|
+
@path = File.expand_path(@path) if @path
|
37
|
+
|
38
|
+
# If path is given as the second arg
|
39
|
+
if @dir && File.extname(@dir) != ""
|
40
|
+
@dir, @path = nil, @dir
|
41
|
+
end
|
42
|
+
|
43
|
+
# Default dir to the directory of the path
|
44
|
+
@dir ||= File.dirname(@path) if @path
|
45
|
+
|
46
|
+
# If directory is given w/o path, pick a random manifest.json location
|
47
|
+
if @dir && @path.nil?
|
48
|
+
# Find the first manifest.json in the directory
|
49
|
+
paths = Dir[File.join(@dir, "manifest*.json")]
|
50
|
+
if paths.any?
|
51
|
+
@path = paths.first
|
52
|
+
else
|
53
|
+
@path = File.join(@dir, "manifest-#{SecureRandom.hex(16)}.json")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
unless @dir && @path
|
58
|
+
raise ArgumentError, "manifest requires output path"
|
34
59
|
end
|
35
60
|
|
36
61
|
data = nil
|
37
62
|
|
38
63
|
begin
|
39
64
|
if File.exist?(@path)
|
40
|
-
data =
|
65
|
+
data = json_decode(File.read(@path))
|
41
66
|
end
|
42
67
|
rescue MultiJson::DecodeError => e
|
43
68
|
logger.error "#{@path} is invalid: #{e.class} #{e.message}"
|
@@ -83,14 +108,19 @@ module Sprockets
|
|
83
108
|
# compile("application.js")
|
84
109
|
#
|
85
110
|
def compile(*args)
|
111
|
+
unless environment
|
112
|
+
raise Error, "manifest requires environment for compilation"
|
113
|
+
end
|
114
|
+
|
86
115
|
paths = environment.each_logical_path(*args).to_a +
|
87
|
-
args.flatten.select { |fn| Pathname.new(fn).absolute? }
|
116
|
+
args.flatten.select { |fn| Pathname.new(fn).absolute? if fn.is_a?(String)}
|
88
117
|
|
89
118
|
paths.each do |path|
|
90
119
|
if asset = find_asset(path)
|
91
120
|
files[asset.digest_path] = {
|
92
121
|
'logical_path' => asset.logical_path,
|
93
122
|
'mtime' => asset.mtime.iso8601,
|
123
|
+
'size' => asset.bytesize,
|
94
124
|
'digest' => asset.digest
|
95
125
|
}
|
96
126
|
assets[asset.logical_path] = asset.digest_path
|
@@ -102,12 +132,13 @@ module Sprockets
|
|
102
132
|
else
|
103
133
|
logger.info "Writing #{target}"
|
104
134
|
asset.write_to target
|
135
|
+
asset.write_to "#{target}.gz" if asset.is_a?(BundledAsset)
|
105
136
|
end
|
106
137
|
|
107
|
-
save
|
108
|
-
asset
|
109
138
|
end
|
110
139
|
end
|
140
|
+
save
|
141
|
+
paths
|
111
142
|
end
|
112
143
|
|
113
144
|
# Removes file from directory and from manifest. `filename` must
|
@@ -117,6 +148,7 @@ module Sprockets
|
|
117
148
|
#
|
118
149
|
def remove(filename)
|
119
150
|
path = File.join(dir, filename)
|
151
|
+
gzip = "#{path}.gz"
|
120
152
|
logical_path = files[filename]['logical_path']
|
121
153
|
|
122
154
|
if assets[logical_path] == filename
|
@@ -125,10 +157,11 @@ module Sprockets
|
|
125
157
|
|
126
158
|
files.delete(filename)
|
127
159
|
FileUtils.rm(path) if File.exist?(path)
|
160
|
+
FileUtils.rm(gzip) if File.exist?(gzip)
|
128
161
|
|
129
162
|
save
|
130
163
|
|
131
|
-
logger.
|
164
|
+
logger.info "Removed #{filename}"
|
132
165
|
|
133
166
|
nil
|
134
167
|
end
|
@@ -151,7 +184,7 @@ module Sprockets
|
|
151
184
|
# Wipe directive
|
152
185
|
def clobber
|
153
186
|
FileUtils.rm_r(@dir) if File.exist?(@dir)
|
154
|
-
logger.
|
187
|
+
logger.info "Removed #{@dir}"
|
155
188
|
nil
|
156
189
|
end
|
157
190
|
|
@@ -177,21 +210,46 @@ module Sprockets
|
|
177
210
|
ms = benchmark do
|
178
211
|
asset = environment.find_asset(logical_path)
|
179
212
|
end
|
180
|
-
logger.
|
213
|
+
logger.debug "Compiled #{logical_path} (#{ms}ms)"
|
181
214
|
asset
|
182
215
|
end
|
183
216
|
|
184
217
|
# Persist manfiest back to FS
|
185
218
|
def save
|
186
|
-
FileUtils.mkdir_p
|
219
|
+
FileUtils.mkdir_p File.dirname(path)
|
187
220
|
File.open(path, 'w') do |f|
|
188
|
-
f.write
|
221
|
+
f.write json_encode(@data)
|
189
222
|
end
|
190
223
|
end
|
191
224
|
|
192
225
|
private
|
226
|
+
# Feature detect newer MultiJson API
|
227
|
+
if MultiJson.respond_to?(:dump)
|
228
|
+
def json_decode(obj)
|
229
|
+
MultiJson.load(obj)
|
230
|
+
end
|
231
|
+
|
232
|
+
def json_encode(obj)
|
233
|
+
MultiJson.dump(obj)
|
234
|
+
end
|
235
|
+
else
|
236
|
+
def json_decode(obj)
|
237
|
+
MultiJson.decode(obj)
|
238
|
+
end
|
239
|
+
|
240
|
+
def json_encode(obj)
|
241
|
+
MultiJson.encode(obj)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
193
245
|
def logger
|
194
|
-
environment
|
246
|
+
if environment
|
247
|
+
environment.logger
|
248
|
+
else
|
249
|
+
logger = Logger.new($stderr)
|
250
|
+
logger.level = Logger::FATAL
|
251
|
+
logger
|
252
|
+
end
|
195
253
|
end
|
196
254
|
|
197
255
|
def benchmark
|
data/lib/sprockets/mime.rb
CHANGED
@@ -15,6 +15,11 @@ module Sprockets
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
# Returns a `Hash` of explicitly registered mime types.
|
19
|
+
def registered_mime_types
|
20
|
+
@mime_types.dup
|
21
|
+
end
|
22
|
+
|
18
23
|
if {}.respond_to?(:key)
|
19
24
|
def extension_for_mime_type(type)
|
20
25
|
mime_types.key(type)
|
@@ -41,8 +46,4 @@ module Sprockets
|
|
41
46
|
end
|
42
47
|
end
|
43
48
|
end
|
44
|
-
|
45
|
-
# Extend Sprockets module to provide global registry
|
46
|
-
extend Mime
|
47
|
-
@mime_types = {}
|
48
49
|
end
|
@@ -1,16 +1,11 @@
|
|
1
|
-
require 'sprockets/errors'
|
2
|
-
require 'pathname'
|
3
|
-
|
4
1
|
module Sprockets
|
5
|
-
|
6
|
-
# the `Environment` and `Index` classes.
|
7
|
-
module Trail
|
2
|
+
module Paths
|
8
3
|
# Returns `Environment` root.
|
9
4
|
#
|
10
5
|
# All relative paths are expanded with root as its base. To be
|
11
6
|
# useful set this to your applications root directory. (`Rails.root`)
|
12
7
|
def root
|
13
|
-
trail.root.dup
|
8
|
+
@trail.root.dup
|
14
9
|
end
|
15
10
|
|
16
11
|
# Returns an `Array` of path `String`s.
|
@@ -21,14 +16,13 @@ module Sprockets
|
|
21
16
|
# have no affect on the environment. See `append_path`,
|
22
17
|
# `prepend_path`, and `clear_paths`.
|
23
18
|
def paths
|
24
|
-
trail.paths.dup
|
19
|
+
@trail.paths.dup
|
25
20
|
end
|
26
21
|
|
27
22
|
# Prepend a `path` to the `paths` list.
|
28
23
|
#
|
29
24
|
# Paths at the end of the `Array` have the least priority.
|
30
25
|
def prepend_path(path)
|
31
|
-
expire_index!
|
32
26
|
@trail.prepend_path(path)
|
33
27
|
end
|
34
28
|
|
@@ -36,7 +30,6 @@ module Sprockets
|
|
36
30
|
#
|
37
31
|
# Paths at the beginning of the `Array` have a higher priority.
|
38
32
|
def append_path(path)
|
39
|
-
expire_index!
|
40
33
|
@trail.append_path(path)
|
41
34
|
end
|
42
35
|
|
@@ -46,7 +39,6 @@ module Sprockets
|
|
46
39
|
# completely wipe the paths list and reappend them in the order
|
47
40
|
# you want.
|
48
41
|
def clear_paths
|
49
|
-
expire_index!
|
50
42
|
@trail.paths.dup.each { |path| @trail.remove_path(path) }
|
51
43
|
end
|
52
44
|
|
@@ -57,34 +49,10 @@ module Sprockets
|
|
57
49
|
# # => [".js", ".css", ".coffee", ".sass", ...]
|
58
50
|
#
|
59
51
|
def extensions
|
60
|
-
trail.extensions.dup
|
61
|
-
end
|
62
|
-
|
63
|
-
# Finds the expanded real path for a given logical path by
|
64
|
-
# searching the environment's paths.
|
65
|
-
#
|
66
|
-
# resolve("application.js")
|
67
|
-
# # => "/path/to/app/javascripts/application.js.coffee"
|
68
|
-
#
|
69
|
-
# A `FileNotFound` exception is raised if the file does not exist.
|
70
|
-
def resolve(logical_path, options = {})
|
71
|
-
# If a block is given, preform an iterable search
|
72
|
-
if block_given?
|
73
|
-
args = attributes_for(logical_path).search_paths + [options]
|
74
|
-
trail.find(*args) do |path|
|
75
|
-
yield Pathname.new(path)
|
76
|
-
end
|
77
|
-
else
|
78
|
-
resolve(logical_path, options) do |pathname|
|
79
|
-
return pathname
|
80
|
-
end
|
81
|
-
raise FileNotFound, "couldn't find file '#{logical_path}'"
|
82
|
-
end
|
52
|
+
@trail.extensions.dup
|
83
53
|
end
|
84
54
|
|
85
55
|
protected
|
86
|
-
|
87
|
-
@trail
|
88
|
-
end
|
56
|
+
attr_reader :trail
|
89
57
|
end
|
90
58
|
end
|