sprockets 3.0.0 → 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 +397 -408
- data/bin/sprockets +12 -7
- data/lib/rake/sprocketstask.rb +3 -2
- data/lib/sprockets/add_source_map_comment_to_asset_processor.rb +60 -0
- data/lib/sprockets/asset.rb +19 -23
- data/lib/sprockets/autoload/babel.rb +8 -0
- data/lib/sprockets/autoload/closure.rb +1 -0
- data/lib/sprockets/autoload/coffee_script.rb +1 -0
- data/lib/sprockets/autoload/eco.rb +1 -0
- data/lib/sprockets/autoload/ejs.rb +1 -0
- data/lib/sprockets/autoload/jsminc.rb +8 -0
- data/lib/sprockets/autoload/sass.rb +1 -0
- data/lib/sprockets/autoload/sassc.rb +8 -0
- data/lib/sprockets/autoload/uglifier.rb +1 -0
- data/lib/sprockets/autoload/yui.rb +1 -0
- data/lib/sprockets/autoload/zopfli.rb +7 -0
- data/lib/sprockets/autoload.rb +5 -0
- data/lib/sprockets/babel_processor.rb +66 -0
- data/lib/sprockets/base.rb +59 -11
- data/lib/sprockets/bower.rb +5 -2
- data/lib/sprockets/bundle.rb +44 -4
- data/lib/sprockets/cache/file_store.rb +32 -7
- data/lib/sprockets/cache/memory_store.rb +9 -0
- data/lib/sprockets/cache/null_store.rb +8 -0
- data/lib/sprockets/cache.rb +42 -5
- data/lib/sprockets/cached_environment.rb +14 -19
- data/lib/sprockets/closure_compressor.rb +6 -11
- data/lib/sprockets/coffee_script_processor.rb +19 -5
- data/lib/sprockets/compressing.rb +62 -2
- data/lib/sprockets/configuration.rb +3 -7
- data/lib/sprockets/context.rb +98 -23
- data/lib/sprockets/dependencies.rb +9 -8
- data/lib/sprockets/digest_utils.rb +104 -60
- data/lib/sprockets/directive_processor.rb +45 -35
- data/lib/sprockets/eco_processor.rb +3 -2
- data/lib/sprockets/ejs_processor.rb +3 -2
- data/lib/sprockets/encoding_utils.rb +8 -4
- data/lib/sprockets/environment.rb +9 -4
- data/lib/sprockets/erb_processor.rb +28 -21
- data/lib/sprockets/errors.rb +1 -1
- 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 +1 -0
- data/lib/sprockets/http_utils.rb +26 -6
- data/lib/sprockets/jsminc_compressor.rb +32 -0
- data/lib/sprockets/jst_processor.rb +11 -10
- data/lib/sprockets/loader.rb +236 -69
- data/lib/sprockets/manifest.rb +97 -44
- data/lib/sprockets/manifest_utils.rb +9 -6
- data/lib/sprockets/mime.rb +8 -42
- data/lib/sprockets/npm.rb +52 -0
- data/lib/sprockets/path_dependency_utils.rb +3 -11
- data/lib/sprockets/path_digest_utils.rb +2 -1
- data/lib/sprockets/path_utils.rb +106 -21
- data/lib/sprockets/paths.rb +1 -0
- data/lib/sprockets/preprocessors/default_source_map.rb +49 -0
- data/lib/sprockets/processing.rb +31 -51
- data/lib/sprockets/processor_utils.rb +81 -15
- data/lib/sprockets/resolve.rb +182 -95
- data/lib/sprockets/sass_cache_store.rb +1 -0
- data/lib/sprockets/sass_compressor.rb +21 -17
- data/lib/sprockets/sass_functions.rb +1 -0
- data/lib/sprockets/sass_importer.rb +1 -0
- data/lib/sprockets/sass_processor.rb +45 -17
- data/lib/sprockets/sassc_compressor.rb +56 -0
- data/lib/sprockets/sassc_processor.rb +297 -0
- data/lib/sprockets/server.rb +57 -34
- data/lib/sprockets/source_map_processor.rb +66 -0
- data/lib/sprockets/source_map_utils.rb +483 -0
- data/lib/sprockets/transformers.rb +63 -35
- data/lib/sprockets/uglifier_compressor.rb +23 -20
- data/lib/sprockets/unloaded_asset.rb +139 -0
- data/lib/sprockets/uri_tar.rb +99 -0
- data/lib/sprockets/uri_utils.rb +15 -14
- data/lib/sprockets/utils/gzip.rb +99 -0
- data/lib/sprockets/utils.rb +43 -59
- data/lib/sprockets/version.rb +2 -1
- data/lib/sprockets/yui_compressor.rb +5 -14
- data/lib/sprockets.rb +103 -33
- metadata +151 -22
- data/LICENSE +0 -21
- data/lib/sprockets/coffee_script_template.rb +0 -6
- data/lib/sprockets/eco_template.rb +0 -6
- data/lib/sprockets/ejs_template.rb +0 -6
- data/lib/sprockets/engines.rb +0 -81
- data/lib/sprockets/erb_template.rb +0 -6
- data/lib/sprockets/legacy.rb +0 -314
- data/lib/sprockets/legacy_proc_processor.rb +0 -35
- data/lib/sprockets/legacy_tilt_processor.rb +0 -29
- data/lib/sprockets/sass_template.rb +0 -7
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
|
|
@@ -51,6 +52,10 @@ OptionParser.new do |opts|
|
|
51
52
|
opts.on("--noenv", "Disables .sprocketsrc file") do
|
52
53
|
end
|
53
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
|
+
|
54
59
|
opts.on_tail("-h", "--help", "Shows this help message") do
|
55
60
|
opts.show_usage
|
56
61
|
end
|
@@ -63,8 +68,8 @@ OptionParser.new do |opts|
|
|
63
68
|
opts.show_usage if ARGV.empty?
|
64
69
|
|
65
70
|
begin
|
66
|
-
opts.order(ARGV) do |
|
67
|
-
|
71
|
+
opts.order(ARGV) do |path|
|
72
|
+
paths << path
|
68
73
|
end
|
69
74
|
rescue OptionParser::ParseError => e
|
70
75
|
opts.warn e.message
|
@@ -74,14 +79,14 @@ end
|
|
74
79
|
|
75
80
|
if environment.paths.empty?
|
76
81
|
warn "No load paths given"
|
77
|
-
warn "Usage: sprockets -Ijavascripts/
|
82
|
+
warn "Usage: sprockets -Ijavascripts/ path"
|
78
83
|
exit 1
|
79
84
|
end
|
80
85
|
|
81
86
|
if manifest
|
82
|
-
manifest.compile(
|
83
|
-
elsif
|
84
|
-
puts environment.find_asset(
|
87
|
+
manifest.compile(paths)
|
88
|
+
elsif paths.length == 1
|
89
|
+
puts environment.find_asset(paths.first).to_s
|
85
90
|
else
|
86
91
|
warn "Only one file can be compiled to stdout at a time"
|
87
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
|
|
@@ -124,7 +125,7 @@ module Rake
|
|
124
125
|
end
|
125
126
|
end
|
126
127
|
|
127
|
-
task :
|
128
|
+
task clobber: ["clobber_#{name}"]
|
128
129
|
|
129
130
|
desc name == :assets ? "Clean old assets" : "Clean old #{name} assets"
|
130
131
|
task "clean_#{name}" do
|
@@ -133,7 +134,7 @@ module Rake
|
|
133
134
|
end
|
134
135
|
end
|
135
136
|
|
136
|
-
task :
|
137
|
+
task clean: ["clean_#{name}"]
|
137
138
|
end
|
138
139
|
|
139
140
|
private
|
@@ -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,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'fileutils'
|
2
3
|
require 'sprockets/digest_utils'
|
3
4
|
|
@@ -13,17 +14,14 @@ module Sprockets
|
|
13
14
|
# attributes - Hash of ivars
|
14
15
|
#
|
15
16
|
# Returns Asset.
|
16
|
-
def initialize(
|
17
|
-
@environment = environment
|
17
|
+
def initialize(attributes = {})
|
18
18
|
@attributes = attributes
|
19
19
|
@content_type = attributes[:content_type]
|
20
20
|
@filename = attributes[:filename]
|
21
21
|
@id = attributes[:id]
|
22
|
-
@integrity = attributes[:integrity]
|
23
22
|
@load_path = attributes[:load_path]
|
24
23
|
@logical_path = attributes[:logical_path]
|
25
24
|
@metadata = attributes[:metadata]
|
26
|
-
@mtime = attributes[:mtime]
|
27
25
|
@name = attributes[:name]
|
28
26
|
@source = attributes[:source]
|
29
27
|
@uri = attributes[:uri]
|
@@ -69,6 +67,13 @@ module Sprockets
|
|
69
67
|
logical_path.sub(/\.(\w+)$/) { |ext| "-#{etag}#{ext}" }
|
70
68
|
end
|
71
69
|
|
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)
|
75
|
+
end
|
76
|
+
|
72
77
|
# Public: Returns String MIME type of asset. Returns nil if type is unknown.
|
73
78
|
attr_reader :content_type
|
74
79
|
|
@@ -81,14 +86,6 @@ module Sprockets
|
|
81
86
|
metadata[:links] || Set.new
|
82
87
|
end
|
83
88
|
|
84
|
-
# Public: Get all internally required assets that were concated into this
|
85
|
-
# asset.
|
86
|
-
#
|
87
|
-
# Returns Array of String asset URIs.
|
88
|
-
def included
|
89
|
-
metadata[:included]
|
90
|
-
end
|
91
|
-
|
92
89
|
# Public: Return `String` of concatenated source.
|
93
90
|
#
|
94
91
|
# Returns String.
|
@@ -121,26 +118,28 @@ module Sprockets
|
|
121
118
|
end
|
122
119
|
alias_method :bytesize, :length
|
123
120
|
|
121
|
+
# Public: Returns String byte digest of source.
|
122
|
+
def digest
|
123
|
+
metadata[:digest]
|
124
|
+
end
|
125
|
+
|
124
126
|
# Public: Returns String hexdigest of source.
|
125
127
|
def hexdigest
|
126
|
-
DigestUtils.pack_hexdigest(
|
128
|
+
DigestUtils.pack_hexdigest(digest)
|
127
129
|
end
|
128
130
|
|
129
|
-
# Deprecated: Returns String hexdigest of source.
|
130
|
-
#
|
131
|
-
# In 4.x this will be changed to return a raw Digest byte String.
|
132
|
-
alias_method :digest, :hexdigest
|
133
|
-
|
134
131
|
# Pubic: ETag String of Asset.
|
135
132
|
alias_method :etag, :hexdigest
|
136
133
|
|
137
134
|
# Public: Returns String base64 digest of source.
|
138
135
|
def base64digest
|
139
|
-
DigestUtils.pack_base64digest(
|
136
|
+
DigestUtils.pack_base64digest(digest)
|
140
137
|
end
|
141
138
|
|
142
139
|
# Public: A "named information" URL for subresource integrity.
|
143
|
-
|
140
|
+
def integrity
|
141
|
+
DigestUtils.integrity_uri(metadata[:digest])
|
142
|
+
end
|
144
143
|
|
145
144
|
# Public: Add enumerator to allow `Asset` instances to be used as Rack
|
146
145
|
# compatible body objects.
|
@@ -165,9 +164,6 @@ module Sprockets
|
|
165
164
|
f.write source
|
166
165
|
end
|
167
166
|
|
168
|
-
# Set mtime correctly
|
169
|
-
File.utime(mtime, mtime, filename)
|
170
|
-
|
171
167
|
nil
|
172
168
|
end
|
173
169
|
|
data/lib/sprockets/autoload.rb
CHANGED
@@ -1,11 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Sprockets
|
2
3
|
module Autoload
|
4
|
+
autoload :Babel, 'sprockets/autoload/babel'
|
3
5
|
autoload :Closure, 'sprockets/autoload/closure'
|
4
6
|
autoload :CoffeeScript, 'sprockets/autoload/coffee_script'
|
5
7
|
autoload :Eco, 'sprockets/autoload/eco'
|
6
8
|
autoload :EJS, 'sprockets/autoload/ejs'
|
9
|
+
autoload :JSMinC, 'sprockets/autoload/jsminc'
|
7
10
|
autoload :Sass, 'sprockets/autoload/sass'
|
11
|
+
autoload :SassC, 'sprockets/autoload/sassc'
|
8
12
|
autoload :Uglifier, 'sprockets/autoload/uglifier'
|
9
13
|
autoload :YUI, 'sprockets/autoload/yui'
|
14
|
+
autoload :Zopfli, 'sprockets/autoload/zopfli'
|
10
15
|
end
|
11
16
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'sprockets/autoload'
|
3
|
+
require 'sprockets/path_utils'
|
4
|
+
require 'sprockets/source_map_utils'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
module Sprockets
|
8
|
+
class BabelProcessor
|
9
|
+
VERSION = '1'
|
10
|
+
|
11
|
+
def self.instance
|
12
|
+
@instance ||= new
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.call(input)
|
16
|
+
instance.call(input)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.cache_key
|
20
|
+
instance.cache_key
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :cache_key
|
24
|
+
|
25
|
+
def initialize(options = {})
|
26
|
+
@options = options.merge({
|
27
|
+
'blacklist' => (options['blacklist'] || []) + ['useStrict'],
|
28
|
+
'sourceMap' => true
|
29
|
+
}).freeze
|
30
|
+
|
31
|
+
@cache_key = [
|
32
|
+
self.class.name,
|
33
|
+
Autoload::Babel::Transpiler::VERSION,
|
34
|
+
Autoload::Babel::Source::VERSION,
|
35
|
+
VERSION,
|
36
|
+
@options
|
37
|
+
].freeze
|
38
|
+
end
|
39
|
+
|
40
|
+
def call(input)
|
41
|
+
data = input[:data]
|
42
|
+
|
43
|
+
result = input[:cache].fetch(@cache_key + [input[:filename]] + [data]) do
|
44
|
+
opts = {
|
45
|
+
'moduleRoot' => nil,
|
46
|
+
'filename' => input[:filename],
|
47
|
+
'filenameRelative' => PathUtils.split_subpath(input[:load_path], input[:filename]),
|
48
|
+
'sourceFileName' => File.basename(input[:filename]),
|
49
|
+
'sourceMapTarget' => input[:filename]
|
50
|
+
}.merge(@options)
|
51
|
+
|
52
|
+
if opts['moduleIds'] && opts['moduleRoot']
|
53
|
+
opts['moduleId'] ||= File.join(opts['moduleRoot'], input[:name])
|
54
|
+
elsif opts['moduleIds']
|
55
|
+
opts['moduleId'] ||= input[:name]
|
56
|
+
end
|
57
|
+
Autoload::Babel::Transpiler.transform(data, opts)
|
58
|
+
end
|
59
|
+
|
60
|
+
map = SourceMapUtils.format_source_map(result["map"], input)
|
61
|
+
map = SourceMapUtils.combine_source_maps(input[:metadata][:map], map)
|
62
|
+
|
63
|
+
{ data: result['code'], map: map }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/sprockets/base.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'sprockets/asset'
|
2
3
|
require 'sprockets/bower'
|
3
4
|
require 'sprockets/cache'
|
@@ -5,20 +6,36 @@ require 'sprockets/configuration'
|
|
5
6
|
require 'sprockets/digest_utils'
|
6
7
|
require 'sprockets/errors'
|
7
8
|
require 'sprockets/loader'
|
8
|
-
require 'sprockets/
|
9
|
+
require 'sprockets/npm'
|
9
10
|
require 'sprockets/path_dependency_utils'
|
11
|
+
require 'sprockets/path_digest_utils'
|
10
12
|
require 'sprockets/path_utils'
|
11
13
|
require 'sprockets/resolve'
|
12
14
|
require 'sprockets/server'
|
15
|
+
require 'sprockets/source_map_utils'
|
16
|
+
require 'sprockets/uri_tar'
|
13
17
|
|
14
18
|
module Sprockets
|
15
|
-
|
19
|
+
|
20
|
+
class DoubleLinkError < Sprockets::Error
|
21
|
+
def initialize(parent_filename:, logical_path:, last_filename:, filename:)
|
22
|
+
super <<~MSG
|
23
|
+
Multiple files with the same output path cannot be linked (#{logical_path.inspect})
|
24
|
+
In #{parent_filename.inspect} these files were linked:
|
25
|
+
- #{last_filename}
|
26
|
+
- #{filename}
|
27
|
+
MSG
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# `Base` class for `Environment` and `CachedEnvironment`.
|
16
32
|
class Base
|
17
|
-
include PathUtils, PathDependencyUtils, PathDigestUtils, DigestUtils
|
33
|
+
include PathUtils, PathDependencyUtils, PathDigestUtils, DigestUtils, SourceMapUtils
|
18
34
|
include Configuration
|
19
35
|
include Server
|
20
36
|
include Resolve, Loader
|
21
37
|
include Bower
|
38
|
+
include Npm
|
22
39
|
|
23
40
|
# Get persistent cache store
|
24
41
|
attr_reader :cache
|
@@ -32,7 +49,7 @@ module Sprockets
|
|
32
49
|
@cache = Cache.new(cache, logger)
|
33
50
|
end
|
34
51
|
|
35
|
-
# Return an `
|
52
|
+
# Return an `CachedEnvironment`. Must be implemented by the subclass.
|
36
53
|
def cached
|
37
54
|
raise NotImplementedError
|
38
55
|
end
|
@@ -48,33 +65,46 @@ module Sprockets
|
|
48
65
|
# Caveat: Digests are cached by the path's current mtime. Its possible
|
49
66
|
# for a files contents to have changed and its mtime to have been
|
50
67
|
# negligently reset thus appearing as if the file hasn't changed on
|
51
|
-
# disk. Also, the mtime is only read to the nearest second.
|
68
|
+
# disk. Also, the mtime is only read to the nearest second. It's
|
52
69
|
# also possible the file was updated more than once in a given second.
|
53
|
-
|
70
|
+
key = UnloadedAsset.new(path, self).file_digest_key(stat.mtime.to_i)
|
71
|
+
cache.fetch(key) do
|
54
72
|
self.stat_digest(path, stat)
|
55
73
|
end
|
56
74
|
end
|
57
75
|
end
|
58
76
|
|
59
77
|
# Find asset by logical path or expanded path.
|
60
|
-
def find_asset(
|
61
|
-
uri, _ = resolve(
|
78
|
+
def find_asset(*args, **options)
|
79
|
+
uri, _ = resolve(*args, **options)
|
62
80
|
if uri
|
63
81
|
load(uri)
|
64
82
|
end
|
65
83
|
end
|
66
84
|
|
67
|
-
def find_all_linked_assets(
|
68
|
-
return to_enum(__method__,
|
85
|
+
def find_all_linked_assets(*args)
|
86
|
+
return to_enum(__method__, *args) unless block_given?
|
69
87
|
|
70
|
-
asset = find_asset(
|
88
|
+
parent_asset = asset = find_asset(*args)
|
71
89
|
return unless asset
|
72
90
|
|
73
91
|
yield asset
|
74
92
|
stack = asset.links.to_a
|
93
|
+
linked_paths = {}
|
75
94
|
|
76
95
|
while uri = stack.shift
|
77
96
|
yield asset = load(uri)
|
97
|
+
|
98
|
+
last_filename = linked_paths[asset.logical_path]
|
99
|
+
if last_filename && last_filename != asset.filename
|
100
|
+
raise DoubleLinkError.new(
|
101
|
+
parent_filename: parent_asset.filename,
|
102
|
+
last_filename: last_filename,
|
103
|
+
logical_path: asset.logical_path,
|
104
|
+
filename: asset.filename
|
105
|
+
)
|
106
|
+
end
|
107
|
+
linked_paths[asset.logical_path] = asset.filename
|
78
108
|
stack = asset.links.to_a + stack
|
79
109
|
end
|
80
110
|
|
@@ -89,11 +119,29 @@ module Sprockets
|
|
89
119
|
find_asset(*args)
|
90
120
|
end
|
91
121
|
|
122
|
+
# Find asset by logical path or expanded path.
|
123
|
+
#
|
124
|
+
# If the asset is not found an error will be raised.
|
125
|
+
def find_asset!(*args)
|
126
|
+
uri, _ = resolve!(*args)
|
127
|
+
if uri
|
128
|
+
load(uri)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
92
132
|
# Pretty inspect
|
93
133
|
def inspect
|
94
134
|
"#<#{self.class}:0x#{object_id.to_s(16)} " +
|
95
135
|
"root=#{root.to_s.inspect}, " +
|
96
136
|
"paths=#{paths.inspect}>"
|
97
137
|
end
|
138
|
+
|
139
|
+
def compress_from_root(uri)
|
140
|
+
URITar.new(uri, self).compress
|
141
|
+
end
|
142
|
+
|
143
|
+
def expand_from_root(uri)
|
144
|
+
URITar.new(uri, self).expand
|
145
|
+
end
|
98
146
|
end
|
99
147
|
end
|
data/lib/sprockets/bower.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'json'
|
2
3
|
|
3
4
|
module Sprockets
|
@@ -17,7 +18,7 @@ module Sprockets
|
|
17
18
|
candidates, deps = super
|
18
19
|
|
19
20
|
# bower.json can only be nested one level deep
|
20
|
-
if !logical_path.index('/')
|
21
|
+
if !logical_path.index('/'.freeze)
|
21
22
|
dirname = File.join(load_path, logical_path)
|
22
23
|
|
23
24
|
if directory?(dirname)
|
@@ -27,7 +28,9 @@ module Sprockets
|
|
27
28
|
if filename
|
28
29
|
deps << build_file_digest_uri(filename)
|
29
30
|
read_bower_main(dirname, filename) do |path|
|
30
|
-
|
31
|
+
if file?(path)
|
32
|
+
candidates << path
|
33
|
+
end
|
31
34
|
end
|
32
35
|
end
|
33
36
|
end
|
data/lib/sprockets/bundle.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'set'
|
2
3
|
require 'sprockets/utils'
|
4
|
+
require 'sprockets/uri_utils'
|
3
5
|
|
4
6
|
module Sprockets
|
5
7
|
# Internal: Bundle processor takes a single file asset and prepends all the
|
@@ -15,15 +17,32 @@ module Sprockets
|
|
15
17
|
def self.call(input)
|
16
18
|
env = input[:environment]
|
17
19
|
type = input[:content_type]
|
20
|
+
input[:links] ||= Set.new
|
18
21
|
dependencies = Set.new(input[:metadata][:dependencies])
|
19
22
|
|
20
|
-
processed_uri, deps = env.resolve(input[:filename], accept: type, pipeline: :self
|
23
|
+
processed_uri, deps = env.resolve(input[:filename], accept: type, pipeline: :self)
|
21
24
|
dependencies.merge(deps)
|
22
25
|
|
26
|
+
# DirectiveProcessor (and any other transformers called here with pipeline=self)
|
27
|
+
primary_asset = env.load(processed_uri)
|
28
|
+
to_load = primary_asset.metadata.delete(:to_load) || Set.new
|
29
|
+
to_link = primary_asset.metadata.delete(:to_link) || Set.new
|
30
|
+
|
31
|
+
to_load.each do |uri|
|
32
|
+
loaded_asset = env.load(uri)
|
33
|
+
dependencies.merge(loaded_asset.metadata[:dependencies])
|
34
|
+
if to_link.include?(uri)
|
35
|
+
primary_metadata = primary_asset.metadata
|
36
|
+
input[:links] << loaded_asset.uri
|
37
|
+
primary_metadata[:links] << loaded_asset.uri
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
23
41
|
find_required = proc { |uri| env.load(uri).metadata[:required] }
|
24
42
|
required = Utils.dfs(processed_uri, &find_required)
|
25
43
|
stubbed = Utils.dfs(env.load(processed_uri).metadata[:stubbed], &find_required)
|
26
44
|
required.subtract(stubbed)
|
45
|
+
dedup(required)
|
27
46
|
assets = required.map { |uri| env.load(uri) }
|
28
47
|
|
29
48
|
(required + stubbed).each do |uri|
|
@@ -31,20 +50,41 @@ module Sprockets
|
|
31
50
|
end
|
32
51
|
|
33
52
|
reducers = Hash[env.match_mime_type_keys(env.config[:bundle_reducers], type).flat_map(&:to_a)]
|
34
|
-
process_bundle_reducers(assets, reducers).merge(dependencies: dependencies, included: assets.map(&:uri))
|
53
|
+
process_bundle_reducers(input, assets, reducers).merge(dependencies: dependencies, included: assets.map(&:uri))
|
54
|
+
end
|
55
|
+
|
56
|
+
# Internal: Removes uri from required if it's already included as an alias.
|
57
|
+
#
|
58
|
+
# required - Set of required uris
|
59
|
+
#
|
60
|
+
# Returns deduped set of uris
|
61
|
+
def self.dedup(required)
|
62
|
+
dupes = required.reduce([]) do |r, uri|
|
63
|
+
path, params = URIUtils.parse_asset_uri(uri)
|
64
|
+
if (params.delete(:index_alias))
|
65
|
+
r << URIUtils.build_asset_uri(path, params)
|
66
|
+
end
|
67
|
+
r
|
68
|
+
end
|
69
|
+
required.subtract(dupes)
|
35
70
|
end
|
36
71
|
|
37
72
|
# Internal: Run bundle reducers on set of Assets producing a reduced
|
38
73
|
# metadata Hash.
|
39
74
|
#
|
75
|
+
# filename - String bundle filename
|
40
76
|
# assets - Array of Assets
|
41
77
|
# reducers - Array of [initial, reducer_proc] pairs
|
42
78
|
#
|
43
79
|
# Returns reduced asset metadata Hash.
|
44
|
-
def self.process_bundle_reducers(assets, reducers)
|
80
|
+
def self.process_bundle_reducers(input, assets, reducers)
|
45
81
|
initial = {}
|
46
82
|
reducers.each do |k, (v, _)|
|
47
|
-
|
83
|
+
if v.respond_to?(:call)
|
84
|
+
initial[k] = v.call(input)
|
85
|
+
elsif !v.nil?
|
86
|
+
initial[k] = v
|
87
|
+
end
|
48
88
|
end
|
49
89
|
|
50
90
|
assets.reduce(initial) do |h, asset|
|