sprockets 4.0.0.beta4 → 4.0.0.beta5
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 +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +5 -6
- data/lib/sprockets.rb +2 -8
- data/lib/sprockets/babel_processor.rb +4 -4
- data/lib/sprockets/base.rb +2 -0
- data/lib/sprockets/bundle.rb +38 -3
- data/lib/sprockets/cache.rb +34 -0
- data/lib/sprockets/cache/file_store.rb +17 -1
- data/lib/sprockets/cache/memory_store.rb +8 -0
- data/lib/sprockets/cache/null_store.rb +7 -0
- data/lib/sprockets/cached_environment.rb +10 -16
- data/lib/sprockets/coffee_script_processor.rb +9 -2
- data/lib/sprockets/digest_utils.rb +3 -0
- data/lib/sprockets/directive_processor.rb +21 -13
- data/lib/sprockets/loader.rb +1 -7
- data/lib/sprockets/manifest.rb +13 -9
- data/lib/sprockets/manifest_utils.rb +0 -1
- data/lib/sprockets/npm.rb +52 -0
- data/lib/sprockets/path_utils.rb +25 -1
- data/lib/sprockets/preprocessors/default_source_map.rb +27 -7
- data/lib/sprockets/sass_compressor.rb +3 -5
- data/lib/sprockets/sass_processor.rb +2 -18
- data/lib/sprockets/sassc_compressor.rb +11 -10
- data/lib/sprockets/sassc_processor.rb +10 -17
- data/lib/sprockets/server.rb +1 -1
- data/lib/sprockets/source_map_comment_processor.rb +6 -1
- data/lib/sprockets/source_map_processor.rb +16 -18
- data/lib/sprockets/source_map_utils.rb +197 -70
- data/lib/sprockets/uglifier_compressor.rb +14 -8
- data/lib/sprockets/version.rb +1 -1
- metadata +7 -6
data/lib/sprockets/loader.rb
CHANGED
@@ -140,10 +140,6 @@ module Sprockets
|
|
140
140
|
|
141
141
|
# Read into memory and process if theres a processor pipeline
|
142
142
|
if processors.any?
|
143
|
-
source_uri, _ = resolve!(unloaded.filename, pipeline: :source)
|
144
|
-
source_asset = load(source_uri)
|
145
|
-
|
146
|
-
source_path = source_asset.digest_path
|
147
143
|
|
148
144
|
result = call_processors(processors, {
|
149
145
|
environment: self,
|
@@ -151,12 +147,10 @@ module Sprockets
|
|
151
147
|
uri: unloaded.uri,
|
152
148
|
filename: unloaded.filename,
|
153
149
|
load_path: load_path,
|
154
|
-
source_path: source_path,
|
155
150
|
name: name,
|
156
151
|
content_type: type,
|
157
152
|
metadata: {
|
158
|
-
dependencies: dependencies
|
159
|
-
map: []
|
153
|
+
dependencies: dependencies
|
160
154
|
}
|
161
155
|
})
|
162
156
|
validate_processor_result!(result)
|
data/lib/sprockets/manifest.rb
CHANGED
@@ -120,11 +120,14 @@ module Sprockets
|
|
120
120
|
return to_enum(__method__, *args) unless block_given?
|
121
121
|
|
122
122
|
environment = self.environment.cached
|
123
|
-
args.flatten.
|
124
|
-
|
125
|
-
|
123
|
+
promises = args.flatten.map do |path|
|
124
|
+
Concurrent::Promise.execute(executor: executor) do
|
125
|
+
environment.find_all_linked_assets(path) do |asset|
|
126
|
+
yield asset
|
127
|
+
end
|
126
128
|
end
|
127
129
|
end
|
130
|
+
promises.each(&:wait!)
|
128
131
|
|
129
132
|
nil
|
130
133
|
end
|
@@ -160,7 +163,6 @@ module Sprockets
|
|
160
163
|
|
161
164
|
filenames = []
|
162
165
|
concurrent_exporters = []
|
163
|
-
executor = Concurrent::FixedThreadPool.new(Concurrent.processor_count)
|
164
166
|
|
165
167
|
find(*args) do |asset|
|
166
168
|
mtime = Time.now.iso8601
|
@@ -183,11 +185,6 @@ module Sprockets
|
|
183
185
|
exporters_for_asset(asset) do |exporter|
|
184
186
|
next if exporter.skip?(logger)
|
185
187
|
|
186
|
-
if !environment.export_concurrent
|
187
|
-
exporter.call
|
188
|
-
next
|
189
|
-
end
|
190
|
-
|
191
188
|
if promise.nil?
|
192
189
|
promise = Concurrent::Promise.new(executor: executor) { exporter.call }
|
193
190
|
concurrent_exporters << promise.execute
|
@@ -265,6 +262,8 @@ module Sprockets
|
|
265
262
|
def clobber
|
266
263
|
FileUtils.rm_r(directory) if File.exist?(directory)
|
267
264
|
logger.info "Removed #{directory}"
|
265
|
+
# if we have an environment clear the cache too
|
266
|
+
environment.cache.clear if environment
|
268
267
|
nil
|
269
268
|
end
|
270
269
|
|
@@ -294,6 +293,7 @@ module Sprockets
|
|
294
293
|
exporters = [Exporters::FileExporter]
|
295
294
|
|
296
295
|
environment.exporters.each do |mime_type, exporter_list|
|
296
|
+
next unless asset.content_type
|
297
297
|
next unless environment.match_mime_type? asset.content_type, mime_type
|
298
298
|
exporter_list.each do |exporter|
|
299
299
|
exporters << exporter
|
@@ -324,5 +324,9 @@ module Sprockets
|
|
324
324
|
logger
|
325
325
|
end
|
326
326
|
end
|
327
|
+
|
328
|
+
def executor
|
329
|
+
@executor ||= environment.export_concurrent ? :fast : :immediate
|
330
|
+
end
|
327
331
|
end
|
328
332
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Sprockets
|
5
|
+
module Npm
|
6
|
+
# Internal: Override resolve_alternates to install package.json behavior.
|
7
|
+
#
|
8
|
+
# load_path - String environment path
|
9
|
+
# logical_path - String path relative to base
|
10
|
+
#
|
11
|
+
# Returns candiate filenames.
|
12
|
+
def resolve_alternates(load_path, logical_path)
|
13
|
+
candidates, deps = super
|
14
|
+
|
15
|
+
dirname = File.join(load_path, logical_path)
|
16
|
+
|
17
|
+
if directory?(dirname)
|
18
|
+
filename = File.join(dirname, 'package.json')
|
19
|
+
|
20
|
+
if self.file?(filename)
|
21
|
+
deps << build_file_digest_uri(filename)
|
22
|
+
read_package_directives(dirname, filename) do |path|
|
23
|
+
if file?(path)
|
24
|
+
candidates << path
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
return candidates, deps
|
31
|
+
end
|
32
|
+
|
33
|
+
# Internal: Read package.json's main and style directives.
|
34
|
+
#
|
35
|
+
# dirname - String path to component directory.
|
36
|
+
# filename - String path to package.json.
|
37
|
+
#
|
38
|
+
# Returns nothing.
|
39
|
+
def read_package_directives(dirname, filename)
|
40
|
+
package = JSON.parse(File.read(filename), create_additions: false)
|
41
|
+
|
42
|
+
case package['main']
|
43
|
+
when String
|
44
|
+
yield File.expand_path(package['main'], dirname)
|
45
|
+
when nil
|
46
|
+
yield File.expand_path('index.js', dirname)
|
47
|
+
end
|
48
|
+
|
49
|
+
yield File.expand_path(package['style'], dirname) if package['style']
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/sprockets/path_utils.rb
CHANGED
@@ -81,7 +81,7 @@ module Sprockets
|
|
81
81
|
end
|
82
82
|
else
|
83
83
|
def absolute_path?(path)
|
84
|
-
path
|
84
|
+
path.start_with?(File::SEPARATOR)
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
@@ -128,6 +128,30 @@ module Sprockets
|
|
128
128
|
(Pathname.new(base) + path).to_s
|
129
129
|
end
|
130
130
|
|
131
|
+
# Public: Sets pipeline for path
|
132
|
+
#
|
133
|
+
# path - String path
|
134
|
+
# extensions - List of file extensions
|
135
|
+
# pipeline - Pipeline
|
136
|
+
#
|
137
|
+
# Examples
|
138
|
+
#
|
139
|
+
# set_pipeline('path/file.js.erb', config[:mime_exts], config[:pipeline_exts], :source)
|
140
|
+
# # => 'path/file.source.js.erb'
|
141
|
+
#
|
142
|
+
# set_pipeline('path/some.file.source.js.erb', config[:mime_exts], config[:pipeline_exts], :debug)
|
143
|
+
# # => 'path/some.file.debug.js.erb'
|
144
|
+
#
|
145
|
+
# Returns string path with pipeline parsed in
|
146
|
+
def set_pipeline(path, mime_exts, pipeline_exts, pipeline)
|
147
|
+
extension, _ = match_path_extname(path, mime_exts)
|
148
|
+
path.chomp!(extension)
|
149
|
+
pipeline_old, _ = match_path_extname(path, pipeline_exts)
|
150
|
+
path.chomp!(pipeline_old)
|
151
|
+
|
152
|
+
"#{path}.#{pipeline}#{extension}"
|
153
|
+
end
|
154
|
+
|
131
155
|
# Internal: Get relative path for root path and subpath.
|
132
156
|
#
|
133
157
|
# path - String path
|
@@ -9,17 +9,37 @@ module Sprockets
|
|
9
9
|
# available.
|
10
10
|
class DefaultSourceMap
|
11
11
|
def call(input)
|
12
|
-
result
|
13
|
-
map
|
12
|
+
result = { data: input[:data] }
|
13
|
+
map = input[:metadata][:map]
|
14
|
+
filename = input[:filename]
|
15
|
+
load_path = input[:load_path]
|
16
|
+
lines = input[:data].lines.count
|
17
|
+
basename = File.basename(filename)
|
18
|
+
mime_exts = input[:environment].config[:mime_exts]
|
19
|
+
pipeline_exts = input[:environment].config[:pipeline_exts]
|
14
20
|
if map.nil? || map.empty?
|
15
|
-
result[:map]
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
21
|
+
result[:map] = {
|
22
|
+
"version" => 3,
|
23
|
+
"file" => PathUtils.split_subpath(load_path, filename),
|
24
|
+
"mappings" => default_mappings(lines),
|
25
|
+
"sources" => [PathUtils.set_pipeline(basename, mime_exts, pipeline_exts, :source)],
|
26
|
+
"names" => []
|
27
|
+
}
|
20
28
|
end
|
21
29
|
return result
|
22
30
|
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def default_mappings(lines)
|
35
|
+
if (lines == 0)
|
36
|
+
""
|
37
|
+
elsif (lines == 1)
|
38
|
+
"AAAA"
|
39
|
+
else
|
40
|
+
"AAAA;" + "AACA;"*(lines - 2) + "AACA"
|
41
|
+
end
|
42
|
+
end
|
23
43
|
end
|
24
44
|
end
|
25
45
|
end
|
@@ -49,15 +49,13 @@ module Sprockets
|
|
49
49
|
def call(input)
|
50
50
|
css, map = Autoload::Sass::Engine.new(
|
51
51
|
input[:data],
|
52
|
-
@options.merge(filename:
|
52
|
+
@options.merge(filename: input[:filename])
|
53
53
|
).render_with_sourcemap('')
|
54
54
|
|
55
55
|
css = css.sub("/*# sourceMappingURL= */\n", '')
|
56
56
|
|
57
|
-
map = SourceMapUtils.
|
58
|
-
|
59
|
-
SourceMapUtils.decode_json_source_map(map.to_json(css_uri: 'uri'))["mappings"]
|
60
|
-
)
|
57
|
+
map = SourceMapUtils.format_source_map(JSON.parse(map.to_json(css_uri: '')), input)
|
58
|
+
map = SourceMapUtils.combine_source_maps(input[:metadata][:map], map)
|
61
59
|
|
62
60
|
{ data: css, map: map }
|
63
61
|
end
|
@@ -80,13 +80,8 @@ module Sprockets
|
|
80
80
|
|
81
81
|
css = css.sub("\n/*# sourceMappingURL= */\n", '')
|
82
82
|
|
83
|
-
map = SourceMapUtils.
|
84
|
-
|
85
|
-
expand_map_sources(
|
86
|
-
SourceMapUtils.decode_json_source_map(map.to_json(css_uri: '', type: :inline))["mappings"],
|
87
|
-
input[:environment]
|
88
|
-
)
|
89
|
-
)
|
83
|
+
map = SourceMapUtils.format_source_map(JSON.parse(map.to_json(css_uri: '')), input)
|
84
|
+
map = SourceMapUtils.combine_source_maps(input[:metadata][:map], map)
|
90
85
|
|
91
86
|
# Track all imported files
|
92
87
|
sass_dependencies = Set.new([input[:filename]])
|
@@ -100,17 +95,6 @@ module Sprockets
|
|
100
95
|
|
101
96
|
private
|
102
97
|
|
103
|
-
def expand_source(source, env)
|
104
|
-
uri, _ = env.resolve!(source, pipeline: :source)
|
105
|
-
env.load(uri).digest_path
|
106
|
-
end
|
107
|
-
|
108
|
-
def expand_map_sources(mapping, env)
|
109
|
-
mapping.each do |map|
|
110
|
-
map[:source] = expand_source(map[:source], env)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
98
|
# Public: Build the cache store to be used by the Sass engine.
|
115
99
|
#
|
116
100
|
# input - the input hash.
|
@@ -9,23 +9,24 @@ module Sprockets
|
|
9
9
|
@options = {
|
10
10
|
syntax: :scss,
|
11
11
|
style: :compressed,
|
12
|
-
|
13
|
-
|
12
|
+
source_map_contents: false,
|
13
|
+
omit_source_map_url: true,
|
14
14
|
}.merge(options).freeze
|
15
15
|
end
|
16
16
|
|
17
17
|
def call(input)
|
18
18
|
# SassC requires the template to be modifiable
|
19
19
|
input_data = input[:data].frozen? ? input[:data].dup : input[:data]
|
20
|
-
|
20
|
+
engine = Autoload::SassC::Engine.new(input_data, @options.merge(filename: input[:filename], source_map_file: "#{input[:filename]}.map"))
|
21
|
+
|
22
|
+
css = engine.render.sub(/^\n^\/\*# sourceMappingURL=.*\*\/$/m, '')
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
input[:metadata][:map]
|
27
|
-
|
28
|
-
)
|
24
|
+
begin
|
25
|
+
map = SourceMapUtils.format_source_map(JSON.parse(engine.source_map), input)
|
26
|
+
map = SourceMapUtils.combine_source_maps(input[:metadata][:map], map)
|
27
|
+
rescue SassC::NotRenderedError
|
28
|
+
map = input[:metadata][:map]
|
29
|
+
end
|
29
30
|
|
30
31
|
{ data: css, map: map }
|
31
32
|
end
|
@@ -27,25 +27,18 @@ module Sprockets
|
|
27
27
|
engine.render.sub(/^\n^\/\*# sourceMappingURL=.*\*\/$/m, '')
|
28
28
|
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
map = map["mappings"].each do |m|
|
36
|
-
m[:source] = PathUtils.join(File.dirname(input[:filename]), m[:source])
|
37
|
-
end
|
38
|
-
|
39
|
-
map = SourceMapUtils.combine_source_maps(
|
40
|
-
input[:metadata][:map],
|
41
|
-
expand_map_sources(map, input[:environment])
|
42
|
-
)
|
30
|
+
begin
|
31
|
+
map = SourceMapUtils.format_source_map(JSON.parse(engine.source_map), input)
|
32
|
+
map = SourceMapUtils.combine_source_maps(input[:metadata][:map], map)
|
43
33
|
|
44
|
-
|
45
|
-
|
34
|
+
engine.dependencies.each do |dependency|
|
35
|
+
context.metadata[:dependencies] << URIUtils.build_file_digest_uri(dependency.filename)
|
36
|
+
end
|
37
|
+
rescue SassC::NotRenderedError
|
38
|
+
map = input[:metadata][:map]
|
46
39
|
end
|
47
40
|
|
48
|
-
context.metadata.merge(data: css, map: map
|
41
|
+
context.metadata.merge(data: css, map: map)
|
49
42
|
end
|
50
43
|
|
51
44
|
private
|
@@ -56,7 +49,7 @@ module Sprockets
|
|
56
49
|
syntax: self.class.syntax,
|
57
50
|
load_paths: input[:environment].paths,
|
58
51
|
importer: @importer_class,
|
59
|
-
source_map_contents:
|
52
|
+
source_map_contents: false,
|
60
53
|
source_map_file: "#{input[:filename]}.map",
|
61
54
|
omit_source_map_url: true,
|
62
55
|
sprockets: {
|
data/lib/sprockets/server.rb
CHANGED
@@ -241,7 +241,7 @@ module Sprockets
|
|
241
241
|
# If the request url contains a fingerprint, set a long
|
242
242
|
# expires on the response
|
243
243
|
if path_fingerprint(env["PATH_INFO"])
|
244
|
-
headers["Cache-Control"] << ", max-age=31536000"
|
244
|
+
headers["Cache-Control"] << ", max-age=31536000, immutable"
|
245
245
|
|
246
246
|
# Otherwise set `must-revalidate` since the asset could be modified.
|
247
247
|
else
|
@@ -1,4 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require 'sprockets/uri_utils'
|
3
|
+
require 'sprockets/path_utils'
|
4
|
+
|
2
5
|
module Sprockets
|
3
6
|
class SourceMapCommentProcessor
|
4
7
|
def self.call(input)
|
@@ -21,7 +24,9 @@ module Sprockets
|
|
21
24
|
uri, _ = env.resolve!(input[:filename], accept: map_type)
|
22
25
|
map = env.load(uri)
|
23
26
|
|
24
|
-
|
27
|
+
uri, params = URIUtils.parse_asset_uri(input[:uri])
|
28
|
+
uri = env.expand_from_root(params[:index_alias]) if params[:index_alias]
|
29
|
+
path = PathUtils.relative_path_from(PathUtils.split_subpath(input[:load_path], uri), map.digest_path)
|
25
30
|
|
26
31
|
asset.metadata.merge(
|
27
32
|
data: asset.source + (comment % path),
|
@@ -3,24 +3,25 @@ require 'set'
|
|
3
3
|
|
4
4
|
module Sprockets
|
5
5
|
class SourceMapProcessor
|
6
|
-
def self.
|
7
|
-
case
|
6
|
+
def self.original_content_type(source_map_content_type, error_when_not_found: true)
|
7
|
+
case source_map_content_type
|
8
8
|
when "application/js-sourcemap+json"
|
9
9
|
accept = "application/javascript"
|
10
10
|
when "application/css-sourcemap+json"
|
11
11
|
accept = "text/css"
|
12
12
|
else
|
13
|
-
fail
|
13
|
+
fail(source_map_content_type) if error_when_not_found
|
14
|
+
source_map_content_type
|
14
15
|
end
|
16
|
+
end
|
15
17
|
|
18
|
+
def self.call(input)
|
16
19
|
links = Set.new(input[:metadata][:links])
|
17
|
-
|
18
20
|
env = input[:environment]
|
19
21
|
|
20
|
-
uri, _
|
21
|
-
asset
|
22
|
-
map
|
23
|
-
sources = asset.metadata[:sources]
|
22
|
+
uri, _ = env.resolve!(input[:filename], accept: original_content_type(input[:content_type]))
|
23
|
+
asset = env.load(uri)
|
24
|
+
map = asset.metadata[:map]
|
24
25
|
|
25
26
|
# TODO: Because of the default piplene hack we have to apply dependencies
|
26
27
|
# from compiled asset to the source map, otherwise the source map cache
|
@@ -28,19 +29,16 @@ module Sprockets
|
|
28
29
|
dependencies = Set.new(input[:metadata][:dependencies])
|
29
30
|
dependencies.merge(asset.metadata[:dependencies])
|
30
31
|
|
31
|
-
map
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
path = source
|
38
|
-
end
|
39
|
-
uri, _ = env.resolve!(path)
|
32
|
+
map["file"] = PathUtils.split_subpath(input[:load_path], input[:filename])
|
33
|
+
sources = map["sections"] ? map["sections"].map { |s| s["map"]["sources"] }.flatten : map["sources"]
|
34
|
+
|
35
|
+
sources.each do |source|
|
36
|
+
source = PathUtils.join(File.dirname(map["file"]), source)
|
37
|
+
uri, _ = env.resolve!(source)
|
40
38
|
links << uri
|
41
39
|
end
|
42
40
|
|
43
|
-
json =
|
41
|
+
json = JSON.generate(map)
|
44
42
|
|
45
43
|
{ data: json, links: links, dependencies: dependencies }
|
46
44
|
end
|