sprockets 2.2.3 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|