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/bin/sprockets
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
$VERBOSE = nil
|
2
3
|
|
3
4
|
require 'sprockets'
|
4
5
|
require 'optparse'
|
@@ -11,7 +12,7 @@ unless ARGV.delete("--noenv")
|
|
11
12
|
end
|
12
13
|
end
|
13
14
|
|
14
|
-
|
15
|
+
paths = []
|
15
16
|
environment = Sprockets::Environment.new(Dir.pwd)
|
16
17
|
manifest = nil
|
17
18
|
|
@@ -40,9 +41,21 @@ OptionParser.new do |opts|
|
|
40
41
|
manifest = Sprockets::Manifest.new(environment, directory)
|
41
42
|
end
|
42
43
|
|
44
|
+
opts.on("--css-compressor=COMPRESSOR", "Use CSS compressor") do |compressor|
|
45
|
+
environment.css_compressor = compressor.to_sym
|
46
|
+
end
|
47
|
+
|
48
|
+
opts.on("--js-compressor=COMPRESSOR", "Use JavaScript compressor") do |compressor|
|
49
|
+
environment.js_compressor = compressor.to_sym
|
50
|
+
end
|
51
|
+
|
43
52
|
opts.on("--noenv", "Disables .sprocketsrc file") do
|
44
53
|
end
|
45
54
|
|
55
|
+
opts.on("--cache=DIRECTORY", "Enables the FileStore cache using the specified directory") do |directory|
|
56
|
+
environment.cache = Sprockets::Cache::FileStore.new(directory)
|
57
|
+
end
|
58
|
+
|
46
59
|
opts.on_tail("-h", "--help", "Shows this help message") do
|
47
60
|
opts.show_usage
|
48
61
|
end
|
@@ -55,8 +68,8 @@ OptionParser.new do |opts|
|
|
55
68
|
opts.show_usage if ARGV.empty?
|
56
69
|
|
57
70
|
begin
|
58
|
-
opts.order(ARGV) do |
|
59
|
-
|
71
|
+
opts.order(ARGV) do |path|
|
72
|
+
paths << path
|
60
73
|
end
|
61
74
|
rescue OptionParser::ParseError => e
|
62
75
|
opts.warn e.message
|
@@ -66,14 +79,14 @@ end
|
|
66
79
|
|
67
80
|
if environment.paths.empty?
|
68
81
|
warn "No load paths given"
|
69
|
-
warn "Usage: sprockets -Ijavascripts/
|
82
|
+
warn "Usage: sprockets -Ijavascripts/ path"
|
70
83
|
exit 1
|
71
84
|
end
|
72
85
|
|
73
86
|
if manifest
|
74
|
-
manifest.compile(
|
75
|
-
elsif
|
76
|
-
puts environment.find_asset(
|
87
|
+
manifest.compile(paths)
|
88
|
+
elsif paths.length == 1
|
89
|
+
puts environment.find_asset(paths.first).to_s
|
77
90
|
else
|
78
91
|
warn "Only one file can be compiled to stdout at a time"
|
79
92
|
exit 1
|
data/lib/rake/sprocketstask.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'rake'
|
2
3
|
require 'rake/tasklib'
|
3
4
|
|
@@ -37,6 +38,25 @@ module Rake
|
|
37
38
|
end
|
38
39
|
attr_writer :environment
|
39
40
|
|
41
|
+
# Returns cached cached environment
|
42
|
+
def cached
|
43
|
+
@cached ||= environment.cached if environment
|
44
|
+
end
|
45
|
+
alias_method :index, :cached
|
46
|
+
|
47
|
+
# `Manifest` instance used for already compiled assets.
|
48
|
+
#
|
49
|
+
# Will be created by default if an environment and output
|
50
|
+
# directory are given
|
51
|
+
def manifest
|
52
|
+
if !@manifest.is_a?(Sprockets::Manifest) && @manifest.respond_to?(:call)
|
53
|
+
@manifest = @manifest.call
|
54
|
+
else
|
55
|
+
@manifest
|
56
|
+
end
|
57
|
+
end
|
58
|
+
attr_writer :manifest
|
59
|
+
|
40
60
|
# Directory to write compiled assets too. As well as the manifest file.
|
41
61
|
#
|
42
62
|
# t.output = "./public/assets"
|
@@ -79,6 +99,7 @@ module Rake
|
|
79
99
|
def initialize(name = :assets)
|
80
100
|
@name = name
|
81
101
|
@environment = lambda { Sprockets::Environment.new(Dir.pwd) }
|
102
|
+
@manifest = lambda { Sprockets::Manifest.new(cached, output) }
|
82
103
|
@logger = Logger.new($stderr)
|
83
104
|
@logger.level = Logger::INFO
|
84
105
|
@keep = 2
|
@@ -104,7 +125,7 @@ module Rake
|
|
104
125
|
end
|
105
126
|
end
|
106
127
|
|
107
|
-
task :
|
128
|
+
task clobber: ["clobber_#{name}"]
|
108
129
|
|
109
130
|
desc name == :assets ? "Clean old assets" : "Clean old #{name} assets"
|
110
131
|
task "clean_#{name}" do
|
@@ -113,28 +134,20 @@ module Rake
|
|
113
134
|
end
|
114
135
|
end
|
115
136
|
|
116
|
-
task :
|
137
|
+
task clean: ["clean_#{name}"]
|
117
138
|
end
|
118
139
|
|
119
140
|
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
141
|
# Sub out environment logger with our rake task logger that
|
131
142
|
# writes to stderr.
|
132
143
|
def with_logger
|
133
|
-
|
134
|
-
|
144
|
+
if env = manifest.environment
|
145
|
+
old_logger = env.logger
|
146
|
+
env.logger = @logger
|
147
|
+
end
|
135
148
|
yield
|
136
149
|
ensure
|
137
|
-
|
150
|
+
env.logger = old_logger if env
|
138
151
|
end
|
139
152
|
end
|
140
153
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'sprockets/uri_utils'
|
3
|
+
require 'sprockets/path_utils'
|
4
|
+
|
5
|
+
module Sprockets
|
6
|
+
# This is a processor designed to add a source map "comment"
|
7
|
+
# to the bottom of a css or JS file that is serving a source
|
8
|
+
# map. An example of a comment might look like this
|
9
|
+
#
|
10
|
+
# //# application.js-80af0efcc960fc2ac93eda2f7b12e3db40ab360bf6ea269ceed3bea3678326f9.map
|
11
|
+
#
|
12
|
+
# As an asset is built it gets source map information added
|
13
|
+
# to the `asset.to_hash[:metadata][:map]` key. This contains all the
|
14
|
+
# information that is needed to build a source map file.
|
15
|
+
#
|
16
|
+
# To add this comment we must have an asset we can link to.
|
17
|
+
# To do this we ensure that the original aset is loaded, then
|
18
|
+
# we use a use a special mime type. For example `application/js-sourcemap+json`
|
19
|
+
# for a JS source map.
|
20
|
+
#
|
21
|
+
# This will trigger a new asset to be loaded and generated by the
|
22
|
+
# `SourceMapProcessor` processor.
|
23
|
+
#
|
24
|
+
# Finally once we have that file, we can generate a link to it
|
25
|
+
# with it's full fingerprint. This is done and then
|
26
|
+
# added to the original asset as a comment at the bottom.
|
27
|
+
#
|
28
|
+
class AddSourceMapCommentToAssetProcessor
|
29
|
+
def self.call(input)
|
30
|
+
|
31
|
+
case input[:content_type]
|
32
|
+
when "application/javascript"
|
33
|
+
comment = "\n//# sourceMappingURL=%s"
|
34
|
+
map_type = "application/js-sourcemap+json"
|
35
|
+
when "text/css"
|
36
|
+
comment = "\n/*# sourceMappingURL=%s */"
|
37
|
+
map_type = "application/css-sourcemap+json"
|
38
|
+
else
|
39
|
+
fail input[:content_type]
|
40
|
+
end
|
41
|
+
|
42
|
+
env = input[:environment]
|
43
|
+
|
44
|
+
uri, _ = env.resolve!(input[:filename], accept: input[:content_type])
|
45
|
+
asset = env.load(uri)
|
46
|
+
|
47
|
+
uri, _ = env.resolve!(input[:filename], accept: map_type)
|
48
|
+
map = env.load(uri)
|
49
|
+
|
50
|
+
uri, params = URIUtils.parse_asset_uri(input[:uri])
|
51
|
+
uri = env.expand_from_root(params[:index_alias]) if params[:index_alias]
|
52
|
+
path = PathUtils.relative_path_from(PathUtils.split_subpath(input[:load_path], uri), map.digest_path)
|
53
|
+
|
54
|
+
asset.metadata.merge(
|
55
|
+
data: asset.source + (comment % path) + "\n",
|
56
|
+
links: asset.links + [asset.uri, map.uri]
|
57
|
+
)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/sprockets/asset.rb
CHANGED
@@ -1,260 +1,195 @@
|
|
1
|
-
|
2
|
-
require '
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'fileutils'
|
3
|
+
require 'sprockets/digest_utils'
|
3
4
|
|
4
5
|
module Sprockets
|
5
|
-
# `Asset` is the base class for `BundledAsset` and `StaticAsset`.
|
6
6
|
class Asset
|
7
|
-
|
8
|
-
def self.from_hash(environment, hash)
|
9
|
-
return unless hash.is_a?(Hash)
|
7
|
+
attr_reader :logical_path
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
@
|
37
|
-
@pathname = Pathname.new(pathname)
|
38
|
-
@content_type = environment.content_type_of(pathname)
|
39
|
-
@mtime = environment.stat(pathname).mtime
|
40
|
-
@length = environment.stat(pathname).size
|
41
|
-
@digest = environment.file_digest(pathname).hexdigest
|
9
|
+
# Private: Intialize Asset wrapper from attributes Hash.
|
10
|
+
#
|
11
|
+
# Asset wrappers should not be initialized directly, only
|
12
|
+
# Environment#find_asset should vend them.
|
13
|
+
#
|
14
|
+
# attributes - Hash of ivars
|
15
|
+
#
|
16
|
+
# Returns Asset.
|
17
|
+
def initialize(attributes = {})
|
18
|
+
@attributes = attributes
|
19
|
+
@content_type = attributes[:content_type]
|
20
|
+
@filename = attributes[:filename]
|
21
|
+
@id = attributes[:id]
|
22
|
+
@load_path = attributes[:load_path]
|
23
|
+
@logical_path = attributes[:logical_path]
|
24
|
+
@metadata = attributes[:metadata]
|
25
|
+
@name = attributes[:name]
|
26
|
+
@source = attributes[:source]
|
27
|
+
@uri = attributes[:uri]
|
28
|
+
end
|
29
|
+
|
30
|
+
# Internal: Return all internal instance variables as a hash.
|
31
|
+
#
|
32
|
+
# Returns a Hash.
|
33
|
+
def to_hash
|
34
|
+
@attributes
|
42
35
|
end
|
43
36
|
|
44
|
-
#
|
45
|
-
|
46
|
-
|
37
|
+
# Public: Metadata accumulated from pipeline process.
|
38
|
+
#
|
39
|
+
# The API status of the keys is dependent on the pipeline processors
|
40
|
+
# itself. So some values maybe considered public and others internal.
|
41
|
+
# See the pipeline proccessor documentation itself.
|
42
|
+
#
|
43
|
+
# Returns Hash.
|
44
|
+
attr_reader :metadata
|
47
45
|
|
48
|
-
|
49
|
-
|
50
|
-
@digest = coder['digest']
|
46
|
+
# Public: Returns String path of asset.
|
47
|
+
attr_reader :filename
|
51
48
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
if mtime = coder['mtime']
|
58
|
-
# Parse time string
|
59
|
-
@mtime = Time.parse(mtime)
|
60
|
-
end
|
61
|
-
|
62
|
-
if length = coder['length']
|
63
|
-
# Convert length to an `Integer`
|
64
|
-
@length = Integer(length)
|
65
|
-
end
|
66
|
-
end
|
49
|
+
# Internal: Unique asset object ID.
|
50
|
+
#
|
51
|
+
# Returns a String.
|
52
|
+
attr_reader :id
|
67
53
|
|
68
|
-
#
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
coder['mtime'] = mtime.iso8601
|
75
|
-
coder['length'] = length
|
76
|
-
coder['digest'] = digest
|
77
|
-
end
|
54
|
+
# Public: Internal URI to lookup asset by.
|
55
|
+
#
|
56
|
+
# NOT a publically accessible URL.
|
57
|
+
#
|
58
|
+
# Returns URI.
|
59
|
+
attr_reader :uri
|
78
60
|
|
79
|
-
# Return logical path with digest spliced in.
|
61
|
+
# Public: Return logical path with digest spliced in.
|
80
62
|
#
|
81
63
|
# "foo/bar-37b51d194a7513e45b56f6524f2d51f2.js"
|
82
64
|
#
|
65
|
+
# Returns String.
|
83
66
|
def digest_path
|
84
|
-
logical_path.sub(/\.(\w+)$/) { |ext| "-#{
|
67
|
+
logical_path.sub(/\.(\w+)$/) { |ext| "-#{etag}#{ext}" }
|
85
68
|
end
|
86
69
|
|
87
|
-
# Return
|
88
|
-
|
89
|
-
|
70
|
+
# Public: Return load path + logical path with digest spliced in.
|
71
|
+
#
|
72
|
+
# Returns String.
|
73
|
+
def full_digest_path
|
74
|
+
File.join(@load_path, digest_path)
|
90
75
|
end
|
91
76
|
|
92
|
-
#
|
77
|
+
# Public: Returns String MIME type of asset. Returns nil if type is unknown.
|
78
|
+
attr_reader :content_type
|
79
|
+
|
80
|
+
# Public: Get all externally linked asset filenames from asset.
|
93
81
|
#
|
94
|
-
#
|
95
|
-
# the asset's contents as a whole.
|
82
|
+
# All linked assets should be compiled anytime this asset is.
|
96
83
|
#
|
97
|
-
#
|
98
|
-
|
99
|
-
|
100
|
-
[self]
|
84
|
+
# Returns Set of String asset URIs.
|
85
|
+
def links
|
86
|
+
metadata[:links] || Set.new
|
101
87
|
end
|
102
88
|
|
103
|
-
# `
|
104
|
-
|
105
|
-
|
89
|
+
# Public: Return `String` of concatenated source.
|
90
|
+
#
|
91
|
+
# Returns String.
|
92
|
+
def source
|
93
|
+
if @source
|
94
|
+
@source
|
95
|
+
else
|
96
|
+
# File is read everytime to avoid memory bloat of large binary files
|
97
|
+
File.binread(filename)
|
98
|
+
end
|
106
99
|
end
|
107
100
|
|
108
|
-
#
|
101
|
+
# Public: Alias for #source.
|
102
|
+
#
|
103
|
+
# Returns String.
|
109
104
|
def to_s
|
110
105
|
source
|
111
106
|
end
|
112
107
|
|
113
|
-
#
|
114
|
-
#
|
115
|
-
|
116
|
-
|
108
|
+
# Public: Get charset of source.
|
109
|
+
#
|
110
|
+
# Returns a String charset name or nil if binary.
|
111
|
+
def charset
|
112
|
+
metadata[:charset]
|
117
113
|
end
|
118
114
|
|
119
|
-
#
|
120
|
-
|
121
|
-
|
122
|
-
# Used to test if cached models need to be rebuilt.
|
123
|
-
def fresh?(environment)
|
124
|
-
# Check current mtime and digest
|
125
|
-
dependency_fresh?(environment, self)
|
115
|
+
# Public: Returns Integer length of source.
|
116
|
+
def length
|
117
|
+
metadata[:length]
|
126
118
|
end
|
119
|
+
alias_method :bytesize, :length
|
127
120
|
|
128
|
-
#
|
129
|
-
|
130
|
-
|
131
|
-
# Subclass must override `fresh?` or `stale?`.
|
132
|
-
def stale?(environment)
|
133
|
-
!fresh?(environment)
|
121
|
+
# Public: Returns String byte digest of source.
|
122
|
+
def digest
|
123
|
+
metadata[:digest]
|
134
124
|
end
|
135
125
|
|
136
|
-
#
|
137
|
-
def
|
138
|
-
|
139
|
-
|
126
|
+
# Public: Returns String hexdigest of source.
|
127
|
+
def hexdigest
|
128
|
+
DigestUtils.pack_hexdigest(digest)
|
129
|
+
end
|
140
130
|
|
141
|
-
|
131
|
+
# Pubic: ETag String of Asset.
|
132
|
+
alias_method :etag, :hexdigest
|
142
133
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
134
|
+
# Public: Returns String base64 digest of source.
|
135
|
+
def base64digest
|
136
|
+
DigestUtils.pack_base64digest(digest)
|
137
|
+
end
|
138
|
+
|
139
|
+
# Public: A "named information" URL for subresource integrity.
|
140
|
+
def integrity
|
141
|
+
DigestUtils.integrity_uri(metadata[:digest])
|
142
|
+
end
|
143
|
+
|
144
|
+
# Public: Add enumerator to allow `Asset` instances to be used as Rack
|
145
|
+
# compatible body objects.
|
146
|
+
#
|
147
|
+
# block
|
148
|
+
# part - String body chunk
|
149
|
+
#
|
150
|
+
# Returns nothing.
|
151
|
+
def each
|
152
|
+
yield to_s
|
153
|
+
end
|
155
154
|
|
156
|
-
|
157
|
-
|
155
|
+
# Deprecated: Save asset to disk.
|
156
|
+
#
|
157
|
+
# filename - String target
|
158
|
+
#
|
159
|
+
# Returns nothing.
|
160
|
+
def write_to(filename)
|
161
|
+
FileUtils.mkdir_p File.dirname(filename)
|
158
162
|
|
159
|
-
|
160
|
-
|
163
|
+
PathUtils.atomic_write(filename) do |f|
|
164
|
+
f.write source
|
165
|
+
end
|
161
166
|
|
162
167
|
nil
|
163
|
-
ensure
|
164
|
-
# Ensure tmp file gets cleaned up
|
165
|
-
FileUtils.rm("#{filename}+") if File.exist?("#{filename}+")
|
166
168
|
end
|
167
169
|
|
168
|
-
# Pretty inspect
|
170
|
+
# Public: Pretty inspect
|
171
|
+
#
|
172
|
+
# Returns String.
|
169
173
|
def inspect
|
170
|
-
"#<#{self.class}
|
171
|
-
"pathname=#{pathname.to_s.inspect}, " +
|
172
|
-
"mtime=#{mtime.inspect}, " +
|
173
|
-
"digest=#{digest.inspect}" +
|
174
|
-
">"
|
174
|
+
"#<#{self.class}:#{object_id.to_s(16)} #{uri.inspect}>"
|
175
175
|
end
|
176
176
|
|
177
|
+
# Public: Implements Object#hash so Assets can be used as a Hash key or
|
178
|
+
# in a Set.
|
179
|
+
#
|
180
|
+
# Returns Integer hash of the id.
|
177
181
|
def hash
|
178
|
-
|
182
|
+
id.hash
|
179
183
|
end
|
180
184
|
|
181
|
-
#
|
185
|
+
# Public: Compare assets.
|
186
|
+
#
|
187
|
+
# Assets are equal if they share the same path and digest.
|
188
|
+
#
|
189
|
+
# Returns true or false.
|
182
190
|
def eql?(other)
|
183
|
-
|
184
|
-
other.logical_path == self.logical_path &&
|
185
|
-
other.mtime.to_i == self.mtime.to_i &&
|
186
|
-
other.digest == self.digest
|
191
|
+
self.class == other.class && self.id == other.id
|
187
192
|
end
|
188
193
|
alias_method :==, :eql?
|
189
|
-
|
190
|
-
protected
|
191
|
-
# Internal: String paths that are marked as dependencies after processing.
|
192
|
-
#
|
193
|
-
# Default to an empty `Array`.
|
194
|
-
def dependency_paths
|
195
|
-
@dependency_paths ||= []
|
196
|
-
end
|
197
|
-
|
198
|
-
# Internal: `ProccessedAsset`s that are required after processing.
|
199
|
-
#
|
200
|
-
# Default to an empty `Array`.
|
201
|
-
def required_assets
|
202
|
-
@required_assets ||= []
|
203
|
-
end
|
204
|
-
|
205
|
-
# Get pathname with its root stripped.
|
206
|
-
def relative_pathname
|
207
|
-
@relative_pathname ||= Pathname.new(relativize_root_path(pathname))
|
208
|
-
end
|
209
|
-
|
210
|
-
# Replace `$root` placeholder with actual environment root.
|
211
|
-
def expand_root_path(path)
|
212
|
-
path.to_s.sub(/^\$root/, @root)
|
213
|
-
end
|
214
|
-
|
215
|
-
# Replace actual environment root with `$root` placeholder.
|
216
|
-
def relativize_root_path(path)
|
217
|
-
path.to_s.sub(/^#{Regexp.escape(@root)}/, '$root')
|
218
|
-
end
|
219
|
-
|
220
|
-
# Check if dependency is fresh.
|
221
|
-
#
|
222
|
-
# `dep` is a `Hash` with `path`, `mtime` and `hexdigest` keys.
|
223
|
-
#
|
224
|
-
# A `Hash` is used rather than other `Asset` object because we
|
225
|
-
# want to test non-asset files and directories.
|
226
|
-
def dependency_fresh?(environment, dep)
|
227
|
-
path, mtime, hexdigest = dep.pathname.to_s, dep.mtime, dep.digest
|
228
|
-
|
229
|
-
stat = environment.stat(path)
|
230
|
-
|
231
|
-
# If path no longer exists, its definitely stale.
|
232
|
-
if stat.nil?
|
233
|
-
return false
|
234
|
-
end
|
235
|
-
|
236
|
-
# Compare dependency mime to the actual mtime. If the
|
237
|
-
# dependency mtime is newer than the actual mtime, the file
|
238
|
-
# hasn't changed since we created this `Asset` instance.
|
239
|
-
#
|
240
|
-
# However, if the mtime is newer it doesn't mean the asset is
|
241
|
-
# stale. Many deployment environments may recopy or recheckout
|
242
|
-
# assets on each deploy. In this case the mtime would be the
|
243
|
-
# time of deploy rather than modified time.
|
244
|
-
if mtime >= stat.mtime
|
245
|
-
return true
|
246
|
-
end
|
247
|
-
|
248
|
-
digest = environment.file_digest(path)
|
249
|
-
|
250
|
-
# If the mtime is newer, do a full digest comparsion. Return
|
251
|
-
# fresh if the digests match.
|
252
|
-
if hexdigest == digest.hexdigest
|
253
|
-
return true
|
254
|
-
end
|
255
|
-
|
256
|
-
# Otherwise, its stale.
|
257
|
-
false
|
258
|
-
end
|
259
194
|
end
|
260
195
|
end
|