sprockets 2.12.5 → 3.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sprockets might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/LICENSE +2 -2
- data/README.md +61 -34
- data/lib/rake/sprocketstask.rb +5 -4
- data/lib/sprockets.rb +123 -85
- data/lib/sprockets/asset.rb +161 -200
- data/lib/sprockets/asset_uri.rb +64 -0
- data/lib/sprockets/base.rb +138 -373
- data/lib/sprockets/bower.rb +56 -0
- data/lib/sprockets/bundle.rb +32 -0
- data/lib/sprockets/cache.rb +220 -0
- data/lib/sprockets/cache/file_store.rb +145 -13
- data/lib/sprockets/cache/memory_store.rb +66 -0
- data/lib/sprockets/cache/null_store.rb +46 -0
- data/lib/sprockets/cached_environment.rb +103 -0
- data/lib/sprockets/closure_compressor.rb +30 -12
- data/lib/sprockets/coffee_script_template.rb +23 -0
- data/lib/sprockets/compressing.rb +20 -25
- data/lib/sprockets/configuration.rb +95 -0
- data/lib/sprockets/context.rb +68 -131
- data/lib/sprockets/directive_processor.rb +138 -179
- data/lib/sprockets/eco_template.rb +10 -19
- data/lib/sprockets/ejs_template.rb +10 -19
- data/lib/sprockets/encoding_utils.rb +246 -0
- data/lib/sprockets/engines.rb +40 -29
- data/lib/sprockets/environment.rb +10 -66
- data/lib/sprockets/erb_template.rb +23 -0
- data/lib/sprockets/errors.rb +5 -13
- data/lib/sprockets/http_utils.rb +97 -0
- data/lib/sprockets/jst_processor.rb +28 -15
- data/lib/sprockets/lazy_processor.rb +15 -0
- data/lib/sprockets/legacy.rb +23 -0
- data/lib/sprockets/legacy_proc_processor.rb +35 -0
- data/lib/sprockets/legacy_tilt_processor.rb +29 -0
- data/lib/sprockets/manifest.rb +128 -99
- data/lib/sprockets/mime.rb +114 -33
- data/lib/sprockets/path_utils.rb +179 -0
- data/lib/sprockets/paths.rb +13 -26
- data/lib/sprockets/processing.rb +198 -107
- data/lib/sprockets/resolve.rb +289 -0
- data/lib/sprockets/sass_compressor.rb +36 -17
- data/lib/sprockets/sass_template.rb +269 -46
- data/lib/sprockets/server.rb +113 -83
- data/lib/sprockets/transformers.rb +69 -0
- data/lib/sprockets/uglifier_compressor.rb +36 -15
- data/lib/sprockets/utils.rb +161 -44
- data/lib/sprockets/version.rb +1 -1
- data/lib/sprockets/yui_compressor.rb +37 -12
- metadata +64 -106
- data/lib/sprockets/asset_attributes.rb +0 -137
- data/lib/sprockets/bundled_asset.rb +0 -78
- data/lib/sprockets/caching.rb +0 -96
- data/lib/sprockets/charset_normalizer.rb +0 -41
- data/lib/sprockets/index.rb +0 -100
- data/lib/sprockets/processed_asset.rb +0 -152
- data/lib/sprockets/processor.rb +0 -32
- data/lib/sprockets/safety_colons.rb +0 -28
- data/lib/sprockets/sass_cache_store.rb +0 -29
- data/lib/sprockets/sass_functions.rb +0 -70
- data/lib/sprockets/sass_importer.rb +0 -30
- data/lib/sprockets/scss_template.rb +0 -13
- data/lib/sprockets/static_asset.rb +0 -60
data/lib/sprockets/context.rb
CHANGED
@@ -1,15 +1,13 @@
|
|
1
|
-
require 'base64'
|
2
|
-
require 'rack/utils'
|
3
|
-
require 'sprockets/errors'
|
4
|
-
require 'sprockets/utils'
|
5
1
|
require 'pathname'
|
2
|
+
require 'rack/utils'
|
6
3
|
require 'set'
|
4
|
+
require 'sprockets/errors'
|
7
5
|
|
8
6
|
module Sprockets
|
9
|
-
# `Context` provides helper methods to all `
|
10
|
-
# are typically accessed by ERB templates. You can mix in custom
|
11
|
-
#
|
12
|
-
#
|
7
|
+
# Deprecated: `Context` provides helper methods to all `Template` processors.
|
8
|
+
# They are typically accessed by ERB templates. You can mix in custom helpers
|
9
|
+
# by injecting them into `Environment#context_class`. Do not mix them into
|
10
|
+
# `Context` directly.
|
13
11
|
#
|
14
12
|
# environment.context_class.class_eval do
|
15
13
|
# include MyHelper
|
@@ -21,49 +19,52 @@ module Sprockets
|
|
21
19
|
# The `Context` also collects dependencies declared by
|
22
20
|
# assets. See `DirectiveProcessor` for an example of this.
|
23
21
|
class Context
|
24
|
-
attr_reader :environment, :pathname
|
25
|
-
attr_reader :_required_paths, :_stubbed_assets
|
26
|
-
attr_reader :_dependency_paths, :_dependency_assets
|
27
|
-
attr_writer :__LINE__
|
22
|
+
attr_reader :environment, :filename, :pathname
|
28
23
|
|
29
|
-
def initialize(
|
30
|
-
@environment = environment
|
31
|
-
@
|
32
|
-
@
|
33
|
-
@
|
24
|
+
def initialize(input)
|
25
|
+
@environment = input[:environment]
|
26
|
+
@metadata = input[:metadata]
|
27
|
+
@load_path = input[:load_path]
|
28
|
+
@logical_path = input[:name]
|
29
|
+
@filename = input[:filename]
|
30
|
+
@dirname = File.dirname(@filename)
|
31
|
+
@pathname = Pathname.new(@filename)
|
32
|
+
@content_type = input[:content_type]
|
34
33
|
|
35
|
-
@
|
36
|
-
@
|
37
|
-
@
|
38
|
-
@
|
34
|
+
@required = Set.new(@metadata[:required])
|
35
|
+
@stubbed = Set.new(@metadata[:stubbed])
|
36
|
+
@links = Set.new(@metadata[:links])
|
37
|
+
@dependency_paths = Set.new(@metadata[:dependency_paths])
|
38
|
+
end
|
39
|
+
|
40
|
+
def metadata
|
41
|
+
{ required: @required,
|
42
|
+
stubbed: @stubbed,
|
43
|
+
links: @links,
|
44
|
+
dependency_paths: @dependency_paths }
|
39
45
|
end
|
40
46
|
|
41
47
|
# Returns the environment path that contains the file.
|
42
48
|
#
|
43
49
|
# If `app/javascripts` and `app/stylesheets` are in your path, and
|
44
|
-
# current file is `app/javascripts/foo/bar.js`, `
|
50
|
+
# current file is `app/javascripts/foo/bar.js`, `load_path` would
|
45
51
|
# return `app/javascripts`.
|
46
|
-
|
47
|
-
|
48
|
-
end
|
52
|
+
attr_reader :load_path
|
53
|
+
alias_method :root_path, :load_path
|
49
54
|
|
50
55
|
# Returns logical path without any file extensions.
|
51
56
|
#
|
52
57
|
# 'app/javascripts/application.js'
|
53
58
|
# # => 'application'
|
54
59
|
#
|
55
|
-
|
56
|
-
@logical_path.chomp(File.extname(@logical_path))
|
57
|
-
end
|
60
|
+
attr_reader :logical_path
|
58
61
|
|
59
62
|
# Returns content type of file
|
60
63
|
#
|
61
64
|
# 'application/javascript'
|
62
65
|
# 'text/css'
|
63
66
|
#
|
64
|
-
|
65
|
-
environment.content_type_of(pathname)
|
66
|
-
end
|
67
|
+
attr_reader :content_type
|
67
68
|
|
68
69
|
# Given a logical path, `resolve` will find and return the fully
|
69
70
|
# expanded path. Relative paths will also be resolved. An optional
|
@@ -76,36 +77,21 @@ module Sprockets
|
|
76
77
|
# resolve("./bar.js")
|
77
78
|
# # => "/path/to/app/javascripts/bar.js"
|
78
79
|
#
|
79
|
-
def resolve(path, options = {}
|
80
|
-
|
81
|
-
|
80
|
+
def resolve(path, options = {})
|
81
|
+
options[:content_type] = self.content_type if options[:content_type] == :self
|
82
|
+
options[:accept] = options.delete(:content_type)
|
82
83
|
|
83
|
-
if
|
84
|
-
|
85
|
-
|
84
|
+
if environment.absolute_path?(path)
|
85
|
+
path
|
86
|
+
elsif environment.relative_path?(path)
|
87
|
+
path = File.expand_path(path, @dirname)
|
88
|
+
if logical_path = @environment.split_subpath(load_path, path)
|
89
|
+
environment.resolve_in_load_path(load_path, logical_path, options)
|
86
90
|
else
|
87
|
-
raise
|
91
|
+
raise FileOutsidePaths, "#{path} isn't under path: #{load_path}"
|
88
92
|
end
|
89
|
-
|
90
|
-
elsif content_type = options[:content_type]
|
91
|
-
content_type = self.content_type if content_type == :self
|
92
|
-
|
93
|
-
if attributes.format_extension
|
94
|
-
if content_type != attributes.content_type
|
95
|
-
raise ContentTypeMismatch, "#{path} is " +
|
96
|
-
"'#{attributes.content_type}', not '#{content_type}'"
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
resolve(path) do |candidate|
|
101
|
-
if self.content_type == environment.content_type_of(candidate)
|
102
|
-
return candidate
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
raise FileNotFound, "couldn't find file '#{path}'"
|
107
93
|
else
|
108
|
-
environment.resolve(path,
|
94
|
+
environment.resolve(path, options)
|
109
95
|
end
|
110
96
|
end
|
111
97
|
|
@@ -116,7 +102,7 @@ module Sprockets
|
|
116
102
|
# the dependency file with invalidate the cache of the
|
117
103
|
# source file.
|
118
104
|
def depend_on(path)
|
119
|
-
@
|
105
|
+
@dependency_paths << resolve(path).to_s
|
120
106
|
nil
|
121
107
|
end
|
122
108
|
|
@@ -128,8 +114,9 @@ module Sprockets
|
|
128
114
|
# file. Unlike `depend_on`, this will include recursively include
|
129
115
|
# the target asset's dependencies.
|
130
116
|
def depend_on_asset(path)
|
131
|
-
|
132
|
-
|
117
|
+
if asset = @environment.find_asset(resolve(path))
|
118
|
+
@dependency_paths.merge(asset.metadata[:dependency_paths])
|
119
|
+
end
|
133
120
|
nil
|
134
121
|
end
|
135
122
|
|
@@ -143,9 +130,8 @@ module Sprockets
|
|
143
130
|
# <%= require_asset "#{framework}.js" %>
|
144
131
|
#
|
145
132
|
def require_asset(path)
|
146
|
-
|
147
|
-
|
148
|
-
@_required_paths << pathname.to_s
|
133
|
+
filename = resolve(path, accept: @content_type)
|
134
|
+
@required << @environment.resolve_asset_uri(filename, accept: @content_type, bundle: false)
|
149
135
|
nil
|
150
136
|
end
|
151
137
|
|
@@ -153,55 +139,22 @@ module Sprockets
|
|
153
139
|
# `path` must be an asset which may or may not already be included
|
154
140
|
# in the bundle.
|
155
141
|
def stub_asset(path)
|
156
|
-
|
142
|
+
filename = resolve(path, accept: @content_type)
|
143
|
+
@stubbed << @environment.resolve_asset_uri(filename, accept: @content_type, bundle: false)
|
157
144
|
nil
|
158
145
|
end
|
159
146
|
|
160
|
-
#
|
161
|
-
#
|
162
|
-
|
163
|
-
pathname = resolve(path)
|
164
|
-
content_type = environment.content_type_of(pathname)
|
165
|
-
stat = environment.stat(path)
|
166
|
-
return false unless stat && stat.file?
|
167
|
-
self.content_type.nil? || self.content_type == content_type
|
168
|
-
end
|
169
|
-
|
170
|
-
# Reads `path` and runs processors on the file.
|
171
|
-
#
|
172
|
-
# This allows you to capture the result of an asset and include it
|
173
|
-
# directly in another.
|
147
|
+
# `link_asset` declares an external dependency on an asset without directly
|
148
|
+
# including it. The target asset is returned from this function making it
|
149
|
+
# easy to construct a link to it.
|
174
150
|
#
|
175
|
-
#
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
processors = options[:processors] || attributes.processors
|
181
|
-
|
182
|
-
if options[:data]
|
183
|
-
result = options[:data]
|
184
|
-
else
|
185
|
-
if environment.respond_to?(:default_external_encoding)
|
186
|
-
mime_type = environment.mime_types(pathname.extname)
|
187
|
-
encoding = environment.encoding_for_mime_type(mime_type)
|
188
|
-
result = Sprockets::Utils.read_unicode(pathname, encoding)
|
189
|
-
else
|
190
|
-
result = Sprockets::Utils.read_unicode(pathname)
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
processors.each do |processor|
|
195
|
-
begin
|
196
|
-
template = processor.new(pathname.to_s) { result }
|
197
|
-
result = template.render(self, {})
|
198
|
-
rescue Exception => e
|
199
|
-
annotate_exception! e
|
200
|
-
raise
|
201
|
-
end
|
151
|
+
# Returns an Asset or nil.
|
152
|
+
def link_asset(path)
|
153
|
+
if asset = @environment.find_asset(resolve(path))
|
154
|
+
@dependency_paths.merge(asset.metadata[:dependency_paths])
|
155
|
+
@links << asset.uri
|
202
156
|
end
|
203
|
-
|
204
|
-
result
|
157
|
+
asset
|
205
158
|
end
|
206
159
|
|
207
160
|
# Returns a Base64-encoded `data:` URI with the contents of the
|
@@ -216,9 +169,8 @@ module Sprockets
|
|
216
169
|
#
|
217
170
|
def asset_data_uri(path)
|
218
171
|
depend_on_asset(path)
|
219
|
-
asset
|
220
|
-
base64
|
221
|
-
"data:#{asset.content_type};base64,#{Rack::Utils.escape(base64)}"
|
172
|
+
asset = environment.find_asset(path, accept_encoding: 'base64')
|
173
|
+
"data:#{asset.content_type};base64,#{Rack::Utils.escape(asset.to_s)}"
|
222
174
|
end
|
223
175
|
|
224
176
|
# Expands logical path to full url to asset.
|
@@ -243,47 +195,32 @@ Extend your environment context with a custom method.
|
|
243
195
|
|
244
196
|
# Expand logical image asset path.
|
245
197
|
def image_path(path)
|
246
|
-
asset_path(path, :
|
198
|
+
asset_path(path, type: :image)
|
247
199
|
end
|
248
200
|
|
249
201
|
# Expand logical video asset path.
|
250
202
|
def video_path(path)
|
251
|
-
asset_path(path, :
|
203
|
+
asset_path(path, type: :video)
|
252
204
|
end
|
253
205
|
|
254
206
|
# Expand logical audio asset path.
|
255
207
|
def audio_path(path)
|
256
|
-
asset_path(path, :
|
208
|
+
asset_path(path, type: :audio)
|
257
209
|
end
|
258
210
|
|
259
211
|
# Expand logical font asset path.
|
260
212
|
def font_path(path)
|
261
|
-
asset_path(path, :
|
213
|
+
asset_path(path, type: :font)
|
262
214
|
end
|
263
215
|
|
264
216
|
# Expand logical javascript asset path.
|
265
217
|
def javascript_path(path)
|
266
|
-
asset_path(path, :
|
218
|
+
asset_path(path, type: :javascript)
|
267
219
|
end
|
268
220
|
|
269
221
|
# Expand logical stylesheet asset path.
|
270
222
|
def stylesheet_path(path)
|
271
|
-
asset_path(path, :
|
223
|
+
asset_path(path, type: :stylesheet)
|
272
224
|
end
|
273
|
-
|
274
|
-
private
|
275
|
-
# Annotates exception backtrace with the original template that
|
276
|
-
# the exception was raised in.
|
277
|
-
def annotate_exception!(exception)
|
278
|
-
location = pathname.to_s
|
279
|
-
location << ":#{@__LINE__}" if @__LINE__
|
280
|
-
|
281
|
-
exception.extend(Sprockets::EngineError)
|
282
|
-
exception.sprockets_annotation = " (in #{location})"
|
283
|
-
end
|
284
|
-
|
285
|
-
def logger
|
286
|
-
environment.logger
|
287
|
-
end
|
288
225
|
end
|
289
226
|
end
|
@@ -1,7 +1,5 @@
|
|
1
|
-
require '
|
1
|
+
require 'set'
|
2
2
|
require 'shellwords'
|
3
|
-
require 'tilt'
|
4
|
-
require 'yaml'
|
5
3
|
|
6
4
|
module Sprockets
|
7
5
|
# The `DirectiveProcessor` is responsible for parsing and evaluating
|
@@ -20,10 +18,9 @@ module Sprockets
|
|
20
18
|
# *= require "baz"
|
21
19
|
# */
|
22
20
|
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
# custom directives or invent your own directive syntax.
|
21
|
+
# This makes it possible to disable or modify the processor to do whatever
|
22
|
+
# you'd like. You could add your own custom directives or invent your own
|
23
|
+
# directive syntax.
|
27
24
|
#
|
28
25
|
# `Environment#processors` includes `DirectiveProcessor` by default.
|
29
26
|
#
|
@@ -36,7 +33,9 @@ module Sprockets
|
|
36
33
|
#
|
37
34
|
# env.register_processor('text/css', MyProcessor)
|
38
35
|
#
|
39
|
-
class DirectiveProcessor
|
36
|
+
class DirectiveProcessor
|
37
|
+
VERSION = '1'
|
38
|
+
|
40
39
|
# Directives will only be picked up if they are in the header
|
41
40
|
# of the source file. C style (/* */), JavaScript (//), and
|
42
41
|
# Ruby (#) comments are supported.
|
@@ -68,76 +67,82 @@ module Sprockets
|
|
68
67
|
^ \W* = \s* (\w+.*?) (\*\/)? $
|
69
68
|
/x
|
70
69
|
|
71
|
-
|
72
|
-
|
70
|
+
def self.call(input)
|
71
|
+
new.call(input)
|
72
|
+
end
|
73
73
|
|
74
|
-
def
|
75
|
-
@
|
74
|
+
def call(input)
|
75
|
+
@environment = input[:environment]
|
76
|
+
@uri = input[:uri]
|
77
|
+
@load_path = input[:load_path]
|
78
|
+
@filename = input[:filename]
|
79
|
+
@dirname = File.dirname(@filename)
|
80
|
+
@content_type = input[:content_type]
|
81
|
+
|
82
|
+
data = input[:data]
|
83
|
+
cache_key = ['DirectiveProcessor', VERSION, data]
|
84
|
+
result = input[:cache].fetch(cache_key) do
|
85
|
+
process_source(data)
|
86
|
+
end
|
76
87
|
|
77
|
-
|
78
|
-
@body = $' || data
|
79
|
-
# Ensure body ends in a new line
|
80
|
-
@body += "\n" if @body != "" && @body !~ /\n\Z/m
|
88
|
+
data, directives = result.values_at(:data, :directives)
|
81
89
|
|
82
|
-
@
|
83
|
-
@
|
84
|
-
|
90
|
+
@required = Set.new(input[:metadata][:required])
|
91
|
+
@stubbed = Set.new(input[:metadata][:stubbed])
|
92
|
+
@links = Set.new(input[:metadata][:links])
|
93
|
+
@dependency_paths = Set.new(input[:metadata][:dependency_paths])
|
85
94
|
|
86
|
-
|
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
|
95
|
+
process_directives(directives)
|
93
96
|
|
94
|
-
|
95
|
-
|
97
|
+
{ data: data,
|
98
|
+
required: @required,
|
99
|
+
stubbed: @stubbed,
|
100
|
+
links: @links,
|
101
|
+
dependency_paths: @dependency_paths }
|
102
|
+
end
|
96
103
|
|
97
|
-
|
104
|
+
protected
|
105
|
+
def process_source(source)
|
106
|
+
header = source[HEADER_PATTERN, 0] || ""
|
107
|
+
body = $' || source
|
98
108
|
|
99
|
-
|
100
|
-
process_source
|
109
|
+
header, directives = extract_directives(header)
|
101
110
|
|
102
|
-
|
103
|
-
|
111
|
+
data = ""
|
112
|
+
data.force_encoding(body.encoding)
|
113
|
+
data << header << "\n" unless header.empty?
|
114
|
+
data << body
|
115
|
+
# Ensure body ends in a new line
|
116
|
+
data << "\n" if data.length > 0 && data[-1] != "\n"
|
104
117
|
|
105
|
-
|
106
|
-
|
107
|
-
lineno = 0
|
108
|
-
@processed_header ||= header.lines.map { |line|
|
109
|
-
lineno += 1
|
110
|
-
# Replace directive line with a clean break
|
111
|
-
directives.assoc(lineno) ? "\n" : line
|
112
|
-
}.join.chomp
|
113
|
-
end
|
118
|
+
{ data: data, directives: directives }
|
119
|
+
end
|
114
120
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
121
|
+
# Returns an Array of directive structures. Each structure
|
122
|
+
# is an Array with the line number as the first element, the
|
123
|
+
# directive name as the second element, followed by any
|
124
|
+
# arguments.
|
125
|
+
#
|
126
|
+
# [[1, "require", "foo"], [2, "require", "bar"]]
|
127
|
+
#
|
128
|
+
def extract_directives(header)
|
129
|
+
processed_header = ""
|
130
|
+
directives = []
|
119
131
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
@directives ||= header.lines.each_with_index.map { |line, index|
|
129
|
-
if directive = line[DIRECTIVE_PATTERN, 1]
|
130
|
-
name, *args = Shellwords.shellwords(directive)
|
131
|
-
if respond_to?("process_#{name}_directive", true)
|
132
|
-
[index + 1, name, *args]
|
132
|
+
header.lines.each_with_index do |line, index|
|
133
|
+
if directive = line[DIRECTIVE_PATTERN, 1]
|
134
|
+
name, *args = Shellwords.shellwords(directive)
|
135
|
+
if respond_to?("process_#{name}_directive", true)
|
136
|
+
directives << [index + 1, name, *args]
|
137
|
+
# Replace directive line with a clean break
|
138
|
+
line = "\n"
|
139
|
+
end
|
133
140
|
end
|
141
|
+
processed_header << line
|
134
142
|
end
|
135
|
-
}.compact
|
136
|
-
end
|
137
143
|
|
138
|
-
|
139
|
-
|
140
|
-
attr_reader :context
|
144
|
+
return processed_header.chomp, directives
|
145
|
+
end
|
141
146
|
|
142
147
|
# Gathers comment directives in the source and processes them.
|
143
148
|
# Any directive method matching `process_*_directive` will
|
@@ -150,7 +155,7 @@ module Sprockets
|
|
150
155
|
#
|
151
156
|
# class DirectiveProcessor < Sprockets::DirectiveProcessor
|
152
157
|
# def process_require_glob_directive
|
153
|
-
# Dir["#{
|
158
|
+
# Dir["#{dirname}/#{glob}"].sort.each do |filename|
|
154
159
|
# require(filename)
|
155
160
|
# end
|
156
161
|
# end
|
@@ -161,29 +166,14 @@ module Sprockets
|
|
161
166
|
# env.unregister_processor('text/css', Sprockets::DirectiveProcessor)
|
162
167
|
# env.register_processor('text/css', DirectiveProcessor)
|
163
168
|
#
|
164
|
-
def process_directives
|
169
|
+
def process_directives(directives)
|
165
170
|
directives.each do |line_number, name, *args|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
def process_source
|
173
|
-
unless @has_written_body || processed_header.empty?
|
174
|
-
@result << processed_header << "\n"
|
175
|
-
end
|
176
|
-
|
177
|
-
included_pathnames.each do |pathname|
|
178
|
-
@result << context.evaluate(pathname)
|
179
|
-
end
|
180
|
-
|
181
|
-
unless @has_written_body
|
182
|
-
@result << body
|
183
|
-
end
|
184
|
-
|
185
|
-
if compat? && constants.any?
|
186
|
-
@result.gsub!(/<%=(.*?)%>/) { constants[$1.strip] }
|
171
|
+
begin
|
172
|
+
send("process_#{name}_directive", *args)
|
173
|
+
rescue Exception => e
|
174
|
+
e.set_backtrace(["#{@filename}:#{line_number}"] + e.backtrace)
|
175
|
+
raise e
|
176
|
+
end
|
187
177
|
end
|
188
178
|
end
|
189
179
|
|
@@ -206,22 +196,13 @@ module Sprockets
|
|
206
196
|
# //= require "./bar"
|
207
197
|
#
|
208
198
|
def process_require_directive(path)
|
209
|
-
|
210
|
-
if path =~ /<([^>]+)>/
|
211
|
-
path = $1
|
212
|
-
else
|
213
|
-
path = "./#{path}" unless relative?(path)
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
context.require_asset(path)
|
199
|
+
@required << resolve_uri(path)
|
218
200
|
end
|
219
201
|
|
220
|
-
# `require_self` causes the body of the current file to be
|
221
|
-
#
|
222
|
-
#
|
223
|
-
#
|
224
|
-
# before other dependencies are loaded.
|
202
|
+
# `require_self` causes the body of the current file to be inserted
|
203
|
+
# before any subsequent `require` directives. Useful in CSS files, where
|
204
|
+
# it's common for the index file to contain global styles that need to
|
205
|
+
# be defined before other dependencies are loaded.
|
225
206
|
#
|
226
207
|
# /*= require "reset"
|
227
208
|
# *= require_self
|
@@ -229,26 +210,10 @@ module Sprockets
|
|
229
210
|
# */
|
230
211
|
#
|
231
212
|
def process_require_self_directive
|
232
|
-
if @
|
213
|
+
if @required.include?(@uri)
|
233
214
|
raise ArgumentError, "require_self can only be called once per source file"
|
234
215
|
end
|
235
|
-
|
236
|
-
context.require_asset(pathname)
|
237
|
-
process_source
|
238
|
-
included_pathnames.clear
|
239
|
-
@has_written_body = true
|
240
|
-
end
|
241
|
-
|
242
|
-
# The `include` directive works similar to `require` but
|
243
|
-
# inserts the contents of the dependency even if it already
|
244
|
-
# has been required.
|
245
|
-
#
|
246
|
-
# //= include "header"
|
247
|
-
#
|
248
|
-
def process_include_directive(path)
|
249
|
-
pathname = context.resolve(path)
|
250
|
-
context.depend_on_asset(pathname)
|
251
|
-
included_pathnames << pathname
|
216
|
+
@required << @uri
|
252
217
|
end
|
253
218
|
|
254
219
|
# `require_directory` requires all the files inside a single
|
@@ -258,21 +223,20 @@ module Sprockets
|
|
258
223
|
# //= require_directory "./javascripts"
|
259
224
|
#
|
260
225
|
def process_require_directory_directive(path = ".")
|
261
|
-
if
|
262
|
-
root =
|
226
|
+
if @environment.relative_path?(path)
|
227
|
+
root = expand_relative_path(path)
|
263
228
|
|
264
|
-
unless (stats = stat(root)) && stats.directory?
|
229
|
+
unless (stats = @environment.stat(root)) && stats.directory?
|
265
230
|
raise ArgumentError, "require_directory argument must be a directory"
|
266
231
|
end
|
267
232
|
|
268
|
-
|
233
|
+
@dependency_paths << root
|
269
234
|
|
270
|
-
|
271
|
-
|
272
|
-
if pathname.to_s == self.file
|
235
|
+
@environment.stat_directory(root).each do |subpath, stat|
|
236
|
+
if subpath == @filename
|
273
237
|
next
|
274
|
-
elsif
|
275
|
-
|
238
|
+
elsif @environment.resolve_path_transform_type(subpath, @content_type)
|
239
|
+
@required << @environment.resolve_asset_uri(subpath, accept: @content_type, bundle: false)
|
276
240
|
end
|
277
241
|
end
|
278
242
|
else
|
@@ -287,24 +251,28 @@ module Sprockets
|
|
287
251
|
# //= require_tree "./public"
|
288
252
|
#
|
289
253
|
def process_require_tree_directive(path = ".")
|
290
|
-
if
|
291
|
-
root =
|
254
|
+
if @environment.relative_path?(path)
|
255
|
+
root = expand_relative_path(path)
|
292
256
|
|
293
|
-
unless (stats = stat(root)) && stats.directory?
|
257
|
+
unless (stats = @environment.stat(root)) && stats.directory?
|
294
258
|
raise ArgumentError, "require_tree argument must be a directory"
|
295
259
|
end
|
296
260
|
|
297
|
-
|
261
|
+
@dependency_paths << root
|
298
262
|
|
299
|
-
|
300
|
-
|
263
|
+
required = []
|
264
|
+
@environment.stat_tree(root).each do |subpath, stat|
|
265
|
+
if subpath == @filename
|
301
266
|
next
|
302
|
-
elsif stat
|
303
|
-
|
304
|
-
elsif
|
305
|
-
|
267
|
+
elsif stat.directory?
|
268
|
+
@dependency_paths << subpath
|
269
|
+
elsif @environment.resolve_path_transform_type(subpath, @content_type)
|
270
|
+
required << subpath
|
306
271
|
end
|
307
272
|
end
|
273
|
+
required.sort_by(&:to_s).each do |subpath|
|
274
|
+
@required << @environment.resolve_asset_uri(subpath, accept: @content_type, bundle: false)
|
275
|
+
end
|
308
276
|
else
|
309
277
|
# The path must be relative and start with a `./`.
|
310
278
|
raise ArgumentError, "require_tree argument must be a relative path"
|
@@ -324,7 +292,7 @@ module Sprockets
|
|
324
292
|
# //= depend_on "foo.png"
|
325
293
|
#
|
326
294
|
def process_depend_on_directive(path)
|
327
|
-
|
295
|
+
@dependency_paths << resolve(path, accept: "#{@content_type}, */*")
|
328
296
|
end
|
329
297
|
|
330
298
|
# Allows you to state a dependency on an asset without including
|
@@ -339,7 +307,9 @@ module Sprockets
|
|
339
307
|
# //= depend_on_asset "bar.js"
|
340
308
|
#
|
341
309
|
def process_depend_on_asset_directive(path)
|
342
|
-
|
310
|
+
if asset = @environment.find_asset(resolve(path, accept: "#{@content_type}, */*"))
|
311
|
+
@dependency_paths.merge(asset.metadata[:dependency_paths])
|
312
|
+
end
|
343
313
|
end
|
344
314
|
|
345
315
|
# Allows dependency to be excluded from the asset bundle.
|
@@ -351,58 +321,47 @@ module Sprockets
|
|
351
321
|
# //= stub "jquery"
|
352
322
|
#
|
353
323
|
def process_stub_directive(path)
|
354
|
-
|
324
|
+
@stubbed << resolve_uri(path)
|
355
325
|
end
|
356
326
|
|
357
|
-
#
|
327
|
+
# Declares a linked dependency on the target asset.
|
358
328
|
#
|
359
|
-
#
|
360
|
-
#
|
329
|
+
# The `path` must be a valid asset and should not already be part of the
|
330
|
+
# bundle. Any linked assets will automatically be compiled along with the
|
331
|
+
# current.
|
361
332
|
#
|
362
|
-
#
|
333
|
+
# /*= link "logo.png" */
|
363
334
|
#
|
364
|
-
def
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
# Checks if Sprockets 1.x compat mode enabled
|
369
|
-
def compat?
|
370
|
-
@compat
|
371
|
-
end
|
372
|
-
|
373
|
-
# Sprockets 1.x allowed for constant interpolation if a
|
374
|
-
# constants.yml was present. This is only available if
|
375
|
-
# compat mode is on.
|
376
|
-
def constants
|
377
|
-
if compat?
|
378
|
-
pathname = Pathname.new(context.root_path).join("constants.yml")
|
379
|
-
stat(pathname) ? YAML.load_file(pathname) : {}
|
380
|
-
else
|
381
|
-
{}
|
335
|
+
def process_link_directive(path)
|
336
|
+
if asset = @environment.find_asset(resolve(path, accept: "#{@content_type}, */*"))
|
337
|
+
@dependency_paths.merge(asset.metadata[:dependency_paths])
|
338
|
+
@links << asset.uri
|
382
339
|
end
|
383
340
|
end
|
384
341
|
|
385
|
-
# `provide` is stubbed out for Sprockets 1.x compat.
|
386
|
-
# Mutating the path when an asset is being built is
|
387
|
-
# not permitted.
|
388
|
-
def process_provide_directive(path)
|
389
|
-
end
|
390
|
-
|
391
342
|
private
|
392
|
-
def
|
393
|
-
path
|
343
|
+
def expand_relative_path(path)
|
344
|
+
File.expand_path(path, @dirname)
|
394
345
|
end
|
395
346
|
|
396
|
-
def
|
397
|
-
|
347
|
+
def resolve_uri(path)
|
348
|
+
filename = resolve(path, accept: @content_type)
|
349
|
+
@environment.resolve_asset_uri(filename, accept: @content_type, bundle: false)
|
398
350
|
end
|
399
351
|
|
400
|
-
def
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
352
|
+
def resolve(path, options = {})
|
353
|
+
if @environment.absolute_path?(path)
|
354
|
+
raise FileOutsidePaths, "can't require absolute file: #{path}"
|
355
|
+
elsif @environment.relative_path?(path)
|
356
|
+
path = expand_relative_path(path)
|
357
|
+
if logical_path = @environment.split_subpath(@load_path, path)
|
358
|
+
@environment.resolve_in_load_path(@load_path, logical_path, options)
|
359
|
+
else
|
360
|
+
raise FileOutsidePaths, "#{path} isn't under path: #{@load_path}"
|
361
|
+
end
|
362
|
+
else
|
363
|
+
@environment.resolve(path, options)
|
364
|
+
end
|
406
365
|
end
|
407
366
|
end
|
408
367
|
end
|