sprockets 4.0.0.beta7 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 603199dd1236b7db51572143c09ce33649d81ecd2151d73d01d539b05fb14caa
4
- data.tar.gz: 84e1bf98ebe75d603c8e4ab0c813de0626812226c8315cccdc408bd46ac7e630
3
+ metadata.gz: 7bbf26f3dfff9a86ca4b4407072f1786fafed4040a2f3f25c875842dc834bdcf
4
+ data.tar.gz: 5a6dd07a6568dca18b5d1eca850a1e3a78030c20a6530781d8a16ac31c25649c
5
5
  SHA512:
6
- metadata.gz: 6ca211b8b2f1eadd44b4b199e9ffb88f12efcc844b11d86abd3dd7eb78abdb8fc7a24405d95eb6f53b89686cee97417ca47257fbafbe76d35193c4ac2bf5ba35
7
- data.tar.gz: dd22ed98ff05afe2820a24ca7bfb305ba7c1361a4854ecc69b467653297dffc6c872d17d66095561b0b4ef64f9bcee72999a150afa6b721fd0b0b77ada344d70
6
+ metadata.gz: fa3fb386fe8ded820388ff86e1b505736dadcf5e072fedc124c8635955af70df9db7386ce66f4e2d4f412c652e88df9c8dc93a451ac31b2982f0457393911202
7
+ data.tar.gz: 3dde983e601b16c7b4bc71343543c69b7b8787b70daaaad711bc45ec47b4dd53507d67f6b6a9c1f8de1a7069bfbc12f72c96a0eaa088f976187fe9d4ca8f78f8
@@ -2,7 +2,30 @@
2
2
 
3
3
  Get upgrade notes from Sprockets 3.x to 4.x at https://github.com/rails/sprockets/blob/master/UPGRADING.md
4
4
 
5
- ## Master
5
+ ## 4.0.1
6
+
7
+ - Fix for Ruby 2.7 keyword arguments warning in `base.rb`. [#660](https://github.com/rails/sprockets/pull/660)
8
+ - Fix for when `x_sprockets_linecount` is missing from a source map.
9
+ - Fix subresource integrity to match the digest of the asset.
10
+
11
+ ## 4.0.0
12
+
13
+ - Fixes for Ruby 2.7 keyword arguments warnings [#625](https://github.com/rails/sprockets/pull/625)
14
+ - Manifest files are sorted alphabetically [#626](https://github.com/rails/sprockets/pull/626)
15
+
16
+ ## 4.0.0.beta10
17
+
18
+ - Fix YACB (Yet Another Caching Bug) [Fix broken expansion of asset link paths](https://github.com/rails/sprockets/pull/614)
19
+
20
+ ## 4.0.0.beta9
21
+
22
+ - Minimum Ruby version for Sprockets 4 is now 2.5+ which matches minimum ruby verision of Rails [#604]
23
+ - Fix threading bug introduced in Sprockets 4 [#603]
24
+ - Warn when two potential manifest files exist. [#560]
25
+
26
+ ## 4.0.0.beta8
27
+
28
+ - Security release for [CVE-2018-3760](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3760)
6
29
 
7
30
  ## 4.0.0.beta7
8
31
 
@@ -47,4 +70,3 @@ Get upgrade notes from Sprockets 3.x to 4.x at https://github.com/rails/sprocket
47
70
  - Initial release of Sprockets 4
48
71
 
49
72
  Please upgrade to the latest Sprockets 3 version before upgrading to Sprockets 4. Check the 3.x branch for previous changes https://github.com/rails/sprockets/blob/3.x/CHANGELOG.md.
50
-
data/README.md CHANGED
@@ -115,9 +115,9 @@ Here is a list of the available directives:
115
115
  - [`require_self`](#require_self) - Change order of where current contents are concatenated to current
116
116
  - [`require_directory`](#require_directory) - Add contents of each file in a folder to current
117
117
  - [`require_tree`](#require_tree) - Add contents of all files in all directories in a path to current
118
- - [`link`](#link) - Make target file compile and be publically available without adding contents to current
119
- - [`link_directory`](#link_directory) - Make target directory compile and be publically available without adding contents to current
120
- - [`link_tree`](#link_tree) - Make target tree compile and be publically available without adding contents to current
118
+ - [`link`](#link) - Make target file compile and be publicly available without adding contents to current
119
+ - [`link_directory`](#link_directory) - Make target directory compile and be publicly available without adding contents to current
120
+ - [`link_tree`](#link_tree) - Make target tree compile and be publicly available without adding contents to current
121
121
  - [`depend_on`](#depend_on) - Recompile current file if target has changed
122
122
  - [`stub`](#stub) - Ignore target file
123
123
 
@@ -363,37 +363,70 @@ directory specified by *path*.
363
363
  ### link
364
364
 
365
365
  `link` *path* declares a dependency on the target *path* and adds it to a list
366
- of subdependencies to automatically be compiled when the asset is written out to
366
+ of subdependencies to be compiled when the asset is written out to
367
367
  disk.
368
368
 
369
369
  Example:
370
370
 
371
- If you've got a `manifest.js` file and you want to explicitly make sure an `admin.js` file is
372
- generated and made available to the public you can link it like this:
371
+ If you've got a `manifest.js` file and you want to specify that a `admin.js` source file should be
372
+ generated and made available to the public you can link it by including this in the `manifest.js` file:
373
373
 
374
374
  ```
375
375
  //= link admin.js
376
376
  ```
377
377
 
378
+ The argument to `link` is a _logical path_, that is it will be resolved according to the
379
+ configured asset load paths. See [Accesing Assets](#accessing-assets) above. A path relative to
380
+ the current file won't work, it must be a logical path.
381
+
382
+ **Caution**: the "link" directive should always have an explicit extension on the end.
383
+
378
384
  ### link_directory
379
385
 
380
- `link_directory` *path* links all the files inside the directory specified by the *path*
386
+ `link_directory` *path* links all the files inside the directory specified by the *path*. By "link", we mean they are specified as compilation targets to be written out to disk, and made available to be served to user-agents.
387
+
388
+ Files in subdirectories will not be linked (Compare to [link_tree](#link_tree)).
389
+
390
+ The *path* argument to `link_directory` is _not_ a logical path (it does not use the asset load paths), but is a path relative to the file the `link_directory` directive is found in, and can use `..` to . For instance, you might want:
391
+
392
+ ```js
393
+ //= link_directory ../stylesheets
394
+ ```
395
+
396
+ `link_directory` can take an optional second argument with an extension or content-type, with the
397
+ two arguments separated by a space:
398
+
399
+ ```js
400
+ //= link_directory ../stylesheets text/css
401
+ //= link_directory ../more_stylesheets .css
402
+ ```
403
+
404
+ This will limit the matching files to link to only files recognized as that type. An extension is
405
+ just a shortcut for the type referenced, it does not need to match the source file exactly, but
406
+ instead identifies the content-type the source file must be recognized as.
381
407
 
382
408
  ### link_tree
383
409
 
384
- `link_tree` *path* works like `link_directory`, but operates
410
+ `link_tree` *path* works like [link_directory](#link_directory), but operates
385
411
  recursively to link all files in all subdirectories of the
386
412
  directory specified by *path*.
387
413
 
388
414
  Example:
389
415
 
390
- You can specify a file extension so any extra files will be ignored:
416
+ ```js
417
+ //= link_tree ./path/to/folder
418
+ ```
419
+
420
+ Like `link_directory`, the argument is path relative to the current file, it is *not* a 'logical path' tresolved against load paths.
421
+
422
+
423
+ As with `link_directory`, you can also specify a second argument -- separated by a space -- so any extra files not matching the content-type specified will be ignored:
391
424
 
392
425
  ```js
393
- //= link_tree path/to/folder .js
426
+ //= link_tree ./path/to/folder text/javascript
427
+ //= link_tree ./path/to/other_folder .js
394
428
  ```
395
429
 
396
- > Note: There is an intentional space between the path and the extension
397
430
 
398
431
  ### depend_on
399
432
 
@@ -119,8 +119,8 @@ module Sprockets
119
119
  register_bundle_processor 'application/javascript', Bundle
120
120
  register_bundle_processor 'text/css', Bundle
121
121
 
122
- register_bundle_metadata_reducer '*/*', :data, proc { String.new("") }, :concat
123
- register_bundle_metadata_reducer 'application/javascript', :data, proc { String.new("") }, Utils.method(:concat_javascript_sources)
122
+ register_bundle_metadata_reducer '*/*', :data, proc { +"" }, :concat
123
+ register_bundle_metadata_reducer 'application/javascript', :data, proc { +"" }, Utils.method(:concat_javascript_sources)
124
124
  register_bundle_metadata_reducer '*/*', :links, :+
125
125
  register_bundle_metadata_reducer '*/*', :sources, proc { [] }, :+
126
126
 
@@ -165,11 +165,11 @@ module Sprockets
165
165
  register_transformer 'application/javascript+function', 'application/javascript', JstProcessor
166
166
 
167
167
  # CSS processors
168
- require 'sprockets/sass_processor'
168
+ require 'sprockets/sassc_processor'
169
169
  register_mime_type 'text/sass', extensions: ['.sass', '.css.sass']
170
170
  register_mime_type 'text/scss', extensions: ['.scss', '.css.scss']
171
- register_transformer 'text/sass', 'text/css', SassProcessor
172
- register_transformer 'text/scss', 'text/css', ScssProcessor
171
+ register_transformer 'text/sass', 'text/css', SasscProcessor
172
+ register_transformer 'text/scss', 'text/css', ScsscProcessor
173
173
  register_preprocessor 'text/sass', DirectiveProcessor.new(comments: ["//", ["/*", "*/"]])
174
174
  register_preprocessor 'text/scss', DirectiveProcessor.new(comments: ["//", ["/*", "*/"]])
175
175
  register_bundle_metadata_reducer 'text/css', :sass_dependencies, Set.new, :+
@@ -123,13 +123,20 @@ module Sprockets
123
123
  metadata[:digest]
124
124
  end
125
125
 
126
+ # Private: Return the version of the environment where the asset was generated.
127
+ def environment_version
128
+ metadata[:environment_version]
129
+ end
130
+
126
131
  # Public: Returns String hexdigest of source.
127
132
  def hexdigest
128
133
  DigestUtils.pack_hexdigest(digest)
129
134
  end
130
135
 
131
136
  # Pubic: ETag String of Asset.
132
- alias_method :etag, :hexdigest
137
+ def etag
138
+ DigestUtils.pack_hexdigest(environment_version + digest)
139
+ end
133
140
 
134
141
  # Public: Returns String base64 digest of source.
135
142
  def base64digest
@@ -138,7 +145,7 @@ module Sprockets
138
145
 
139
146
  # Public: A "named information" URL for subresource integrity.
140
147
  def integrity
141
- DigestUtils.integrity_uri(metadata[:digest])
148
+ DigestUtils.integrity_uri(digest)
142
149
  end
143
150
 
144
151
  # Public: Add enumerator to allow `Asset` instances to be used as Rack
@@ -19,12 +19,12 @@ module Sprockets
19
19
 
20
20
  class DoubleLinkError < Sprockets::Error
21
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)
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
28
  end
29
29
  end
30
30
 
@@ -75,8 +75,8 @@ module Sprockets
75
75
  end
76
76
 
77
77
  # Find asset by logical path or expanded path.
78
- def find_asset(*args)
79
- uri, _ = resolve(*args)
78
+ def find_asset(*args, **options)
79
+ uri, _ = resolve(*args, **options)
80
80
  if uri
81
81
  load(uri)
82
82
  end
@@ -115,8 +115,8 @@ module Sprockets
115
115
  #
116
116
  # environment['application.js']
117
117
  #
118
- def [](*args)
119
- find_asset(*args)
118
+ def [](*args, **options)
119
+ find_asset(*args, **options)
120
120
  end
121
121
 
122
122
  # Find asset by logical path or expanded path.
@@ -137,8 +137,10 @@ module Sprockets
137
137
  #
138
138
  # Returns true
139
139
  def clear(options=nil)
140
- root_dirs = Dir.entries(@root).reject { |f| (EXCLUDED_DIRS + GITKEEP_FILES).include?(f) }
141
- FileUtils.rm_r(root_dirs.collect{ |f| File.join(@root, f) })
140
+ if File.exist?(@root)
141
+ root_dirs = Dir.entries(@root).reject { |f| (EXCLUDED_DIRS + GITKEEP_FILES).include?(f) }
142
+ FileUtils.rm_r(root_dirs.collect{ |f| File.join(@root, f) })
143
+ end
142
144
  true
143
145
  end
144
146
 
@@ -121,7 +121,7 @@ module Sprockets
121
121
 
122
122
  header, directives = extract_directives(header)
123
123
 
124
- data = String.new("")
124
+ data = +""
125
125
  data.force_encoding(body.encoding)
126
126
  data << header unless header.empty?
127
127
  data << body
@@ -139,7 +139,7 @@ module Sprockets
139
139
  # [[1, "require", "foo"], [2, "require", "bar"]]
140
140
  #
141
141
  def extract_directives(header)
142
- processed_header = String.new("")
142
+ processed_header = +""
143
143
  directives = []
144
144
 
145
145
  header.lines.each_with_index do |line, index|
@@ -27,8 +27,8 @@ module Sprockets
27
27
  end
28
28
  alias_method :index, :cached
29
29
 
30
- def find_asset(*args)
31
- cached.find_asset(*args)
30
+ def find_asset(*args, **options)
31
+ cached.find_asset(*args, **options)
32
32
  end
33
33
 
34
34
  def find_asset!(*args)
@@ -18,7 +18,12 @@ class Sprockets::ERBProcessor
18
18
  end
19
19
 
20
20
  def call(input)
21
- engine = ::ERB.new(input[:data], nil, '<>')
21
+ match = ERB.version.match(/\Aerb\.rb \[(?<version>[^ ]+) /)
22
+ if match && match[:version] >= "2.2.0" # Ruby 2.6+
23
+ engine = ::ERB.new(input[:data], trim_mode: '<>')
24
+ else
25
+ engine = ::ERB.new(input[:data], nil, '<>')
26
+ end
22
27
  engine.filename = input[:filename]
23
28
 
24
29
  context = input[:environment].context_class.new(input)
@@ -69,4 +69,3 @@ module Sprockets
69
69
  end
70
70
  end
71
71
  end
72
-
@@ -86,14 +86,16 @@ module Sprockets
86
86
  raise TypeError, "unknown q_values type: #{q_values.class}"
87
87
  end
88
88
 
89
+ i = 0
89
90
  q_values.each do |accepted, quality|
90
91
  if match = available.find { |option| matcher.call(option, accepted) }
91
- matches << [match, quality]
92
+ i += 1
93
+ matches << [-quality, i, match]
92
94
  end
93
95
  end
94
96
 
95
- matches.sort_by! { |match, quality| -quality }
96
- matches.map! { |match, quality| match }
97
+ matches.sort!
98
+ matches.map! { |_, _, match| match }
97
99
  matches
98
100
  end
99
101
 
@@ -64,6 +64,43 @@ module Sprockets
64
64
  end
65
65
 
66
66
  private
67
+ def compress_key_from_hash(hash, key)
68
+ return unless hash.key?(key)
69
+ value = hash[key].dup
70
+ return if !value
71
+
72
+ if block_given?
73
+ value.map! do |x|
74
+ if yield x
75
+ compress_from_root(x)
76
+ else
77
+ x
78
+ end
79
+ end
80
+ else
81
+ value.map! { |x| compress_from_root(x) }
82
+ end
83
+ hash[key] = value
84
+ end
85
+
86
+
87
+ def expand_key_from_hash(hash, key)
88
+ return unless hash.key?(key)
89
+ value = hash[key].dup
90
+ return if !value
91
+ if block_given?
92
+ value.map! do |x|
93
+ if yield x
94
+ expand_from_root(x)
95
+ else
96
+ x
97
+ end
98
+ end
99
+ else
100
+ value.map! { |x| expand_from_root(x) }
101
+ end
102
+ hash[key] = value
103
+ end
67
104
 
68
105
  # Internal: Load asset hash from cache
69
106
  #
@@ -77,17 +114,17 @@ module Sprockets
77
114
  asset[:uri] = expand_from_root(asset[:uri])
78
115
  asset[:load_path] = expand_from_root(asset[:load_path])
79
116
  asset[:filename] = expand_from_root(asset[:filename])
80
- asset[:metadata][:included].map! { |uri| expand_from_root(uri) } if asset[:metadata][:included]
81
- asset[:metadata][:links].map! { |uri| expand_from_root(uri) } if asset[:metadata][:links]
82
- asset[:metadata][:stubbed].map! { |uri| expand_from_root(uri) } if asset[:metadata][:stubbed]
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]
86
- asset[:metadata][:dependencies].map! { |uri| uri.start_with?("file-digest://") ? expand_from_root(uri) : uri } if asset[:metadata][:dependencies]
117
+ expand_key_from_hash(asset[:metadata], :included)
118
+ expand_key_from_hash(asset[:metadata], :links)
119
+ expand_key_from_hash(asset[:metadata], :stubbed)
120
+ expand_key_from_hash(asset[:metadata], :required)
121
+ expand_key_from_hash(asset[:metadata], :to_load)
122
+ expand_key_from_hash(asset[:metadata], :to_link)
123
+ expand_key_from_hash(asset[:metadata], :dependencies) { |uri| uri.start_with?("file-digest://") }
87
124
 
88
125
  asset[:metadata].each_key do |k|
89
- next unless k =~ /_dependencies\z/
90
- asset[:metadata][k].map! { |uri| expand_from_root(uri) }
126
+ next unless k.match?(/_dependencies\z/) # rubocop:disable Performance/EndWith
127
+ expand_key_from_hash(asset[:metadata], k)
91
128
  end
92
129
  end
93
130
  asset
@@ -158,14 +195,16 @@ module Sprockets
158
195
  source = result.delete(:data)
159
196
  metadata = result
160
197
  metadata[:charset] = source.encoding.name.downcase unless metadata.key?(:charset)
161
- metadata[:digest] = digest(self.version + source)
198
+ metadata[:digest] = digest(source)
162
199
  metadata[:length] = source.bytesize
200
+ metadata[:environment_version] = version
163
201
  else
164
202
  dependencies << build_file_digest_uri(unloaded.filename)
165
203
  metadata = {
166
204
  digest: file_digest(unloaded.filename),
167
205
  length: self.stat(unloaded.filename).size,
168
- dependencies: dependencies
206
+ dependencies: dependencies,
207
+ environment_version: version,
169
208
  }
170
209
  end
171
210
 
@@ -205,48 +244,17 @@ module Sprockets
205
244
  if cached_asset[:metadata]
206
245
  # Deep dup to avoid modifying `asset`
207
246
  cached_asset[:metadata] = cached_asset[:metadata].dup
208
- if cached_asset[:metadata][:included] && !cached_asset[:metadata][:included].empty?
209
- cached_asset[:metadata][:included] = cached_asset[:metadata][:included].dup
210
- cached_asset[:metadata][:included].map! { |uri| compress_from_root(uri) }
211
- end
212
-
213
- if cached_asset[:metadata][:links] && !cached_asset[:metadata][:links].empty?
214
- cached_asset[:metadata][:links] = cached_asset[:metadata][:links].dup
215
- cached_asset[:metadata][:links].map! { |uri| compress_from_root(uri) }
216
- end
217
-
218
- if cached_asset[:metadata][:stubbed] && !cached_asset[:metadata][:stubbed].empty?
219
- cached_asset[:metadata][:stubbed] = cached_asset[:metadata][:stubbed].dup
220
- cached_asset[:metadata][:stubbed].map! { |uri| compress_from_root(uri) }
221
- end
222
-
223
- if cached_asset[:metadata][:required] && !cached_asset[:metadata][:required].empty?
224
- cached_asset[:metadata][:required] = cached_asset[:metadata][:required].dup
225
- cached_asset[:metadata][:required].map! { |uri| compress_from_root(uri) }
226
- end
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
-
238
- if cached_asset[:metadata][:dependencies] && !cached_asset[:metadata][:dependencies].empty?
239
- cached_asset[:metadata][:dependencies] = cached_asset[:metadata][:dependencies].dup
240
- cached_asset[:metadata][:dependencies].map! do |uri|
241
- uri.start_with?("file-digest://".freeze) ? compress_from_root(uri) : uri
242
- end
243
- end
247
+ compress_key_from_hash(cached_asset[:metadata], :included)
248
+ compress_key_from_hash(cached_asset[:metadata], :links)
249
+ compress_key_from_hash(cached_asset[:metadata], :stubbed)
250
+ compress_key_from_hash(cached_asset[:metadata], :required)
251
+ compress_key_from_hash(cached_asset[:metadata], :to_load)
252
+ compress_key_from_hash(cached_asset[:metadata], :to_link)
253
+ compress_key_from_hash(cached_asset[:metadata], :dependencies) { |uri| uri.start_with?("file-digest://") }
244
254
 
245
- # compress all _dependencies in metadata like `sass_dependencies`
246
255
  cached_asset[:metadata].each do |key, value|
247
- next unless key =~ /_dependencies\z/
248
- cached_asset[:metadata][key] = value.dup
249
- cached_asset[:metadata][key].map! {|uri| compress_from_root(uri) }
256
+ next unless key.match?(/_dependencies\z/) # rubocop:disable Performance/EndWith
257
+ compress_key_from_hash(cached_asset[:metadata], key)
250
258
  end
251
259
  end
252
260
 
@@ -53,7 +53,7 @@ module Sprockets
53
53
 
54
54
  # If directory is given w/o filename, pick a random manifest location
55
55
  if @directory && @filename.nil?
56
- @filename = find_directory_manifest(@directory)
56
+ @filename = find_directory_manifest(@directory, logger)
57
57
  end
58
58
 
59
59
  unless @directory && @filename
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require 'securerandom'
3
+ require 'logger'
3
4
 
4
5
  module Sprockets
5
6
  # Public: Manifest utilities.
@@ -33,10 +34,14 @@ module Sprockets
33
34
  # # => "/app/public/assets/.sprockets-manifest-abc123.json"
34
35
  #
35
36
  # Returns String filename.
36
- def find_directory_manifest(dirname)
37
+ def find_directory_manifest(dirname, logger = Logger.new($stderr))
37
38
  entries = File.directory?(dirname) ? Dir.entries(dirname) : []
38
- entry = entries.find { |e| e =~ MANIFEST_RE } ||
39
- generate_manifest_path
39
+ manifest_entries = entries.select { |e| e =~ MANIFEST_RE }
40
+ if manifest_entries.length > 1
41
+ manifest_entries.sort!
42
+ logger.warn("Found multiple manifests: #{manifest_entries}. Choosing the first alphabetically: #{manifest_entries.first}")
43
+ end
44
+ entry = manifest_entries.first || generate_manifest_path
40
45
  File.join(dirname, entry)
41
46
  end
42
47
  end
@@ -98,7 +98,7 @@ module Sprockets
98
98
  #
99
99
  # Returns true if path is relative, otherwise false.
100
100
  def relative_path?(path)
101
- path =~ /^\.\.?($|#{SEPARATOR_PATTERN})/ ? true : false
101
+ path.match?(/^\.\.?($|#{SEPARATOR_PATTERN})/) ? true : false
102
102
  end
103
103
 
104
104
  # Public: Get relative path from `start` to `dest`.
@@ -161,29 +161,9 @@ module Sprockets
161
161
  if !key.instance_of?(Symbol)
162
162
  raise TypeError, "processor metadata[#{key.inspect}] expected to be a Symbol"
163
163
  end
164
-
165
- if !valid_processor_metadata_value?(value)
166
- raise TypeError, "processor metadata[:#{key}] returned a complex type: #{value.inspect}\n" +
167
- "Only #{VALID_METADATA_TYPES.to_a.join(", ")} maybe used."
168
- end
169
164
  end
170
165
 
171
166
  result
172
167
  end
173
-
174
- # Internal: Validate object is in validate metadata whitelist.
175
- #
176
- # value - Any Object
177
- #
178
- # Returns true if class is in whitelist otherwise false.
179
- def valid_processor_metadata_value?(value)
180
- if VALID_METADATA_VALUE_TYPES_HASH[value.class]
181
- true
182
- elsif VALID_METADATA_COMPOUND_TYPES_HASH[value.class]
183
- value.all? { |v| valid_processor_metadata_value?(v) }
184
- else
185
- false
186
- end
187
- end
188
168
  end
189
169
  end
@@ -47,7 +47,7 @@ module Sprockets
47
47
  uri, deps = resolve(path, **kargs)
48
48
 
49
49
  unless uri
50
- message = String.new("couldn't find file '#{path}'")
50
+ message = +"couldn't find file '#{path}'"
51
51
 
52
52
  if relative_path?(path) && kargs[:base_path]
53
53
  load_path, _ = paths_split(config[:paths], kargs[:base_path])
@@ -1,10 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
  require 'sprockets/autoload'
3
- require 'sprockets/sass_compressor'
4
- require 'base64'
3
+ require 'sprockets/source_map_utils'
5
4
 
6
5
  module Sprockets
7
- class SasscCompressor < SassCompressor
6
+ # Public: Sass CSS minifier.
7
+ #
8
+ # To accept the default options
9
+ #
10
+ # environment.register_bundle_processor 'text/css',
11
+ # Sprockets::SasscCompressor
12
+ #
13
+ # Or to pass options to the Sass::Engine class.
14
+ #
15
+ # environment.register_bundle_processor 'text/css',
16
+ # Sprockets::SasscCompressor.new({ ... })
17
+ #
18
+ class SasscCompressor
19
+ # Public: Return singleton instance with default options.
20
+ #
21
+ # Returns SasscCompressor object.
22
+ def self.instance
23
+ @instance ||= new
24
+ end
25
+
26
+ def self.call(input)
27
+ instance.call(input)
28
+ end
29
+
8
30
  def initialize(options = {})
9
31
  @options = {
10
32
  syntax: :scss,
@@ -1,17 +1,49 @@
1
1
  # frozen_string_literal: true
2
- require 'sprockets/sass_processor'
3
- require 'sprockets/path_utils'
4
- require 'base64'
2
+ require 'rack/utils'
3
+ require 'sprockets/autoload'
4
+ require 'sprockets/source_map_utils'
5
+ require 'uri'
5
6
 
6
7
  module Sprockets
7
- class SasscProcessor < SassProcessor
8
+ # Processor engine class for the SASS/SCSS compiler. Depends on the `sassc` gem.
9
+ #
10
+ # For more infomation see:
11
+ #
12
+ # https://github.com/sass/sassc-ruby
13
+ # https://github.com/sass/sassc-rails
14
+ #
15
+ class SasscProcessor
16
+
17
+ # Internal: Defines default sass syntax to use. Exposed so the ScsscProcessor
18
+ # may override it.
19
+ def self.syntax
20
+ :sass
21
+ end
22
+
23
+ # Public: Return singleton instance with default options.
24
+ #
25
+ # Returns SasscProcessor object.
26
+ def self.instance
27
+ @instance ||= new
28
+ end
29
+
30
+ def self.call(input)
31
+ instance.call(input)
32
+ end
33
+
34
+ def self.cache_key
35
+ instance.cache_key
36
+ end
37
+
38
+ attr_reader :cache_key
39
+
8
40
  def initialize(options = {}, &block)
9
41
  @cache_version = options[:cache_version]
10
42
  @cache_key = "#{self.class.name}:#{VERSION}:#{Autoload::SassC::VERSION}:#{@cache_version}".freeze
11
43
  @importer_class = options[:importer]
12
44
  @sass_config = options[:sass_config] || {}
13
45
  @functions = Module.new do
14
- include SassProcessor::Functions
46
+ include Functions
15
47
  include options[:functions] if options[:functions]
16
48
  class_eval(&block) if block_given?
17
49
  end
@@ -43,6 +75,201 @@ module Sprockets
43
75
 
44
76
  private
45
77
 
78
+ def merge_options(options)
79
+ defaults = @sass_config.dup
80
+
81
+ if load_paths = defaults.delete(:load_paths)
82
+ options[:load_paths] += load_paths
83
+ end
84
+
85
+ options.merge!(defaults)
86
+ options
87
+ end
88
+
89
+ # Public: Functions injected into Sass context during Sprockets evaluation.
90
+ #
91
+ # This module may be extended to add global functionality to all Sprockets
92
+ # Sass environments. Though, scoping your functions to just your environment
93
+ # is preferred.
94
+ #
95
+ # module Sprockets::SasscProcessor::Functions
96
+ # def asset_path(path, options = {})
97
+ # end
98
+ # end
99
+ #
100
+ module Functions
101
+ # Public: Generate a url for asset path.
102
+ #
103
+ # Default implementation is deprecated. Currently defaults to
104
+ # Context#asset_path.
105
+ #
106
+ # Will raise NotImplementedError in the future. Users should provide their
107
+ # own base implementation.
108
+ #
109
+ # Returns a SassC::Script::Value::String.
110
+ def asset_path(path, options = {})
111
+ path = path.value
112
+
113
+ path, _, query, fragment = URI.split(path)[5..8]
114
+ path = sprockets_context.asset_path(path, options)
115
+ query = "?#{query}" if query
116
+ fragment = "##{fragment}" if fragment
117
+
118
+ Autoload::SassC::Script::Value::String.new("#{path}#{query}#{fragment}", :string)
119
+ end
120
+
121
+ # Public: Generate a asset url() link.
122
+ #
123
+ # path - SassC::Script::Value::String URL path
124
+ #
125
+ # Returns a SassC::Script::Value::String.
126
+ def asset_url(path, options = {})
127
+ Autoload::SassC::Script::Value::String.new("url(#{asset_path(path, options).value})")
128
+ end
129
+
130
+ # Public: Generate url for image path.
131
+ #
132
+ # path - SassC::Script::Value::String URL path
133
+ #
134
+ # Returns a SassC::Script::Value::String.
135
+ def image_path(path)
136
+ asset_path(path, type: :image)
137
+ end
138
+
139
+ # Public: Generate a image url() link.
140
+ #
141
+ # path - SassC::Script::Value::String URL path
142
+ #
143
+ # Returns a SassC::Script::Value::String.
144
+ def image_url(path)
145
+ asset_url(path, type: :image)
146
+ end
147
+
148
+ # Public: Generate url for video path.
149
+ #
150
+ # path - SassC::Script::Value::String URL path
151
+ #
152
+ # Returns a SassC::Script::Value::String.
153
+ def video_path(path)
154
+ asset_path(path, type: :video)
155
+ end
156
+
157
+ # Public: Generate a video url() link.
158
+ #
159
+ # path - SassC::Script::Value::String URL path
160
+ #
161
+ # Returns a SassC::Script::Value::String.
162
+ def video_url(path)
163
+ asset_url(path, type: :video)
164
+ end
165
+
166
+ # Public: Generate url for audio path.
167
+ #
168
+ # path - SassC::Script::Value::String URL path
169
+ #
170
+ # Returns a SassC::Script::Value::String.
171
+ def audio_path(path)
172
+ asset_path(path, type: :audio)
173
+ end
174
+
175
+ # Public: Generate a audio url() link.
176
+ #
177
+ # path - SassC::Script::Value::String URL path
178
+ #
179
+ # Returns a SassC::Script::Value::String.
180
+ def audio_url(path)
181
+ asset_url(path, type: :audio)
182
+ end
183
+
184
+ # Public: Generate url for font path.
185
+ #
186
+ # path - SassC::Script::Value::String URL path
187
+ #
188
+ # Returns a SassC::Script::Value::String.
189
+ def font_path(path)
190
+ asset_path(path, type: :font)
191
+ end
192
+
193
+ # Public: Generate a font url() link.
194
+ #
195
+ # path - SassC::Script::Value::String URL path
196
+ #
197
+ # Returns a SassC::Script::Value::String.
198
+ def font_url(path)
199
+ asset_url(path, type: :font)
200
+ end
201
+
202
+ # Public: Generate url for javascript path.
203
+ #
204
+ # path - SassC::Script::Value::String URL path
205
+ #
206
+ # Returns a SassC::Script::Value::String.
207
+ def javascript_path(path)
208
+ asset_path(path, type: :javascript)
209
+ end
210
+
211
+ # Public: Generate a javascript url() link.
212
+ #
213
+ # path - SassC::Script::Value::String URL path
214
+ #
215
+ # Returns a SassC::Script::Value::String.
216
+ def javascript_url(path)
217
+ asset_url(path, type: :javascript)
218
+ end
219
+
220
+ # Public: Generate url for stylesheet path.
221
+ #
222
+ # path - SassC::Script::Value::String URL path
223
+ #
224
+ # Returns a SassC::Script::Value::String.
225
+ def stylesheet_path(path)
226
+ asset_path(path, type: :stylesheet)
227
+ end
228
+
229
+ # Public: Generate a stylesheet url() link.
230
+ #
231
+ # path - SassC::Script::Value::String URL path
232
+ #
233
+ # Returns a SassC::Script::Value::String.
234
+ def stylesheet_url(path)
235
+ asset_url(path, type: :stylesheet)
236
+ end
237
+
238
+ # Public: Generate a data URI for asset path.
239
+ #
240
+ # path - SassC::Script::Value::String logical asset path
241
+ #
242
+ # Returns a SassC::Script::Value::String.
243
+ def asset_data_url(path)
244
+ url = sprockets_context.asset_data_uri(path.value)
245
+ Autoload::SassC::Script::Value::String.new("url(" + url + ")")
246
+ end
247
+
248
+ protected
249
+ # Public: The Environment.
250
+ #
251
+ # Returns Sprockets::Environment.
252
+ def sprockets_environment
253
+ options[:sprockets][:environment]
254
+ end
255
+
256
+ # Public: Mutatable set of dependencies.
257
+ #
258
+ # Returns a Set.
259
+ def sprockets_dependencies
260
+ options[:sprockets][:dependencies]
261
+ end
262
+
263
+ # Deprecated: Get the Context instance. Use APIs on
264
+ # sprockets_environment or sprockets_dependencies directly.
265
+ #
266
+ # Returns a Context instance.
267
+ def sprockets_context
268
+ options[:sprockets][:context]
269
+ end
270
+
271
+ end
272
+
46
273
  def engine_options(input, context)
47
274
  merge_options({
48
275
  filename: input[:filename],
@@ -114,7 +114,7 @@ module Sprockets
114
114
  #
115
115
  # http://example.org/assets/../../../etc/passwd
116
116
  #
117
- path.include?("..") || absolute_path?(path)
117
+ path.include?("..") || absolute_path?(path) || path.include?("://")
118
118
  end
119
119
 
120
120
  def head_request?(env)
@@ -248,7 +248,7 @@ module Sprockets
248
248
  headers = {}
249
249
 
250
250
  # Set caching headers
251
- headers["Cache-Control"] = String.new("public")
251
+ headers["Cache-Control"] = +"public"
252
252
  headers["ETag"] = %("#{etag}")
253
253
 
254
254
  # If the request url contains a fingerprint, set a long
@@ -78,7 +78,7 @@ module Sprockets
78
78
  offset = 0
79
79
  if a["sections"].count != 0 && !a["sections"].last["map"]["mappings"].empty?
80
80
  last_line_count = a["sections"].last["map"].delete("x_sprockets_linecount")
81
- offset += last_line_count
81
+ offset += last_line_count || 1
82
82
 
83
83
  last_offset = a["sections"].last["offset"]["line"]
84
84
  offset += last_offset
@@ -428,21 +428,23 @@ module Sprockets
428
428
  # Returns an Array of Integers.
429
429
  def vlq_decode(str)
430
430
  result = []
431
- chars = str.split('')
432
- while chars.any?
433
- vlq = 0
434
- shift = 0
435
- continuation = true
436
- while continuation
437
- char = chars.shift
438
- raise ArgumentError unless char
439
- digit = BASE64_VALUES[char]
440
- continuation = false if (digit & VLQ_CONTINUATION_BIT) == 0
441
- digit &= VLQ_BASE_MASK
442
- vlq += digit << shift
431
+ shift = 0
432
+ value = 0
433
+ i = 0
434
+
435
+ while i < str.size do
436
+ digit = BASE64_VALUES[str[i]]
437
+ raise ArgumentError unless digit
438
+ continuation = (digit & VLQ_CONTINUATION_BIT) != 0
439
+ digit &= VLQ_BASE_MASK
440
+ value += digit << shift
441
+ if continuation
443
442
  shift += VLQ_BASE_SHIFT
443
+ else
444
+ result << ((value & 1) == 1 ? -(value >> 1) : value >> 1)
445
+ value = shift = 0
444
446
  end
445
- result << (vlq & 1 == 1 ? -(vlq >> 1) : vlq >> 1)
447
+ i += 1
446
448
  end
447
449
  result
448
450
  end
@@ -48,8 +48,10 @@ module Sprockets
48
48
  path = URI::Generic::DEFAULT_PARSER.unescape(path)
49
49
  path.force_encoding(Encoding::UTF_8)
50
50
 
51
- # Hack for parsing Windows "file:///C:/Users/IEUser" paths
52
- path.gsub!(/^\/([a-zA-Z]:)/, '\1'.freeze)
51
+ # Hack for parsing Windows "/C:/Users/IEUser" paths
52
+ if File::ALT_SEPARATOR && path[2] == ':'
53
+ path = path[1..-1]
54
+ end
53
55
 
54
56
  [scheme, host, path, query]
55
57
  end
@@ -58,7 +60,7 @@ module Sprockets
58
60
  #
59
61
  # Returns String.
60
62
  def join_file_uri(scheme, host, path, query)
61
- str = String.new("#{scheme}://")
63
+ str = +"#{scheme}://"
62
64
  str << host if host
63
65
  path = "/#{path}" unless path.start_with?("/".freeze)
64
66
  str << URI::Generic::DEFAULT_PARSER.escape(path)
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Sprockets
3
- VERSION = "4.0.0.beta7"
3
+ VERSION = "4.0.1"
4
4
  end
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.beta7
4
+ version: 4.0.1
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: 2018-03-13 00:00:00.000000000 Z
12
+ date: 2020-06-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -171,6 +171,20 @@ dependencies:
171
171
  - - "~>"
172
172
  - !ruby/object:Gem::Version
173
173
  version: '1.1'
174
+ - !ruby/object:Gem::Dependency
175
+ name: timecop
176
+ requirement: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: 0.9.1
181
+ type: :development
182
+ prerelease: false
183
+ version_requirements: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: 0.9.1
174
188
  - !ruby/object:Gem::Dependency
175
189
  name: minitest
176
190
  requirement: !ruby/object:Gem::Requirement
@@ -219,14 +233,14 @@ dependencies:
219
233
  requirements:
220
234
  - - "~>"
221
235
  - !ruby/object:Gem::Version
222
- version: '10.0'
236
+ version: '12.0'
223
237
  type: :development
224
238
  prerelease: false
225
239
  version_requirements: !ruby/object:Gem::Requirement
226
240
  requirements:
227
241
  - - "~>"
228
242
  - !ruby/object:Gem::Version
229
- version: '10.0'
243
+ version: '12.0'
230
244
  - !ruby/object:Gem::Dependency
231
245
  name: sass
232
246
  requirement: !ruby/object:Gem::Requirement
@@ -245,20 +259,14 @@ dependencies:
245
259
  name: sassc
246
260
  requirement: !ruby/object:Gem::Requirement
247
261
  requirements:
248
- - - ">="
249
- - !ruby/object:Gem::Version
250
- version: 1.10.1
251
- - - "<"
262
+ - - "~>"
252
263
  - !ruby/object:Gem::Version
253
264
  version: '2.0'
254
265
  type: :development
255
266
  prerelease: false
256
267
  version_requirements: !ruby/object:Gem::Requirement
257
268
  requirements:
258
- - - ">="
259
- - !ruby/object:Gem::Version
260
- version: 1.10.1
261
- - - "<"
269
+ - - "~>"
262
270
  - !ruby/object:Gem::Version
263
271
  version: '2.0'
264
272
  - !ruby/object:Gem::Dependency
@@ -303,6 +311,20 @@ dependencies:
303
311
  - - "~>"
304
312
  - !ruby/object:Gem::Version
305
313
  version: 0.0.4
314
+ - !ruby/object:Gem::Dependency
315
+ name: rubocop-performance
316
+ requirement: !ruby/object:Gem::Requirement
317
+ requirements:
318
+ - - "~>"
319
+ - !ruby/object:Gem::Version
320
+ version: '1.3'
321
+ type: :development
322
+ prerelease: false
323
+ version_requirements: !ruby/object:Gem::Requirement
324
+ requirements:
325
+ - - "~>"
326
+ - !ruby/object:Gem::Version
327
+ version: '1.3'
306
328
  description: Sprockets is a Rack-based asset packaging system that concatenates and
307
329
  serves JavaScript, CoffeeScript, CSS, Sass, and SCSS.
308
330
  email:
@@ -408,15 +430,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
408
430
  requirements:
409
431
  - - ">="
410
432
  - !ruby/object:Gem::Version
411
- version: 2.2.0
433
+ version: 2.5.0
412
434
  required_rubygems_version: !ruby/object:Gem::Requirement
413
435
  requirements:
414
- - - ">"
436
+ - - ">="
415
437
  - !ruby/object:Gem::Version
416
- version: 1.3.1
438
+ version: '0'
417
439
  requirements: []
418
- rubyforge_project: sprockets
419
- rubygems_version: 2.7.6
440
+ rubygems_version: 3.1.2
420
441
  signing_key:
421
442
  specification_version: 4
422
443
  summary: Rack-based asset packaging system