sprockets 2.2.3 → 2.12.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sprockets might be problematic. Click here for more details.
- checksums.yaml +4 -4
- 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 +14 -7
- data/lib/sprockets/asset_attributes.rb +15 -4
- data/lib/sprockets/base.rb +154 -14
- 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/static_asset.rb +1 -0
- data/lib/sprockets/uglifier_compressor.rb +29 -0
- data/lib/sprockets/version.rb +1 -1
- data/lib/sprockets/yui_compressor.rb +27 -0
- metadata +72 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4ac3ec814692936eab4dc58704519ca15c383880
|
4
|
+
data.tar.gz: 1888571f870ed8cb1a4e7a36dd78b2c7079991ed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a11411a3911b1bb069ec8b350e3017d96377f70a7a41b62db3b8da1616186c57dd31a9d746f01cc7b16c1e717dd7dfcc1c513a2d92420a4ddbc7f1ee292bdb0
|
7
|
+
data.tar.gz: 036a48e5dc1c97776e9aa455e6b254ecfcd83edbd0cabc1c999c1b23f4881685458f9e2683c35e38d9ad72946facbefe05b2bdef962d9cc2ab9fa73c74780b82
|
data/README.md
CHANGED
@@ -159,9 +159,9 @@ variables, mixins, operations and functions.
|
|
159
159
|
|
160
160
|
If the `less` gem is available to your application, you can use LESS
|
161
161
|
to write CSS assets in Sprockets. Note that the LESS compiler is
|
162
|
-
written in JavaScript
|
163
|
-
|
164
|
-
|
162
|
+
written in JavaScript and the `less` gem (on MRI) uses `therubyracer`
|
163
|
+
which embeds the V8 JavaScript runtime in Ruby, while on JRuby you're
|
164
|
+
going to need `therubyrhino` gem installed.
|
165
165
|
|
166
166
|
To write CSS assets with LESS, use the extension `.css.less`.
|
167
167
|
|
@@ -336,6 +336,18 @@ source file before any subsequent `require` or `include` directives.
|
|
336
336
|
including it in the bundle. This is useful when you need to expire an
|
337
337
|
asset's cache in response to a change in another file.
|
338
338
|
|
339
|
+
### The `depend_on_asset` Directive ###
|
340
|
+
|
341
|
+
`depend_on_asset` *path* works like `depend_on`, but operates
|
342
|
+
recursively reading the the file and following the directives found.
|
343
|
+
|
344
|
+
### The `stub` Directive ###
|
345
|
+
|
346
|
+
`stub` *path* allows dependency to be excluded from the asset bundle.
|
347
|
+
The *path* must be a valid asset and may or may not already be part
|
348
|
+
of the bundle. Once stubbed, it is blacklisted and can't be brought
|
349
|
+
back by any other `require`.
|
350
|
+
|
339
351
|
# Development #
|
340
352
|
|
341
353
|
## Contributing ##
|
@@ -354,7 +366,126 @@ submit a pull request.
|
|
354
366
|
|
355
367
|
## Version History ##
|
356
368
|
|
357
|
-
**2.
|
369
|
+
**2.12.3** (October 28, 2014)
|
370
|
+
|
371
|
+
* Security: Fix directory traversal bug in development mode server.
|
372
|
+
|
373
|
+
**2.12.2** (September 5, 2014)
|
374
|
+
|
375
|
+
* Ensure internal asset lookups calls are still restricted to load paths within
|
376
|
+
asset compiles. Though, you should not depend on internal asset resolves to be
|
377
|
+
completely restricted for security reasons. Assets themselves should be
|
378
|
+
considered full scripting environments with filesystem access.
|
379
|
+
|
380
|
+
**2.12.1** (April 17, 2014)
|
381
|
+
|
382
|
+
* Fix making manifest target directory when its different than the output directory.
|
383
|
+
|
384
|
+
**2.12.0** (March 13, 2014)
|
385
|
+
|
386
|
+
* Avoid context reference in SassImporter hack so its Marshallable. Fixes
|
387
|
+
issues with Sass 3.3.x.
|
388
|
+
|
389
|
+
**2.11.0** (February 19, 2014)
|
390
|
+
|
391
|
+
* Support for `.bower.json`
|
392
|
+
|
393
|
+
**2.10.0** (May 24, 2013)
|
394
|
+
|
395
|
+
* Support for `bower.json`
|
396
|
+
|
397
|
+
**2.9.3** (April 20, 2013)
|
398
|
+
|
399
|
+
* Fixed sass caching bug
|
400
|
+
|
401
|
+
**2.9.2** (April 8, 2013)
|
402
|
+
|
403
|
+
* Improve file freshness check performance
|
404
|
+
* Directive processor encoding fixes
|
405
|
+
|
406
|
+
**2.9.1** (April 6, 2013)
|
407
|
+
|
408
|
+
* Support for Uglifier 2.x
|
409
|
+
|
410
|
+
**2.9.0** (February 25, 2013)
|
411
|
+
|
412
|
+
* Write out gzipped variants of bundled assets.
|
413
|
+
|
414
|
+
**2.8.2** (December 10, 2012)
|
415
|
+
|
416
|
+
* Fixed top level Sass constant references
|
417
|
+
* Fixed manifest logger when environment is disabled
|
418
|
+
|
419
|
+
**2.8.1** (October 31, 2012)
|
420
|
+
|
421
|
+
* Fixed Sass importer bug
|
422
|
+
|
423
|
+
**2.8.0** (October 16, 2012)
|
424
|
+
|
425
|
+
* Allow manifest location to be seperated from output directory
|
426
|
+
* Pass logical path and absolute path to each_logical_path iterator
|
427
|
+
|
428
|
+
**2.7.0** (October 10, 2012)
|
429
|
+
|
430
|
+
* Added --css-compressor and --js-compressor command line flags
|
431
|
+
* Added css/js compressor shorthand
|
432
|
+
* Change default manifest.json filename to be a randomized manifest-16HEXBYTES.json
|
433
|
+
* Allow nil environment to be passed to manifest
|
434
|
+
* Allow manifest instance to be set on rake task
|
435
|
+
|
436
|
+
**2.6.0** (September 19, 2012)
|
437
|
+
|
438
|
+
* Added bower component.json require support
|
439
|
+
|
440
|
+
**2.5.0** (September 4, 2012)
|
441
|
+
|
442
|
+
* Fixed Ruby 2.0 RegExp warning
|
443
|
+
* Provide stubbed implementation of context *_path helpers
|
444
|
+
* Add SassCompressor
|
445
|
+
|
446
|
+
**2.4.5** (July 10, 2012)
|
447
|
+
|
448
|
+
* Tweaked some logger levels
|
449
|
+
|
450
|
+
**2.4.4** (July 2, 2012)
|
451
|
+
|
452
|
+
* Canonicalize logical path extensions
|
453
|
+
* Check absolute paths passed to depend_on
|
454
|
+
|
455
|
+
**2.4.3** (May 16, 2012)
|
456
|
+
|
457
|
+
* Exposed :sprockets in sass options
|
458
|
+
* Include dependency paths in asset mtime
|
459
|
+
|
460
|
+
**2.4.2** (May 7, 2012)
|
461
|
+
|
462
|
+
* Fixed MultiJson feature detect
|
463
|
+
|
464
|
+
**2.4.1** (April 26, 2012)
|
465
|
+
|
466
|
+
* Fixed MultiJson API change
|
467
|
+
* Fixed gzip mtime
|
468
|
+
|
469
|
+
**2.4.0** (March 27, 2012)
|
470
|
+
|
471
|
+
* Added global path registry
|
472
|
+
* Added global processor registry
|
473
|
+
|
474
|
+
**2.3.2** (March 26, 2012)
|
475
|
+
|
476
|
+
* Fix Context#logical_path with dots
|
477
|
+
|
478
|
+
**2.3.1** (February 11, 2012)
|
479
|
+
|
480
|
+
* Added bytesize to manifest
|
481
|
+
* Added Asset#bytesize alias
|
482
|
+
* Security: Check path for forbidden access after unescaping
|
483
|
+
|
484
|
+
**2.3.0** (January 16, 2012)
|
485
|
+
|
486
|
+
* Added special Sass importer that automatically tracks any `@import`ed files.
|
487
|
+
|
488
|
+
**2.2.0** (January 10, 2012)
|
358
489
|
|
359
490
|
* Added `sprockets` command line utility.
|
360
491
|
* Added rake/sprocketstask.
|
data/bin/sprockets
CHANGED
@@ -40,6 +40,14 @@ OptionParser.new do |opts|
|
|
40
40
|
manifest = Sprockets::Manifest.new(environment, directory)
|
41
41
|
end
|
42
42
|
|
43
|
+
opts.on("--css-compressor=COMPRESSOR", "Use CSS compressor") do |compressor|
|
44
|
+
environment.css_compressor = compressor.to_sym
|
45
|
+
end
|
46
|
+
|
47
|
+
opts.on("--js-compressor=COMPRESSOR", "Use JavaScript compressor") do |compressor|
|
48
|
+
environment.js_compressor = compressor.to_sym
|
49
|
+
end
|
50
|
+
|
43
51
|
opts.on("--noenv", "Disables .sprocketsrc file") do
|
44
52
|
end
|
45
53
|
|
data/lib/rake/sprocketstask.rb
CHANGED
@@ -37,6 +37,24 @@ module Rake
|
|
37
37
|
end
|
38
38
|
attr_writer :environment
|
39
39
|
|
40
|
+
# Returns cached indexed environment
|
41
|
+
def index
|
42
|
+
@index ||= environment.index if environment
|
43
|
+
end
|
44
|
+
|
45
|
+
# `Manifest` instance used for already compiled assets.
|
46
|
+
#
|
47
|
+
# Will be created by default if an environment and output
|
48
|
+
# directory are given
|
49
|
+
def manifest
|
50
|
+
if !@manifest.is_a?(Sprockets::Manifest) && @manifest.respond_to?(:call)
|
51
|
+
@manifest = @manifest.call
|
52
|
+
else
|
53
|
+
@manifest
|
54
|
+
end
|
55
|
+
end
|
56
|
+
attr_writer :manifest
|
57
|
+
|
40
58
|
# Directory to write compiled assets too. As well as the manifest file.
|
41
59
|
#
|
42
60
|
# t.output = "./public/assets"
|
@@ -79,6 +97,7 @@ module Rake
|
|
79
97
|
def initialize(name = :assets)
|
80
98
|
@name = name
|
81
99
|
@environment = lambda { Sprockets::Environment.new(Dir.pwd) }
|
100
|
+
@manifest = lambda { Sprockets::Manifest.new(index, output) }
|
82
101
|
@logger = Logger.new($stderr)
|
83
102
|
@logger.level = Logger::INFO
|
84
103
|
@keep = 2
|
@@ -117,24 +136,16 @@ module Rake
|
|
117
136
|
end
|
118
137
|
|
119
138
|
private
|
120
|
-
# Returns cached indexed environment
|
121
|
-
def index
|
122
|
-
@index ||= environment.index
|
123
|
-
end
|
124
|
-
|
125
|
-
# Returns manifest for tasks
|
126
|
-
def manifest
|
127
|
-
@manifest ||= Sprockets::Manifest.new(index, output)
|
128
|
-
end
|
129
|
-
|
130
139
|
# Sub out environment logger with our rake task logger that
|
131
140
|
# writes to stderr.
|
132
141
|
def with_logger
|
133
|
-
|
134
|
-
|
142
|
+
if env = manifest.environment
|
143
|
+
old_logger = env.logger
|
144
|
+
env.logger = @logger
|
145
|
+
end
|
135
146
|
yield
|
136
147
|
ensure
|
137
|
-
|
148
|
+
env.logger = old_logger if env
|
138
149
|
end
|
139
150
|
end
|
140
151
|
end
|
data/lib/sprockets.rb
CHANGED
@@ -3,7 +3,6 @@ require 'sprockets/version'
|
|
3
3
|
module Sprockets
|
4
4
|
# Environment
|
5
5
|
autoload :Base, "sprockets/base"
|
6
|
-
autoload :Engines, "sprockets/engines"
|
7
6
|
autoload :Environment, "sprockets/environment"
|
8
7
|
autoload :Index, "sprockets/index"
|
9
8
|
autoload :Manifest, "sprockets/manifest"
|
@@ -15,14 +14,16 @@ module Sprockets
|
|
15
14
|
autoload :StaticAsset, "sprockets/static_asset"
|
16
15
|
|
17
16
|
# Processing
|
18
|
-
autoload :CharsetNormalizer, "sprockets/charset_normalizer"
|
19
17
|
autoload :Context, "sprockets/context"
|
20
|
-
autoload :DirectiveProcessor, "sprockets/directive_processor"
|
21
18
|
autoload :EcoTemplate, "sprockets/eco_template"
|
22
19
|
autoload :EjsTemplate, "sprockets/ejs_template"
|
23
20
|
autoload :JstProcessor, "sprockets/jst_processor"
|
24
21
|
autoload :Processor, "sprockets/processor"
|
25
|
-
autoload :
|
22
|
+
autoload :SassCacheStore, "sprockets/sass_cache_store"
|
23
|
+
autoload :SassFunctions, "sprockets/sass_functions"
|
24
|
+
autoload :SassImporter, "sprockets/sass_importer"
|
25
|
+
autoload :SassTemplate, "sprockets/sass_template"
|
26
|
+
autoload :ScssTemplate, "sprockets/scss_template"
|
26
27
|
|
27
28
|
# Internal utilities
|
28
29
|
autoload :ArgumentError, "sprockets/errors"
|
@@ -39,8 +40,51 @@ module Sprockets
|
|
39
40
|
end
|
40
41
|
|
41
42
|
# Extend Sprockets module to provide global registry
|
42
|
-
|
43
|
-
|
43
|
+
require 'hike'
|
44
|
+
require 'sprockets/engines'
|
45
|
+
require 'sprockets/mime'
|
46
|
+
require 'sprockets/processing'
|
47
|
+
require 'sprockets/compressing'
|
48
|
+
require 'sprockets/paths'
|
49
|
+
extend Engines, Mime, Processing, Compressing, Paths
|
50
|
+
|
51
|
+
@trail = Hike::Trail.new(File.expand_path('..', __FILE__))
|
52
|
+
@mime_types = {}
|
53
|
+
@engines = {}
|
54
|
+
@preprocessors = Hash.new { |h, k| h[k] = [] }
|
55
|
+
@postprocessors = Hash.new { |h, k| h[k] = [] }
|
56
|
+
@bundle_processors = Hash.new { |h, k| h[k] = [] }
|
57
|
+
@compressors = Hash.new { |h, k| h[k] = {} }
|
58
|
+
|
59
|
+
register_mime_type 'text/css', '.css'
|
60
|
+
register_mime_type 'application/javascript', '.js'
|
61
|
+
|
62
|
+
require 'sprockets/directive_processor'
|
63
|
+
register_preprocessor 'text/css', DirectiveProcessor
|
64
|
+
register_preprocessor 'application/javascript', DirectiveProcessor
|
65
|
+
|
66
|
+
require 'sprockets/safety_colons'
|
67
|
+
register_postprocessor 'application/javascript', SafetyColons
|
68
|
+
|
69
|
+
require 'sprockets/charset_normalizer'
|
70
|
+
register_bundle_processor 'text/css', CharsetNormalizer
|
71
|
+
|
72
|
+
require 'sprockets/sass_compressor'
|
73
|
+
register_compressor 'text/css', :sass, SassCompressor
|
74
|
+
register_compressor 'text/css', :scss, SassCompressor
|
75
|
+
|
76
|
+
require 'sprockets/yui_compressor'
|
77
|
+
register_compressor 'text/css', :yui, YUICompressor
|
78
|
+
|
79
|
+
require 'sprockets/closure_compressor'
|
80
|
+
register_compressor 'application/javascript', :closure, ClosureCompressor
|
81
|
+
|
82
|
+
require 'sprockets/uglifier_compressor'
|
83
|
+
register_compressor 'application/javascript', :uglifier, UglifierCompressor
|
84
|
+
register_compressor 'application/javascript', :uglify, UglifierCompressor
|
85
|
+
|
86
|
+
require 'sprockets/yui_compressor'
|
87
|
+
register_compressor 'application/javascript', :yui, YUICompressor
|
44
88
|
|
45
89
|
# Cherry pick the default Tilt engines that make sense for
|
46
90
|
# Sprockets. We don't need ones that only generate html like HAML.
|
@@ -55,8 +99,8 @@ module Sprockets
|
|
55
99
|
|
56
100
|
# CSS engines
|
57
101
|
register_engine '.less', Tilt::LessTemplate
|
58
|
-
register_engine '.sass',
|
59
|
-
register_engine '.scss',
|
102
|
+
register_engine '.sass', SassTemplate
|
103
|
+
register_engine '.scss', ScssTemplate
|
60
104
|
|
61
105
|
# Other
|
62
106
|
register_engine '.erb', Tilt::ERBTemplate
|
data/lib/sprockets/asset.rb
CHANGED
@@ -30,13 +30,17 @@ module Sprockets
|
|
30
30
|
|
31
31
|
attr_reader :logical_path, :pathname
|
32
32
|
attr_reader :content_type, :mtime, :length, :digest
|
33
|
+
alias_method :bytesize, :length
|
33
34
|
|
34
35
|
def initialize(environment, logical_path, pathname)
|
36
|
+
raise ArgumentError, "Asset logical path has no extension: #{logical_path}" if File.extname(logical_path) == ""
|
37
|
+
|
35
38
|
@root = environment.root
|
36
39
|
@logical_path = logical_path.to_s
|
37
40
|
@pathname = Pathname.new(pathname)
|
38
41
|
@content_type = environment.content_type_of(pathname)
|
39
|
-
|
42
|
+
# drop precision to 1 second, same pattern followed elsewhere
|
43
|
+
@mtime = Time.at(environment.stat(pathname).mtime.to_i)
|
40
44
|
@length = environment.stat(pathname).size
|
41
45
|
@digest = environment.file_digest(pathname).hexdigest
|
42
46
|
end
|
@@ -55,8 +59,7 @@ module Sprockets
|
|
55
59
|
end
|
56
60
|
|
57
61
|
if mtime = coder['mtime']
|
58
|
-
|
59
|
-
@mtime = Time.parse(mtime)
|
62
|
+
@mtime = Time.at(mtime)
|
60
63
|
end
|
61
64
|
|
62
65
|
if length = coder['length']
|
@@ -71,7 +74,7 @@ module Sprockets
|
|
71
74
|
coder['logical_path'] = logical_path
|
72
75
|
coder['pathname'] = relativize_root_path(pathname).to_s
|
73
76
|
coder['content_type'] = content_type
|
74
|
-
coder['mtime'] = mtime.
|
77
|
+
coder['mtime'] = mtime.to_i
|
75
78
|
coder['length'] = length
|
76
79
|
coder['digest'] = digest
|
77
80
|
end
|
@@ -144,12 +147,12 @@ module Sprockets
|
|
144
147
|
if options[:compress]
|
145
148
|
# Run contents through `Zlib`
|
146
149
|
gz = Zlib::GzipWriter.new(f, Zlib::BEST_COMPRESSION)
|
150
|
+
gz.mtime = mtime.to_i
|
147
151
|
gz.write to_s
|
148
152
|
gz.close
|
149
153
|
else
|
150
154
|
# Write out as is
|
151
155
|
f.write to_s
|
152
|
-
f.close
|
153
156
|
end
|
154
157
|
end
|
155
158
|
|
@@ -233,7 +236,7 @@ module Sprockets
|
|
233
236
|
return false
|
234
237
|
end
|
235
238
|
|
236
|
-
# Compare dependency
|
239
|
+
# Compare dependency mtime to the actual mtime. If the
|
237
240
|
# dependency mtime is newer than the actual mtime, the file
|
238
241
|
# hasn't changed since we created this `Asset` instance.
|
239
242
|
#
|
@@ -241,7 +244,11 @@ module Sprockets
|
|
241
244
|
# stale. Many deployment environments may recopy or recheckout
|
242
245
|
# assets on each deploy. In this case the mtime would be the
|
243
246
|
# time of deploy rather than modified time.
|
244
|
-
|
247
|
+
#
|
248
|
+
# Note: to_i is used in eql? and write_to we assume fidelity of 1 second
|
249
|
+
# if people save files more frequently than 1 second sprockets may
|
250
|
+
# not pick it up, by design
|
251
|
+
if mtime.to_i >= stat.mtime.to_i
|
245
252
|
return true
|
246
253
|
end
|
247
254
|
|
@@ -17,10 +17,21 @@ module Sprockets
|
|
17
17
|
def search_paths
|
18
18
|
paths = [pathname.to_s]
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
extension = format_extension
|
21
|
+
path_without_extension = extension ?
|
22
|
+
pathname.sub(extension, '') :
|
23
|
+
pathname
|
24
|
+
|
25
|
+
# optimization: bower.json can only be nested one level deep
|
26
|
+
if !path_without_extension.to_s.index('/')
|
27
|
+
paths << path_without_extension.join(".bower.json").to_s
|
28
|
+
paths << path_without_extension.join("bower.json").to_s
|
29
|
+
# DEPRECATED bower configuration file
|
30
|
+
paths << path_without_extension.join("component.json").to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
if pathname.basename(extension.to_s).to_s != 'index'
|
34
|
+
paths << path_without_extension.join("index#{extension}").to_s
|
24
35
|
end
|
25
36
|
|
26
37
|
paths
|
data/lib/sprockets/base.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
require 'sprockets/asset_attributes'
|
2
2
|
require 'sprockets/bundled_asset'
|
3
3
|
require 'sprockets/caching'
|
4
|
+
require 'sprockets/errors'
|
4
5
|
require 'sprockets/processed_asset'
|
5
|
-
require 'sprockets/processing'
|
6
6
|
require 'sprockets/server'
|
7
7
|
require 'sprockets/static_asset'
|
8
|
-
require '
|
8
|
+
require 'multi_json'
|
9
9
|
require 'pathname'
|
10
10
|
|
11
11
|
module Sprockets
|
12
12
|
# `Base` class for `Environment` and `Index`.
|
13
13
|
class Base
|
14
|
-
include Caching, Processing,
|
14
|
+
include Caching, Paths, Mime, Processing, Compressing, Engines, Server
|
15
15
|
|
16
16
|
# Returns a `Digest` implementation class.
|
17
17
|
#
|
@@ -98,6 +98,114 @@ module Sprockets
|
|
98
98
|
@cache = cache
|
99
99
|
end
|
100
100
|
|
101
|
+
def prepend_path(path)
|
102
|
+
# Overrides the global behavior to expire the index
|
103
|
+
expire_index!
|
104
|
+
super
|
105
|
+
end
|
106
|
+
|
107
|
+
def append_path(path)
|
108
|
+
# Overrides the global behavior to expire the index
|
109
|
+
expire_index!
|
110
|
+
super
|
111
|
+
end
|
112
|
+
|
113
|
+
def clear_paths
|
114
|
+
# Overrides the global behavior to expire the index
|
115
|
+
expire_index!
|
116
|
+
super
|
117
|
+
end
|
118
|
+
|
119
|
+
# Finds the expanded real path for a given logical path by
|
120
|
+
# searching the environment's paths.
|
121
|
+
#
|
122
|
+
# resolve("application.js")
|
123
|
+
# # => "/path/to/app/javascripts/application.js.coffee"
|
124
|
+
#
|
125
|
+
# A `FileNotFound` exception is raised if the file does not exist.
|
126
|
+
def resolve(logical_path, options = {})
|
127
|
+
# If a block is given, preform an iterable search
|
128
|
+
if block_given?
|
129
|
+
args = attributes_for(logical_path).search_paths + [options]
|
130
|
+
@trail.find(*args) do |path|
|
131
|
+
pathname = Pathname.new(path)
|
132
|
+
if %w( .bower.json bower.json component.json ).include?(pathname.basename.to_s)
|
133
|
+
bower = json_decode(pathname.read)
|
134
|
+
case bower['main']
|
135
|
+
when String
|
136
|
+
yield pathname.dirname.join(bower['main'])
|
137
|
+
when Array
|
138
|
+
extname = File.extname(logical_path)
|
139
|
+
bower['main'].each do |fn|
|
140
|
+
if extname == "" || extname == File.extname(fn)
|
141
|
+
yield pathname.dirname.join(fn)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
else
|
146
|
+
yield pathname
|
147
|
+
end
|
148
|
+
end
|
149
|
+
else
|
150
|
+
resolve(logical_path, options) do |pathname|
|
151
|
+
return pathname
|
152
|
+
end
|
153
|
+
raise FileNotFound, "couldn't find file '#{logical_path}'"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Register a new mime type.
|
158
|
+
def register_mime_type(mime_type, ext)
|
159
|
+
# Overrides the global behavior to expire the index
|
160
|
+
expire_index!
|
161
|
+
@trail.append_extension(ext)
|
162
|
+
super
|
163
|
+
end
|
164
|
+
|
165
|
+
# Registers a new Engine `klass` for `ext`.
|
166
|
+
def register_engine(ext, klass)
|
167
|
+
# Overrides the global behavior to expire the index
|
168
|
+
expire_index!
|
169
|
+
add_engine_to_trail(ext, klass)
|
170
|
+
super
|
171
|
+
end
|
172
|
+
|
173
|
+
def register_preprocessor(mime_type, klass, &block)
|
174
|
+
# Overrides the global behavior to expire the index
|
175
|
+
expire_index!
|
176
|
+
super
|
177
|
+
end
|
178
|
+
|
179
|
+
def unregister_preprocessor(mime_type, klass)
|
180
|
+
# Overrides the global behavior to expire the index
|
181
|
+
expire_index!
|
182
|
+
super
|
183
|
+
end
|
184
|
+
|
185
|
+
def register_postprocessor(mime_type, klass, &block)
|
186
|
+
# Overrides the global behavior to expire the index
|
187
|
+
expire_index!
|
188
|
+
super
|
189
|
+
end
|
190
|
+
|
191
|
+
def unregister_postprocessor(mime_type, klass)
|
192
|
+
# Overrides the global behavior to expire the index
|
193
|
+
expire_index!
|
194
|
+
super
|
195
|
+
end
|
196
|
+
|
197
|
+
def register_bundle_processor(mime_type, klass, &block)
|
198
|
+
# Overrides the global behavior to expire the index
|
199
|
+
expire_index!
|
200
|
+
super
|
201
|
+
end
|
202
|
+
|
203
|
+
def unregister_bundle_processor(mime_type, klass)
|
204
|
+
# Overrides the global behavior to expire the index
|
205
|
+
expire_index!
|
206
|
+
super
|
207
|
+
end
|
208
|
+
|
101
209
|
# Return an `Index`. Must be implemented by the subclass.
|
102
210
|
def index
|
103
211
|
raise NotImplementedError
|
@@ -113,14 +221,14 @@ module Sprockets
|
|
113
221
|
#
|
114
222
|
# Subclasses may cache this method.
|
115
223
|
def entries(pathname)
|
116
|
-
trail.entries(pathname)
|
224
|
+
@trail.entries(pathname)
|
117
225
|
end
|
118
226
|
|
119
227
|
# Works like `File.stat`.
|
120
228
|
#
|
121
229
|
# Subclasses may cache this method.
|
122
230
|
def stat(path)
|
123
|
-
trail.stat(path)
|
231
|
+
@trail.stat(path)
|
124
232
|
end
|
125
233
|
|
126
234
|
# Read and compute digest of filename.
|
@@ -153,7 +261,7 @@ module Sprockets
|
|
153
261
|
# Find asset by logical path or expanded path.
|
154
262
|
def find_asset(path, options = {})
|
155
263
|
logical_path = path
|
156
|
-
pathname = Pathname.new(path)
|
264
|
+
pathname = Pathname.new(path).cleanpath
|
157
265
|
|
158
266
|
if pathname.absolute?
|
159
267
|
return unless stat(pathname)
|
@@ -161,6 +269,16 @@ module Sprockets
|
|
161
269
|
else
|
162
270
|
begin
|
163
271
|
pathname = resolve(logical_path)
|
272
|
+
|
273
|
+
# If logical path is missing a mime type extension, append
|
274
|
+
# the absolute path extname so it has one.
|
275
|
+
#
|
276
|
+
# Ensures some consistency between finding "foo/bar" vs
|
277
|
+
# "foo/bar.js".
|
278
|
+
if File.extname(logical_path) == ""
|
279
|
+
expanded_logical_path = attributes_for(pathname).logical_path
|
280
|
+
logical_path += File.extname(expanded_logical_path)
|
281
|
+
end
|
164
282
|
rescue FileNotFound
|
165
283
|
return nil
|
166
284
|
end
|
@@ -210,13 +328,20 @@ module Sprockets
|
|
210
328
|
nil
|
211
329
|
end
|
212
330
|
|
213
|
-
def each_logical_path(*args)
|
331
|
+
def each_logical_path(*args, &block)
|
214
332
|
return to_enum(__method__, *args) unless block_given?
|
215
333
|
filters = args.flatten
|
216
334
|
files = {}
|
217
335
|
each_file do |filename|
|
218
336
|
if logical_path = logical_path_for_filename(filename, filters)
|
219
|
-
|
337
|
+
unless files[logical_path]
|
338
|
+
if block.arity == 2
|
339
|
+
yield logical_path, filename.to_s
|
340
|
+
else
|
341
|
+
yield logical_path
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
220
345
|
files[logical_path] = true
|
221
346
|
end
|
222
347
|
end
|
@@ -275,14 +400,14 @@ module Sprockets
|
|
275
400
|
def logical_path_for_filename(filename, filters)
|
276
401
|
logical_path = attributes_for(filename).logical_path.to_s
|
277
402
|
|
278
|
-
if matches_filter(filters, logical_path)
|
403
|
+
if matches_filter(filters, logical_path, filename)
|
279
404
|
return logical_path
|
280
405
|
end
|
281
406
|
|
282
407
|
# If filename is an index file, retest with alias
|
283
408
|
if File.basename(logical_path)[/[^\.]+/, 0] == 'index'
|
284
409
|
path = logical_path.sub(/\/index\./, '.')
|
285
|
-
if matches_filter(filters, path)
|
410
|
+
if matches_filter(filters, path, filename)
|
286
411
|
return path
|
287
412
|
end
|
288
413
|
end
|
@@ -290,18 +415,33 @@ module Sprockets
|
|
290
415
|
nil
|
291
416
|
end
|
292
417
|
|
293
|
-
def matches_filter(filters, filename)
|
418
|
+
def matches_filter(filters, logical_path, filename)
|
294
419
|
return true if filters.empty?
|
295
420
|
|
296
421
|
filters.any? do |filter|
|
297
422
|
if filter.is_a?(Regexp)
|
298
|
-
filter.match(
|
423
|
+
filter.match(logical_path)
|
299
424
|
elsif filter.respond_to?(:call)
|
300
|
-
filter.
|
425
|
+
if filter.arity == 1
|
426
|
+
filter.call(logical_path)
|
427
|
+
else
|
428
|
+
filter.call(logical_path, filename.to_s)
|
429
|
+
end
|
301
430
|
else
|
302
|
-
File.fnmatch(filter.to_s,
|
431
|
+
File.fnmatch(filter.to_s, logical_path)
|
303
432
|
end
|
304
433
|
end
|
305
434
|
end
|
435
|
+
|
436
|
+
# Feature detect newer MultiJson API
|
437
|
+
if MultiJson.respond_to?(:dump)
|
438
|
+
def json_decode(obj)
|
439
|
+
MultiJson.load(obj)
|
440
|
+
end
|
441
|
+
else
|
442
|
+
def json_decode(obj)
|
443
|
+
MultiJson.decode(obj)
|
444
|
+
end
|
445
|
+
end
|
306
446
|
end
|
307
447
|
end
|