sprockets 3.7.2 → 4.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +2 -295
- data/README.md +21 -35
- data/bin/sprockets +11 -8
- data/lib/rake/sprocketstask.rb +2 -2
- data/lib/sprockets.rb +79 -34
- data/lib/sprockets/asset.rb +8 -21
- data/lib/sprockets/autoload.rb +3 -0
- data/lib/sprockets/autoload/babel.rb +7 -0
- data/lib/sprockets/autoload/jsminc.rb +7 -0
- data/lib/sprockets/autoload/sassc.rb +7 -0
- data/lib/sprockets/babel_processor.rb +58 -0
- data/lib/sprockets/base.rb +8 -8
- data/lib/sprockets/bower.rb +4 -2
- data/lib/sprockets/bundle.rb +1 -1
- data/lib/sprockets/cache.rb +2 -4
- data/lib/sprockets/closure_compressor.rb +1 -2
- data/lib/sprockets/coffee_script_processor.rb +9 -3
- data/lib/sprockets/compressing.rb +2 -2
- data/lib/sprockets/configuration.rb +1 -7
- data/lib/sprockets/context.rb +10 -18
- data/lib/sprockets/digest_utils.rb +40 -52
- data/lib/sprockets/directive_processor.rb +10 -13
- data/lib/sprockets/http_utils.rb +19 -4
- data/lib/sprockets/jsminc_compressor.rb +31 -0
- data/lib/sprockets/jst_processor.rb +10 -10
- data/lib/sprockets/loader.rb +34 -28
- data/lib/sprockets/manifest.rb +3 -35
- data/lib/sprockets/manifest_utils.rb +0 -2
- data/lib/sprockets/mime.rb +7 -42
- data/lib/sprockets/path_dependency_utils.rb +2 -11
- data/lib/sprockets/path_digest_utils.rb +1 -1
- data/lib/sprockets/path_utils.rb +43 -18
- data/lib/sprockets/preprocessors/default_source_map.rb +24 -0
- data/lib/sprockets/processing.rb +30 -61
- data/lib/sprockets/processor_utils.rb +27 -28
- data/lib/sprockets/resolve.rb +172 -92
- data/lib/sprockets/sass_cache_store.rb +1 -6
- data/lib/sprockets/sass_compressor.rb +14 -1
- data/lib/sprockets/sass_processor.rb +18 -8
- data/lib/sprockets/sassc_compressor.rb +30 -0
- data/lib/sprockets/sassc_processor.rb +68 -0
- data/lib/sprockets/server.rb +9 -20
- data/lib/sprockets/source_map_comment_processor.rb +29 -0
- data/lib/sprockets/source_map_processor.rb +40 -0
- data/lib/sprockets/source_map_utils.rb +345 -0
- data/lib/sprockets/transformers.rb +62 -35
- data/lib/sprockets/uglifier_compressor.rb +12 -5
- data/lib/sprockets/unloaded_asset.rb +12 -11
- data/lib/sprockets/uri_tar.rb +4 -2
- data/lib/sprockets/uri_utils.rb +5 -5
- data/lib/sprockets/utils.rb +30 -78
- data/lib/sprockets/version.rb +1 -1
- metadata +62 -20
- data/LICENSE +0 -21
- data/lib/sprockets/coffee_script_template.rb +0 -17
- data/lib/sprockets/deprecation.rb +0 -90
- data/lib/sprockets/eco_template.rb +0 -17
- data/lib/sprockets/ejs_template.rb +0 -17
- data/lib/sprockets/engines.rb +0 -92
- data/lib/sprockets/erb_template.rb +0 -11
- data/lib/sprockets/legacy.rb +0 -330
- data/lib/sprockets/legacy_proc_processor.rb +0 -35
- data/lib/sprockets/legacy_tilt_processor.rb +0 -29
- data/lib/sprockets/sass_template.rb +0 -19
@@ -0,0 +1,24 @@
|
|
1
|
+
module Sprockets
|
2
|
+
module Preprocessors
|
3
|
+
# Private: Adds a default map to assets when one is not present
|
4
|
+
#
|
5
|
+
# If the input file already has a source map, it effectively returns the original
|
6
|
+
# result. Otherwise it maps 1 for 1 lines original to generated. This is needed
|
7
|
+
# Because other generators run after might depend on having a valid source map
|
8
|
+
# available.
|
9
|
+
class DefaultSourceMap
|
10
|
+
def call(input)
|
11
|
+
result = { data: input[:data] }
|
12
|
+
map = input[:metadata][:map]
|
13
|
+
if map.nil? || map.empty?
|
14
|
+
result[:map] ||= []
|
15
|
+
input[:data].each_line.with_index do |_, index|
|
16
|
+
line = index + 1
|
17
|
+
result[:map] << { source: input[:source_path], generated: [line , 0], original: [line, 0] }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
return result
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/sprockets/processing.rb
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
require 'sprockets/engines'
|
2
1
|
require 'sprockets/file_reader'
|
3
|
-
require 'sprockets/legacy_proc_processor'
|
4
|
-
require 'sprockets/legacy_tilt_processor'
|
5
2
|
require 'sprockets/mime'
|
6
3
|
require 'sprockets/processor_utils'
|
7
4
|
require 'sprockets/uri_utils'
|
@@ -17,9 +14,14 @@ module Sprockets
|
|
17
14
|
config[:pipelines]
|
18
15
|
end
|
19
16
|
|
17
|
+
# Registers a pipeline that will be called by `call_processor` method.
|
20
18
|
def register_pipeline(name, proc = nil, &block)
|
21
19
|
proc ||= block
|
22
20
|
|
21
|
+
self.config = hash_reassoc(config, :pipeline_exts) do |pipeline_exts|
|
22
|
+
pipeline_exts.merge(".#{name}".freeze => name.to_sym)
|
23
|
+
end
|
24
|
+
|
23
25
|
self.config = hash_reassoc(config, :pipelines) do |pipelines|
|
24
26
|
pipelines.merge(name.to_sym => proc)
|
25
27
|
end
|
@@ -43,12 +45,13 @@ module Sprockets
|
|
43
45
|
#
|
44
46
|
# A block can be passed for to create a shorthand processor.
|
45
47
|
#
|
46
|
-
# register_preprocessor 'text/css'
|
47
|
-
# data.gsub(...)
|
48
|
+
# register_preprocessor 'text/css' do |input|
|
49
|
+
# input[:data].gsub(...)
|
48
50
|
# end
|
49
51
|
#
|
50
52
|
def register_preprocessor(*args, &block)
|
51
53
|
register_config_processor(:preprocessors, *args, &block)
|
54
|
+
compute_transformers!(self.config[:registered_transformers])
|
52
55
|
end
|
53
56
|
alias_method :register_processor, :register_preprocessor
|
54
57
|
|
@@ -58,12 +61,13 @@ module Sprockets
|
|
58
61
|
#
|
59
62
|
# A block can be passed for to create a shorthand processor.
|
60
63
|
#
|
61
|
-
# register_postprocessor 'application/javascript'
|
62
|
-
# data.gsub(...)
|
64
|
+
# register_postprocessor 'application/javascript' do |input|
|
65
|
+
# input[:data].gsub(...)
|
63
66
|
# end
|
64
67
|
#
|
65
68
|
def register_postprocessor(*args, &block)
|
66
69
|
register_config_processor(:postprocessors, *args, &block)
|
70
|
+
compute_transformers!(self.config[:registered_transformers])
|
67
71
|
end
|
68
72
|
|
69
73
|
# Remove Preprocessor `klass` for `mime_type`.
|
@@ -72,6 +76,7 @@ module Sprockets
|
|
72
76
|
#
|
73
77
|
def unregister_preprocessor(*args)
|
74
78
|
unregister_config_processor(:preprocessors, *args)
|
79
|
+
compute_transformers!(self.config[:registered_transformers])
|
75
80
|
end
|
76
81
|
alias_method :unregister_processor, :unregister_preprocessor
|
77
82
|
|
@@ -81,6 +86,7 @@ module Sprockets
|
|
81
86
|
#
|
82
87
|
def unregister_postprocessor(*args)
|
83
88
|
unregister_config_processor(:postprocessors, *args)
|
89
|
+
compute_transformers!(self.config[:registered_transformers])
|
84
90
|
end
|
85
91
|
|
86
92
|
# Bundle Processors are ran on concatenated assets rather than
|
@@ -95,8 +101,8 @@ module Sprockets
|
|
95
101
|
#
|
96
102
|
# A block can be passed for to create a shorthand processor.
|
97
103
|
#
|
98
|
-
# register_bundle_processor 'application/javascript'
|
99
|
-
# data.gsub(...)
|
104
|
+
# register_bundle_processor 'application/javascript' do |input|
|
105
|
+
# input[:data].gsub(...)
|
100
106
|
# end
|
101
107
|
#
|
102
108
|
def register_bundle_processor(*args, &block)
|
@@ -154,46 +160,44 @@ module Sprockets
|
|
154
160
|
protected
|
155
161
|
def resolve_processors_cache_key_uri(uri)
|
156
162
|
params = parse_uri_query_params(uri[11..-1])
|
157
|
-
|
158
|
-
processors = processors_for(params[:type], params[:file_type], params[:engine_extnames], params[:pipeline])
|
163
|
+
processors = processors_for(params[:type], params[:file_type], params[:pipeline])
|
159
164
|
processors_cache_keys(processors)
|
160
165
|
end
|
161
166
|
|
162
|
-
def build_processors_uri(type, file_type,
|
163
|
-
engines = engine_extnames.join(',') if engine_extnames.any?
|
167
|
+
def build_processors_uri(type, file_type, pipeline)
|
164
168
|
query = encode_uri_query_params(
|
165
169
|
type: type,
|
166
170
|
file_type: file_type,
|
167
|
-
engines: engines,
|
168
171
|
pipeline: pipeline
|
169
172
|
)
|
170
173
|
"processors:#{query}"
|
171
174
|
end
|
172
175
|
|
173
|
-
def processors_for(type, file_type,
|
176
|
+
def processors_for(type, file_type, pipeline)
|
174
177
|
pipeline ||= :default
|
175
|
-
config[:pipelines][pipeline.to_sym]
|
178
|
+
if fn = config[:pipelines][pipeline.to_sym]
|
179
|
+
fn.call(self, type, file_type)
|
180
|
+
else
|
181
|
+
raise Error, "no pipeline: #{pipeline}"
|
182
|
+
end
|
176
183
|
end
|
177
184
|
|
178
|
-
def default_processors_for(type, file_type
|
185
|
+
def default_processors_for(type, file_type)
|
179
186
|
bundled_processors = config[:bundle_processors][type]
|
180
187
|
if bundled_processors.any?
|
181
188
|
bundled_processors
|
182
189
|
else
|
183
|
-
self_processors_for(type, file_type
|
190
|
+
self_processors_for(type, file_type)
|
184
191
|
end
|
185
192
|
end
|
186
193
|
|
187
|
-
def self_processors_for(type, file_type
|
194
|
+
def self_processors_for(type, file_type)
|
188
195
|
processors = []
|
189
196
|
|
190
197
|
processors.concat config[:postprocessors][type]
|
191
|
-
|
192
198
|
if type != file_type && processor = config[:transformers][file_type][type]
|
193
199
|
processors << processor
|
194
200
|
end
|
195
|
-
|
196
|
-
processors.concat engine_extnames.map { |ext| engines[ext] }
|
197
201
|
processors.concat config[:preprocessors][file_type]
|
198
202
|
|
199
203
|
if processors.any? || mime_type_charset_detecter(type)
|
@@ -204,55 +208,20 @@ module Sprockets
|
|
204
208
|
end
|
205
209
|
|
206
210
|
private
|
207
|
-
def register_config_processor(type, mime_type,
|
208
|
-
|
209
|
-
processor = wrap_processor(klass, proc)
|
211
|
+
def register_config_processor(type, mime_type, processor = nil, &block)
|
212
|
+
processor ||= block
|
210
213
|
|
211
214
|
self.config = hash_reassoc(config, type, mime_type) do |processors|
|
212
215
|
processors.unshift(processor)
|
213
216
|
processors
|
214
217
|
end
|
215
|
-
|
216
|
-
compute_transformers!
|
217
218
|
end
|
218
219
|
|
219
|
-
def unregister_config_processor(type, mime_type,
|
220
|
-
if klass.is_a?(String) || klass.is_a?(Symbol)
|
221
|
-
klass = config[type][mime_type].detect do |cls|
|
222
|
-
cls.respond_to?(:name) && cls.name == "Sprockets::LegacyProcProcessor (#{klass})"
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
220
|
+
def unregister_config_processor(type, mime_type, proccessor)
|
226
221
|
self.config = hash_reassoc(config, type, mime_type) do |processors|
|
227
|
-
processors.delete(
|
222
|
+
processors.delete(proccessor)
|
228
223
|
processors
|
229
224
|
end
|
230
|
-
|
231
|
-
compute_transformers!
|
232
|
-
end
|
233
|
-
|
234
|
-
def deprecate_legacy_processor_interface(interface)
|
235
|
-
msg = "You are using a deprecated processor interface #{ interface.inspect }.\n" +
|
236
|
-
"Please update your processor interface:\n" +
|
237
|
-
"https://github.com/rails/sprockets/blob/master/guides/extending_sprockets.md#supporting-all-versions-of-sprockets-in-processors\n"
|
238
|
-
|
239
|
-
Deprecation.new([caller[3]]).warn msg
|
240
|
-
end
|
241
|
-
|
242
|
-
def wrap_processor(klass, proc)
|
243
|
-
if !proc
|
244
|
-
if klass.respond_to?(:call)
|
245
|
-
klass
|
246
|
-
else
|
247
|
-
deprecate_legacy_processor_interface(klass)
|
248
|
-
LegacyTiltProcessor.new(klass)
|
249
|
-
end
|
250
|
-
elsif proc.respond_to?(:arity) && proc.arity == 2
|
251
|
-
deprecate_legacy_processor_interface(proc)
|
252
|
-
LegacyProcProcessor.new(klass.to_s, proc)
|
253
|
-
else
|
254
|
-
proc
|
255
|
-
end
|
256
225
|
end
|
257
226
|
end
|
258
227
|
end
|
@@ -16,26 +16,34 @@ module Sprockets
|
|
16
16
|
module ProcessorUtils
|
17
17
|
extend self
|
18
18
|
|
19
|
+
class CompositeProcessor < Struct.new(:processor_strategy, :param, :processors) # :nodoc:
|
20
|
+
SINGULAR = lambda { |param, input| ProcessorUtils.call_processor param, input }
|
21
|
+
PLURAL = lambda { |param, input| ProcessorUtils.call_processors param, input }
|
22
|
+
|
23
|
+
def self.create(processors)
|
24
|
+
if processors.length == 1
|
25
|
+
new SINGULAR, processors.first, processors
|
26
|
+
else
|
27
|
+
new PLURAL, processors, processors
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def call(input)
|
32
|
+
processor_strategy.call param, input
|
33
|
+
end
|
34
|
+
|
35
|
+
def cache_key
|
36
|
+
ProcessorUtils.processors_cache_keys(processors)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
19
40
|
# Public: Compose processors in right to left order.
|
20
41
|
#
|
21
42
|
# processors - Array of processors callables
|
22
43
|
#
|
23
44
|
# Returns a composed Proc.
|
24
45
|
def compose_processors(*processors)
|
25
|
-
|
26
|
-
|
27
|
-
if processors.length == 1
|
28
|
-
obj = method(:call_processor).to_proc.curry[processors.first]
|
29
|
-
else
|
30
|
-
obj = method(:call_processors).to_proc.curry[processors]
|
31
|
-
end
|
32
|
-
|
33
|
-
metaclass = (class << obj; self; end)
|
34
|
-
metaclass.send(:define_method, :cache_key) do
|
35
|
-
context.processors_cache_keys(processors)
|
36
|
-
end
|
37
|
-
|
38
|
-
obj
|
46
|
+
CompositeProcessor.create processors
|
39
47
|
end
|
40
48
|
|
41
49
|
# Public: Invoke list of processors in right to left order.
|
@@ -107,10 +115,12 @@ module Sprockets
|
|
107
115
|
VALID_METADATA_VALUE_TYPES = Set.new([
|
108
116
|
String,
|
109
117
|
Symbol,
|
118
|
+
Fixnum,
|
119
|
+
Bignum,
|
110
120
|
TrueClass,
|
111
121
|
FalseClass,
|
112
122
|
NilClass
|
113
|
-
]
|
123
|
+
]).freeze
|
114
124
|
|
115
125
|
# Internal: Set of all nested compound metadata types that can nest values.
|
116
126
|
VALID_METADATA_COMPOUND_TYPES = Set.new([
|
@@ -119,17 +129,6 @@ module Sprockets
|
|
119
129
|
Set
|
120
130
|
]).freeze
|
121
131
|
|
122
|
-
# Internal: Hash of all "simple" value types allowed to be returned in
|
123
|
-
# processor metadata.
|
124
|
-
VALID_METADATA_VALUE_TYPES_HASH = VALID_METADATA_VALUE_TYPES.each_with_object({}) do |type, hash|
|
125
|
-
hash[type] = true
|
126
|
-
end.freeze
|
127
|
-
|
128
|
-
# Internal: Hash of all nested compound metadata types that can nest values.
|
129
|
-
VALID_METADATA_COMPOUND_TYPES_HASH = VALID_METADATA_COMPOUND_TYPES.each_with_object({}) do |type, hash|
|
130
|
-
hash[type] = true
|
131
|
-
end.freeze
|
132
|
-
|
133
132
|
# Internal: Set of all allowed metadata types.
|
134
133
|
VALID_METADATA_TYPES = (VALID_METADATA_VALUE_TYPES + VALID_METADATA_COMPOUND_TYPES).freeze
|
135
134
|
|
@@ -168,9 +167,9 @@ module Sprockets
|
|
168
167
|
#
|
169
168
|
# Returns true if class is in whitelist otherwise false.
|
170
169
|
def valid_processor_metadata_value?(value)
|
171
|
-
if
|
170
|
+
if VALID_METADATA_VALUE_TYPES.include?(value.class)
|
172
171
|
true
|
173
|
-
elsif
|
172
|
+
elsif VALID_METADATA_COMPOUND_TYPES.include?(value.class)
|
174
173
|
value.all? { |v| valid_processor_metadata_value?(v) }
|
175
174
|
else
|
176
175
|
false
|
data/lib/sprockets/resolve.rb
CHANGED
@@ -20,27 +20,21 @@ module Sprockets
|
|
20
20
|
# # => "file:///path/to/app/javascripts/application.coffee?type=application/javascript"
|
21
21
|
#
|
22
22
|
# The String Asset URI is returned or nil if no results are found.
|
23
|
-
def resolve(path,
|
24
|
-
|
25
|
-
paths = options[:load_paths] || config[:paths]
|
26
|
-
accept = options[:accept]
|
23
|
+
def resolve(path, load_paths: config[:paths], accept: nil, pipeline: nil, base_path: nil)
|
24
|
+
paths = load_paths
|
27
25
|
|
28
26
|
if valid_asset_uri?(path)
|
29
27
|
uri, deps = resolve_asset_uri(path)
|
30
28
|
elsif absolute_path?(path)
|
31
29
|
filename, type, deps = resolve_absolute_path(paths, path, accept)
|
32
30
|
elsif relative_path?(path)
|
33
|
-
filename, type,
|
31
|
+
filename, type, path_pipeline, deps, index_alias = resolve_relative_path(paths, path, base_path, accept)
|
34
32
|
else
|
35
|
-
filename, type,
|
33
|
+
filename, type, path_pipeline, deps, index_alias = resolve_logical_path(paths, path, accept)
|
36
34
|
end
|
37
35
|
|
38
36
|
if filename
|
39
|
-
|
40
|
-
params[:type] = type if type
|
41
|
-
params[:pipeline] = pipeline if pipeline
|
42
|
-
params[:pipeline] = options[:pipeline] if options[:pipeline]
|
43
|
-
uri = build_asset_uri(filename, params)
|
37
|
+
uri = build_asset_uri(filename, type: type, pipeline: pipeline || path_pipeline, index_alias: index_alias)
|
44
38
|
end
|
45
39
|
|
46
40
|
return uri, deps
|
@@ -48,19 +42,18 @@ module Sprockets
|
|
48
42
|
|
49
43
|
# Public: Same as resolve() but raises a FileNotFound exception instead of
|
50
44
|
# nil if no assets are found.
|
51
|
-
def resolve!(path,
|
52
|
-
uri, deps = resolve(path,
|
45
|
+
def resolve!(path, **kargs)
|
46
|
+
uri, deps = resolve(path, **kargs)
|
53
47
|
|
54
48
|
unless uri
|
55
49
|
message = "couldn't find file '#{path}'"
|
56
50
|
|
57
|
-
if relative_path?(path) &&
|
58
|
-
load_path, _ = paths_split(config[:paths],
|
51
|
+
if relative_path?(path) && kargs[:base_path]
|
52
|
+
load_path, _ = paths_split(config[:paths], kargs[:base_path])
|
59
53
|
message << " under '#{load_path}'"
|
60
54
|
end
|
61
55
|
|
62
|
-
message << " with type '#{
|
63
|
-
message << "\nChecked in these paths: \n #{ config[:paths].join("\n ") }"
|
56
|
+
message << " with type '#{kargs[:accept]}'" if kargs[:accept]
|
64
57
|
|
65
58
|
raise FileNotFound, message
|
66
59
|
end
|
@@ -69,143 +62,230 @@ module Sprockets
|
|
69
62
|
end
|
70
63
|
|
71
64
|
protected
|
65
|
+
|
66
|
+
# Internal: Finds an asset given a URI
|
67
|
+
#
|
68
|
+
# uri - String. Contains file:// scheme, absolute path to
|
69
|
+
# file.
|
70
|
+
# e.g. "file:///Users/schneems/sprockets/test/fixtures/default/gallery.js?type=application/javascript"
|
71
|
+
#
|
72
|
+
# Returns Array. Contains a String uri and Set of dependencies
|
72
73
|
def resolve_asset_uri(uri)
|
73
|
-
filename, _ = parse_asset_uri(uri)
|
74
|
-
return uri, Set.new([build_file_digest_uri(filename)])
|
74
|
+
filename, _ = URIUtils.parse_asset_uri(uri)
|
75
|
+
return uri, Set.new( [URIUtils.build_file_digest_uri(filename)] )
|
75
76
|
end
|
76
77
|
|
78
|
+
# Internal: Finds a file in a set of given paths
|
79
|
+
#
|
80
|
+
# paths - Array of Strings.
|
81
|
+
# filename - String containing absolute path to a file including extension.
|
82
|
+
# e.g. "/Users/schneems/sprockets/test/fixtures/asset/application.js"
|
83
|
+
# accept - String. A Quality value incoded set of
|
84
|
+
# mime types that we are looking for. Can be nil.
|
85
|
+
# e.g. "application/javascript" or "text/css, */*"
|
86
|
+
#
|
87
|
+
# Returns Array. Filename, type, path_pipeline, deps, index_alias
|
77
88
|
def resolve_absolute_path(paths, filename, accept)
|
78
89
|
deps = Set.new
|
79
90
|
filename = File.expand_path(filename)
|
80
91
|
|
81
92
|
# Ensure path is under load paths
|
82
|
-
return nil, nil, deps unless paths_split(paths, filename)
|
93
|
+
return nil, nil, deps unless PathUtils.paths_split(paths, filename)
|
83
94
|
|
84
|
-
_, mime_type
|
95
|
+
_, mime_type = PathUtils.match_path_extname(filename, config[:mime_exts])
|
85
96
|
type = resolve_transform_type(mime_type, accept)
|
86
97
|
return nil, nil, deps if accept && !type
|
87
98
|
|
88
99
|
return nil, nil, deps unless file?(filename)
|
89
100
|
|
90
|
-
deps << build_file_digest_uri(filename)
|
101
|
+
deps << URIUtils.build_file_digest_uri(filename)
|
91
102
|
return filename, type, deps
|
92
103
|
end
|
93
104
|
|
105
|
+
# Internal: Finds a relative file in a set of given paths
|
106
|
+
#
|
107
|
+
# paths - Array of Strings.
|
108
|
+
# path - String. A relative filename with or without extension
|
109
|
+
# e.g. "./jquery" or "../foo.js"
|
110
|
+
# dirname - String. Base path where we start looking for the given file.
|
111
|
+
# accept - String. A Quality value incoded set of
|
112
|
+
# mime types that we are looking for. Can be nil.
|
113
|
+
# e.g. "application/javascript" or "text/css, */*"
|
114
|
+
#
|
115
|
+
# Returns Array. Filename, type, path_pipeline, deps, index_alias
|
94
116
|
def resolve_relative_path(paths, path, dirname, accept)
|
95
117
|
filename = File.expand_path(path, dirname)
|
96
|
-
load_path, _ = paths_split(paths, dirname)
|
97
|
-
if load_path && logical_path = split_subpath(load_path, filename)
|
118
|
+
load_path, _ = PathUtils.paths_split(paths, dirname)
|
119
|
+
if load_path && logical_path = PathUtils.split_subpath(load_path, filename)
|
98
120
|
resolve_logical_path([load_path], logical_path, accept)
|
99
121
|
else
|
100
|
-
return nil, nil, Set.new
|
122
|
+
return nil, nil, nil, Set.new
|
101
123
|
end
|
102
124
|
end
|
103
125
|
|
126
|
+
# Internal: Finds a file in a set of given paths
|
127
|
+
#
|
128
|
+
# paths - Array of Strings.
|
129
|
+
# logical_path - String. A filename with extension
|
130
|
+
# e.g. "coffee/foo.js" or "foo.js"
|
131
|
+
# accept - String. A Quality value incoded set of
|
132
|
+
# mime types that we are looking for. Can be nil.
|
133
|
+
# e.g. "application/javascript" or "text/css, */*"
|
134
|
+
#
|
135
|
+
# Finds a file on the given paths.
|
136
|
+
#
|
137
|
+
# Returns Array. Filename, type, path_pipeline, deps, index_alias
|
104
138
|
def resolve_logical_path(paths, logical_path, accept)
|
105
|
-
|
139
|
+
extname, mime_type = PathUtils.match_path_extname(logical_path, config[:mime_exts])
|
140
|
+
logical_name = logical_path.chomp(extname)
|
141
|
+
|
142
|
+
extname, pipeline = PathUtils.match_path_extname(logical_name, config[:pipeline_exts])
|
143
|
+
logical_name = logical_name.chomp(extname)
|
144
|
+
|
106
145
|
parsed_accept = parse_accept_options(mime_type, accept)
|
107
146
|
transformed_accepts = expand_transform_accepts(parsed_accept)
|
108
|
-
|
147
|
+
|
148
|
+
filename, mime_type, deps, index_alias = resolve_under_paths(paths, logical_name, transformed_accepts)
|
109
149
|
|
110
150
|
if filename
|
111
151
|
deps << build_file_digest_uri(filename)
|
112
152
|
type = resolve_transform_type(mime_type, parsed_accept)
|
113
|
-
return filename, type, pipeline, deps
|
153
|
+
return filename, type, pipeline, deps, index_alias
|
114
154
|
else
|
115
155
|
return nil, nil, nil, deps
|
116
156
|
end
|
117
157
|
end
|
118
158
|
|
159
|
+
# Internal: Finds a file in a set of given paths
|
160
|
+
#
|
161
|
+
# paths - Array of Strings.
|
162
|
+
# logical_name - String. A filename without extension
|
163
|
+
# e.g. "application" or "coffee/foo"
|
164
|
+
# accepts - Array of array containing mime/version pairs
|
165
|
+
# e.g. [["application/javascript", 1.0]]
|
166
|
+
#
|
167
|
+
# Finds a file with the same name as `logical_name` or "index" inside
|
168
|
+
# of the `logical_name` directory that matches a valid mime-type/version from
|
169
|
+
# `accepts`.
|
170
|
+
#
|
171
|
+
# Returns Array. Filename, type, dependencies, and index_alias
|
119
172
|
def resolve_under_paths(paths, logical_name, accepts)
|
120
|
-
|
121
|
-
return nil, nil,
|
173
|
+
deps = Set.new
|
174
|
+
return nil, nil, deps if accepts.empty?
|
175
|
+
|
176
|
+
# TODO: Allow new path resolves to be registered
|
177
|
+
@resolvers ||= [
|
178
|
+
method(:resolve_main_under_path),
|
179
|
+
method(:resolve_alts_under_path),
|
180
|
+
method(:resolve_index_under_path)
|
181
|
+
]
|
182
|
+
mime_exts = config[:mime_exts]
|
122
183
|
|
123
|
-
logical_basename = File.basename(logical_name)
|
124
184
|
paths.each do |load_path|
|
125
|
-
candidates
|
126
|
-
|
127
|
-
|
128
|
-
|
185
|
+
candidates = []
|
186
|
+
@resolvers.each do |fn|
|
187
|
+
result = fn.call(load_path, logical_name, mime_exts)
|
188
|
+
candidates.concat(result[0])
|
189
|
+
deps.merge(result[1])
|
129
190
|
end
|
130
|
-
return candidate + [all_deps] if candidate
|
131
|
-
end
|
132
191
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
def parse_accept_options(mime_type, types)
|
137
|
-
accepts = []
|
138
|
-
accepts += parse_q_values(types) if types
|
139
|
-
|
140
|
-
if mime_type
|
141
|
-
if accepts.empty? || accepts.any? { |accept, _| match_mime_type?(mime_type, accept) }
|
142
|
-
accepts = [[mime_type, 1.0]]
|
143
|
-
else
|
144
|
-
return []
|
192
|
+
candidate = HTTPUtils.find_best_q_match(accepts, candidates) do |c, matcher|
|
193
|
+
match_mime_type?(c[:type] || "application/octet-stream", matcher)
|
145
194
|
end
|
195
|
+
return candidate[:filename], candidate[:type], deps, candidate[:index_alias] if candidate
|
146
196
|
end
|
147
197
|
|
148
|
-
|
149
|
-
accepts << ['*/*', 1.0]
|
150
|
-
end
|
151
|
-
|
152
|
-
accepts
|
198
|
+
return nil, nil, deps
|
153
199
|
end
|
154
200
|
|
155
|
-
|
201
|
+
# Internal: Finds candidate files on a given path
|
202
|
+
#
|
203
|
+
# load_path - String. An absolute path to a directory
|
204
|
+
# logical_name - String. A filename without extension
|
205
|
+
# e.g. "application" or "coffee/foo"
|
206
|
+
# mime_exts - Hash of file extensions and their mime types
|
207
|
+
# e.g. {".xml.builder"=>"application/xml+builder"}
|
208
|
+
#
|
209
|
+
# Finds files that match a given `logical_name` with an acceptable
|
210
|
+
# mime type that is included in `mime_exts` on the `load_path`.
|
211
|
+
#
|
212
|
+
# Returns Array. First element is an Array of hashes or empty, second is a String
|
213
|
+
def resolve_main_under_path(load_path, logical_name, mime_exts)
|
156
214
|
dirname = File.dirname(File.join(load_path, logical_name))
|
157
|
-
candidates =
|
158
|
-
|
159
|
-
|
160
|
-
result = resolve_alternates(load_path, logical_name)
|
161
|
-
result[0].each do |fn|
|
162
|
-
candidates << [fn, parse_path_extnames(fn)[1]]
|
215
|
+
candidates = self.find_matching_path_for_extensions(dirname, File.basename(logical_name), mime_exts)
|
216
|
+
candidates.map! do |c|
|
217
|
+
{ filename: c[0], type: c[1] }
|
163
218
|
end
|
164
|
-
|
219
|
+
return candidates, [ URIUtils.build_file_digest_uri(dirname) ]
|
220
|
+
end
|
221
|
+
|
165
222
|
|
223
|
+
# Internal: Finds candidate index files in a given path
|
224
|
+
#
|
225
|
+
# load_path - String. An absolute path to a directory
|
226
|
+
# logical_name - String. A filename without extension
|
227
|
+
# e.g. "application" or "coffee/foo"
|
228
|
+
# mime_exts - Hash of file extensions and their mime types
|
229
|
+
# e.g. {".xml.builder"=>"application/xml+builder"}
|
230
|
+
#
|
231
|
+
# Looking in the given `load_path` this method will find all files under the `logical_name` directory
|
232
|
+
# that are named `index` and have a matching mime type in `mime_exts`.
|
233
|
+
#
|
234
|
+
# Returns Array. First element is an Array of hashes or empty, second is a String
|
235
|
+
def resolve_index_under_path(load_path, logical_name, mime_exts)
|
166
236
|
dirname = File.join(load_path, logical_name)
|
167
|
-
|
168
|
-
|
169
|
-
candidates.
|
237
|
+
|
238
|
+
if self.directory?(dirname)
|
239
|
+
candidates = self.find_matching_path_for_extensions(dirname, "index".freeze, mime_exts)
|
240
|
+
else
|
241
|
+
candidates = []
|
170
242
|
end
|
171
243
|
|
172
|
-
|
244
|
+
candidates.map! do |c|
|
245
|
+
{ filename: c[0],
|
246
|
+
type: c[1],
|
247
|
+
index_alias: compress_from_root(c[0].sub(/\/index(\.[^\/]+)$/, '\1')) }
|
248
|
+
end
|
173
249
|
|
174
|
-
return candidates
|
250
|
+
return candidates, [ URIUtils.build_file_digest_uri(dirname) ]
|
175
251
|
end
|
176
252
|
|
177
|
-
def
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
name, type, _, _ = parse_path_extnames(entry)
|
183
|
-
if basename == name
|
184
|
-
candidates << [File.join(dirname, entry), type]
|
185
|
-
end
|
253
|
+
def resolve_alts_under_path(load_path, logical_name, mime_exts)
|
254
|
+
filenames, deps = self.resolve_alternates(load_path, logical_name)
|
255
|
+
filenames.map! do |fn|
|
256
|
+
_, mime_type = PathUtils.match_path_extname(fn, mime_exts)
|
257
|
+
{ filename: fn, type: mime_type }
|
186
258
|
end
|
187
|
-
|
259
|
+
return filenames, deps
|
188
260
|
end
|
189
261
|
|
190
|
-
|
191
|
-
return [], Set.new
|
192
|
-
end
|
193
|
-
|
194
|
-
# Internal: Returns the name, mime type and `Array` of engine extensions.
|
262
|
+
# Internal: Converts mimetype into accept Array
|
195
263
|
#
|
196
|
-
#
|
197
|
-
#
|
264
|
+
# - mime_type - String, optional. e.g. "text/html"
|
265
|
+
# - explicit_type - String, optional. e.g. "application/javascript"
|
198
266
|
#
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
267
|
+
# When called with an explicit_type and a mime_type, only a mime_type
|
268
|
+
# that matches the given explicit_type will be accepted.
|
269
|
+
#
|
270
|
+
# Returns Array of Array
|
271
|
+
#
|
272
|
+
# [["application/javascript", 1.0]]
|
273
|
+
# [["*/*", 1.0]]
|
274
|
+
# []
|
275
|
+
def parse_accept_options(mime_type, explicit_type)
|
276
|
+
if mime_type
|
277
|
+
return [[mime_type, 1.0]] if explicit_type.nil?
|
278
|
+
return [[mime_type, 1.0]] if HTTPUtils.parse_q_values(explicit_type).any? { |accept, _| HTTPUtils.match_mime_type?(mime_type, accept) }
|
279
|
+
return []
|
206
280
|
end
|
207
281
|
|
208
|
-
|
282
|
+
accepts = HTTPUtils.parse_q_values(explicit_type)
|
283
|
+
accepts << ['*/*'.freeze, 1.0] if accepts.empty?
|
284
|
+
return accepts
|
285
|
+
end
|
286
|
+
|
287
|
+
def resolve_alternates(load_path, logical_name)
|
288
|
+
return [], Set.new
|
209
289
|
end
|
210
290
|
end
|
211
291
|
end
|