sprockets 2.11.3 → 3.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +296 -0
- data/LICENSE +2 -2
- data/README.md +235 -242
- data/bin/sprockets +1 -0
- data/lib/rake/sprocketstask.rb +5 -4
- data/lib/sprockets/asset.rb +143 -210
- data/lib/sprockets/autoload/closure.rb +7 -0
- data/lib/sprockets/autoload/coffee_script.rb +7 -0
- data/lib/sprockets/autoload/eco.rb +7 -0
- data/lib/sprockets/autoload/ejs.rb +7 -0
- data/lib/sprockets/autoload/sass.rb +7 -0
- data/lib/sprockets/autoload/uglifier.rb +7 -0
- data/lib/sprockets/autoload/yui.rb +7 -0
- data/lib/sprockets/autoload.rb +11 -0
- data/lib/sprockets/base.rb +56 -393
- data/lib/sprockets/bower.rb +58 -0
- data/lib/sprockets/bundle.rb +69 -0
- data/lib/sprockets/cache/file_store.rb +168 -14
- data/lib/sprockets/cache/memory_store.rb +66 -0
- data/lib/sprockets/cache/null_store.rb +46 -0
- data/lib/sprockets/cache.rb +236 -0
- data/lib/sprockets/cached_environment.rb +69 -0
- data/lib/sprockets/closure_compressor.rb +35 -10
- data/lib/sprockets/coffee_script_processor.rb +25 -0
- data/lib/sprockets/coffee_script_template.rb +17 -0
- data/lib/sprockets/compressing.rb +44 -23
- data/lib/sprockets/configuration.rb +83 -0
- data/lib/sprockets/context.rb +86 -144
- data/lib/sprockets/dependencies.rb +73 -0
- data/lib/sprockets/deprecation.rb +90 -0
- data/lib/sprockets/digest_utils.rb +180 -0
- data/lib/sprockets/directive_processor.rb +207 -211
- data/lib/sprockets/eco_processor.rb +32 -0
- data/lib/sprockets/eco_template.rb +9 -30
- data/lib/sprockets/ejs_processor.rb +31 -0
- data/lib/sprockets/ejs_template.rb +9 -29
- data/lib/sprockets/encoding_utils.rb +261 -0
- data/lib/sprockets/engines.rb +53 -35
- data/lib/sprockets/environment.rb +17 -64
- data/lib/sprockets/erb_processor.rb +30 -0
- data/lib/sprockets/erb_template.rb +11 -0
- data/lib/sprockets/errors.rb +4 -13
- data/lib/sprockets/file_reader.rb +15 -0
- data/lib/sprockets/http_utils.rb +117 -0
- data/lib/sprockets/jst_processor.rb +35 -15
- data/lib/sprockets/legacy.rb +330 -0
- data/lib/sprockets/legacy_proc_processor.rb +35 -0
- data/lib/sprockets/legacy_tilt_processor.rb +29 -0
- data/lib/sprockets/loader.rb +325 -0
- data/lib/sprockets/manifest.rb +202 -127
- data/lib/sprockets/manifest_utils.rb +45 -0
- data/lib/sprockets/mime.rb +112 -31
- data/lib/sprockets/path_dependency_utils.rb +85 -0
- data/lib/sprockets/path_digest_utils.rb +47 -0
- data/lib/sprockets/path_utils.rb +287 -0
- data/lib/sprockets/paths.rb +42 -19
- data/lib/sprockets/processing.rb +178 -126
- data/lib/sprockets/processor_utils.rb +180 -0
- data/lib/sprockets/resolve.rb +211 -0
- data/lib/sprockets/sass_cache_store.rb +22 -17
- data/lib/sprockets/sass_compressor.rb +39 -15
- data/lib/sprockets/sass_functions.rb +2 -70
- data/lib/sprockets/sass_importer.rb +2 -29
- data/lib/sprockets/sass_processor.rb +292 -0
- data/lib/sprockets/sass_template.rb +12 -53
- data/lib/sprockets/server.rb +129 -84
- data/lib/sprockets/transformers.rb +145 -0
- data/lib/sprockets/uglifier_compressor.rb +39 -12
- data/lib/sprockets/unloaded_asset.rb +137 -0
- data/lib/sprockets/uri_tar.rb +98 -0
- data/lib/sprockets/uri_utils.rb +188 -0
- data/lib/sprockets/utils/gzip.rb +67 -0
- data/lib/sprockets/utils.rb +210 -44
- data/lib/sprockets/version.rb +1 -1
- data/lib/sprockets/yui_compressor.rb +39 -11
- data/lib/sprockets.rb +142 -81
- metadata +100 -80
- data/lib/sprockets/asset_attributes.rb +0 -137
- data/lib/sprockets/bundled_asset.rb +0 -78
- data/lib/sprockets/caching.rb +0 -96
- data/lib/sprockets/charset_normalizer.rb +0 -41
- data/lib/sprockets/index.rb +0 -100
- 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/scss_template.rb +0 -13
- data/lib/sprockets/static_asset.rb +0 -58
@@ -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
|
data/lib/sprockets/index.rb
DELETED
@@ -1,100 +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
|
-
@compressors = environment.compressors
|
35
|
-
|
36
|
-
# Initialize caches
|
37
|
-
@assets = {}
|
38
|
-
@digests = {}
|
39
|
-
end
|
40
|
-
|
41
|
-
# No-op return self as index
|
42
|
-
def index
|
43
|
-
self
|
44
|
-
end
|
45
|
-
|
46
|
-
# Cache calls to `file_digest`
|
47
|
-
def file_digest(pathname)
|
48
|
-
key = pathname.to_s
|
49
|
-
if @digests.key?(key)
|
50
|
-
@digests[key]
|
51
|
-
else
|
52
|
-
@digests[key] = super
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
# Cache `find_asset` calls
|
57
|
-
def find_asset(path, options = {})
|
58
|
-
options[:bundle] = true unless options.key?(:bundle)
|
59
|
-
if asset = @assets[cache_key_for(path, options)]
|
60
|
-
asset
|
61
|
-
elsif asset = super
|
62
|
-
logical_path_cache_key = cache_key_for(path, options)
|
63
|
-
full_path_cache_key = cache_key_for(asset.pathname, options)
|
64
|
-
|
65
|
-
# Cache on Index
|
66
|
-
@assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
|
67
|
-
|
68
|
-
# Push cache upstream to Environment
|
69
|
-
@environment.instance_eval do
|
70
|
-
@assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
|
71
|
-
end
|
72
|
-
|
73
|
-
asset
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
protected
|
78
|
-
# Index is immutable, any methods that try to clear the cache
|
79
|
-
# should bomb.
|
80
|
-
def expire_index!
|
81
|
-
raise TypeError, "can't modify immutable index"
|
82
|
-
end
|
83
|
-
|
84
|
-
# Cache asset building in memory and in persisted cache.
|
85
|
-
def build_asset(path, pathname, options)
|
86
|
-
# Memory cache
|
87
|
-
key = cache_key_for(pathname, options)
|
88
|
-
if @assets.key?(key)
|
89
|
-
@assets[key]
|
90
|
-
else
|
91
|
-
@assets[key] = begin
|
92
|
-
# Persisted cache
|
93
|
-
cache_asset(key) do
|
94
|
-
super
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
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.debug "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 'text/css', :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,13 +0,0 @@
|
|
1
|
-
require 'sprockets/sass_template'
|
2
|
-
|
3
|
-
module Sprockets
|
4
|
-
# Scss handler to replace Tilt's builtin one. See `SassTemplate` and
|
5
|
-
# `SassImporter` for more infomation.
|
6
|
-
class ScssTemplate < SassTemplate
|
7
|
-
self.default_mime_type = 'text/css'
|
8
|
-
|
9
|
-
def syntax
|
10
|
-
:scss
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
@@ -1,58 +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
|
-
gz.mtime = mtime.to_i
|
34
|
-
buf = ""
|
35
|
-
while rd.read(16384, buf)
|
36
|
-
gz.write(buf)
|
37
|
-
end
|
38
|
-
gz.close
|
39
|
-
end
|
40
|
-
end
|
41
|
-
else
|
42
|
-
# If no compression needs to be done, we can just copy it into place.
|
43
|
-
FileUtils.cp(pathname, "#{filename}+")
|
44
|
-
end
|
45
|
-
|
46
|
-
# Atomic write
|
47
|
-
FileUtils.mv("#{filename}+", filename)
|
48
|
-
|
49
|
-
# Set mtime correctly
|
50
|
-
File.utime(mtime, mtime, filename)
|
51
|
-
|
52
|
-
nil
|
53
|
-
ensure
|
54
|
-
# Ensure tmp file gets cleaned up
|
55
|
-
FileUtils.rm("#{filename}+") if File.exist?("#{filename}+")
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|