sprockets 4.0.0.beta6 → 4.0.0.beta7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +432 -306
- data/lib/sprockets.rb +7 -2
- data/lib/sprockets/{source_map_comment_processor.rb → add_source_map_comment_to_asset_processor.rb} +24 -1
- data/lib/sprockets/base.rb +25 -1
- data/lib/sprockets/context.rb +54 -5
- data/lib/sprockets/loader.rb +12 -1
- data/lib/sprockets/manifest.rb +5 -0
- data/lib/sprockets/server.rb +2 -2
- data/lib/sprockets/source_map_processor.rb +33 -13
- data/lib/sprockets/version.rb +1 -1
- metadata +18 -4
data/lib/sprockets.rb
CHANGED
@@ -72,10 +72,14 @@ module Sprockets
|
|
72
72
|
register_mime_type 'audio/aiff', extensions: ['.aiff']
|
73
73
|
register_mime_type 'audio/mpeg', extensions: ['.mp3', '.mp2', '.m2a', '.m3a']
|
74
74
|
register_mime_type 'application/ogg', extensions: ['.ogx']
|
75
|
+
register_mime_type 'audio/ogg', extensions: ['.ogg', '.oga']
|
75
76
|
register_mime_type 'audio/midi', extensions: ['.midi', '.mid']
|
76
77
|
register_mime_type 'video/avi', extensions: ['.avi']
|
77
78
|
register_mime_type 'audio/wave', extensions: ['.wav', '.wave']
|
78
79
|
register_mime_type 'video/mp4', extensions: ['.mp4', '.m4v']
|
80
|
+
register_mime_type 'audio/aac', extensions: ['.aac']
|
81
|
+
register_mime_type 'audio/mp4', extensions: ['.m4a']
|
82
|
+
register_mime_type 'audio/flac', extensions: ['.flac']
|
79
83
|
|
80
84
|
# Common font types
|
81
85
|
register_mime_type 'application/vnd.ms-fontobject', extensions: ['.eot']
|
@@ -102,9 +106,9 @@ module Sprockets
|
|
102
106
|
env.default_processors_for(type, file_type)
|
103
107
|
end
|
104
108
|
|
105
|
-
require 'sprockets/
|
109
|
+
require 'sprockets/add_source_map_comment_to_asset_processor'
|
106
110
|
register_pipeline :debug do
|
107
|
-
[
|
111
|
+
[AddSourceMapCommentToAssetProcessor]
|
108
112
|
end
|
109
113
|
|
110
114
|
require 'sprockets/directive_processor'
|
@@ -184,6 +188,7 @@ module Sprockets
|
|
184
188
|
text/sass
|
185
189
|
text/scss
|
186
190
|
text/yaml
|
191
|
+
text/eco
|
187
192
|
), 'application/\2+ruby', '.erb', ERBProcessor)
|
188
193
|
|
189
194
|
register_mime_type 'application/html+ruby', extensions: ['.html.erb', '.erb', '.rhtml'], charset: :html
|
data/lib/sprockets/{source_map_comment_processor.rb → add_source_map_comment_to_asset_processor.rb}
RENAMED
@@ -3,8 +3,31 @@ require 'sprockets/uri_utils'
|
|
3
3
|
require 'sprockets/path_utils'
|
4
4
|
|
5
5
|
module Sprockets
|
6
|
-
|
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
|
7
29
|
def self.call(input)
|
30
|
+
|
8
31
|
case input[:content_type]
|
9
32
|
when "application/javascript"
|
10
33
|
comment = "\n//# sourceMappingURL=%s"
|
data/lib/sprockets/base.rb
CHANGED
@@ -16,6 +16,18 @@ require 'sprockets/source_map_utils'
|
|
16
16
|
require 'sprockets/uri_tar'
|
17
17
|
|
18
18
|
module Sprockets
|
19
|
+
|
20
|
+
class DoubleLinkError < Sprockets::Error
|
21
|
+
def initialize(parent_filename:, logical_path:, last_filename:, filename:)
|
22
|
+
message = String.new
|
23
|
+
message << "Multiple files with the same output path cannot be linked (#{logical_path.inspect})\n"
|
24
|
+
message << "In #{parent_filename.inspect} these files were linked:\n"
|
25
|
+
message << " - #{last_filename}\n"
|
26
|
+
message << " - #{filename}\n"
|
27
|
+
super(message)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
19
31
|
# `Base` class for `Environment` and `CachedEnvironment`.
|
20
32
|
class Base
|
21
33
|
include PathUtils, PathDependencyUtils, PathDigestUtils, DigestUtils, SourceMapUtils
|
@@ -73,14 +85,26 @@ module Sprockets
|
|
73
85
|
def find_all_linked_assets(*args)
|
74
86
|
return to_enum(__method__, *args) unless block_given?
|
75
87
|
|
76
|
-
asset = find_asset(*args)
|
88
|
+
parent_asset = asset = find_asset(*args)
|
77
89
|
return unless asset
|
78
90
|
|
79
91
|
yield asset
|
80
92
|
stack = asset.links.to_a
|
93
|
+
linked_paths = {}
|
81
94
|
|
82
95
|
while uri = stack.shift
|
83
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
|
84
108
|
stack = asset.links.to_a + stack
|
85
109
|
end
|
86
110
|
|
data/lib/sprockets/context.rb
CHANGED
@@ -186,9 +186,10 @@ module Sprockets
|
|
186
186
|
asset
|
187
187
|
end
|
188
188
|
|
189
|
-
# Returns a
|
190
|
-
#
|
191
|
-
#
|
189
|
+
# Returns a `data:` URI with the contents of the asset at the specified
|
190
|
+
# path, and marks that path as a dependency of the current file.
|
191
|
+
#
|
192
|
+
# Uses URI encoding for SVG files, base64 encoding for all the other files.
|
192
193
|
#
|
193
194
|
# Use `asset_data_uri` from ERB with CSS or JavaScript assets:
|
194
195
|
#
|
@@ -198,8 +199,11 @@ module Sprockets
|
|
198
199
|
#
|
199
200
|
def asset_data_uri(path)
|
200
201
|
asset = depend_on_asset(path)
|
201
|
-
|
202
|
-
|
202
|
+
if asset.content_type == 'image/svg+xml'
|
203
|
+
svg_asset_data_uri(asset)
|
204
|
+
else
|
205
|
+
base64_asset_data_uri(asset)
|
206
|
+
end
|
203
207
|
end
|
204
208
|
|
205
209
|
# Expands logical path to full url to asset.
|
@@ -251,5 +255,50 @@ Extend your environment context with a custom method.
|
|
251
255
|
def stylesheet_path(path)
|
252
256
|
asset_path(path, type: :stylesheet)
|
253
257
|
end
|
258
|
+
|
259
|
+
protected
|
260
|
+
|
261
|
+
# Returns a URI-encoded data URI (always "-quoted).
|
262
|
+
def svg_asset_data_uri(asset)
|
263
|
+
svg = asset.source.dup
|
264
|
+
optimize_svg_for_uri_escaping!(svg)
|
265
|
+
data = Rack::Utils.escape(svg)
|
266
|
+
optimize_quoted_uri_escapes!(data)
|
267
|
+
"\"data:#{asset.content_type};charset=utf-8,#{data}\""
|
268
|
+
end
|
269
|
+
|
270
|
+
# Returns a Base64-encoded data URI.
|
271
|
+
def base64_asset_data_uri(asset)
|
272
|
+
data = Rack::Utils.escape(EncodingUtils.base64(asset.source))
|
273
|
+
"data:#{asset.content_type};base64,#{data}"
|
274
|
+
end
|
275
|
+
|
276
|
+
# Optimizes an SVG for being URI-escaped.
|
277
|
+
#
|
278
|
+
# This method only performs these basic but crucial optimizations:
|
279
|
+
# * Replaces " with ', because ' does not need escaping.
|
280
|
+
# * Removes comments, meta, doctype, and newlines.
|
281
|
+
# * Collapses whitespace.
|
282
|
+
def optimize_svg_for_uri_escaping!(svg)
|
283
|
+
# Remove comments, xml meta, and doctype
|
284
|
+
svg.gsub!(/<!--.*?-->|<\?.*?\?>|<!.*?>/m, '')
|
285
|
+
# Replace consecutive whitespace and newlines with a space
|
286
|
+
svg.gsub!(/\s+/, ' ')
|
287
|
+
# Collapse inter-tag whitespace
|
288
|
+
svg.gsub!('> <', '><')
|
289
|
+
# Replace " with '
|
290
|
+
svg.gsub!(/([\w:])="(.*?)"/, "\\1='\\2'")
|
291
|
+
svg.strip!
|
292
|
+
end
|
293
|
+
|
294
|
+
# Un-escapes characters in the given URI-escaped string that do not need
|
295
|
+
# escaping in "-quoted data URIs.
|
296
|
+
def optimize_quoted_uri_escapes!(escaped)
|
297
|
+
escaped.gsub!('%3D', '=')
|
298
|
+
escaped.gsub!('%3A', ':')
|
299
|
+
escaped.gsub!('%2F', '/')
|
300
|
+
escaped.gsub!('%27', "'")
|
301
|
+
escaped.tr!('+', ' ')
|
302
|
+
end
|
254
303
|
end
|
255
304
|
end
|
data/lib/sprockets/loader.rb
CHANGED
@@ -81,6 +81,8 @@ module Sprockets
|
|
81
81
|
asset[:metadata][:links].map! { |uri| expand_from_root(uri) } if asset[:metadata][:links]
|
82
82
|
asset[:metadata][:stubbed].map! { |uri| expand_from_root(uri) } if asset[:metadata][:stubbed]
|
83
83
|
asset[:metadata][:required].map! { |uri| expand_from_root(uri) } if asset[:metadata][:required]
|
84
|
+
asset[:metadata][:to_load].map! { |uri| expand_from_root(uri) } if asset[:metadata][:to_load]
|
85
|
+
asset[:metadata][:to_link].map! { |uri| expand_from_root(uri) } if asset[:metadata][:to_link]
|
84
86
|
asset[:metadata][:dependencies].map! { |uri| uri.start_with?("file-digest://") ? expand_from_root(uri) : uri } if asset[:metadata][:dependencies]
|
85
87
|
|
86
88
|
asset[:metadata].each_key do |k|
|
@@ -140,7 +142,6 @@ module Sprockets
|
|
140
142
|
|
141
143
|
# Read into memory and process if theres a processor pipeline
|
142
144
|
if processors.any?
|
143
|
-
|
144
145
|
result = call_processors(processors, {
|
145
146
|
environment: self,
|
146
147
|
cache: self.cache,
|
@@ -224,6 +225,16 @@ module Sprockets
|
|
224
225
|
cached_asset[:metadata][:required].map! { |uri| compress_from_root(uri) }
|
225
226
|
end
|
226
227
|
|
228
|
+
if cached_asset[:metadata][:to_load] && !cached_asset[:metadata][:to_load].empty?
|
229
|
+
cached_asset[:metadata][:to_load] = cached_asset[:metadata][:to_load].dup
|
230
|
+
cached_asset[:metadata][:to_load].map! { |uri| compress_from_root(uri) }
|
231
|
+
end
|
232
|
+
|
233
|
+
if cached_asset[:metadata][:to_link] && !cached_asset[:metadata][:to_link].empty?
|
234
|
+
cached_asset[:metadata][:to_link] = cached_asset[:metadata][:to_link].dup
|
235
|
+
cached_asset[:metadata][:to_link].map! { |uri| compress_from_root(uri) }
|
236
|
+
end
|
237
|
+
|
227
238
|
if cached_asset[:metadata][:dependencies] && !cached_asset[:metadata][:dependencies].empty?
|
228
239
|
cached_asset[:metadata][:dependencies] = cached_asset[:metadata][:dependencies].dup
|
229
240
|
cached_asset[:metadata][:dependencies].map! do |uri|
|
data/lib/sprockets/manifest.rb
CHANGED
@@ -165,7 +165,12 @@ module Sprockets
|
|
165
165
|
filenames = []
|
166
166
|
concurrent_exporters = []
|
167
167
|
|
168
|
+
assets_to_export = Concurrent::Array.new
|
168
169
|
find(*args) do |asset|
|
170
|
+
assets_to_export << asset
|
171
|
+
end
|
172
|
+
|
173
|
+
assets_to_export.each do |asset|
|
169
174
|
mtime = Time.now.iso8601
|
170
175
|
files[asset.digest_path] = {
|
171
176
|
'logical_path' => asset.logical_path,
|
data/lib/sprockets/server.rb
CHANGED
@@ -54,11 +54,11 @@ module Sprockets
|
|
54
54
|
if fingerprint
|
55
55
|
if_match = fingerprint
|
56
56
|
elsif env['HTTP_IF_MATCH']
|
57
|
-
if_match = env['HTTP_IF_MATCH'][
|
57
|
+
if_match = env['HTTP_IF_MATCH'][/"(\w+)"$/, 1]
|
58
58
|
end
|
59
59
|
|
60
60
|
if env['HTTP_IF_NONE_MATCH']
|
61
|
-
if_none_match = env['HTTP_IF_NONE_MATCH'][
|
61
|
+
if_none_match = env['HTTP_IF_NONE_MATCH'][/"(\w+)"$/, 1]
|
62
62
|
end
|
63
63
|
|
64
64
|
# Look up the asset.
|
@@ -2,24 +2,32 @@
|
|
2
2
|
require 'set'
|
3
3
|
|
4
4
|
module Sprockets
|
5
|
-
class SourceMapProcessor
|
6
|
-
def self.original_content_type(source_map_content_type, error_when_not_found: true)
|
7
|
-
case source_map_content_type
|
8
|
-
when "application/js-sourcemap+json"
|
9
|
-
"application/javascript"
|
10
|
-
when "application/css-sourcemap+json"
|
11
|
-
"text/css"
|
12
|
-
else
|
13
|
-
fail(source_map_content_type) if error_when_not_found
|
14
|
-
source_map_content_type
|
15
|
-
end
|
16
|
-
end
|
17
5
|
|
6
|
+
# The purpose of this class is to generate a source map file
|
7
|
+
# that can be read and understood by browsers.
|
8
|
+
#
|
9
|
+
# When a file is passed in it will have a `application/js-sourcemap+json`
|
10
|
+
# or `application/css-sourcemap+json` mime type. The filename will be
|
11
|
+
# match the original asset. The original asset is loaded. As it
|
12
|
+
# gets processed by Sprockets it will aquire all information
|
13
|
+
# needed to build a source map file in the `asset.to_hash[:metadata][:map]`
|
14
|
+
# key.
|
15
|
+
#
|
16
|
+
# The output is an asset with a properly formatted source map file:
|
17
|
+
#
|
18
|
+
# {
|
19
|
+
# "version": 3,
|
20
|
+
# "sources": ["foo.js"],
|
21
|
+
# "names": [ ],
|
22
|
+
# "mappings": "AAAA,GAAIA"
|
23
|
+
# }
|
24
|
+
#
|
25
|
+
class SourceMapProcessor
|
18
26
|
def self.call(input)
|
19
27
|
links = Set.new(input[:metadata][:links])
|
20
28
|
env = input[:environment]
|
21
29
|
|
22
|
-
uri, _ = env.resolve!(input[:filename], accept: original_content_type(input[:content_type]))
|
30
|
+
uri, _ = env.resolve!(input[:filename], accept: self.original_content_type(input[:content_type]))
|
23
31
|
asset = env.load(uri)
|
24
32
|
map = asset.metadata[:map]
|
25
33
|
|
@@ -42,5 +50,17 @@ module Sprockets
|
|
42
50
|
|
43
51
|
{ data: json, links: links, dependencies: dependencies }
|
44
52
|
end
|
53
|
+
|
54
|
+
def self.original_content_type(source_map_content_type, error_when_not_found: true)
|
55
|
+
case source_map_content_type
|
56
|
+
when "application/js-sourcemap+json"
|
57
|
+
"application/javascript"
|
58
|
+
when "application/css-sourcemap+json"
|
59
|
+
"text/css"
|
60
|
+
else
|
61
|
+
fail(source_map_content_type) if error_when_not_found
|
62
|
+
source_map_content_type
|
63
|
+
end
|
64
|
+
end
|
45
65
|
end
|
46
66
|
end
|
data/lib/sprockets/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sprockets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.0.
|
4
|
+
version: 4.0.0.beta7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Stephenson
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2018-03-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
@@ -45,6 +45,20 @@ dependencies:
|
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '1.0'
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: m
|
50
|
+
requirement: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
48
62
|
- !ruby/object:Gem::Dependency
|
49
63
|
name: babel-transpiler
|
50
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -304,6 +318,7 @@ files:
|
|
304
318
|
- bin/sprockets
|
305
319
|
- lib/rake/sprocketstask.rb
|
306
320
|
- lib/sprockets.rb
|
321
|
+
- lib/sprockets/add_source_map_comment_to_asset_processor.rb
|
307
322
|
- lib/sprockets/asset.rb
|
308
323
|
- lib/sprockets/autoload.rb
|
309
324
|
- lib/sprockets/autoload/babel.rb
|
@@ -370,7 +385,6 @@ files:
|
|
370
385
|
- lib/sprockets/sassc_compressor.rb
|
371
386
|
- lib/sprockets/sassc_processor.rb
|
372
387
|
- lib/sprockets/server.rb
|
373
|
-
- lib/sprockets/source_map_comment_processor.rb
|
374
388
|
- lib/sprockets/source_map_processor.rb
|
375
389
|
- lib/sprockets/source_map_utils.rb
|
376
390
|
- lib/sprockets/transformers.rb
|
@@ -402,7 +416,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
402
416
|
version: 1.3.1
|
403
417
|
requirements: []
|
404
418
|
rubyforge_project: sprockets
|
405
|
-
rubygems_version: 2.6
|
419
|
+
rubygems_version: 2.7.6
|
406
420
|
signing_key:
|
407
421
|
specification_version: 4
|
408
422
|
summary: Rack-based asset packaging system
|