giga-lite-hub 0.0.1
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.
- checksums.yaml +7 -0
- data/giga-lite-hub.gemspec +12 -0
- data/sprockets-4.2.2/CHANGELOG.md +118 -0
- data/sprockets-4.2.2/MIT-LICENSE +21 -0
- data/sprockets-4.2.2/README.md +716 -0
- data/sprockets-4.2.2/bin/sprockets +93 -0
- data/sprockets-4.2.2/lib/rake/sprocketstask.rb +157 -0
- data/sprockets-4.2.2/lib/sprockets/add_source_map_comment_to_asset_processor.rb +60 -0
- data/sprockets-4.2.2/lib/sprockets/asset.rb +212 -0
- data/sprockets-4.2.2/lib/sprockets/autoload/babel.rb +8 -0
- data/sprockets-4.2.2/lib/sprockets/autoload/closure.rb +8 -0
- data/sprockets-4.2.2/lib/sprockets/autoload/coffee_script.rb +8 -0
- data/sprockets-4.2.2/lib/sprockets/autoload/eco.rb +8 -0
- data/sprockets-4.2.2/lib/sprockets/autoload/ejs.rb +8 -0
- data/sprockets-4.2.2/lib/sprockets/autoload/jsminc.rb +8 -0
- data/sprockets-4.2.2/lib/sprockets/autoload/sass.rb +8 -0
- data/sprockets-4.2.2/lib/sprockets/autoload/sassc.rb +8 -0
- data/sprockets-4.2.2/lib/sprockets/autoload/uglifier.rb +8 -0
- data/sprockets-4.2.2/lib/sprockets/autoload/yui.rb +8 -0
- data/sprockets-4.2.2/lib/sprockets/autoload/zopfli.rb +7 -0
- data/sprockets-4.2.2/lib/sprockets/autoload.rb +16 -0
- data/sprockets-4.2.2/lib/sprockets/babel_processor.rb +66 -0
- data/sprockets-4.2.2/lib/sprockets/base.rb +147 -0
- data/sprockets-4.2.2/lib/sprockets/bower.rb +61 -0
- data/sprockets-4.2.2/lib/sprockets/bundle.rb +105 -0
- data/sprockets-4.2.2/lib/sprockets/cache/file_store.rb +208 -0
- data/sprockets-4.2.2/lib/sprockets/cache/memory_store.rb +84 -0
- data/sprockets-4.2.2/lib/sprockets/cache/null_store.rb +54 -0
- data/sprockets-4.2.2/lib/sprockets/cache.rb +271 -0
- data/sprockets-4.2.2/lib/sprockets/cached_environment.rb +64 -0
- data/sprockets-4.2.2/lib/sprockets/closure_compressor.rb +48 -0
- data/sprockets-4.2.2/lib/sprockets/coffee_script_processor.rb +39 -0
- data/sprockets-4.2.2/lib/sprockets/compressing.rb +134 -0
- data/sprockets-4.2.2/lib/sprockets/configuration.rb +79 -0
- data/sprockets-4.2.2/lib/sprockets/context.rb +305 -0
- data/sprockets-4.2.2/lib/sprockets/dependencies.rb +74 -0
- data/sprockets-4.2.2/lib/sprockets/digest_utils.rb +197 -0
- data/sprockets-4.2.2/lib/sprockets/directive_processor.rb +432 -0
- data/sprockets-4.2.2/lib/sprockets/eco_processor.rb +33 -0
- data/sprockets-4.2.2/lib/sprockets/ejs_processor.rb +32 -0
- data/sprockets-4.2.2/lib/sprockets/encoding_utils.rb +261 -0
- data/sprockets-4.2.2/lib/sprockets/environment.rb +46 -0
- data/sprockets-4.2.2/lib/sprockets/erb_processor.rb +43 -0
- data/sprockets-4.2.2/lib/sprockets/errors.rb +12 -0
- data/sprockets-4.2.2/lib/sprockets/exporters/base.rb +71 -0
- data/sprockets-4.2.2/lib/sprockets/exporters/file_exporter.rb +24 -0
- data/sprockets-4.2.2/lib/sprockets/exporters/zlib_exporter.rb +33 -0
- data/sprockets-4.2.2/lib/sprockets/exporters/zopfli_exporter.rb +14 -0
- data/sprockets-4.2.2/lib/sprockets/exporting.rb +73 -0
- data/sprockets-4.2.2/lib/sprockets/file_reader.rb +16 -0
- data/sprockets-4.2.2/lib/sprockets/http_utils.rb +135 -0
- data/sprockets-4.2.2/lib/sprockets/jsminc_compressor.rb +32 -0
- data/sprockets-4.2.2/lib/sprockets/jst_processor.rb +50 -0
- data/sprockets-4.2.2/lib/sprockets/loader.rb +347 -0
- data/sprockets-4.2.2/lib/sprockets/manifest.rb +339 -0
- data/sprockets-4.2.2/lib/sprockets/manifest_utils.rb +48 -0
- data/sprockets-4.2.2/lib/sprockets/mime.rb +96 -0
- data/sprockets-4.2.2/lib/sprockets/npm.rb +52 -0
- data/sprockets-4.2.2/lib/sprockets/path_dependency_utils.rb +77 -0
- data/sprockets-4.2.2/lib/sprockets/path_digest_utils.rb +48 -0
- data/sprockets-4.2.2/lib/sprockets/path_utils.rb +367 -0
- data/sprockets-4.2.2/lib/sprockets/paths.rb +82 -0
- data/sprockets-4.2.2/lib/sprockets/preprocessors/default_source_map.rb +49 -0
- data/sprockets-4.2.2/lib/sprockets/processing.rb +228 -0
- data/sprockets-4.2.2/lib/sprockets/processor_utils.rb +170 -0
- data/sprockets-4.2.2/lib/sprockets/resolve.rb +295 -0
- data/sprockets-4.2.2/lib/sprockets/sass_cache_store.rb +30 -0
- data/sprockets-4.2.2/lib/sprockets/sass_compressor.rb +63 -0
- data/sprockets-4.2.2/lib/sprockets/sass_functions.rb +3 -0
- data/sprockets-4.2.2/lib/sprockets/sass_importer.rb +3 -0
- data/sprockets-4.2.2/lib/sprockets/sass_processor.rb +313 -0
- data/sprockets-4.2.2/lib/sprockets/sassc_compressor.rb +56 -0
- data/sprockets-4.2.2/lib/sprockets/sassc_processor.rb +297 -0
- data/sprockets-4.2.2/lib/sprockets/server.rb +315 -0
- data/sprockets-4.2.2/lib/sprockets/source_map_processor.rb +66 -0
- data/sprockets-4.2.2/lib/sprockets/source_map_utils.rb +483 -0
- data/sprockets-4.2.2/lib/sprockets/transformers.rb +173 -0
- data/sprockets-4.2.2/lib/sprockets/uglifier_compressor.rb +66 -0
- data/sprockets-4.2.2/lib/sprockets/unloaded_asset.rb +139 -0
- data/sprockets-4.2.2/lib/sprockets/uri_tar.rb +99 -0
- data/sprockets-4.2.2/lib/sprockets/uri_utils.rb +194 -0
- data/sprockets-4.2.2/lib/sprockets/utils/gzip.rb +99 -0
- data/sprockets-4.2.2/lib/sprockets/utils.rb +210 -0
- data/sprockets-4.2.2/lib/sprockets/version.rb +4 -0
- data/sprockets-4.2.2/lib/sprockets/yui_compressor.rb +56 -0
- data/sprockets-4.2.2/lib/sprockets.rb +232 -0
- metadata +126 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'sprockets/file_reader'
|
|
3
|
+
require 'sprockets/mime'
|
|
4
|
+
require 'sprockets/processor_utils'
|
|
5
|
+
require 'sprockets/uri_utils'
|
|
6
|
+
require 'sprockets/utils'
|
|
7
|
+
|
|
8
|
+
module Sprockets
|
|
9
|
+
# `Processing` is an internal mixin whose public methods are exposed on
|
|
10
|
+
# the `Environment` and `CachedEnvironment` classes.
|
|
11
|
+
module Processing
|
|
12
|
+
include ProcessorUtils, URIUtils, Utils
|
|
13
|
+
|
|
14
|
+
def pipelines
|
|
15
|
+
config[:pipelines]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Registers a pipeline that will be called by `call_processor` method.
|
|
19
|
+
def register_pipeline(name, proc = nil, &block)
|
|
20
|
+
proc ||= block
|
|
21
|
+
|
|
22
|
+
self.config = hash_reassoc(config, :pipeline_exts) do |pipeline_exts|
|
|
23
|
+
pipeline_exts.merge(".#{name}".freeze => name.to_sym)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
self.config = hash_reassoc(config, :pipelines) do |pipelines|
|
|
27
|
+
pipelines.merge(name.to_sym => proc)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Preprocessors are ran before Postprocessors and Engine
|
|
32
|
+
# processors.
|
|
33
|
+
def preprocessors
|
|
34
|
+
config[:preprocessors]
|
|
35
|
+
end
|
|
36
|
+
alias_method :processors, :preprocessors
|
|
37
|
+
|
|
38
|
+
# Postprocessors are ran after Preprocessors and Engine processors.
|
|
39
|
+
def postprocessors
|
|
40
|
+
config[:postprocessors]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Registers a new Preprocessor `klass` for `mime_type`.
|
|
44
|
+
#
|
|
45
|
+
# register_preprocessor 'text/css', Sprockets::DirectiveProcessor
|
|
46
|
+
#
|
|
47
|
+
# A block can be passed for to create a shorthand processor.
|
|
48
|
+
#
|
|
49
|
+
# register_preprocessor 'text/css' do |input|
|
|
50
|
+
# input[:data].gsub(...)
|
|
51
|
+
# end
|
|
52
|
+
#
|
|
53
|
+
def register_preprocessor(*args, &block)
|
|
54
|
+
register_config_processor(:preprocessors, *args, &block)
|
|
55
|
+
compute_transformers!(self.config[:registered_transformers])
|
|
56
|
+
end
|
|
57
|
+
alias_method :register_processor, :register_preprocessor
|
|
58
|
+
|
|
59
|
+
# Registers a new Postprocessor `klass` for `mime_type`.
|
|
60
|
+
#
|
|
61
|
+
# register_postprocessor 'application/javascript', Sprockets::DirectiveProcessor
|
|
62
|
+
#
|
|
63
|
+
# A block can be passed for to create a shorthand processor.
|
|
64
|
+
#
|
|
65
|
+
# register_postprocessor 'application/javascript' do |input|
|
|
66
|
+
# input[:data].gsub(...)
|
|
67
|
+
# end
|
|
68
|
+
#
|
|
69
|
+
def register_postprocessor(*args, &block)
|
|
70
|
+
register_config_processor(:postprocessors, *args, &block)
|
|
71
|
+
compute_transformers!(self.config[:registered_transformers])
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Remove Preprocessor `klass` for `mime_type`.
|
|
75
|
+
#
|
|
76
|
+
# unregister_preprocessor 'text/css', Sprockets::DirectiveProcessor
|
|
77
|
+
#
|
|
78
|
+
def unregister_preprocessor(*args)
|
|
79
|
+
unregister_config_processor(:preprocessors, *args)
|
|
80
|
+
compute_transformers!(self.config[:registered_transformers])
|
|
81
|
+
end
|
|
82
|
+
alias_method :unregister_processor, :unregister_preprocessor
|
|
83
|
+
|
|
84
|
+
# Remove Postprocessor `klass` for `mime_type`.
|
|
85
|
+
#
|
|
86
|
+
# unregister_postprocessor 'text/css', Sprockets::DirectiveProcessor
|
|
87
|
+
#
|
|
88
|
+
def unregister_postprocessor(*args)
|
|
89
|
+
unregister_config_processor(:postprocessors, *args)
|
|
90
|
+
compute_transformers!(self.config[:registered_transformers])
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Bundle Processors are ran on concatenated assets rather than
|
|
94
|
+
# individual files.
|
|
95
|
+
def bundle_processors
|
|
96
|
+
config[:bundle_processors]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Registers a new Bundle Processor `klass` for `mime_type`.
|
|
100
|
+
#
|
|
101
|
+
# register_bundle_processor 'application/javascript', Sprockets::DirectiveProcessor
|
|
102
|
+
#
|
|
103
|
+
# A block can be passed for to create a shorthand processor.
|
|
104
|
+
#
|
|
105
|
+
# register_bundle_processor 'application/javascript' do |input|
|
|
106
|
+
# input[:data].gsub(...)
|
|
107
|
+
# end
|
|
108
|
+
#
|
|
109
|
+
def register_bundle_processor(*args, &block)
|
|
110
|
+
register_config_processor(:bundle_processors, *args, &block)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Remove Bundle Processor `klass` for `mime_type`.
|
|
114
|
+
#
|
|
115
|
+
# unregister_bundle_processor 'application/javascript', Sprockets::DirectiveProcessor
|
|
116
|
+
#
|
|
117
|
+
def unregister_bundle_processor(*args)
|
|
118
|
+
unregister_config_processor(:bundle_processors, *args)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Public: Register bundle metadata reducer function.
|
|
122
|
+
#
|
|
123
|
+
# Examples
|
|
124
|
+
#
|
|
125
|
+
# Sprockets.register_bundle_metadata_reducer 'application/javascript', :jshint_errors, [], :+
|
|
126
|
+
#
|
|
127
|
+
# Sprockets.register_bundle_metadata_reducer 'text/css', :selector_count, 0 { |total, count|
|
|
128
|
+
# total + count
|
|
129
|
+
# }
|
|
130
|
+
#
|
|
131
|
+
# mime_type - String MIME Type. Use '*/*' applies to all types.
|
|
132
|
+
# key - Symbol metadata key
|
|
133
|
+
# initial - Initial memo to pass to the reduce function (default: nil)
|
|
134
|
+
# block - Proc accepting the memo accumulator and current value
|
|
135
|
+
#
|
|
136
|
+
# Returns nothing.
|
|
137
|
+
def register_bundle_metadata_reducer(mime_type, key, *args, &block)
|
|
138
|
+
case args.size
|
|
139
|
+
when 0
|
|
140
|
+
reducer = block
|
|
141
|
+
when 1
|
|
142
|
+
if block_given?
|
|
143
|
+
initial = args[0]
|
|
144
|
+
reducer = block
|
|
145
|
+
else
|
|
146
|
+
initial = nil
|
|
147
|
+
reducer = args[0].to_proc
|
|
148
|
+
end
|
|
149
|
+
when 2
|
|
150
|
+
initial = args[0]
|
|
151
|
+
reducer = args[1].to_proc
|
|
152
|
+
else
|
|
153
|
+
raise ArgumentError, "wrong number of arguments (#{args.size} for 0..2)"
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
self.config = hash_reassoc(config, :bundle_reducers, mime_type) do |reducers|
|
|
157
|
+
reducers.merge(key => [initial, reducer])
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
protected
|
|
162
|
+
def resolve_processors_cache_key_uri(uri)
|
|
163
|
+
params = parse_uri_query_params(uri[11..-1])
|
|
164
|
+
processors = processors_for(params[:type], params[:file_type], params[:pipeline])
|
|
165
|
+
processors_cache_keys(processors)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def build_processors_uri(type, file_type, pipeline)
|
|
169
|
+
query = encode_uri_query_params(
|
|
170
|
+
type: type,
|
|
171
|
+
file_type: file_type,
|
|
172
|
+
pipeline: pipeline
|
|
173
|
+
)
|
|
174
|
+
"processors:#{query}"
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def processors_for(type, file_type, pipeline)
|
|
178
|
+
pipeline ||= :default
|
|
179
|
+
if fn = config[:pipelines][pipeline.to_sym]
|
|
180
|
+
fn.call(self, type, file_type)
|
|
181
|
+
else
|
|
182
|
+
raise Error, "no pipeline: #{pipeline}"
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def default_processors_for(type, file_type)
|
|
187
|
+
bundled_processors = config[:bundle_processors][type]
|
|
188
|
+
if bundled_processors.any?
|
|
189
|
+
bundled_processors
|
|
190
|
+
else
|
|
191
|
+
self_processors_for(type, file_type)
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def self_processors_for(type, file_type)
|
|
196
|
+
processors = []
|
|
197
|
+
|
|
198
|
+
processors.concat config[:postprocessors][type]
|
|
199
|
+
if type != file_type && processor = config[:transformers][file_type][type]
|
|
200
|
+
processors << processor
|
|
201
|
+
end
|
|
202
|
+
processors.concat config[:preprocessors][file_type]
|
|
203
|
+
|
|
204
|
+
if processors.any? || mime_type_charset_detecter(type)
|
|
205
|
+
processors << FileReader
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
processors
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
private
|
|
212
|
+
def register_config_processor(type, mime_type, processor = nil, &block)
|
|
213
|
+
processor ||= block
|
|
214
|
+
|
|
215
|
+
self.config = hash_reassoc(config, type, mime_type) do |processors|
|
|
216
|
+
processors.unshift(processor)
|
|
217
|
+
processors
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def unregister_config_processor(type, mime_type, processor)
|
|
222
|
+
self.config = hash_reassoc(config, type, mime_type) do |processors|
|
|
223
|
+
processors.delete_if { |p| p == processor || p.class == processor }
|
|
224
|
+
processors
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'set'
|
|
3
|
+
|
|
4
|
+
module Sprockets
|
|
5
|
+
# Functional utilities for dealing with Processor functions.
|
|
6
|
+
#
|
|
7
|
+
# A Processor is a general function that may modify or transform an asset as
|
|
8
|
+
# part of the pipeline. CoffeeScript to JavaScript conversion, Minification
|
|
9
|
+
# or Concatenation are all implemented as separate Processor steps.
|
|
10
|
+
#
|
|
11
|
+
# Processors maybe any object that responds to call. So procs or a class that
|
|
12
|
+
# defines a self.call method.
|
|
13
|
+
#
|
|
14
|
+
# For ergonomics, processors may return a number of shorthand values.
|
|
15
|
+
# Unfortunately, this means that processors can not compose via ordinary
|
|
16
|
+
# function composition. The composition helpers here can help.
|
|
17
|
+
module ProcessorUtils
|
|
18
|
+
extend self
|
|
19
|
+
|
|
20
|
+
class CompositeProcessor < Struct.new(:processor_strategy, :param, :processors) # :nodoc:
|
|
21
|
+
SINGULAR = lambda { |param, input| ProcessorUtils.call_processor param, input }
|
|
22
|
+
PLURAL = lambda { |param, input| ProcessorUtils.call_processors param, input }
|
|
23
|
+
|
|
24
|
+
def self.create(processors)
|
|
25
|
+
if processors.length == 1
|
|
26
|
+
new SINGULAR, processors.first, processors
|
|
27
|
+
else
|
|
28
|
+
new PLURAL, processors, processors
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def call(input)
|
|
33
|
+
processor_strategy.call param, input
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def cache_key
|
|
37
|
+
ProcessorUtils.processors_cache_keys(processors)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Public: Compose processors in right to left order.
|
|
42
|
+
#
|
|
43
|
+
# processors - Array of processors callables
|
|
44
|
+
#
|
|
45
|
+
# Returns a composed Proc.
|
|
46
|
+
def compose_processors(*processors)
|
|
47
|
+
CompositeProcessor.create processors
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Public: Invoke list of processors in right to left order.
|
|
51
|
+
#
|
|
52
|
+
# The right to left order processing mirrors standard function composition.
|
|
53
|
+
# Think about:
|
|
54
|
+
#
|
|
55
|
+
# bundle.call(uglify.call(coffee.call(input)))
|
|
56
|
+
#
|
|
57
|
+
# processors - Array of processor callables
|
|
58
|
+
# input - Hash of input data to pass to each processor
|
|
59
|
+
#
|
|
60
|
+
# Returns a Hash with :data and other processor metadata key/values.
|
|
61
|
+
def call_processors(processors, input)
|
|
62
|
+
data = input[:data] || ""
|
|
63
|
+
metadata = (input[:metadata] || {}).dup
|
|
64
|
+
|
|
65
|
+
processors.reverse_each do |processor|
|
|
66
|
+
result = call_processor(processor, input.merge(data: data, metadata: metadata))
|
|
67
|
+
data = result.delete(:data)
|
|
68
|
+
metadata.merge!(result)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
metadata.merge(data: data)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Public: Invoke processor.
|
|
75
|
+
#
|
|
76
|
+
# processor - Processor callables
|
|
77
|
+
# input - Hash of input data to pass to processor
|
|
78
|
+
#
|
|
79
|
+
# Returns a Hash with :data and other processor metadata key/values.
|
|
80
|
+
def call_processor(processor, input)
|
|
81
|
+
metadata = (input[:metadata] || {}).dup
|
|
82
|
+
metadata[:data] = input[:data]
|
|
83
|
+
|
|
84
|
+
case result = processor.call({data: "", metadata: {}}.merge(input))
|
|
85
|
+
when NilClass
|
|
86
|
+
metadata
|
|
87
|
+
when Hash
|
|
88
|
+
metadata.merge(result)
|
|
89
|
+
when String
|
|
90
|
+
metadata.merge(data: result)
|
|
91
|
+
else
|
|
92
|
+
raise TypeError, "invalid processor return type: #{result.class}"
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Internal: Get processor defined cached key.
|
|
97
|
+
#
|
|
98
|
+
# processor - Processor function
|
|
99
|
+
#
|
|
100
|
+
# Returns JSON serializable key or nil.
|
|
101
|
+
def processor_cache_key(processor)
|
|
102
|
+
processor.cache_key if processor.respond_to?(:cache_key)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Internal: Get combined cache keys for set of processors.
|
|
106
|
+
#
|
|
107
|
+
# processors - Array of processor functions
|
|
108
|
+
#
|
|
109
|
+
# Returns Array of JSON serializable keys.
|
|
110
|
+
def processors_cache_keys(processors)
|
|
111
|
+
processors.map { |processor| processor_cache_key(processor) }
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Internal: Set of all "simple" value types allowed to be returned in
|
|
115
|
+
# processor metadata.
|
|
116
|
+
VALID_METADATA_VALUE_TYPES = Set.new([
|
|
117
|
+
String,
|
|
118
|
+
Symbol,
|
|
119
|
+
TrueClass,
|
|
120
|
+
FalseClass,
|
|
121
|
+
NilClass,
|
|
122
|
+
Integer
|
|
123
|
+
]).freeze
|
|
124
|
+
|
|
125
|
+
# Internal: Set of all nested compound metadata types that can nest values.
|
|
126
|
+
VALID_METADATA_COMPOUND_TYPES = Set.new([
|
|
127
|
+
Array,
|
|
128
|
+
Hash,
|
|
129
|
+
Set
|
|
130
|
+
]).freeze
|
|
131
|
+
|
|
132
|
+
# Internal: Hash of all "simple" value types allowed to be returned in
|
|
133
|
+
# processor metadata.
|
|
134
|
+
VALID_METADATA_VALUE_TYPES_HASH = VALID_METADATA_VALUE_TYPES.each_with_object({}) do |type, hash|
|
|
135
|
+
hash[type] = true
|
|
136
|
+
end.freeze
|
|
137
|
+
|
|
138
|
+
# Internal: Hash of all nested compound metadata types that can nest values.
|
|
139
|
+
VALID_METADATA_COMPOUND_TYPES_HASH = VALID_METADATA_COMPOUND_TYPES.each_with_object({}) do |type, hash|
|
|
140
|
+
hash[type] = true
|
|
141
|
+
end.freeze
|
|
142
|
+
|
|
143
|
+
# Internal: Set of all allowed metadata types.
|
|
144
|
+
VALID_METADATA_TYPES = (VALID_METADATA_VALUE_TYPES + VALID_METADATA_COMPOUND_TYPES).freeze
|
|
145
|
+
|
|
146
|
+
# Internal: Validate returned result of calling a processor pipeline and
|
|
147
|
+
# raise a friendly user error message.
|
|
148
|
+
#
|
|
149
|
+
# result - Metadata Hash returned from call_processors
|
|
150
|
+
#
|
|
151
|
+
# Returns result or raises a TypeError.
|
|
152
|
+
def validate_processor_result!(result)
|
|
153
|
+
if !result.instance_of?(Hash)
|
|
154
|
+
raise TypeError, "processor metadata result was expected to be a Hash, but was #{result.class}"
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
if !result[:data].instance_of?(String)
|
|
158
|
+
raise TypeError, "processor :data was expected to be a String, but as #{result[:data].class}"
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
result.each do |key, value|
|
|
162
|
+
if !key.instance_of?(Symbol)
|
|
163
|
+
raise TypeError, "processor metadata[#{key.inspect}] expected to be a Symbol"
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
result
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'set'
|
|
3
|
+
require 'sprockets/http_utils'
|
|
4
|
+
require 'sprockets/path_dependency_utils'
|
|
5
|
+
require 'sprockets/uri_utils'
|
|
6
|
+
|
|
7
|
+
module Sprockets
|
|
8
|
+
module Resolve
|
|
9
|
+
include HTTPUtils, PathDependencyUtils, URIUtils
|
|
10
|
+
|
|
11
|
+
# Public: Find Asset URI for given a logical path by searching the
|
|
12
|
+
# environment's load paths.
|
|
13
|
+
#
|
|
14
|
+
# resolve("application.js")
|
|
15
|
+
# # => "file:///path/to/app/javascripts/application.js?type=application/javascript"
|
|
16
|
+
#
|
|
17
|
+
# An accept content type can be given if the logical path doesn't have a
|
|
18
|
+
# format extension.
|
|
19
|
+
#
|
|
20
|
+
# resolve("application", accept: "application/javascript")
|
|
21
|
+
# # => "file:///path/to/app/javascripts/application.coffee?type=application/javascript"
|
|
22
|
+
#
|
|
23
|
+
# The String Asset URI is returned or nil if no results are found.
|
|
24
|
+
def resolve(path, load_paths: config[:paths], accept: nil, pipeline: nil, base_path: nil)
|
|
25
|
+
paths = load_paths
|
|
26
|
+
|
|
27
|
+
if valid_asset_uri?(path)
|
|
28
|
+
uri, deps = resolve_asset_uri(path)
|
|
29
|
+
elsif absolute_path?(path)
|
|
30
|
+
filename, type, deps = resolve_absolute_path(paths, path, accept)
|
|
31
|
+
elsif relative_path?(path)
|
|
32
|
+
filename, type, path_pipeline, deps, index_alias = resolve_relative_path(paths, path, base_path, accept)
|
|
33
|
+
else
|
|
34
|
+
filename, type, path_pipeline, deps, index_alias = resolve_logical_path(paths, path, accept)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
if filename
|
|
38
|
+
uri = build_asset_uri(filename, type: type, pipeline: pipeline || path_pipeline, index_alias: index_alias)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
return uri, deps
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Public: Same as resolve() but raises a FileNotFound exception instead of
|
|
45
|
+
# nil if no assets are found.
|
|
46
|
+
def resolve!(path, **kargs)
|
|
47
|
+
uri, deps = resolve(path, **kargs)
|
|
48
|
+
|
|
49
|
+
unless uri
|
|
50
|
+
message = +"couldn't find file '#{path}'"
|
|
51
|
+
|
|
52
|
+
if relative_path?(path) && kargs[:base_path]
|
|
53
|
+
load_path, _ = paths_split(config[:paths], kargs[:base_path])
|
|
54
|
+
message << " under '#{load_path}'"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
message << " with type '#{kargs[:accept]}'" if kargs[:accept]
|
|
58
|
+
|
|
59
|
+
load_paths = kargs[:load_paths] || config[:paths]
|
|
60
|
+
message << "\nChecked in these paths: \n #{ load_paths.join("\n ") }"
|
|
61
|
+
|
|
62
|
+
raise FileNotFound, message
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
return uri, deps
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
protected
|
|
69
|
+
|
|
70
|
+
# Internal: Finds an asset given a URI
|
|
71
|
+
#
|
|
72
|
+
# uri - String. Contains file:// scheme, absolute path to
|
|
73
|
+
# file.
|
|
74
|
+
# e.g. "file:///Users/schneems/sprockets/test/fixtures/default/gallery.js?type=application/javascript"
|
|
75
|
+
#
|
|
76
|
+
# Returns Array. Contains a String uri and Set of dependencies
|
|
77
|
+
def resolve_asset_uri(uri)
|
|
78
|
+
filename, _ = URIUtils.parse_asset_uri(uri)
|
|
79
|
+
return uri, Set.new( [URIUtils.build_file_digest_uri(filename)] )
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Internal: Finds a file in a set of given paths
|
|
83
|
+
#
|
|
84
|
+
# paths - Array of Strings.
|
|
85
|
+
# filename - String containing absolute path to a file including extension.
|
|
86
|
+
# e.g. "/Users/schneems/sprockets/test/fixtures/asset/application.js"
|
|
87
|
+
# accept - String. A Quality value incoded set of
|
|
88
|
+
# mime types that we are looking for. Can be nil.
|
|
89
|
+
# e.g. "application/javascript" or "text/css, */*"
|
|
90
|
+
#
|
|
91
|
+
# Returns Array. Filename, type, path_pipeline, deps, index_alias
|
|
92
|
+
def resolve_absolute_path(paths, filename, accept)
|
|
93
|
+
deps = Set.new
|
|
94
|
+
filename = File.expand_path(filename)
|
|
95
|
+
|
|
96
|
+
# Ensure path is under load paths
|
|
97
|
+
return nil, nil, deps unless PathUtils.paths_split(paths, filename)
|
|
98
|
+
|
|
99
|
+
_, mime_type = PathUtils.match_path_extname(filename, config[:mime_exts])
|
|
100
|
+
type = resolve_transform_type(mime_type, accept)
|
|
101
|
+
return nil, nil, deps if accept && !type
|
|
102
|
+
|
|
103
|
+
return nil, nil, deps unless file?(filename)
|
|
104
|
+
|
|
105
|
+
deps << URIUtils.build_file_digest_uri(filename)
|
|
106
|
+
return filename, type, deps
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Internal: Finds a relative file in a set of given paths
|
|
110
|
+
#
|
|
111
|
+
# paths - Array of Strings.
|
|
112
|
+
# path - String. A relative filename with or without extension
|
|
113
|
+
# e.g. "./jquery" or "../foo.js"
|
|
114
|
+
# dirname - String. Base path where we start looking for the given file.
|
|
115
|
+
# accept - String. A Quality value incoded set of
|
|
116
|
+
# mime types that we are looking for. Can be nil.
|
|
117
|
+
# e.g. "application/javascript" or "text/css, */*"
|
|
118
|
+
#
|
|
119
|
+
# Returns Array. Filename, type, path_pipeline, deps, index_alias
|
|
120
|
+
def resolve_relative_path(paths, path, dirname, accept)
|
|
121
|
+
filename = File.expand_path(path, dirname)
|
|
122
|
+
load_path, _ = PathUtils.paths_split(paths, dirname)
|
|
123
|
+
if load_path && logical_path = PathUtils.split_subpath(load_path, filename)
|
|
124
|
+
resolve_logical_path([load_path], logical_path, accept)
|
|
125
|
+
else
|
|
126
|
+
return nil, nil, nil, Set.new
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Internal: Finds a file in a set of given paths
|
|
131
|
+
#
|
|
132
|
+
# paths - Array of Strings.
|
|
133
|
+
# logical_path - String. A filename with extension
|
|
134
|
+
# e.g. "coffee/foo.js" or "foo.js"
|
|
135
|
+
# accept - String. A Quality value incoded set of
|
|
136
|
+
# mime types that we are looking for. Can be nil.
|
|
137
|
+
# e.g. "application/javascript" or "text/css, */*"
|
|
138
|
+
#
|
|
139
|
+
# Finds a file on the given paths.
|
|
140
|
+
#
|
|
141
|
+
# Returns Array. Filename, type, path_pipeline, deps, index_alias
|
|
142
|
+
def resolve_logical_path(paths, logical_path, accept)
|
|
143
|
+
extname, mime_type = PathUtils.match_path_extname(logical_path, config[:mime_exts])
|
|
144
|
+
logical_name = logical_path.chomp(extname)
|
|
145
|
+
|
|
146
|
+
extname, pipeline = PathUtils.match_path_extname(logical_name, config[:pipeline_exts])
|
|
147
|
+
logical_name = logical_name.chomp(extname)
|
|
148
|
+
|
|
149
|
+
parsed_accept = parse_accept_options(mime_type, accept)
|
|
150
|
+
transformed_accepts = expand_transform_accepts(parsed_accept)
|
|
151
|
+
|
|
152
|
+
filename, mime_type, deps, index_alias = resolve_under_paths(paths, logical_name, transformed_accepts)
|
|
153
|
+
|
|
154
|
+
if filename
|
|
155
|
+
deps << build_file_digest_uri(filename)
|
|
156
|
+
type = resolve_transform_type(mime_type, parsed_accept)
|
|
157
|
+
return filename, type, pipeline, deps, index_alias
|
|
158
|
+
else
|
|
159
|
+
return nil, nil, nil, deps
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Internal: Finds a file in a set of given paths
|
|
164
|
+
#
|
|
165
|
+
# paths - Array of Strings.
|
|
166
|
+
# logical_name - String. A filename without extension
|
|
167
|
+
# e.g. "application" or "coffee/foo"
|
|
168
|
+
# accepts - Array of array containing mime/version pairs
|
|
169
|
+
# e.g. [["application/javascript", 1.0]]
|
|
170
|
+
#
|
|
171
|
+
# Finds a file with the same name as `logical_name` or "index" inside
|
|
172
|
+
# of the `logical_name` directory that matches a valid mime-type/version from
|
|
173
|
+
# `accepts`.
|
|
174
|
+
#
|
|
175
|
+
# Returns Array. Filename, type, dependencies, and index_alias
|
|
176
|
+
def resolve_under_paths(paths, logical_name, accepts)
|
|
177
|
+
deps = Set.new
|
|
178
|
+
return nil, nil, deps if accepts.empty?
|
|
179
|
+
|
|
180
|
+
# TODO: Allow new path resolves to be registered
|
|
181
|
+
@resolvers ||= [
|
|
182
|
+
method(:resolve_main_under_path),
|
|
183
|
+
method(:resolve_alts_under_path),
|
|
184
|
+
method(:resolve_index_under_path)
|
|
185
|
+
]
|
|
186
|
+
mime_exts = config[:mime_exts]
|
|
187
|
+
|
|
188
|
+
paths.each do |load_path|
|
|
189
|
+
candidates = []
|
|
190
|
+
@resolvers.each do |fn|
|
|
191
|
+
result = fn.call(load_path, logical_name, mime_exts)
|
|
192
|
+
candidates.concat(result[0])
|
|
193
|
+
deps.merge(result[1])
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
candidate = HTTPUtils.find_best_q_match(accepts, candidates) do |c, matcher|
|
|
197
|
+
match_mime_type?(c[:type] || "application/octet-stream", matcher)
|
|
198
|
+
end
|
|
199
|
+
return candidate[:filename], candidate[:type], deps, candidate[:index_alias] if candidate
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
return nil, nil, deps
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Internal: Finds candidate files on a given path
|
|
206
|
+
#
|
|
207
|
+
# load_path - String. An absolute path to a directory
|
|
208
|
+
# logical_name - String. A filename without extension
|
|
209
|
+
# e.g. "application" or "coffee/foo"
|
|
210
|
+
# mime_exts - Hash of file extensions and their mime types
|
|
211
|
+
# e.g. {".xml.builder"=>"application/xml+builder"}
|
|
212
|
+
#
|
|
213
|
+
# Finds files that match a given `logical_name` with an acceptable
|
|
214
|
+
# mime type that is included in `mime_exts` on the `load_path`.
|
|
215
|
+
#
|
|
216
|
+
# Returns Array. First element is an Array of hashes or empty, second is a String
|
|
217
|
+
def resolve_main_under_path(load_path, logical_name, mime_exts)
|
|
218
|
+
dirname = File.dirname(File.join(load_path, logical_name))
|
|
219
|
+
candidates = self.find_matching_path_for_extensions(dirname, File.basename(logical_name), mime_exts)
|
|
220
|
+
candidates.map! do |c|
|
|
221
|
+
{ filename: c[0], type: c[1] }
|
|
222
|
+
end
|
|
223
|
+
return candidates, [ URIUtils.build_file_digest_uri(dirname) ]
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
# Internal: Finds candidate index files in a given path
|
|
228
|
+
#
|
|
229
|
+
# load_path - String. An absolute path to a directory
|
|
230
|
+
# logical_name - String. A filename without extension
|
|
231
|
+
# e.g. "application" or "coffee/foo"
|
|
232
|
+
# mime_exts - Hash of file extensions and their mime types
|
|
233
|
+
# e.g. {".xml.builder"=>"application/xml+builder"}
|
|
234
|
+
#
|
|
235
|
+
# Looking in the given `load_path` this method will find all files under the `logical_name` directory
|
|
236
|
+
# that are named `index` and have a matching mime type in `mime_exts`.
|
|
237
|
+
#
|
|
238
|
+
# Returns Array. First element is an Array of hashes or empty, second is a String
|
|
239
|
+
def resolve_index_under_path(load_path, logical_name, mime_exts)
|
|
240
|
+
dirname = File.join(load_path, logical_name)
|
|
241
|
+
|
|
242
|
+
if self.directory?(dirname)
|
|
243
|
+
candidates = self.find_matching_path_for_extensions(dirname, "index".freeze, mime_exts)
|
|
244
|
+
else
|
|
245
|
+
candidates = []
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
candidates.map! do |c|
|
|
249
|
+
{ filename: c[0],
|
|
250
|
+
type: c[1],
|
|
251
|
+
index_alias: compress_from_root(c[0].sub(/\/index(\.[^\/]+)$/, '\1')) }
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
return candidates, [ URIUtils.build_file_digest_uri(dirname) ]
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def resolve_alts_under_path(load_path, logical_name, mime_exts)
|
|
258
|
+
filenames, deps = self.resolve_alternates(load_path, logical_name)
|
|
259
|
+
filenames.map! do |fn|
|
|
260
|
+
_, mime_type = PathUtils.match_path_extname(fn, mime_exts)
|
|
261
|
+
{ filename: fn, type: mime_type }
|
|
262
|
+
end
|
|
263
|
+
return filenames, deps
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# Internal: Converts mimetype into accept Array
|
|
267
|
+
#
|
|
268
|
+
# - mime_type - String, optional. e.g. "text/html"
|
|
269
|
+
# - explicit_type - String, optional. e.g. "application/javascript"
|
|
270
|
+
#
|
|
271
|
+
# When called with an explicit_type and a mime_type, only a mime_type
|
|
272
|
+
# that matches the given explicit_type will be accepted.
|
|
273
|
+
#
|
|
274
|
+
# Returns Array of Array
|
|
275
|
+
#
|
|
276
|
+
# [["application/javascript", 1.0]]
|
|
277
|
+
# [["*/*", 1.0]]
|
|
278
|
+
# []
|
|
279
|
+
def parse_accept_options(mime_type, explicit_type)
|
|
280
|
+
if mime_type
|
|
281
|
+
return [[mime_type, 1.0]] if explicit_type.nil?
|
|
282
|
+
return [[mime_type, 1.0]] if HTTPUtils.parse_q_values(explicit_type).any? { |accept, _| HTTPUtils.match_mime_type?(mime_type, accept) }
|
|
283
|
+
return []
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
accepts = HTTPUtils.parse_q_values(explicit_type)
|
|
287
|
+
accepts << ['*/*'.freeze, 1.0] if accepts.empty?
|
|
288
|
+
return accepts
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def resolve_alternates(load_path, logical_name)
|
|
292
|
+
return [], Set.new
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
end
|