sprockets 2.2.3 → 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.
Files changed (99) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +68 -0
  3. data/README.md +482 -255
  4. data/bin/sprockets +20 -7
  5. data/lib/rake/sprocketstask.rb +28 -15
  6. data/lib/sprockets/add_source_map_comment_to_asset_processor.rb +60 -0
  7. data/lib/sprockets/asset.rb +142 -207
  8. data/lib/sprockets/autoload/babel.rb +8 -0
  9. data/lib/sprockets/autoload/closure.rb +8 -0
  10. data/lib/sprockets/autoload/coffee_script.rb +8 -0
  11. data/lib/sprockets/autoload/eco.rb +8 -0
  12. data/lib/sprockets/autoload/ejs.rb +8 -0
  13. data/lib/sprockets/autoload/jsminc.rb +8 -0
  14. data/lib/sprockets/autoload/sass.rb +8 -0
  15. data/lib/sprockets/autoload/sassc.rb +8 -0
  16. data/lib/sprockets/autoload/uglifier.rb +8 -0
  17. data/lib/sprockets/autoload/yui.rb +8 -0
  18. data/lib/sprockets/autoload/zopfli.rb +7 -0
  19. data/lib/sprockets/autoload.rb +16 -0
  20. data/lib/sprockets/babel_processor.rb +66 -0
  21. data/lib/sprockets/base.rb +89 -249
  22. data/lib/sprockets/bower.rb +61 -0
  23. data/lib/sprockets/bundle.rb +105 -0
  24. data/lib/sprockets/cache/file_store.rb +190 -14
  25. data/lib/sprockets/cache/memory_store.rb +75 -0
  26. data/lib/sprockets/cache/null_store.rb +54 -0
  27. data/lib/sprockets/cache.rb +271 -0
  28. data/lib/sprockets/cached_environment.rb +64 -0
  29. data/lib/sprockets/closure_compressor.rb +48 -0
  30. data/lib/sprockets/coffee_script_processor.rb +39 -0
  31. data/lib/sprockets/compressing.rb +134 -0
  32. data/lib/sprockets/configuration.rb +79 -0
  33. data/lib/sprockets/context.rb +204 -135
  34. data/lib/sprockets/dependencies.rb +74 -0
  35. data/lib/sprockets/digest_utils.rb +200 -0
  36. data/lib/sprockets/directive_processor.rb +224 -216
  37. data/lib/sprockets/eco_processor.rb +33 -0
  38. data/lib/sprockets/ejs_processor.rb +32 -0
  39. data/lib/sprockets/encoding_utils.rb +262 -0
  40. data/lib/sprockets/environment.rb +23 -68
  41. data/lib/sprockets/erb_processor.rb +37 -0
  42. data/lib/sprockets/errors.rb +6 -13
  43. data/lib/sprockets/exporters/base.rb +72 -0
  44. data/lib/sprockets/exporters/file_exporter.rb +24 -0
  45. data/lib/sprockets/exporters/zlib_exporter.rb +33 -0
  46. data/lib/sprockets/exporters/zopfli_exporter.rb +14 -0
  47. data/lib/sprockets/exporting.rb +73 -0
  48. data/lib/sprockets/file_reader.rb +16 -0
  49. data/lib/sprockets/http_utils.rb +135 -0
  50. data/lib/sprockets/jsminc_compressor.rb +32 -0
  51. data/lib/sprockets/jst_processor.rb +36 -19
  52. data/lib/sprockets/loader.rb +343 -0
  53. data/lib/sprockets/manifest.rb +231 -96
  54. data/lib/sprockets/manifest_utils.rb +48 -0
  55. data/lib/sprockets/mime.rb +80 -32
  56. data/lib/sprockets/npm.rb +52 -0
  57. data/lib/sprockets/path_dependency_utils.rb +77 -0
  58. data/lib/sprockets/path_digest_utils.rb +48 -0
  59. data/lib/sprockets/path_utils.rb +367 -0
  60. data/lib/sprockets/paths.rb +82 -0
  61. data/lib/sprockets/preprocessors/default_source_map.rb +49 -0
  62. data/lib/sprockets/processing.rb +140 -192
  63. data/lib/sprockets/processor_utils.rb +169 -0
  64. data/lib/sprockets/resolve.rb +295 -0
  65. data/lib/sprockets/sass_cache_store.rb +30 -0
  66. data/lib/sprockets/sass_compressor.rb +63 -0
  67. data/lib/sprockets/sass_functions.rb +3 -0
  68. data/lib/sprockets/sass_importer.rb +3 -0
  69. data/lib/sprockets/sass_processor.rb +313 -0
  70. data/lib/sprockets/sassc_compressor.rb +56 -0
  71. data/lib/sprockets/sassc_processor.rb +297 -0
  72. data/lib/sprockets/server.rb +138 -90
  73. data/lib/sprockets/source_map_processor.rb +66 -0
  74. data/lib/sprockets/source_map_utils.rb +483 -0
  75. data/lib/sprockets/transformers.rb +173 -0
  76. data/lib/sprockets/uglifier_compressor.rb +66 -0
  77. data/lib/sprockets/unloaded_asset.rb +139 -0
  78. data/lib/sprockets/uri_tar.rb +99 -0
  79. data/lib/sprockets/uri_utils.rb +191 -0
  80. data/lib/sprockets/utils/gzip.rb +99 -0
  81. data/lib/sprockets/utils.rb +186 -53
  82. data/lib/sprockets/version.rb +2 -1
  83. data/lib/sprockets/yui_compressor.rb +56 -0
  84. data/lib/sprockets.rb +217 -52
  85. metadata +250 -59
  86. data/LICENSE +0 -21
  87. data/lib/sprockets/asset_attributes.rb +0 -126
  88. data/lib/sprockets/bundled_asset.rb +0 -79
  89. data/lib/sprockets/caching.rb +0 -96
  90. data/lib/sprockets/charset_normalizer.rb +0 -41
  91. data/lib/sprockets/eco_template.rb +0 -38
  92. data/lib/sprockets/ejs_template.rb +0 -37
  93. data/lib/sprockets/engines.rb +0 -74
  94. data/lib/sprockets/index.rb +0 -99
  95. data/lib/sprockets/processed_asset.rb +0 -152
  96. data/lib/sprockets/processor.rb +0 -32
  97. data/lib/sprockets/safety_colons.rb +0 -28
  98. data/lib/sprockets/static_asset.rb +0 -57
  99. data/lib/sprockets/trail.rb +0 -90
@@ -1,7 +1,6 @@
1
- require 'pathname'
1
+ # frozen_string_literal: true
2
+ require 'set'
2
3
  require 'shellwords'
3
- require 'tilt'
4
- require 'yaml'
5
4
 
6
5
  module Sprockets
7
6
  # The `DirectiveProcessor` is responsible for parsing and evaluating
@@ -20,10 +19,9 @@ module Sprockets
20
19
  # *= require "baz"
21
20
  # */
22
21
  #
23
- # The Processor is implemented as a `Tilt::Template` and is loosely
24
- # coupled to Sprockets. This makes it possible to disable or modify
25
- # the processor to do whatever you'd like. You could add your own
26
- # custom directives or invent your own directive syntax.
22
+ # This makes it possible to disable or modify the processor to do whatever
23
+ # you'd like. You could add your own custom directives or invent your own
24
+ # directive syntax.
27
25
  #
28
26
  # `Environment#processors` includes `DirectiveProcessor` by default.
29
27
  #
@@ -36,25 +34,7 @@ module Sprockets
36
34
  #
37
35
  # env.register_processor('text/css', MyProcessor)
38
36
  #
39
- class DirectiveProcessor < Tilt::Template
40
- # Directives will only be picked up if they are in the header
41
- # of the source file. C style (/* */), JavaScript (//), and
42
- # Ruby (#) comments are supported.
43
- #
44
- # Directives in comments after the first non-whitespace line
45
- # of code will not be processed.
46
- #
47
- HEADER_PATTERN = /
48
- \A (
49
- (?m:\s*) (
50
- (\/\* (?m:.*?) \*\/) |
51
- (\#\#\# (?m:.*?) \#\#\#) |
52
- (\/\/ .* \n?)+ |
53
- (\# .* \n?)+
54
- )
55
- )+
56
- /x
57
-
37
+ class DirectiveProcessor
58
38
  # Directives are denoted by a `=` followed by the name, then
59
39
  # argument list.
60
40
  #
@@ -65,77 +45,121 @@ module Sprockets
65
45
  # //= require "foo"
66
46
  #
67
47
  DIRECTIVE_PATTERN = /
68
- ^ [\W]* = \s* (\w+.*?) (\*\/)? $
48
+ ^ \W* = \s* (\w+.*?) (\*\/)? $
69
49
  /x
70
50
 
71
- attr_reader :pathname
72
- attr_reader :header, :body
51
+ def self.instance
52
+ # Default to C comment styles
53
+ @instance ||= new(comments: ["//", ["/*", "*/"]])
54
+ end
55
+
56
+ def self.call(input)
57
+ instance.call(input)
58
+ end
73
59
 
74
- def prepare
75
- @pathname = Pathname.new(file)
60
+ def initialize(comments: [])
61
+ @header_pattern = compile_header_pattern(Array(comments))
62
+ end
76
63
 
77
- @header = data[HEADER_PATTERN, 0] || ""
78
- @body = $' || data
79
- # Ensure body ends in a new line
80
- @body += "\n" if @body != "" && @body !~ /\n\Z/m
64
+ def call(input)
65
+ dup._call(input)
66
+ end
81
67
 
82
- @included_pathnames = []
83
- @compat = false
68
+ def _call(input)
69
+ @environment = input[:environment]
70
+ @uri = input[:uri]
71
+ @filename = input[:filename]
72
+ @dirname = File.dirname(@filename)
73
+ # If loading a source map file like `application.js.map` resolve
74
+ # dependencies using `.js` instead of `.js.map`
75
+ @content_type = SourceMapProcessor.original_content_type(input[:content_type], error_when_not_found: false)
76
+ @required = Set.new(input[:metadata][:required])
77
+ @stubbed = Set.new(input[:metadata][:stubbed])
78
+ @links = Set.new(input[:metadata][:links])
79
+ @dependencies = Set.new(input[:metadata][:dependencies])
80
+ @to_link = Set.new
81
+ @to_load = Set.new
82
+
83
+ data, directives = process_source(input[:data])
84
+ process_directives(directives)
85
+
86
+ {
87
+ data: data,
88
+ required: @required,
89
+ stubbed: @stubbed,
90
+ links: @links,
91
+ to_load: @to_load,
92
+ to_link: @to_link,
93
+ dependencies: @dependencies
94
+ }
84
95
  end
85
96
 
86
- # Implemented for Tilt#render.
87
- #
88
- # `context` is a `Context` instance with methods that allow you to
89
- # access the environment and append to the bundle. See `Context`
90
- # for the complete API.
91
- def evaluate(context, locals, &block)
92
- @context = context
97
+ protected
98
+ # Directives will only be picked up if they are in the header
99
+ # of the source file. C style (/* */), JavaScript (//), and
100
+ # Ruby (#) comments are supported.
101
+ #
102
+ # Directives in comments after the first non-whitespace line
103
+ # of code will not be processed.
104
+ def compile_header_pattern(comments)
105
+ re = comments.map { |c|
106
+ case c
107
+ when String
108
+ "(?:#{Regexp.escape(c)}.*\\n?)+"
109
+ when Array
110
+ "(?:#{Regexp.escape(c[0])}(?m:.*?)#{Regexp.escape(c[1])})"
111
+ else
112
+ raise TypeError, "unknown comment type: #{c.class}"
113
+ end
114
+ }.join("|")
115
+ Regexp.compile("\\A(?:(?m:\\s*)(?:#{re}))+")
116
+ end
93
117
 
94
- @result = ""
95
- @has_written_body = false
118
+ def process_source(source)
119
+ header = source[@header_pattern, 0] || ""
120
+ body = $' || source
96
121
 
97
- process_directives
98
- process_source
122
+ header, directives = extract_directives(header)
99
123
 
100
- @result
101
- end
124
+ data = +""
125
+ data.force_encoding(body.encoding)
126
+ data << header unless header.empty?
127
+ data << body
128
+ # Ensure body ends in a new line
129
+ data << "\n" if data.length > 0 && data[-1] != "\n"
102
130
 
103
- # Returns the header String with any directives stripped.
104
- def processed_header
105
- lineno = 0
106
- @processed_header ||= header.lines.map { |line|
107
- lineno += 1
108
- # Replace directive line with a clean break
109
- directives.assoc(lineno) ? "\n" : line
110
- }.join.chomp
111
- end
131
+ return data, directives
132
+ end
112
133
 
113
- # Returns the source String with any directives stripped.
114
- def processed_source
115
- @processed_source ||= processed_header + body
116
- end
134
+ # Returns an Array of directive structures. Each structure
135
+ # is an Array with the line number as the first element, the
136
+ # directive name as the second element, followed by any
137
+ # arguments.
138
+ #
139
+ # [[1, "require", "foo"], [2, "require", "bar"]]
140
+ #
141
+ def extract_directives(header)
142
+ processed_header = +""
143
+ directives = []
117
144
 
118
- # Returns an Array of directive structures. Each structure
119
- # is an Array with the line number as the first element, the
120
- # directive name as the second element, followed by any
121
- # arguments.
122
- #
123
- # [[1, "require", "foo"], [2, "require", "bar"]]
124
- #
125
- def directives
126
- @directives ||= header.lines.each_with_index.map { |line, index|
127
- if directive = line[DIRECTIVE_PATTERN, 1]
128
- name, *args = Shellwords.shellwords(directive)
129
- if respond_to?("process_#{name}_directive", true)
130
- [index + 1, name, *args]
145
+ header.lines.each_with_index do |line, index|
146
+ if directive = line[DIRECTIVE_PATTERN, 1]
147
+ name, *args = Shellwords.shellwords(directive)
148
+ if respond_to?("process_#{name}_directive", true)
149
+ directives << [index + 1, name, *args]
150
+ # Replace directive line with a clean break
151
+ line = "\n"
152
+ end
131
153
  end
154
+ processed_header << line
132
155
  end
133
- }.compact
134
- end
135
156
 
136
- protected
137
- attr_reader :included_pathnames
138
- attr_reader :context
157
+ processed_header.chomp!
158
+ # Ensure header ends in a new line like before it was processed
159
+ processed_header << "\n" if processed_header.length > 0 && header[-1] == "\n"
160
+
161
+ return processed_header, directives
162
+ end
139
163
 
140
164
  # Gathers comment directives in the source and processes them.
141
165
  # Any directive method matching `process_*_directive` will
@@ -147,8 +171,8 @@ module Sprockets
147
171
  # `process_require_glob_directive`.
148
172
  #
149
173
  # class DirectiveProcessor < Sprockets::DirectiveProcessor
150
- # def process_require_glob_directive
151
- # Dir["#{pathname.dirname}/#{glob}"].sort.each do |filename|
174
+ # def process_require_glob_directive(glob)
175
+ # Dir["#{dirname}/#{glob}"].sort.each do |filename|
152
176
  # require(filename)
153
177
  # end
154
178
  # end
@@ -159,35 +183,20 @@ module Sprockets
159
183
  # env.unregister_processor('text/css', Sprockets::DirectiveProcessor)
160
184
  # env.register_processor('text/css', DirectiveProcessor)
161
185
  #
162
- def process_directives
186
+ def process_directives(directives)
163
187
  directives.each do |line_number, name, *args|
164
- context.__LINE__ = line_number
165
- send("process_#{name}_directive", *args)
166
- context.__LINE__ = nil
167
- end
168
- end
169
-
170
- def process_source
171
- unless @has_written_body || processed_header.empty?
172
- @result << processed_header << "\n"
173
- end
174
-
175
- included_pathnames.each do |pathname|
176
- @result << context.evaluate(pathname)
177
- end
178
-
179
- unless @has_written_body
180
- @result << body
181
- end
182
-
183
- if compat? && constants.any?
184
- @result.gsub!(/<%=(.*?)%>/) { constants[$1.strip] }
188
+ begin
189
+ send("process_#{name}_directive", *args)
190
+ rescue Exception => e
191
+ e.set_backtrace(["#{@filename}:#{line_number}"] + e.backtrace)
192
+ raise e
193
+ end
185
194
  end
186
195
  end
187
196
 
188
197
  # The `require` directive functions similar to Ruby's own `require`.
189
198
  # It provides a way to declare a dependency on a file in your path
190
- # and ensures its only loaded once before the source file.
199
+ # and ensures it's only loaded once before the source file.
191
200
  #
192
201
  # `require` works with files in the environment path:
193
202
  #
@@ -204,22 +213,13 @@ module Sprockets
204
213
  # //= require "./bar"
205
214
  #
206
215
  def process_require_directive(path)
207
- if @compat
208
- if path =~ /<([^>]+)>/
209
- path = $1
210
- else
211
- path = "./#{path}" unless relative?(path)
212
- end
213
- end
214
-
215
- context.require_asset(path)
216
+ @required << resolve(path, accept: @content_type, pipeline: :self)
216
217
  end
217
218
 
218
- # `require_self` causes the body of the current file to be
219
- # inserted before any subsequent `require` or `include`
220
- # directives. Useful in CSS files, where it's common for the
221
- # index file to contain global styles that need to be defined
222
- # before other dependencies are loaded.
219
+ # `require_self` causes the body of the current file to be inserted
220
+ # before any subsequent `require` directives. Useful in CSS files, where
221
+ # it's common for the index file to contain global styles that need to
222
+ # be defined before other dependencies are loaded.
223
223
  #
224
224
  # /*= require "reset"
225
225
  # *= require_self
@@ -227,26 +227,10 @@ module Sprockets
227
227
  # */
228
228
  #
229
229
  def process_require_self_directive
230
- if @has_written_body
230
+ if @required.include?(@uri)
231
231
  raise ArgumentError, "require_self can only be called once per source file"
232
232
  end
233
-
234
- context.require_asset(pathname)
235
- process_source
236
- included_pathnames.clear
237
- @has_written_body = true
238
- end
239
-
240
- # The `include` directive works similar to `require` but
241
- # inserts the contents of the dependency even if it already
242
- # has been required.
243
- #
244
- # //= include "header"
245
- #
246
- def process_include_directive(path)
247
- pathname = context.resolve(path)
248
- context.depend_on_asset(pathname)
249
- included_pathnames << pathname
233
+ @required << @uri
250
234
  end
251
235
 
252
236
  # `require_directory` requires all the files inside a single
@@ -256,27 +240,8 @@ module Sprockets
256
240
  # //= require_directory "./javascripts"
257
241
  #
258
242
  def process_require_directory_directive(path = ".")
259
- if relative?(path)
260
- root = pathname.dirname.join(path).expand_path
261
-
262
- unless (stats = stat(root)) && stats.directory?
263
- raise ArgumentError, "require_directory argument must be a directory"
264
- end
265
-
266
- context.depend_on(root)
267
-
268
- entries(root).each do |pathname|
269
- pathname = root.join(pathname)
270
- if pathname.to_s == self.file
271
- next
272
- elsif context.asset_requirable?(pathname)
273
- context.require_asset(pathname)
274
- end
275
- end
276
- else
277
- # The path must be relative and start with a `./`.
278
- raise ArgumentError, "require_directory argument must be a relative path"
279
- end
243
+ path = expand_relative_dirname(:require_directory, path)
244
+ require_paths(*@environment.stat_directory_with_dependencies(path))
280
245
  end
281
246
 
282
247
  # `require_tree` requires all the nested files in a directory.
@@ -285,28 +250,8 @@ module Sprockets
285
250
  # //= require_tree "./public"
286
251
  #
287
252
  def process_require_tree_directive(path = ".")
288
- if relative?(path)
289
- root = pathname.dirname.join(path).expand_path
290
-
291
- unless (stats = stat(root)) && stats.directory?
292
- raise ArgumentError, "require_tree argument must be a directory"
293
- end
294
-
295
- context.depend_on(root)
296
-
297
- each_entry(root) do |pathname|
298
- if pathname.to_s == self.file
299
- next
300
- elsif stat(pathname).directory?
301
- context.depend_on(pathname)
302
- elsif context.asset_requirable?(pathname)
303
- context.require_asset(pathname)
304
- end
305
- end
306
- else
307
- # The path must be relative and start with a `./`.
308
- raise ArgumentError, "require_tree argument must be a relative path"
309
- end
253
+ path = expand_relative_dirname(:require_tree, path)
254
+ require_paths(*@environment.stat_sorted_tree_with_dependencies(path))
310
255
  end
311
256
 
312
257
  # Allows you to state a dependency on a file without
@@ -322,22 +267,22 @@ module Sprockets
322
267
  # //= depend_on "foo.png"
323
268
  #
324
269
  def process_depend_on_directive(path)
325
- context.depend_on(path)
270
+ resolve(path)
326
271
  end
327
272
 
328
273
  # Allows you to state a dependency on an asset without including
329
274
  # it.
330
275
  #
331
276
  # This is used for caching purposes. Any changes that would
332
- # invalid the asset dependency will invalidate the cache our the
333
- # source file.
277
+ # invalidate the asset dependency will invalidate the cache of
278
+ # the source file.
334
279
  #
335
280
  # Unlike `depend_on`, the path must be a requirable asset.
336
281
  #
337
282
  # //= depend_on_asset "bar.js"
338
283
  #
339
284
  def process_depend_on_asset_directive(path)
340
- context.depend_on_asset(path)
285
+ to_load(resolve(path))
341
286
  end
342
287
 
343
288
  # Allows dependency to be excluded from the asset bundle.
@@ -349,58 +294,121 @@ module Sprockets
349
294
  # //= stub "jquery"
350
295
  #
351
296
  def process_stub_directive(path)
352
- context.stub_asset(path)
297
+ @stubbed << resolve(path, accept: @content_type, pipeline: :self)
298
+ end
299
+
300
+ # Declares a linked dependency on the target asset.
301
+ #
302
+ # The `path` must be a valid asset and should not already be part of the
303
+ # bundle. Any linked assets will automatically be compiled along with the
304
+ # current.
305
+ #
306
+ # /*= link "logo.png" */
307
+ #
308
+ def process_link_directive(path)
309
+ uri = to_load(resolve(path))
310
+ @to_link << uri
353
311
  end
354
312
 
355
- # Enable Sprockets 1.x compat mode.
313
+ # `link_directory` links all the files inside a single
314
+ # directory. It's similar to `path/*` since it does not follow
315
+ # nested directories.
316
+ #
317
+ # //= link_directory "./fonts"
356
318
  #
357
- # Makes it possible to use the same JavaScript source
358
- # file in both Sprockets 1 and 2.
319
+ # Use caution when linking against JS or CSS assets. Include an explicit
320
+ # extension or content type in these cases.
359
321
  #
360
- # //= compat
322
+ # //= link_directory "./scripts" .js
361
323
  #
362
- def process_compat_directive
363
- @compat = true
324
+ def process_link_directory_directive(path = ".", accept = nil)
325
+ path = expand_relative_dirname(:link_directory, path)
326
+ accept = expand_accept_shorthand(accept)
327
+ link_paths(*@environment.stat_directory_with_dependencies(path), accept)
364
328
  end
365
329
 
366
- # Checks if Sprockets 1.x compat mode enabled
367
- def compat?
368
- @compat
330
+ # `link_tree` links all the nested files in a directory.
331
+ # Its glob equivalent is `path/**/*`.
332
+ #
333
+ # //= link_tree "./images"
334
+ #
335
+ # Use caution when linking against JS or CSS assets. Include an explicit
336
+ # extension or content type in these cases.
337
+ #
338
+ # //= link_tree "./styles" .css
339
+ #
340
+ def process_link_tree_directive(path = ".", accept = nil)
341
+ path = expand_relative_dirname(:link_tree, path)
342
+ accept = expand_accept_shorthand(accept)
343
+ link_paths(*@environment.stat_sorted_tree_with_dependencies(path), accept)
369
344
  end
370
345
 
371
- # Sprockets 1.x allowed for constant interpolation if a
372
- # constants.yml was present. This is only available if
373
- # compat mode is on.
374
- def constants
375
- if compat?
376
- pathname = Pathname.new(context.root_path).join("constants.yml")
377
- stat(pathname) ? YAML.load_file(pathname) : {}
346
+ private
347
+ def expand_accept_shorthand(accept)
348
+ if accept.nil?
349
+ nil
350
+ elsif accept.include?("/")
351
+ accept
352
+ elsif accept.start_with?(".")
353
+ @environment.mime_exts[accept]
378
354
  else
379
- {}
355
+ @environment.mime_exts[".#{accept}"]
380
356
  end
381
357
  end
382
358
 
383
- # `provide` is stubbed out for Sprockets 1.x compat.
384
- # Mutating the path when an asset is being built is
385
- # not permitted.
386
- def process_provide_directive(path)
359
+ def require_paths(paths, deps)
360
+ resolve_paths(paths, deps, accept: @content_type, pipeline: :self) do |uri|
361
+ @required << uri
362
+ end
387
363
  end
388
364
 
389
- private
390
- def relative?(path)
391
- path =~ /^\.($|\.?\/)/
365
+ def link_paths(paths, deps, accept)
366
+ resolve_paths(paths, deps, accept: accept) do |uri|
367
+ @to_link << to_load(uri)
368
+ end
392
369
  end
393
370
 
394
- def stat(path)
395
- context.environment.stat(path)
371
+ def resolve_paths(paths, deps, **kargs)
372
+ @dependencies.merge(deps)
373
+ paths.each do |subpath, stat|
374
+ next if subpath == @filename || stat.directory?
375
+ uri, deps = @environment.resolve(subpath, **kargs)
376
+ @dependencies.merge(deps)
377
+ yield uri if uri
378
+ end
396
379
  end
397
380
 
398
- def entries(path)
399
- context.environment.entries(path)
381
+ def expand_relative_dirname(directive, path)
382
+ if @environment.relative_path?(path)
383
+ path = File.expand_path(path, @dirname)
384
+ stat = @environment.stat(path)
385
+
386
+ if stat && stat.directory?
387
+ path
388
+ else
389
+ raise ArgumentError, "#{directive} argument must be a directory"
390
+ end
391
+ else
392
+ # The path must be relative and start with a `./`.
393
+ raise ArgumentError, "#{directive} argument must be a relative path"
394
+ end
395
+ end
396
+
397
+ def to_load(uri)
398
+ @to_load << uri
399
+ uri
400
400
  end
401
401
 
402
- def each_entry(root, &block)
403
- context.environment.each_entry(root, &block)
402
+ def resolve(path, **kargs)
403
+ # Prevent absolute paths in directives
404
+ if @environment.absolute_path?(path)
405
+ raise FileOutsidePaths, "can't require absolute file: #{path}"
406
+ end
407
+
408
+ kargs[:base_path] = @dirname
409
+ uri, deps = @environment.resolve!(path, **kargs)
410
+ @dependencies.merge(deps)
411
+ uri
404
412
  end
405
413
  end
406
414
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ require 'sprockets/autoload'
3
+
4
+ module Sprockets
5
+ # Processor engine class for the Eco compiler. Depends on the `eco` gem.
6
+ #
7
+ # For more infomation see:
8
+ #
9
+ # https://github.com/sstephenson/ruby-eco
10
+ # https://github.com/sstephenson/eco
11
+ #
12
+ module EcoProcessor
13
+ VERSION = '1'
14
+
15
+ def self.cache_key
16
+ @cache_key ||= "#{name}:#{Autoload::Eco::Source::VERSION}:#{VERSION}".freeze
17
+ end
18
+
19
+ # Compile template data with Eco compiler.
20
+ #
21
+ # Returns a JS function definition String. The result should be
22
+ # assigned to a JS variable.
23
+ #
24
+ # # => "function(...) {...}"
25
+ #
26
+ def self.call(input)
27
+ data = input[:data]
28
+ input[:cache].fetch([cache_key, data]) do
29
+ Autoload::Eco.compile(data)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ require 'sprockets/autoload'
3
+
4
+ module Sprockets
5
+ # Processor engine class for the EJS compiler. Depends on the `ejs` gem.
6
+ #
7
+ # For more infomation see:
8
+ #
9
+ # https://github.com/sstephenson/ruby-ejs
10
+ #
11
+ module EjsProcessor
12
+ VERSION = '1'
13
+
14
+ def self.cache_key
15
+ @cache_key ||= "#{name}:#{VERSION}".freeze
16
+ end
17
+
18
+ # Compile template data with EJS compiler.
19
+ #
20
+ # Returns a JS function definition String. The result should be
21
+ # assigned to a JS variable.
22
+ #
23
+ # # => "function(obj){...}"
24
+ #
25
+ def self.call(input)
26
+ data = input[:data]
27
+ input[:cache].fetch([cache_key, data]) do
28
+ Autoload::EJS.compile(data)
29
+ end
30
+ end
31
+ end
32
+ end