sprockets 3.7.2 → 4.0.0.beta1

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.
Files changed (65) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +2 -295
  3. data/README.md +21 -35
  4. data/bin/sprockets +11 -8
  5. data/lib/rake/sprocketstask.rb +2 -2
  6. data/lib/sprockets.rb +79 -34
  7. data/lib/sprockets/asset.rb +8 -21
  8. data/lib/sprockets/autoload.rb +3 -0
  9. data/lib/sprockets/autoload/babel.rb +7 -0
  10. data/lib/sprockets/autoload/jsminc.rb +7 -0
  11. data/lib/sprockets/autoload/sassc.rb +7 -0
  12. data/lib/sprockets/babel_processor.rb +58 -0
  13. data/lib/sprockets/base.rb +8 -8
  14. data/lib/sprockets/bower.rb +4 -2
  15. data/lib/sprockets/bundle.rb +1 -1
  16. data/lib/sprockets/cache.rb +2 -4
  17. data/lib/sprockets/closure_compressor.rb +1 -2
  18. data/lib/sprockets/coffee_script_processor.rb +9 -3
  19. data/lib/sprockets/compressing.rb +2 -2
  20. data/lib/sprockets/configuration.rb +1 -7
  21. data/lib/sprockets/context.rb +10 -18
  22. data/lib/sprockets/digest_utils.rb +40 -52
  23. data/lib/sprockets/directive_processor.rb +10 -13
  24. data/lib/sprockets/http_utils.rb +19 -4
  25. data/lib/sprockets/jsminc_compressor.rb +31 -0
  26. data/lib/sprockets/jst_processor.rb +10 -10
  27. data/lib/sprockets/loader.rb +34 -28
  28. data/lib/sprockets/manifest.rb +3 -35
  29. data/lib/sprockets/manifest_utils.rb +0 -2
  30. data/lib/sprockets/mime.rb +7 -42
  31. data/lib/sprockets/path_dependency_utils.rb +2 -11
  32. data/lib/sprockets/path_digest_utils.rb +1 -1
  33. data/lib/sprockets/path_utils.rb +43 -18
  34. data/lib/sprockets/preprocessors/default_source_map.rb +24 -0
  35. data/lib/sprockets/processing.rb +30 -61
  36. data/lib/sprockets/processor_utils.rb +27 -28
  37. data/lib/sprockets/resolve.rb +172 -92
  38. data/lib/sprockets/sass_cache_store.rb +1 -6
  39. data/lib/sprockets/sass_compressor.rb +14 -1
  40. data/lib/sprockets/sass_processor.rb +18 -8
  41. data/lib/sprockets/sassc_compressor.rb +30 -0
  42. data/lib/sprockets/sassc_processor.rb +68 -0
  43. data/lib/sprockets/server.rb +9 -20
  44. data/lib/sprockets/source_map_comment_processor.rb +29 -0
  45. data/lib/sprockets/source_map_processor.rb +40 -0
  46. data/lib/sprockets/source_map_utils.rb +345 -0
  47. data/lib/sprockets/transformers.rb +62 -35
  48. data/lib/sprockets/uglifier_compressor.rb +12 -5
  49. data/lib/sprockets/unloaded_asset.rb +12 -11
  50. data/lib/sprockets/uri_tar.rb +4 -2
  51. data/lib/sprockets/uri_utils.rb +5 -5
  52. data/lib/sprockets/utils.rb +30 -78
  53. data/lib/sprockets/version.rb +1 -1
  54. metadata +62 -20
  55. data/LICENSE +0 -21
  56. data/lib/sprockets/coffee_script_template.rb +0 -17
  57. data/lib/sprockets/deprecation.rb +0 -90
  58. data/lib/sprockets/eco_template.rb +0 -17
  59. data/lib/sprockets/ejs_template.rb +0 -17
  60. data/lib/sprockets/engines.rb +0 -92
  61. data/lib/sprockets/erb_template.rb +0 -11
  62. data/lib/sprockets/legacy.rb +0 -330
  63. data/lib/sprockets/legacy_proc_processor.rb +0 -35
  64. data/lib/sprockets/legacy_tilt_processor.rb +0 -29
  65. data/lib/sprockets/sass_template.rb +0 -19
@@ -44,7 +44,7 @@ module Sprockets
44
44
  # Internal: Cache key version for this class. Rarely should have to change
45
45
  # unless the cache format radically changes. Will be bump on major version
46
46
  # releases though.
47
- VERSION = '3.0'
47
+ VERSION = '4.0'
48
48
 
49
49
  def self.default_logger
50
50
  logger = Logger.new($stderr)
@@ -153,9 +153,7 @@ module Sprockets
153
153
  #
154
154
  # Returns a String with a length less than 250 characters.
155
155
  def expand_key(key)
156
- digest_key = DigestUtils.pack_urlsafe_base64digest(DigestUtils.digest(key))
157
- namespace = digest_key[0, 2]
158
- "sprockets/v#{VERSION}/#{namespace}/#{digest_key}"
156
+ "sprockets/v#{VERSION}/#{DigestUtils.pack_urlsafe_base64digest(DigestUtils.digest(key))}"
159
157
  end
160
158
 
161
159
  PEEK_SIZE = 100
@@ -35,12 +35,11 @@ module Sprockets
35
35
  attr_reader :cache_key
36
36
 
37
37
  def initialize(options = {})
38
- @options = options
38
+ @compiler = Autoload::Closure::Compiler.new(options)
39
39
  @cache_key = "#{self.class.name}:#{Autoload::Closure::VERSION}:#{Autoload::Closure::COMPILER_VERSION}:#{VERSION}:#{DigestUtils.digest(options)}".freeze
40
40
  end
41
41
 
42
42
  def call(input)
43
- @compiler ||= Autoload::Closure::Compiler.new(@options)
44
43
  @compiler.compile(input[:data])
45
44
  end
46
45
  end
@@ -1,4 +1,5 @@
1
1
  require 'sprockets/autoload'
2
+ require 'sprockets/source_map_utils'
2
3
 
3
4
  module Sprockets
4
5
  # Processor engine class for the CoffeeScript compiler.
@@ -9,7 +10,7 @@ module Sprockets
9
10
  # https://github.com/josh/ruby-coffee-script
10
11
  #
11
12
  module CoffeeScriptProcessor
12
- VERSION = '1'
13
+ VERSION = '2'
13
14
 
14
15
  def self.cache_key
15
16
  @cache_key ||= "#{name}:#{Autoload::CoffeeScript::Source.version}:#{VERSION}".freeze
@@ -17,9 +18,14 @@ module Sprockets
17
18
 
18
19
  def self.call(input)
19
20
  data = input[:data]
20
- input[:cache].fetch([self.cache_key, data]) do
21
- Autoload::CoffeeScript.compile(data)
21
+
22
+ js, map = input[:cache].fetch([self.cache_key, data]) do
23
+ result = Autoload::CoffeeScript.compile(data, sourceMap: true, sourceFiles: [input[:source_path]])
24
+ [result['js'], SourceMapUtils.decode_json_source_map(result['v3SourceMap'])['mappings']]
22
25
  end
26
+
27
+ map = SourceMapUtils.combine_source_maps(input[:metadata][:map], map)
28
+ { data: js, map: map }
23
29
  end
24
30
  end
25
31
  end
@@ -35,7 +35,7 @@ module Sprockets
35
35
  if compressor.is_a?(Symbol)
36
36
  @css_compressor = klass = config[:compressors]['text/css'][compressor] || raise(Error, "unknown compressor: #{compressor}")
37
37
  elsif compressor.respond_to?(:compress)
38
- klass = LegacyProcProcessor.new(:css_compressor, proc { |context, data| compressor.compress(data) })
38
+ klass = proc { |input| compressor.compress(input[:data]) }
39
39
  @css_compressor = :css_compressor
40
40
  else
41
41
  @css_compressor = klass = compressor
@@ -62,7 +62,7 @@ module Sprockets
62
62
  if compressor.is_a?(Symbol)
63
63
  @js_compressor = klass = config[:compressors]['application/javascript'][compressor] || raise(Error, "unknown compressor: #{compressor}")
64
64
  elsif compressor.respond_to?(:compress)
65
- klass = LegacyProcProcessor.new(:js_compressor, proc { |context, data| compressor.compress(data) })
65
+ klass = proc { |input| compressor.compress(input[:data]) }
66
66
  @js_compressor = :js_compressor
67
67
  else
68
68
  @js_compressor = klass = compressor
@@ -1,6 +1,5 @@
1
1
  require 'sprockets/compressing'
2
2
  require 'sprockets/dependencies'
3
- require 'sprockets/engines'
4
3
  require 'sprockets/mime'
5
4
  require 'sprockets/paths'
6
5
  require 'sprockets/processing'
@@ -9,19 +8,16 @@ require 'sprockets/utils'
9
8
 
10
9
  module Sprockets
11
10
  module Configuration
12
- include Paths, Mime, Engines, Transformers, Processing, Compressing, Dependencies, Utils
11
+ include Paths, Mime, Transformers, Processing, Compressing, Dependencies, Utils
13
12
 
14
13
  def initialize_configuration(parent)
15
14
  @config = parent.config
16
- @computed_config = parent.computed_config
17
15
  @logger = parent.logger
18
16
  @context_class = Class.new(parent.context_class)
19
17
  end
20
18
 
21
19
  attr_reader :config
22
20
 
23
- attr_accessor :computed_config
24
-
25
21
  def config=(config)
26
22
  raise TypeError, "can't assign mutable config" unless config.frozen?
27
23
  @config = config
@@ -69,8 +65,6 @@ module Sprockets
69
65
  self.config = config.merge(digest_class: klass).freeze
70
66
  end
71
67
 
72
- # Deprecated: Get `Context` class.
73
- #
74
68
  # This class maybe mutated and mixed in with custom helpers.
75
69
  #
76
70
  # environment.context_class.instance_eval do
@@ -1,10 +1,8 @@
1
- require 'pathname'
2
1
  require 'rack/utils'
3
2
  require 'set'
4
3
  require 'sprockets/errors'
5
4
 
6
5
  module Sprockets
7
- # Deprecated: `Context` provides helper methods to all processors.
8
6
  # They are typically accessed by ERB templates. You can mix in custom helpers
9
7
  # by injecting them into `Environment#context_class`. Do not mix them into
10
8
  # `Context` directly.
@@ -19,10 +17,7 @@ module Sprockets
19
17
  # The `Context` also collects dependencies declared by
20
18
  # assets. See `DirectiveProcessor` for an example of this.
21
19
  class Context
22
- attr_reader :environment, :filename, :pathname
23
-
24
- # Deprecated
25
- attr_accessor :__LINE__
20
+ attr_reader :environment, :filename
26
21
 
27
22
  def initialize(input)
28
23
  @environment = input[:environment]
@@ -31,7 +26,6 @@ module Sprockets
31
26
  @logical_path = input[:name]
32
27
  @filename = input[:filename]
33
28
  @dirname = File.dirname(@filename)
34
- @pathname = Pathname.new(@filename)
35
29
  @content_type = input[:content_type]
36
30
 
37
31
  @required = Set.new(@metadata[:required])
@@ -79,13 +73,13 @@ module Sprockets
79
73
  # resolve("./bar.js")
80
74
  # # => "file:///path/to/app/javascripts/bar.js?type=application/javascript"
81
75
  #
82
- # path - String logical or absolute path
83
- # options
84
- # accept - String content accept type
76
+ # path - String logical or absolute path
77
+ # accept - String content accept type
85
78
  #
86
79
  # Returns an Asset URI String.
87
- def resolve(path, options = {})
88
- uri, deps = environment.resolve!(path, options.merge(base_path: @dirname))
80
+ def resolve(path, **kargs)
81
+ kargs[:base_path] = @dirname
82
+ uri, deps = environment.resolve!(path, **kargs)
89
83
  @dependencies.merge(deps)
90
84
  uri
91
85
  end
@@ -108,12 +102,10 @@ module Sprockets
108
102
  # the dependency file with invalidate the cache of the
109
103
  # source file.
110
104
  def depend_on(path)
111
- path = path.to_s if path.is_a?(Pathname)
112
-
113
105
  if environment.absolute_path?(path) && environment.stat(path)
114
106
  @dependencies << environment.build_file_digest_uri(path)
115
107
  else
116
- resolve(path, compat: false)
108
+ resolve(path)
117
109
  end
118
110
  nil
119
111
  end
@@ -126,7 +118,7 @@ module Sprockets
126
118
  # file. Unlike `depend_on`, this will include recursively include
127
119
  # the target asset's dependencies.
128
120
  def depend_on_asset(path)
129
- load(resolve(path, compat: false))
121
+ load(resolve(path))
130
122
  end
131
123
 
132
124
  # `require_asset` declares `path` as a dependency of the file. The
@@ -139,7 +131,7 @@ module Sprockets
139
131
  # <%= require_asset "#{framework}.js" %>
140
132
  #
141
133
  def require_asset(path)
142
- @required << resolve(path, accept: @content_type, pipeline: :self, compat: false)
134
+ @required << resolve(path, accept: @content_type, pipeline: :self)
143
135
  nil
144
136
  end
145
137
 
@@ -147,7 +139,7 @@ module Sprockets
147
139
  # `path` must be an asset which may or may not already be included
148
140
  # in the bundle.
149
141
  def stub_asset(path)
150
- @stubbed << resolve(path, accept: @content_type, pipeline: :self, compat: false)
142
+ @stubbed << resolve(path, accept: @content_type, pipeline: :self)
151
143
  nil
152
144
  end
153
145
 
@@ -34,56 +34,6 @@ module Sprockets
34
34
  DIGEST_SIZES[bytes.bytesize]
35
35
  end
36
36
 
37
- ADD_VALUE_TO_DIGEST = {
38
- String => ->(val, digest) { digest << val },
39
- FalseClass => ->(val, digest) { digest << 'FalseClass'.freeze },
40
- TrueClass => ->(val, digest) { digest << 'TrueClass'.freeze },
41
- NilClass => ->(val, digest) { digest << 'NilClass'.freeze },
42
-
43
- Symbol => ->(val, digest) {
44
- digest << 'Symbol'.freeze
45
- digest << val.to_s
46
- },
47
- Integer => ->(val, digest) {
48
- digest << 'Integer'.freeze
49
- digest << val.to_s
50
- },
51
- Array => ->(val, digest) {
52
- digest << 'Array'.freeze
53
- val.each do |element|
54
- ADD_VALUE_TO_DIGEST[element.class].call(element, digest)
55
- end
56
- },
57
- Hash => ->(val, digest) {
58
- digest << 'Hash'.freeze
59
- val.sort.each do |array|
60
- ADD_VALUE_TO_DIGEST[Array].call(array, digest)
61
- end
62
- },
63
- Set => ->(val, digest) {
64
- digest << 'Set'.freeze
65
- ADD_VALUE_TO_DIGEST[Array].call(val.to_a, digest)
66
- },
67
- Encoding => ->(val, digest) {
68
- digest << 'Encoding'.freeze
69
- digest << val.name
70
- },
71
- }
72
- if 0.class != Integer # Ruby < 2.4
73
- ADD_VALUE_TO_DIGEST[Fixnum] = ->(val, digest) {
74
- digest << 'Integer'.freeze
75
- digest << val.to_s
76
- }
77
- ADD_VALUE_TO_DIGEST[Bignum] = ->(val, digest) {
78
- digest << 'Integer'.freeze
79
- digest << val.to_s
80
- }
81
- end
82
- ADD_VALUE_TO_DIGEST.default_proc = ->(_, val) {
83
- raise TypeError, "couldn't digest #{ val }"
84
- }
85
- private_constant :ADD_VALUE_TO_DIGEST
86
-
87
37
  # Internal: Generate a hexdigest for a nested JSON serializable object.
88
38
  #
89
39
  # This is used for generating cache keys, so its pretty important its
@@ -94,8 +44,46 @@ module Sprockets
94
44
  # Returns a String digest of the object.
95
45
  def digest(obj)
96
46
  digest = digest_class.new
47
+ queue = [obj]
48
+
49
+ while queue.length > 0
50
+ obj = queue.shift
51
+ klass = obj.class
52
+
53
+ if klass == String
54
+ digest << obj
55
+ elsif klass == Symbol
56
+ digest << 'Symbol'
57
+ digest << obj.to_s
58
+ elsif klass == Fixnum
59
+ digest << 'Fixnum'
60
+ digest << obj.to_s
61
+ elsif klass == Bignum
62
+ digest << 'Bignum'
63
+ digest << obj.to_s
64
+ elsif klass == TrueClass
65
+ digest << 'TrueClass'
66
+ elsif klass == FalseClass
67
+ digest << 'FalseClass'
68
+ elsif klass == NilClass
69
+ digest << 'NilClass'.freeze
70
+ elsif klass == Array
71
+ digest << 'Array'
72
+ queue.concat(obj)
73
+ elsif klass == Hash
74
+ digest << 'Hash'
75
+ queue.concat(obj.sort)
76
+ elsif klass == Set
77
+ digest << 'Set'
78
+ queue.concat(obj.to_a)
79
+ elsif klass == Encoding
80
+ digest << 'Encoding'
81
+ digest << obj.name
82
+ else
83
+ raise TypeError, "couldn't digest #{klass}"
84
+ end
85
+ end
97
86
 
98
- ADD_VALUE_TO_DIGEST[obj.class].call(obj, digest)
99
87
  digest.digest
100
88
  end
101
89
 
@@ -105,7 +93,7 @@ module Sprockets
105
93
  #
106
94
  # Returns hex String.
107
95
  def pack_hexdigest(bin)
108
- bin.unpack('H*').first
96
+ bin.unpack('H*'.freeze).first
109
97
  end
110
98
 
111
99
  # Internal: Unpack a hex encoded digest string into binary bytes.
@@ -34,8 +34,6 @@ module Sprockets
34
34
  # env.register_processor('text/css', MyProcessor)
35
35
  #
36
36
  class DirectiveProcessor
37
- VERSION = '1'
38
-
39
37
  # Directives are denoted by a `=` followed by the name, then
40
38
  # argument list.
41
39
  #
@@ -50,18 +48,16 @@ module Sprockets
50
48
  /x
51
49
 
52
50
  def self.instance
53
- @instance ||= new(
54
- # Deprecated: Default to C and Ruby comment styles
55
- comments: ["//", ["/*", "*/"]] + ["#", ["###", "###"]]
56
- )
51
+ # Default to C omment styles
52
+ @instance ||= new(comments: ["//", ["/*", "*/"]])
57
53
  end
58
54
 
59
55
  def self.call(input)
60
56
  instance.call(input)
61
57
  end
62
58
 
63
- def initialize(options = {})
64
- @header_pattern = compile_header_pattern(Array(options[:comments]))
59
+ def initialize(comments: [])
60
+ @header_pattern = compile_header_pattern(Array(comments))
65
61
  end
66
62
 
67
63
  def call(input)
@@ -162,7 +158,7 @@ module Sprockets
162
158
  # `process_require_glob_directive`.
163
159
  #
164
160
  # class DirectiveProcessor < Sprockets::DirectiveProcessor
165
- # def process_require_glob_directive
161
+ # def process_require_glob_directive(glob)
166
162
  # Dir["#{dirname}/#{glob}"].sort.each do |filename|
167
163
  # require(filename)
168
164
  # end
@@ -358,11 +354,11 @@ module Sprockets
358
354
  end
359
355
  end
360
356
 
361
- def resolve_paths(paths, deps, options = {})
357
+ def resolve_paths(paths, deps, **kargs)
362
358
  @dependencies.merge(deps)
363
359
  paths.each do |subpath, stat|
364
360
  next if subpath == @filename || stat.directory?
365
- uri, deps = @environment.resolve(subpath, options.merge(compat: false))
361
+ uri, deps = @environment.resolve(subpath, **kargs)
366
362
  @dependencies.merge(deps)
367
363
  yield uri if uri
368
364
  end
@@ -390,13 +386,14 @@ module Sprockets
390
386
  asset
391
387
  end
392
388
 
393
- def resolve(path, options = {})
389
+ def resolve(path, **kargs)
394
390
  # Prevent absolute paths in directives
395
391
  if @environment.absolute_path?(path)
396
392
  raise FileOutsidePaths, "can't require absolute file: #{path}"
397
393
  end
398
394
 
399
- uri, deps = @environment.resolve!(path, options.merge(base_path: @dirname))
395
+ kargs[:base_path] = @dirname
396
+ uri, deps = @environment.resolve!(path, **kargs)
400
397
  @dependencies.merge(deps)
401
398
  uri
402
399
  end
@@ -13,9 +13,9 @@ module Sprockets
13
13
  # Returns true if the given value is a mime match for the given mime match
14
14
  # specification, false otherwise.
15
15
  def match_mime_type?(value, matcher)
16
- v1, v2 = value.split('/', 2)
17
- m1, m2 = matcher.split('/', 2)
18
- (m1 == '*' || v1 == m1) && (m2.nil? || m2 == '*' || m2 == v2)
16
+ v1, v2 = value.split('/'.freeze, 2)
17
+ m1, m2 = matcher.split('/'.freeze, 2)
18
+ (m1 == '*'.freeze || v1 == m1) && (m2.nil? || m2 == '*'.freeze || m2 == v2)
19
19
  end
20
20
 
21
21
  # Public: Return values from Hash where the key matches the mime type.
@@ -36,7 +36,22 @@ module Sprockets
36
36
 
37
37
  # Internal: Parse Accept header quality values.
38
38
  #
39
- # Adapted from Rack::Utils#q_values.
39
+ # values - String e.g. "application/javascript"
40
+ #
41
+ # Adapted from Rack::Utils#q_values. Quality values are
42
+ # described in http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
43
+ #
44
+ # parse_q_values("application/javascript")
45
+ # # => [["application/javascript", 1.0]]
46
+ #
47
+ # parse_q_values("*/*")
48
+ # # => [["*/*", 1.0]]
49
+ #
50
+ # parse_q_values("text/plain; q=0.5, image/*")
51
+ # # => [["text/plain", 0.5], ["image/*", 1.0]]
52
+ #
53
+ # parse_q_values("application/javascript, text/css")
54
+ # # => [["application/javascript", 1.0], ["text/css", 1.0]]
40
55
  #
41
56
  # Returns an Array of [String, Float].
42
57
  def parse_q_values(values)
@@ -0,0 +1,31 @@
1
+ require 'sprockets/autoload'
2
+ require 'sprockets/digest_utils'
3
+
4
+ module Sprockets
5
+ class JSMincCompressor
6
+ VERSION = '1'
7
+
8
+ def self.instance
9
+ @instance ||= new
10
+ end
11
+
12
+ def self.call(input)
13
+ instance.call(input)
14
+ end
15
+
16
+ def self.cache_key
17
+ instance.cache_key
18
+ end
19
+
20
+ attr_reader :cache_key
21
+
22
+ def initialize(options = {})
23
+ @compressor_class = Autoload::JSMinC
24
+ @cache_key = "#{self.class.name}:#{Autoload::JSMinC::VERSION}:#{VERSION}:#{DigestUtils.digest(options)}".freeze
25
+ end
26
+
27
+ def call(input)
28
+ @compressor_class.minify(input[:data])
29
+ end
30
+ end
31
+ end