sprockets 2.2.3 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +68 -0
- data/README.md +482 -255
- data/bin/sprockets +20 -7
- data/lib/rake/sprocketstask.rb +28 -15
- data/lib/sprockets/add_source_map_comment_to_asset_processor.rb +60 -0
- data/lib/sprockets/asset.rb +142 -207
- data/lib/sprockets/autoload/babel.rb +8 -0
- data/lib/sprockets/autoload/closure.rb +8 -0
- data/lib/sprockets/autoload/coffee_script.rb +8 -0
- data/lib/sprockets/autoload/eco.rb +8 -0
- data/lib/sprockets/autoload/ejs.rb +8 -0
- data/lib/sprockets/autoload/jsminc.rb +8 -0
- data/lib/sprockets/autoload/sass.rb +8 -0
- data/lib/sprockets/autoload/sassc.rb +8 -0
- data/lib/sprockets/autoload/uglifier.rb +8 -0
- data/lib/sprockets/autoload/yui.rb +8 -0
- data/lib/sprockets/autoload/zopfli.rb +7 -0
- data/lib/sprockets/autoload.rb +16 -0
- data/lib/sprockets/babel_processor.rb +66 -0
- data/lib/sprockets/base.rb +89 -249
- data/lib/sprockets/bower.rb +61 -0
- data/lib/sprockets/bundle.rb +105 -0
- data/lib/sprockets/cache/file_store.rb +190 -14
- data/lib/sprockets/cache/memory_store.rb +75 -0
- data/lib/sprockets/cache/null_store.rb +54 -0
- data/lib/sprockets/cache.rb +271 -0
- data/lib/sprockets/cached_environment.rb +64 -0
- data/lib/sprockets/closure_compressor.rb +48 -0
- data/lib/sprockets/coffee_script_processor.rb +39 -0
- data/lib/sprockets/compressing.rb +134 -0
- data/lib/sprockets/configuration.rb +79 -0
- data/lib/sprockets/context.rb +204 -135
- data/lib/sprockets/dependencies.rb +74 -0
- data/lib/sprockets/digest_utils.rb +200 -0
- data/lib/sprockets/directive_processor.rb +224 -216
- data/lib/sprockets/eco_processor.rb +33 -0
- data/lib/sprockets/ejs_processor.rb +32 -0
- data/lib/sprockets/encoding_utils.rb +262 -0
- data/lib/sprockets/environment.rb +23 -68
- data/lib/sprockets/erb_processor.rb +37 -0
- data/lib/sprockets/errors.rb +6 -13
- data/lib/sprockets/exporters/base.rb +72 -0
- data/lib/sprockets/exporters/file_exporter.rb +24 -0
- data/lib/sprockets/exporters/zlib_exporter.rb +33 -0
- data/lib/sprockets/exporters/zopfli_exporter.rb +14 -0
- data/lib/sprockets/exporting.rb +73 -0
- data/lib/sprockets/file_reader.rb +16 -0
- data/lib/sprockets/http_utils.rb +135 -0
- data/lib/sprockets/jsminc_compressor.rb +32 -0
- data/lib/sprockets/jst_processor.rb +36 -19
- data/lib/sprockets/loader.rb +343 -0
- data/lib/sprockets/manifest.rb +231 -96
- data/lib/sprockets/manifest_utils.rb +48 -0
- data/lib/sprockets/mime.rb +80 -32
- data/lib/sprockets/npm.rb +52 -0
- data/lib/sprockets/path_dependency_utils.rb +77 -0
- data/lib/sprockets/path_digest_utils.rb +48 -0
- data/lib/sprockets/path_utils.rb +367 -0
- data/lib/sprockets/paths.rb +82 -0
- data/lib/sprockets/preprocessors/default_source_map.rb +49 -0
- data/lib/sprockets/processing.rb +140 -192
- data/lib/sprockets/processor_utils.rb +169 -0
- data/lib/sprockets/resolve.rb +295 -0
- data/lib/sprockets/sass_cache_store.rb +30 -0
- data/lib/sprockets/sass_compressor.rb +63 -0
- data/lib/sprockets/sass_functions.rb +3 -0
- data/lib/sprockets/sass_importer.rb +3 -0
- data/lib/sprockets/sass_processor.rb +313 -0
- data/lib/sprockets/sassc_compressor.rb +56 -0
- data/lib/sprockets/sassc_processor.rb +297 -0
- data/lib/sprockets/server.rb +138 -90
- data/lib/sprockets/source_map_processor.rb +66 -0
- data/lib/sprockets/source_map_utils.rb +483 -0
- data/lib/sprockets/transformers.rb +173 -0
- data/lib/sprockets/uglifier_compressor.rb +66 -0
- data/lib/sprockets/unloaded_asset.rb +139 -0
- data/lib/sprockets/uri_tar.rb +99 -0
- data/lib/sprockets/uri_utils.rb +191 -0
- data/lib/sprockets/utils/gzip.rb +99 -0
- data/lib/sprockets/utils.rb +186 -53
- data/lib/sprockets/version.rb +2 -1
- data/lib/sprockets/yui_compressor.rb +56 -0
- data/lib/sprockets.rb +217 -52
- metadata +250 -59
- data/LICENSE +0 -21
- data/lib/sprockets/asset_attributes.rb +0 -126
- data/lib/sprockets/bundled_asset.rb +0 -79
- data/lib/sprockets/caching.rb +0 -96
- data/lib/sprockets/charset_normalizer.rb +0 -41
- data/lib/sprockets/eco_template.rb +0 -38
- data/lib/sprockets/ejs_template.rb +0 -37
- data/lib/sprockets/engines.rb +0 -74
- data/lib/sprockets/index.rb +0 -99
- data/lib/sprockets/processed_asset.rb +0 -152
- data/lib/sprockets/processor.rb +0 -32
- data/lib/sprockets/safety_colons.rb +0 -28
- data/lib/sprockets/static_asset.rb +0 -57
- data/lib/sprockets/trail.rb +0 -90
data/lib/sprockets/caching.rb
DELETED
@@ -1,96 +0,0 @@
|
|
1
|
-
module Sprockets
|
2
|
-
# `Caching` is an internal mixin whose public methods are exposed on
|
3
|
-
# the `Environment` and `Index` classes.
|
4
|
-
module Caching
|
5
|
-
protected
|
6
|
-
# Cache helper method. Takes a `path` argument which maybe a
|
7
|
-
# logical path or fully expanded path. The `&block` is passed
|
8
|
-
# for finding and building the asset if its not in cache.
|
9
|
-
def cache_asset(path)
|
10
|
-
# If `cache` is not set, return fast
|
11
|
-
if cache.nil?
|
12
|
-
yield
|
13
|
-
|
14
|
-
# Check cache for `path`
|
15
|
-
elsif (asset = Asset.from_hash(self, cache_get_hash(path.to_s))) && asset.fresh?(self)
|
16
|
-
asset
|
17
|
-
|
18
|
-
# Otherwise yield block that slowly finds and builds the asset
|
19
|
-
elsif asset = yield
|
20
|
-
hash = {}
|
21
|
-
asset.encode_with(hash)
|
22
|
-
|
23
|
-
# Save the asset to its path
|
24
|
-
cache_set_hash(path.to_s, hash)
|
25
|
-
|
26
|
-
# Since path maybe a logical or full pathname, save the
|
27
|
-
# asset its its full path too
|
28
|
-
if path.to_s != asset.pathname.to_s
|
29
|
-
cache_set_hash(asset.pathname.to_s, hash)
|
30
|
-
end
|
31
|
-
|
32
|
-
asset
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
# Strips `Environment#root` from key to make the key work
|
38
|
-
# consisently across different servers. The key is also hashed
|
39
|
-
# so it does not exceed 250 characters.
|
40
|
-
def expand_cache_key(key)
|
41
|
-
File.join('sprockets', digest_class.hexdigest(key.sub(root, '')))
|
42
|
-
end
|
43
|
-
|
44
|
-
def cache_get_hash(key)
|
45
|
-
hash = cache_get(expand_cache_key(key))
|
46
|
-
if hash.is_a?(Hash) && digest.hexdigest == hash['_version']
|
47
|
-
hash
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def cache_set_hash(key, hash)
|
52
|
-
hash['_version'] = digest.hexdigest
|
53
|
-
cache_set(expand_cache_key(key), hash)
|
54
|
-
hash
|
55
|
-
end
|
56
|
-
|
57
|
-
# Low level cache getter for `key`. Checks a number of supported
|
58
|
-
# cache interfaces.
|
59
|
-
def cache_get(key)
|
60
|
-
# `Cache#get(key)` for Memcache
|
61
|
-
if cache.respond_to?(:get)
|
62
|
-
cache.get(key)
|
63
|
-
|
64
|
-
# `Cache#[key]` so `Hash` can be used
|
65
|
-
elsif cache.respond_to?(:[])
|
66
|
-
cache[key]
|
67
|
-
|
68
|
-
# `Cache#read(key)` for `ActiveSupport::Cache` support
|
69
|
-
elsif cache.respond_to?(:read)
|
70
|
-
cache.read(key)
|
71
|
-
|
72
|
-
else
|
73
|
-
nil
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
# Low level cache setter for `key`. Checks a number of supported
|
78
|
-
# cache interfaces.
|
79
|
-
def cache_set(key, value)
|
80
|
-
# `Cache#set(key, value)` for Memcache
|
81
|
-
if cache.respond_to?(:set)
|
82
|
-
cache.set(key, value)
|
83
|
-
|
84
|
-
# `Cache#[key]=value` so `Hash` can be used
|
85
|
-
elsif cache.respond_to?(:[]=)
|
86
|
-
cache[key] = value
|
87
|
-
|
88
|
-
# `Cache#write(key, value)` for `ActiveSupport::Cache` support
|
89
|
-
elsif cache.respond_to?(:write)
|
90
|
-
cache.write(key, value)
|
91
|
-
end
|
92
|
-
|
93
|
-
value
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'tilt'
|
2
|
-
|
3
|
-
module Sprockets
|
4
|
-
# Some browsers have issues with stylesheets that contain multiple
|
5
|
-
# `@charset` definitions. The issue surfaces while using Sass since
|
6
|
-
# it inserts a `@charset` at the top of each file. Then Sprockets
|
7
|
-
# concatenates them together.
|
8
|
-
#
|
9
|
-
# The `CharsetNormalizer` processor strips out multiple `@charset`
|
10
|
-
# definitions.
|
11
|
-
#
|
12
|
-
# The current implementation is naive. It picks the first `@charset`
|
13
|
-
# it sees and strips the others. This works for most people because
|
14
|
-
# the other definitions are usually `UTF-8`. A more sophisticated
|
15
|
-
# approach would be to re-encode stylesheets with mixed encodings.
|
16
|
-
#
|
17
|
-
# This behavior can be disabled with:
|
18
|
-
#
|
19
|
-
# environment.unregister_bundle_processor 'text/css', Sprockets::CharsetNormalizer
|
20
|
-
#
|
21
|
-
class CharsetNormalizer < Tilt::Template
|
22
|
-
def prepare
|
23
|
-
end
|
24
|
-
|
25
|
-
def evaluate(context, locals, &block)
|
26
|
-
charset = nil
|
27
|
-
|
28
|
-
# Find and strip out any `@charset` definitions
|
29
|
-
filtered_data = data.gsub(/^@charset "([^"]+)";$/) {
|
30
|
-
charset ||= $1; ""
|
31
|
-
}
|
32
|
-
|
33
|
-
if charset
|
34
|
-
# If there was a charset, move it to the top
|
35
|
-
"@charset \"#{charset}\";#{filtered_data}"
|
36
|
-
else
|
37
|
-
data
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
require 'tilt'
|
2
|
-
|
3
|
-
module Sprockets
|
4
|
-
# Tilt engine class for the Eco compiler. Depends on the `eco` gem.
|
5
|
-
#
|
6
|
-
# For more infomation see:
|
7
|
-
#
|
8
|
-
# https://github.com/sstephenson/ruby-eco
|
9
|
-
# https://github.com/sstephenson/eco
|
10
|
-
#
|
11
|
-
class EcoTemplate < Tilt::Template
|
12
|
-
# Check to see if Eco is loaded
|
13
|
-
def self.engine_initialized?
|
14
|
-
defined? ::Eco
|
15
|
-
end
|
16
|
-
|
17
|
-
# Autoload eco library. If the library isn't loaded, Tilt will produce
|
18
|
-
# a thread safetly warning. If you intend to use `.eco` files, you
|
19
|
-
# should explicitly require it.
|
20
|
-
def initialize_engine
|
21
|
-
require_template_library 'eco'
|
22
|
-
end
|
23
|
-
|
24
|
-
def prepare
|
25
|
-
end
|
26
|
-
|
27
|
-
# Compile template data with Eco compiler.
|
28
|
-
#
|
29
|
-
# Returns a JS function definition String. The result should be
|
30
|
-
# assigned to a JS variable.
|
31
|
-
#
|
32
|
-
# # => "function(...) {...}"
|
33
|
-
#
|
34
|
-
def evaluate(scope, locals, &block)
|
35
|
-
Eco.compile(data)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'tilt'
|
2
|
-
|
3
|
-
module Sprockets
|
4
|
-
# Tilt engine class for the EJS compiler. Depends on the `ejs` gem.
|
5
|
-
#
|
6
|
-
# For more infomation see:
|
7
|
-
#
|
8
|
-
# https://github.com/sstephenson/ruby-ejs
|
9
|
-
#
|
10
|
-
class EjsTemplate < Tilt::Template
|
11
|
-
# Check to see if EJS is loaded
|
12
|
-
def self.engine_initialized?
|
13
|
-
defined? ::EJS
|
14
|
-
end
|
15
|
-
|
16
|
-
# Autoload ejs library. If the library isn't loaded, Tilt will produce
|
17
|
-
# a thread safetly warning. If you intend to use `.ejs` files, you
|
18
|
-
# should explicitly require it.
|
19
|
-
def initialize_engine
|
20
|
-
require_template_library 'ejs'
|
21
|
-
end
|
22
|
-
|
23
|
-
def prepare
|
24
|
-
end
|
25
|
-
|
26
|
-
# Compile template data with EJS compiler.
|
27
|
-
#
|
28
|
-
# Returns a JS function definition String. The result should be
|
29
|
-
# assigned to a JS variable.
|
30
|
-
#
|
31
|
-
# # => "function(obj){...}"
|
32
|
-
#
|
33
|
-
def evaluate(scope, locals, &block)
|
34
|
-
EJS.compile(data)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
data/lib/sprockets/engines.rb
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
require 'sprockets/eco_template'
|
2
|
-
require 'sprockets/ejs_template'
|
3
|
-
require 'sprockets/jst_processor'
|
4
|
-
require 'sprockets/utils'
|
5
|
-
require 'tilt'
|
6
|
-
|
7
|
-
module Sprockets
|
8
|
-
# `Engines` provides a global and `Environment` instance registry.
|
9
|
-
#
|
10
|
-
# An engine is a type of processor that is bound to an filename
|
11
|
-
# extension. `application.js.coffee` indicates that the
|
12
|
-
# `CoffeeScriptTemplate` engine will be ran on the file.
|
13
|
-
#
|
14
|
-
# Extensions can be stacked and will be evaulated from right to
|
15
|
-
# left. `application.js.coffee.erb` will first run `ERBTemplate`
|
16
|
-
# then `CoffeeScriptTemplate`.
|
17
|
-
#
|
18
|
-
# All `Engine`s must follow the `Tilt::Template` interface. It is
|
19
|
-
# recommended to subclass `Tilt::Template`.
|
20
|
-
#
|
21
|
-
# Its recommended that you register engine changes on your local
|
22
|
-
# `Environment` instance.
|
23
|
-
#
|
24
|
-
# environment.register_engine '.foo', FooProcessor
|
25
|
-
#
|
26
|
-
# The global registry is exposed for plugins to register themselves.
|
27
|
-
#
|
28
|
-
# Sprockets.register_engine '.sass', SassTemplate
|
29
|
-
#
|
30
|
-
module Engines
|
31
|
-
# Returns an `Array` of `Engine`s registered on the
|
32
|
-
# `Environment`. If an `ext` argument is supplied, the `Engine`
|
33
|
-
# register under that extension will be returned.
|
34
|
-
#
|
35
|
-
# environment.engines
|
36
|
-
# # => [CoffeeScriptTemplate, SassTemplate, ...]
|
37
|
-
#
|
38
|
-
# environment.engines('.coffee')
|
39
|
-
# # => CoffeeScriptTemplate
|
40
|
-
#
|
41
|
-
def engines(ext = nil)
|
42
|
-
if ext
|
43
|
-
ext = Sprockets::Utils.normalize_extension(ext)
|
44
|
-
@engines[ext]
|
45
|
-
else
|
46
|
-
@engines.dup
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
# Returns an `Array` of engine extension `String`s.
|
51
|
-
#
|
52
|
-
# environment.engine_extensions
|
53
|
-
# # => ['.coffee', '.sass', ...]
|
54
|
-
def engine_extensions
|
55
|
-
@engines.keys
|
56
|
-
end
|
57
|
-
|
58
|
-
# Registers a new Engine `klass` for `ext`. If the `ext` already
|
59
|
-
# has an engine registered, it will be overridden.
|
60
|
-
#
|
61
|
-
# environment.register_engine '.coffee', CoffeeScriptTemplate
|
62
|
-
#
|
63
|
-
def register_engine(ext, klass)
|
64
|
-
ext = Sprockets::Utils.normalize_extension(ext)
|
65
|
-
@engines[ext] = klass
|
66
|
-
end
|
67
|
-
|
68
|
-
private
|
69
|
-
def deep_copy_hash(hash)
|
70
|
-
initial = Hash.new { |h, k| h[k] = [] }
|
71
|
-
hash.inject(initial) { |h, (k, a)| h[k] = a.dup; h }
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
data/lib/sprockets/index.rb
DELETED
@@ -1,99 +0,0 @@
|
|
1
|
-
require 'sprockets/base'
|
2
|
-
|
3
|
-
module Sprockets
|
4
|
-
# `Index` is a special cached version of `Environment`.
|
5
|
-
#
|
6
|
-
# The expection is that all of its file system methods are cached
|
7
|
-
# for the instances lifetime. This makes `Index` much faster. This
|
8
|
-
# behavior is ideal in production environments where the file system
|
9
|
-
# is immutable.
|
10
|
-
#
|
11
|
-
# `Index` should not be initialized directly. Instead use
|
12
|
-
# `Environment#index`.
|
13
|
-
class Index < Base
|
14
|
-
def initialize(environment)
|
15
|
-
@environment = environment
|
16
|
-
|
17
|
-
if environment.respond_to?(:default_external_encoding)
|
18
|
-
@default_external_encoding = environment.default_external_encoding
|
19
|
-
end
|
20
|
-
|
21
|
-
# Copy environment attributes
|
22
|
-
@logger = environment.logger
|
23
|
-
@context_class = environment.context_class
|
24
|
-
@cache = environment.cache
|
25
|
-
@trail = environment.trail.index
|
26
|
-
@digest = environment.digest
|
27
|
-
@digest_class = environment.digest_class
|
28
|
-
@version = environment.version
|
29
|
-
@mime_types = environment.mime_types
|
30
|
-
@engines = environment.engines
|
31
|
-
@preprocessors = environment.preprocessors
|
32
|
-
@postprocessors = environment.postprocessors
|
33
|
-
@bundle_processors = environment.bundle_processors
|
34
|
-
|
35
|
-
# Initialize caches
|
36
|
-
@assets = {}
|
37
|
-
@digests = {}
|
38
|
-
end
|
39
|
-
|
40
|
-
# No-op return self as index
|
41
|
-
def index
|
42
|
-
self
|
43
|
-
end
|
44
|
-
|
45
|
-
# Cache calls to `file_digest`
|
46
|
-
def file_digest(pathname)
|
47
|
-
key = pathname.to_s
|
48
|
-
if @digests.key?(key)
|
49
|
-
@digests[key]
|
50
|
-
else
|
51
|
-
@digests[key] = super
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# Cache `find_asset` calls
|
56
|
-
def find_asset(path, options = {})
|
57
|
-
options[:bundle] = true unless options.key?(:bundle)
|
58
|
-
if asset = @assets[cache_key_for(path, options)]
|
59
|
-
asset
|
60
|
-
elsif asset = super
|
61
|
-
logical_path_cache_key = cache_key_for(path, options)
|
62
|
-
full_path_cache_key = cache_key_for(asset.pathname, options)
|
63
|
-
|
64
|
-
# Cache on Index
|
65
|
-
@assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
|
66
|
-
|
67
|
-
# Push cache upstream to Environment
|
68
|
-
@environment.instance_eval do
|
69
|
-
@assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
|
70
|
-
end
|
71
|
-
|
72
|
-
asset
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
protected
|
77
|
-
# Index is immutable, any methods that try to clear the cache
|
78
|
-
# should bomb.
|
79
|
-
def expire_index!
|
80
|
-
raise TypeError, "can't modify immutable index"
|
81
|
-
end
|
82
|
-
|
83
|
-
# Cache asset building in memory and in persisted cache.
|
84
|
-
def build_asset(path, pathname, options)
|
85
|
-
# Memory cache
|
86
|
-
key = cache_key_for(pathname, options)
|
87
|
-
if @assets.key?(key)
|
88
|
-
@assets[key]
|
89
|
-
else
|
90
|
-
@assets[key] = begin
|
91
|
-
# Persisted cache
|
92
|
-
cache_asset(key) do
|
93
|
-
super
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
@@ -1,152 +0,0 @@
|
|
1
|
-
require 'sprockets/asset'
|
2
|
-
require 'sprockets/utils'
|
3
|
-
|
4
|
-
module Sprockets
|
5
|
-
class ProcessedAsset < Asset
|
6
|
-
def initialize(environment, logical_path, pathname)
|
7
|
-
super
|
8
|
-
|
9
|
-
start_time = Time.now.to_f
|
10
|
-
|
11
|
-
context = environment.context_class.new(environment, logical_path, pathname)
|
12
|
-
@source = context.evaluate(pathname)
|
13
|
-
@length = Rack::Utils.bytesize(source)
|
14
|
-
@digest = environment.digest.update(source).hexdigest
|
15
|
-
|
16
|
-
build_required_assets(environment, context)
|
17
|
-
build_dependency_paths(environment, context)
|
18
|
-
|
19
|
-
@dependency_digest = compute_dependency_digest(environment)
|
20
|
-
|
21
|
-
elapsed_time = ((Time.now.to_f - start_time) * 1000).to_i
|
22
|
-
environment.logger.info "Compiled #{logical_path} (#{elapsed_time}ms) (pid #{Process.pid})"
|
23
|
-
end
|
24
|
-
|
25
|
-
# Interal: Used to check equality
|
26
|
-
attr_reader :dependency_digest
|
27
|
-
|
28
|
-
attr_reader :source
|
29
|
-
|
30
|
-
# Initialize `BundledAsset` from serialized `Hash`.
|
31
|
-
def init_with(environment, coder)
|
32
|
-
super
|
33
|
-
|
34
|
-
@source = coder['source']
|
35
|
-
@dependency_digest = coder['dependency_digest']
|
36
|
-
|
37
|
-
@required_assets = coder['required_paths'].map { |p|
|
38
|
-
p = expand_root_path(p)
|
39
|
-
|
40
|
-
unless environment.paths.detect { |path| p[path] }
|
41
|
-
raise UnserializeError, "#{p} isn't in paths"
|
42
|
-
end
|
43
|
-
|
44
|
-
p == pathname.to_s ? self : environment.find_asset(p, :bundle => false)
|
45
|
-
}
|
46
|
-
@dependency_paths = coder['dependency_paths'].map { |h|
|
47
|
-
DependencyFile.new(expand_root_path(h['path']), h['mtime'], h['digest'])
|
48
|
-
}
|
49
|
-
end
|
50
|
-
|
51
|
-
# Serialize custom attributes in `BundledAsset`.
|
52
|
-
def encode_with(coder)
|
53
|
-
super
|
54
|
-
|
55
|
-
coder['source'] = source
|
56
|
-
coder['dependency_digest'] = dependency_digest
|
57
|
-
|
58
|
-
coder['required_paths'] = required_assets.map { |a|
|
59
|
-
relativize_root_path(a.pathname).to_s
|
60
|
-
}
|
61
|
-
coder['dependency_paths'] = dependency_paths.map { |d|
|
62
|
-
{ 'path' => relativize_root_path(d.pathname).to_s,
|
63
|
-
'mtime' => d.mtime.iso8601,
|
64
|
-
'digest' => d.digest }
|
65
|
-
}
|
66
|
-
end
|
67
|
-
|
68
|
-
# Checks if Asset is stale by comparing the actual mtime and
|
69
|
-
# digest to the inmemory model.
|
70
|
-
def fresh?(environment)
|
71
|
-
# Check freshness of all declared dependencies
|
72
|
-
@dependency_paths.all? { |dep| dependency_fresh?(environment, dep) }
|
73
|
-
end
|
74
|
-
|
75
|
-
protected
|
76
|
-
class DependencyFile < Struct.new(:pathname, :mtime, :digest)
|
77
|
-
def initialize(pathname, mtime, digest)
|
78
|
-
pathname = Pathname.new(pathname) unless pathname.is_a?(Pathname)
|
79
|
-
mtime = Time.parse(mtime) if mtime.is_a?(String)
|
80
|
-
super
|
81
|
-
end
|
82
|
-
|
83
|
-
def eql?(other)
|
84
|
-
other.is_a?(DependencyFile) &&
|
85
|
-
pathname.eql?(other.pathname) &&
|
86
|
-
mtime.eql?(other.mtime) &&
|
87
|
-
digest.eql?(other.digest)
|
88
|
-
end
|
89
|
-
|
90
|
-
def hash
|
91
|
-
pathname.to_s.hash
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
private
|
96
|
-
def build_required_assets(environment, context)
|
97
|
-
@required_assets = resolve_dependencies(environment, context._required_paths + [pathname.to_s]) -
|
98
|
-
resolve_dependencies(environment, context._stubbed_assets.to_a)
|
99
|
-
end
|
100
|
-
|
101
|
-
def resolve_dependencies(environment, paths)
|
102
|
-
assets = []
|
103
|
-
cache = {}
|
104
|
-
|
105
|
-
paths.each do |path|
|
106
|
-
if path == self.pathname.to_s
|
107
|
-
unless cache[self]
|
108
|
-
cache[self] = true
|
109
|
-
assets << self
|
110
|
-
end
|
111
|
-
elsif asset = environment.find_asset(path, :bundle => false)
|
112
|
-
asset.required_assets.each do |asset_dependency|
|
113
|
-
unless cache[asset_dependency]
|
114
|
-
cache[asset_dependency] = true
|
115
|
-
assets << asset_dependency
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
assets
|
122
|
-
end
|
123
|
-
|
124
|
-
def build_dependency_paths(environment, context)
|
125
|
-
dependency_paths = {}
|
126
|
-
|
127
|
-
context._dependency_paths.each do |path|
|
128
|
-
dep = DependencyFile.new(path, environment.stat(path).mtime, environment.file_digest(path).hexdigest)
|
129
|
-
dependency_paths[dep] = true
|
130
|
-
end
|
131
|
-
|
132
|
-
context._dependency_assets.each do |path|
|
133
|
-
if path == self.pathname.to_s
|
134
|
-
dep = DependencyFile.new(pathname, environment.stat(path).mtime, environment.file_digest(path).hexdigest)
|
135
|
-
dependency_paths[dep] = true
|
136
|
-
elsif asset = environment.find_asset(path, :bundle => false)
|
137
|
-
asset.dependency_paths.each do |d|
|
138
|
-
dependency_paths[d] = true
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
@dependency_paths = dependency_paths.keys
|
144
|
-
end
|
145
|
-
|
146
|
-
def compute_dependency_digest(environment)
|
147
|
-
required_assets.inject(environment.digest) { |digest, asset|
|
148
|
-
digest.update asset.digest
|
149
|
-
}.hexdigest
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
data/lib/sprockets/processor.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'tilt'
|
2
|
-
|
3
|
-
module Sprockets
|
4
|
-
# `Processor` creates an anonymous processor class from a block.
|
5
|
-
#
|
6
|
-
# register_preprocessor :my_processor do |context, data|
|
7
|
-
# # ...
|
8
|
-
# end
|
9
|
-
#
|
10
|
-
class Processor < Tilt::Template
|
11
|
-
# `processor` is a lambda or block
|
12
|
-
def self.processor
|
13
|
-
@processor
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.name
|
17
|
-
"Sprockets::Processor (#{@name})"
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.to_s
|
21
|
-
name
|
22
|
-
end
|
23
|
-
|
24
|
-
def prepare
|
25
|
-
end
|
26
|
-
|
27
|
-
# Call processor block with `context` and `data`.
|
28
|
-
def evaluate(context, locals)
|
29
|
-
self.class.processor.call(context, data)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'tilt'
|
2
|
-
|
3
|
-
module Sprockets
|
4
|
-
# For JS developers who are colonfobic, concatenating JS files using
|
5
|
-
# the module pattern usually leads to syntax errors.
|
6
|
-
#
|
7
|
-
# The `SafetyColons` processor will insert missing semicolons to the
|
8
|
-
# end of the file.
|
9
|
-
#
|
10
|
-
# This behavior can be disabled with:
|
11
|
-
#
|
12
|
-
# environment.unregister_postprocessor 'application/javascript', Sprockets::SafetyColons
|
13
|
-
#
|
14
|
-
class SafetyColons < Tilt::Template
|
15
|
-
def prepare
|
16
|
-
end
|
17
|
-
|
18
|
-
def evaluate(context, locals, &block)
|
19
|
-
# If the file is blank or ends in a semicolon, leave it as is
|
20
|
-
if data =~ /\A\s*\Z/m || data =~ /;\s*\Z/m
|
21
|
-
data
|
22
|
-
else
|
23
|
-
# Otherwise, append a semicolon and newline
|
24
|
-
"#{data};\n"
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'sprockets/asset'
|
2
|
-
require 'fileutils'
|
3
|
-
require 'zlib'
|
4
|
-
|
5
|
-
module Sprockets
|
6
|
-
# `StaticAsset`s are used for files that are served verbatim without
|
7
|
-
# any processing or concatenation. These are typical images and
|
8
|
-
# other binary files.
|
9
|
-
class StaticAsset < Asset
|
10
|
-
# Returns file contents as its `source`.
|
11
|
-
def source
|
12
|
-
# File is read everytime to avoid memory bloat of large binary files
|
13
|
-
pathname.open('rb') { |f| f.read }
|
14
|
-
end
|
15
|
-
|
16
|
-
# Implemented for Rack SendFile support.
|
17
|
-
def to_path
|
18
|
-
pathname.to_s
|
19
|
-
end
|
20
|
-
|
21
|
-
# Save asset to disk.
|
22
|
-
def write_to(filename, options = {})
|
23
|
-
# Gzip contents if filename has '.gz'
|
24
|
-
options[:compress] ||= File.extname(filename) == '.gz'
|
25
|
-
|
26
|
-
FileUtils.mkdir_p File.dirname(filename)
|
27
|
-
|
28
|
-
if options[:compress]
|
29
|
-
# Open file and run it through `Zlib`
|
30
|
-
pathname.open('rb') do |rd|
|
31
|
-
File.open("#{filename}+", 'wb') do |wr|
|
32
|
-
gz = Zlib::GzipWriter.new(wr, Zlib::BEST_COMPRESSION)
|
33
|
-
buf = ""
|
34
|
-
while rd.read(16384, buf)
|
35
|
-
gz.write(buf)
|
36
|
-
end
|
37
|
-
gz.close
|
38
|
-
end
|
39
|
-
end
|
40
|
-
else
|
41
|
-
# If no compression needs to be done, we can just copy it into place.
|
42
|
-
FileUtils.cp(pathname, "#{filename}+")
|
43
|
-
end
|
44
|
-
|
45
|
-
# Atomic write
|
46
|
-
FileUtils.mv("#{filename}+", filename)
|
47
|
-
|
48
|
-
# Set mtime correctly
|
49
|
-
File.utime(mtime, mtime, filename)
|
50
|
-
|
51
|
-
nil
|
52
|
-
ensure
|
53
|
-
# Ensure tmp file gets cleaned up
|
54
|
-
FileUtils.rm("#{filename}+") if File.exist?("#{filename}+")
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|