sprockets 2.12.5 → 3.7.2
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 +4 -4
- data/CHANGELOG.md +296 -0
- data/LICENSE +2 -2
- data/README.md +235 -262
- data/bin/sprockets +1 -0
- data/lib/rake/sprocketstask.rb +5 -4
- data/lib/sprockets/asset.rb +143 -212
- data/lib/sprockets/autoload/closure.rb +7 -0
- data/lib/sprockets/autoload/coffee_script.rb +7 -0
- data/lib/sprockets/autoload/eco.rb +7 -0
- data/lib/sprockets/autoload/ejs.rb +7 -0
- data/lib/sprockets/autoload/sass.rb +7 -0
- data/lib/sprockets/autoload/uglifier.rb +7 -0
- data/lib/sprockets/autoload/yui.rb +7 -0
- data/lib/sprockets/autoload.rb +11 -0
- data/lib/sprockets/base.rb +56 -393
- data/lib/sprockets/bower.rb +58 -0
- data/lib/sprockets/bundle.rb +69 -0
- data/lib/sprockets/cache/file_store.rb +168 -14
- data/lib/sprockets/cache/memory_store.rb +66 -0
- data/lib/sprockets/cache/null_store.rb +46 -0
- data/lib/sprockets/cache.rb +236 -0
- data/lib/sprockets/cached_environment.rb +69 -0
- data/lib/sprockets/closure_compressor.rb +35 -10
- data/lib/sprockets/coffee_script_processor.rb +25 -0
- data/lib/sprockets/coffee_script_template.rb +17 -0
- data/lib/sprockets/compressing.rb +44 -23
- data/lib/sprockets/configuration.rb +83 -0
- data/lib/sprockets/context.rb +86 -144
- data/lib/sprockets/dependencies.rb +73 -0
- data/lib/sprockets/deprecation.rb +90 -0
- data/lib/sprockets/digest_utils.rb +180 -0
- data/lib/sprockets/directive_processor.rb +207 -211
- data/lib/sprockets/eco_processor.rb +32 -0
- data/lib/sprockets/eco_template.rb +9 -30
- data/lib/sprockets/ejs_processor.rb +31 -0
- data/lib/sprockets/ejs_template.rb +9 -29
- data/lib/sprockets/encoding_utils.rb +261 -0
- data/lib/sprockets/engines.rb +53 -35
- data/lib/sprockets/environment.rb +17 -64
- data/lib/sprockets/erb_processor.rb +30 -0
- data/lib/sprockets/erb_template.rb +11 -0
- data/lib/sprockets/errors.rb +4 -13
- data/lib/sprockets/file_reader.rb +15 -0
- data/lib/sprockets/http_utils.rb +117 -0
- data/lib/sprockets/jst_processor.rb +35 -15
- data/lib/sprockets/legacy.rb +330 -0
- data/lib/sprockets/legacy_proc_processor.rb +35 -0
- data/lib/sprockets/legacy_tilt_processor.rb +29 -0
- data/lib/sprockets/loader.rb +325 -0
- data/lib/sprockets/manifest.rb +202 -127
- data/lib/sprockets/manifest_utils.rb +45 -0
- data/lib/sprockets/mime.rb +112 -31
- data/lib/sprockets/path_dependency_utils.rb +85 -0
- data/lib/sprockets/path_digest_utils.rb +47 -0
- data/lib/sprockets/path_utils.rb +287 -0
- data/lib/sprockets/paths.rb +42 -19
- data/lib/sprockets/processing.rb +178 -126
- data/lib/sprockets/processor_utils.rb +180 -0
- data/lib/sprockets/resolve.rb +211 -0
- data/lib/sprockets/sass_cache_store.rb +22 -17
- data/lib/sprockets/sass_compressor.rb +39 -15
- data/lib/sprockets/sass_functions.rb +2 -70
- data/lib/sprockets/sass_importer.rb +2 -30
- data/lib/sprockets/sass_processor.rb +292 -0
- data/lib/sprockets/sass_template.rb +12 -59
- data/lib/sprockets/server.rb +129 -84
- data/lib/sprockets/transformers.rb +145 -0
- data/lib/sprockets/uglifier_compressor.rb +39 -12
- data/lib/sprockets/unloaded_asset.rb +137 -0
- data/lib/sprockets/uri_tar.rb +98 -0
- data/lib/sprockets/uri_utils.rb +188 -0
- data/lib/sprockets/utils/gzip.rb +67 -0
- data/lib/sprockets/utils.rb +210 -44
- data/lib/sprockets/version.rb +1 -1
- data/lib/sprockets/yui_compressor.rb +39 -11
- data/lib/sprockets.rb +142 -81
- metadata +96 -90
- 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/scss_template.rb +0 -13
- data/lib/sprockets/static_asset.rb +0 -60
|
@@ -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,24 +33,8 @@ module Sprockets
|
|
|
36
33
|
#
|
|
37
34
|
# env.register_processor('text/css', MyProcessor)
|
|
38
35
|
#
|
|
39
|
-
class DirectiveProcessor
|
|
40
|
-
|
|
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
|
|
36
|
+
class DirectiveProcessor
|
|
37
|
+
VERSION = '1'
|
|
57
38
|
|
|
58
39
|
# Directives are denoted by a `=` followed by the name, then
|
|
59
40
|
# argument list.
|
|
@@ -68,76 +49,108 @@ module Sprockets
|
|
|
68
49
|
^ \W* = \s* (\w+.*?) (\*\/)? $
|
|
69
50
|
/x
|
|
70
51
|
|
|
71
|
-
|
|
72
|
-
|
|
52
|
+
def self.instance
|
|
53
|
+
@instance ||= new(
|
|
54
|
+
# Deprecated: Default to C and Ruby comment styles
|
|
55
|
+
comments: ["//", ["/*", "*/"]] + ["#", ["###", "###"]]
|
|
56
|
+
)
|
|
57
|
+
end
|
|
73
58
|
|
|
74
|
-
def
|
|
75
|
-
|
|
59
|
+
def self.call(input)
|
|
60
|
+
instance.call(input)
|
|
61
|
+
end
|
|
76
62
|
|
|
77
|
-
|
|
78
|
-
@
|
|
79
|
-
|
|
80
|
-
@body += "\n" if @body != "" && @body !~ /\n\Z/m
|
|
63
|
+
def initialize(options = {})
|
|
64
|
+
@header_pattern = compile_header_pattern(Array(options[:comments]))
|
|
65
|
+
end
|
|
81
66
|
|
|
82
|
-
|
|
83
|
-
|
|
67
|
+
def call(input)
|
|
68
|
+
dup._call(input)
|
|
84
69
|
end
|
|
85
70
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
@
|
|
71
|
+
def _call(input)
|
|
72
|
+
@environment = input[:environment]
|
|
73
|
+
@uri = input[:uri]
|
|
74
|
+
@filename = input[:filename]
|
|
75
|
+
@dirname = File.dirname(@filename)
|
|
76
|
+
@content_type = input[:content_type]
|
|
77
|
+
@required = Set.new(input[:metadata][:required])
|
|
78
|
+
@stubbed = Set.new(input[:metadata][:stubbed])
|
|
79
|
+
@links = Set.new(input[:metadata][:links])
|
|
80
|
+
@dependencies = Set.new(input[:metadata][:dependencies])
|
|
81
|
+
|
|
82
|
+
data, directives = process_source(input[:data])
|
|
83
|
+
process_directives(directives)
|
|
84
|
+
|
|
85
|
+
{ data: data,
|
|
86
|
+
required: @required,
|
|
87
|
+
stubbed: @stubbed,
|
|
88
|
+
links: @links,
|
|
89
|
+
dependencies: @dependencies }
|
|
90
|
+
end
|
|
93
91
|
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
protected
|
|
93
|
+
# Directives will only be picked up if they are in the header
|
|
94
|
+
# of the source file. C style (/* */), JavaScript (//), and
|
|
95
|
+
# Ruby (#) comments are supported.
|
|
96
|
+
#
|
|
97
|
+
# Directives in comments after the first non-whitespace line
|
|
98
|
+
# of code will not be processed.
|
|
99
|
+
def compile_header_pattern(comments)
|
|
100
|
+
re = comments.map { |c|
|
|
101
|
+
case c
|
|
102
|
+
when String
|
|
103
|
+
"(?:#{Regexp.escape(c)}.*\\n?)+"
|
|
104
|
+
when Array
|
|
105
|
+
"(?:#{Regexp.escape(c[0])}(?m:.*?)#{Regexp.escape(c[1])})"
|
|
106
|
+
else
|
|
107
|
+
raise TypeError, "unknown comment type: #{c.class}"
|
|
108
|
+
end
|
|
109
|
+
}.join("|")
|
|
110
|
+
Regexp.compile("\\A(?:(?m:\\s*)(?:#{re}))+")
|
|
111
|
+
end
|
|
96
112
|
|
|
97
|
-
|
|
113
|
+
def process_source(source)
|
|
114
|
+
header = source[@header_pattern, 0] || ""
|
|
115
|
+
body = $' || source
|
|
98
116
|
|
|
99
|
-
|
|
100
|
-
process_source
|
|
117
|
+
header, directives = extract_directives(header)
|
|
101
118
|
|
|
102
|
-
|
|
103
|
-
|
|
119
|
+
data = ""
|
|
120
|
+
data.force_encoding(body.encoding)
|
|
121
|
+
data << header << "\n" unless header.empty?
|
|
122
|
+
data << body
|
|
123
|
+
# Ensure body ends in a new line
|
|
124
|
+
data << "\n" if data.length > 0 && data[-1] != "\n"
|
|
104
125
|
|
|
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
|
|
126
|
+
return data, directives
|
|
127
|
+
end
|
|
114
128
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
129
|
+
# Returns an Array of directive structures. Each structure
|
|
130
|
+
# is an Array with the line number as the first element, the
|
|
131
|
+
# directive name as the second element, followed by any
|
|
132
|
+
# arguments.
|
|
133
|
+
#
|
|
134
|
+
# [[1, "require", "foo"], [2, "require", "bar"]]
|
|
135
|
+
#
|
|
136
|
+
def extract_directives(header)
|
|
137
|
+
processed_header = ""
|
|
138
|
+
directives = []
|
|
119
139
|
|
|
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]
|
|
140
|
+
header.lines.each_with_index do |line, index|
|
|
141
|
+
if directive = line[DIRECTIVE_PATTERN, 1]
|
|
142
|
+
name, *args = Shellwords.shellwords(directive)
|
|
143
|
+
if respond_to?("process_#{name}_directive", true)
|
|
144
|
+
directives << [index + 1, name, *args]
|
|
145
|
+
# Replace directive line with a clean break
|
|
146
|
+
line = "\n"
|
|
147
|
+
end
|
|
133
148
|
end
|
|
149
|
+
processed_header << line
|
|
134
150
|
end
|
|
135
|
-
}.compact
|
|
136
|
-
end
|
|
137
151
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
attr_reader :context
|
|
152
|
+
return processed_header.chomp, directives
|
|
153
|
+
end
|
|
141
154
|
|
|
142
155
|
# Gathers comment directives in the source and processes them.
|
|
143
156
|
# Any directive method matching `process_*_directive` will
|
|
@@ -150,7 +163,7 @@ module Sprockets
|
|
|
150
163
|
#
|
|
151
164
|
# class DirectiveProcessor < Sprockets::DirectiveProcessor
|
|
152
165
|
# def process_require_glob_directive
|
|
153
|
-
# Dir["#{
|
|
166
|
+
# Dir["#{dirname}/#{glob}"].sort.each do |filename|
|
|
154
167
|
# require(filename)
|
|
155
168
|
# end
|
|
156
169
|
# end
|
|
@@ -161,29 +174,14 @@ module Sprockets
|
|
|
161
174
|
# env.unregister_processor('text/css', Sprockets::DirectiveProcessor)
|
|
162
175
|
# env.register_processor('text/css', DirectiveProcessor)
|
|
163
176
|
#
|
|
164
|
-
def process_directives
|
|
177
|
+
def process_directives(directives)
|
|
165
178
|
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] }
|
|
179
|
+
begin
|
|
180
|
+
send("process_#{name}_directive", *args)
|
|
181
|
+
rescue Exception => e
|
|
182
|
+
e.set_backtrace(["#{@filename}:#{line_number}"] + e.backtrace)
|
|
183
|
+
raise e
|
|
184
|
+
end
|
|
187
185
|
end
|
|
188
186
|
end
|
|
189
187
|
|
|
@@ -206,22 +204,13 @@ module Sprockets
|
|
|
206
204
|
# //= require "./bar"
|
|
207
205
|
#
|
|
208
206
|
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)
|
|
207
|
+
@required << resolve(path, accept: @content_type, pipeline: :self)
|
|
218
208
|
end
|
|
219
209
|
|
|
220
|
-
# `require_self` causes the body of the current file to be
|
|
221
|
-
#
|
|
222
|
-
#
|
|
223
|
-
#
|
|
224
|
-
# before other dependencies are loaded.
|
|
210
|
+
# `require_self` causes the body of the current file to be inserted
|
|
211
|
+
# before any subsequent `require` directives. Useful in CSS files, where
|
|
212
|
+
# it's common for the index file to contain global styles that need to
|
|
213
|
+
# be defined before other dependencies are loaded.
|
|
225
214
|
#
|
|
226
215
|
# /*= require "reset"
|
|
227
216
|
# *= require_self
|
|
@@ -229,26 +218,10 @@ module Sprockets
|
|
|
229
218
|
# */
|
|
230
219
|
#
|
|
231
220
|
def process_require_self_directive
|
|
232
|
-
if @
|
|
221
|
+
if @required.include?(@uri)
|
|
233
222
|
raise ArgumentError, "require_self can only be called once per source file"
|
|
234
223
|
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
|
|
224
|
+
@required << @uri
|
|
252
225
|
end
|
|
253
226
|
|
|
254
227
|
# `require_directory` requires all the files inside a single
|
|
@@ -258,27 +231,8 @@ module Sprockets
|
|
|
258
231
|
# //= require_directory "./javascripts"
|
|
259
232
|
#
|
|
260
233
|
def process_require_directory_directive(path = ".")
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
unless (stats = stat(root)) && stats.directory?
|
|
265
|
-
raise ArgumentError, "require_directory argument must be a directory"
|
|
266
|
-
end
|
|
267
|
-
|
|
268
|
-
context.depend_on(root)
|
|
269
|
-
|
|
270
|
-
entries(root).each do |pathname|
|
|
271
|
-
pathname = root.join(pathname)
|
|
272
|
-
if pathname.to_s == self.file
|
|
273
|
-
next
|
|
274
|
-
elsif context.asset_requirable?(pathname)
|
|
275
|
-
context.require_asset(pathname)
|
|
276
|
-
end
|
|
277
|
-
end
|
|
278
|
-
else
|
|
279
|
-
# The path must be relative and start with a `./`.
|
|
280
|
-
raise ArgumentError, "require_directory argument must be a relative path"
|
|
281
|
-
end
|
|
234
|
+
path = expand_relative_dirname(:require_directory, path)
|
|
235
|
+
require_paths(*@environment.stat_directory_with_dependencies(path))
|
|
282
236
|
end
|
|
283
237
|
|
|
284
238
|
# `require_tree` requires all the nested files in a directory.
|
|
@@ -287,28 +241,8 @@ module Sprockets
|
|
|
287
241
|
# //= require_tree "./public"
|
|
288
242
|
#
|
|
289
243
|
def process_require_tree_directive(path = ".")
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
unless (stats = stat(root)) && stats.directory?
|
|
294
|
-
raise ArgumentError, "require_tree argument must be a directory"
|
|
295
|
-
end
|
|
296
|
-
|
|
297
|
-
context.depend_on(root)
|
|
298
|
-
|
|
299
|
-
each_entry(root) do |pathname|
|
|
300
|
-
if pathname.to_s == self.file
|
|
301
|
-
next
|
|
302
|
-
elsif stat(pathname).directory?
|
|
303
|
-
context.depend_on(pathname)
|
|
304
|
-
elsif context.asset_requirable?(pathname)
|
|
305
|
-
context.require_asset(pathname)
|
|
306
|
-
end
|
|
307
|
-
end
|
|
308
|
-
else
|
|
309
|
-
# The path must be relative and start with a `./`.
|
|
310
|
-
raise ArgumentError, "require_tree argument must be a relative path"
|
|
311
|
-
end
|
|
244
|
+
path = expand_relative_dirname(:require_tree, path)
|
|
245
|
+
require_paths(*@environment.stat_sorted_tree_with_dependencies(path))
|
|
312
246
|
end
|
|
313
247
|
|
|
314
248
|
# Allows you to state a dependency on a file without
|
|
@@ -324,7 +258,7 @@ module Sprockets
|
|
|
324
258
|
# //= depend_on "foo.png"
|
|
325
259
|
#
|
|
326
260
|
def process_depend_on_directive(path)
|
|
327
|
-
|
|
261
|
+
resolve(path)
|
|
328
262
|
end
|
|
329
263
|
|
|
330
264
|
# Allows you to state a dependency on an asset without including
|
|
@@ -339,7 +273,7 @@ module Sprockets
|
|
|
339
273
|
# //= depend_on_asset "bar.js"
|
|
340
274
|
#
|
|
341
275
|
def process_depend_on_asset_directive(path)
|
|
342
|
-
|
|
276
|
+
load(resolve(path))
|
|
343
277
|
end
|
|
344
278
|
|
|
345
279
|
# Allows dependency to be excluded from the asset bundle.
|
|
@@ -351,58 +285,120 @@ module Sprockets
|
|
|
351
285
|
# //= stub "jquery"
|
|
352
286
|
#
|
|
353
287
|
def process_stub_directive(path)
|
|
354
|
-
|
|
288
|
+
@stubbed << resolve(path, accept: @content_type, pipeline: :self)
|
|
355
289
|
end
|
|
356
290
|
|
|
357
|
-
#
|
|
291
|
+
# Declares a linked dependency on the target asset.
|
|
292
|
+
#
|
|
293
|
+
# The `path` must be a valid asset and should not already be part of the
|
|
294
|
+
# bundle. Any linked assets will automatically be compiled along with the
|
|
295
|
+
# current.
|
|
296
|
+
#
|
|
297
|
+
# /*= link "logo.png" */
|
|
298
|
+
#
|
|
299
|
+
def process_link_directive(path)
|
|
300
|
+
@links << load(resolve(path)).uri
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
# `link_directory` links all the files inside a single
|
|
304
|
+
# directory. It's similar to `path/*` since it does not follow
|
|
305
|
+
# nested directories.
|
|
306
|
+
#
|
|
307
|
+
# //= link_directory "./fonts"
|
|
358
308
|
#
|
|
359
|
-
#
|
|
360
|
-
#
|
|
309
|
+
# Use caution when linking against JS or CSS assets. Include an explicit
|
|
310
|
+
# extension or content type in these cases
|
|
361
311
|
#
|
|
362
|
-
# //=
|
|
312
|
+
# //= link_directory "./scripts" .js
|
|
363
313
|
#
|
|
364
|
-
def
|
|
365
|
-
|
|
314
|
+
def process_link_directory_directive(path = ".", accept = nil)
|
|
315
|
+
path = expand_relative_dirname(:link_directory, path)
|
|
316
|
+
accept = expand_accept_shorthand(accept)
|
|
317
|
+
link_paths(*@environment.stat_directory_with_dependencies(path), accept)
|
|
366
318
|
end
|
|
367
319
|
|
|
368
|
-
#
|
|
369
|
-
|
|
370
|
-
|
|
320
|
+
# `link_tree` links all the nested files in a directory.
|
|
321
|
+
# Its glob equivalent is `path/**/*`.
|
|
322
|
+
#
|
|
323
|
+
# //= link_tree "./images"
|
|
324
|
+
#
|
|
325
|
+
# Use caution when linking against JS or CSS assets. Include an explicit
|
|
326
|
+
# extension or content type in these cases
|
|
327
|
+
#
|
|
328
|
+
# //= link_tree "./styles" .css
|
|
329
|
+
#
|
|
330
|
+
def process_link_tree_directive(path = ".", accept = nil)
|
|
331
|
+
path = expand_relative_dirname(:link_tree, path)
|
|
332
|
+
accept = expand_accept_shorthand(accept)
|
|
333
|
+
link_paths(*@environment.stat_sorted_tree_with_dependencies(path), accept)
|
|
371
334
|
end
|
|
372
335
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
336
|
+
private
|
|
337
|
+
def expand_accept_shorthand(accept)
|
|
338
|
+
if accept.nil?
|
|
339
|
+
nil
|
|
340
|
+
elsif accept.include?("/")
|
|
341
|
+
accept
|
|
342
|
+
elsif accept.start_with?(".")
|
|
343
|
+
@environment.mime_exts[accept]
|
|
380
344
|
else
|
|
381
|
-
{}
|
|
345
|
+
@environment.mime_exts[".#{accept}"]
|
|
382
346
|
end
|
|
383
347
|
end
|
|
384
348
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
349
|
+
def require_paths(paths, deps)
|
|
350
|
+
resolve_paths(paths, deps, accept: @content_type, pipeline: :self) do |uri|
|
|
351
|
+
@required << uri
|
|
352
|
+
end
|
|
389
353
|
end
|
|
390
354
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
355
|
+
def link_paths(paths, deps, accept)
|
|
356
|
+
resolve_paths(paths, deps, accept: accept) do |uri|
|
|
357
|
+
@links << load(uri).uri
|
|
358
|
+
end
|
|
394
359
|
end
|
|
395
360
|
|
|
396
|
-
def
|
|
397
|
-
|
|
361
|
+
def resolve_paths(paths, deps, options = {})
|
|
362
|
+
@dependencies.merge(deps)
|
|
363
|
+
paths.each do |subpath, stat|
|
|
364
|
+
next if subpath == @filename || stat.directory?
|
|
365
|
+
uri, deps = @environment.resolve(subpath, options.merge(compat: false))
|
|
366
|
+
@dependencies.merge(deps)
|
|
367
|
+
yield uri if uri
|
|
368
|
+
end
|
|
398
369
|
end
|
|
399
370
|
|
|
400
|
-
def
|
|
401
|
-
|
|
371
|
+
def expand_relative_dirname(directive, path)
|
|
372
|
+
if @environment.relative_path?(path)
|
|
373
|
+
path = File.expand_path(path, @dirname)
|
|
374
|
+
stat = @environment.stat(path)
|
|
375
|
+
|
|
376
|
+
if stat && stat.directory?
|
|
377
|
+
path
|
|
378
|
+
else
|
|
379
|
+
raise ArgumentError, "#{directive} argument must be a directory"
|
|
380
|
+
end
|
|
381
|
+
else
|
|
382
|
+
# The path must be relative and start with a `./`.
|
|
383
|
+
raise ArgumentError, "#{directive} argument must be a relative path"
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
def load(uri)
|
|
388
|
+
asset = @environment.load(uri)
|
|
389
|
+
@dependencies.merge(asset.metadata[:dependencies])
|
|
390
|
+
asset
|
|
402
391
|
end
|
|
403
392
|
|
|
404
|
-
def
|
|
405
|
-
|
|
393
|
+
def resolve(path, options = {})
|
|
394
|
+
# Prevent absolute paths in directives
|
|
395
|
+
if @environment.absolute_path?(path)
|
|
396
|
+
raise FileOutsidePaths, "can't require absolute file: #{path}"
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
uri, deps = @environment.resolve!(path, options.merge(base_path: @dirname))
|
|
400
|
+
@dependencies.merge(deps)
|
|
401
|
+
uri
|
|
406
402
|
end
|
|
407
403
|
end
|
|
408
404
|
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'sprockets/autoload'
|
|
2
|
+
|
|
3
|
+
module Sprockets
|
|
4
|
+
# Processor engine class for the Eco compiler. Depends on the `eco` gem.
|
|
5
|
+
#
|
|
6
|
+
# For more infomation see:
|
|
7
|
+
#
|
|
8
|
+
# https://github.com/sstephenson/ruby-eco
|
|
9
|
+
# https://github.com/sstephenson/eco
|
|
10
|
+
#
|
|
11
|
+
module EcoProcessor
|
|
12
|
+
VERSION = '1'
|
|
13
|
+
|
|
14
|
+
def self.cache_key
|
|
15
|
+
@cache_key ||= "#{name}:#{Autoload::Eco::Source::VERSION}:#{VERSION}".freeze
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Compile template data with Eco compiler.
|
|
19
|
+
#
|
|
20
|
+
# Returns a JS function definition String. The result should be
|
|
21
|
+
# assigned to a JS variable.
|
|
22
|
+
#
|
|
23
|
+
# # => "function(...) {...}"
|
|
24
|
+
#
|
|
25
|
+
def self.call(input)
|
|
26
|
+
data = input[:data]
|
|
27
|
+
input[:cache].fetch([cache_key, data]) do
|
|
28
|
+
Autoload::Eco.compile(data)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -1,38 +1,17 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'sprockets/eco_processor'
|
|
2
2
|
|
|
3
3
|
module Sprockets
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
#
|
|
8
|
-
# https://github.com/sstephenson/ruby-eco
|
|
9
|
-
# https://github.com/sstephenson/eco
|
|
10
|
-
#
|
|
11
|
-
class EcoTemplate < Tilt::Template
|
|
12
|
-
# Check to see if Eco is loaded
|
|
13
|
-
def self.engine_initialized?
|
|
14
|
-
defined? ::Eco
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# Autoload eco library. If the library isn't loaded, Tilt will produce
|
|
18
|
-
# a thread safetly warning. If you intend to use `.eco` files, you
|
|
19
|
-
# should explicitly require it.
|
|
20
|
-
def initialize_engine
|
|
21
|
-
require_template_library 'eco'
|
|
22
|
-
end
|
|
4
|
+
# Deprecated
|
|
5
|
+
module EcoTemplate
|
|
6
|
+
VERSION = EcoProcessor::VERSION
|
|
23
7
|
|
|
24
|
-
def
|
|
8
|
+
def self.cache_key
|
|
9
|
+
EcoProcessor.cache_key
|
|
25
10
|
end
|
|
26
11
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
# assigned to a JS variable.
|
|
31
|
-
#
|
|
32
|
-
# # => "function(...) {...}"
|
|
33
|
-
#
|
|
34
|
-
def evaluate(scope, locals, &block)
|
|
35
|
-
Eco.compile(data)
|
|
12
|
+
def self.call(*args)
|
|
13
|
+
Deprecation.new.warn "EcoTemplate is deprecated please use EcoProcessor instead"
|
|
14
|
+
EcoProcessor.call(*args)
|
|
36
15
|
end
|
|
37
16
|
end
|
|
38
17
|
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'sprockets/autoload'
|
|
2
|
+
|
|
3
|
+
module Sprockets
|
|
4
|
+
# Processor engine class for the EJS compiler. Depends on the `ejs` gem.
|
|
5
|
+
#
|
|
6
|
+
# For more infomation see:
|
|
7
|
+
#
|
|
8
|
+
# https://github.com/sstephenson/ruby-ejs
|
|
9
|
+
#
|
|
10
|
+
module EjsProcessor
|
|
11
|
+
VERSION = '1'
|
|
12
|
+
|
|
13
|
+
def self.cache_key
|
|
14
|
+
@cache_key ||= "#{name}:#{VERSION}".freeze
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Compile template data with EJS compiler.
|
|
18
|
+
#
|
|
19
|
+
# Returns a JS function definition String. The result should be
|
|
20
|
+
# assigned to a JS variable.
|
|
21
|
+
#
|
|
22
|
+
# # => "function(obj){...}"
|
|
23
|
+
#
|
|
24
|
+
def self.call(input)
|
|
25
|
+
data = input[:data]
|
|
26
|
+
input[:cache].fetch([cache_key, data]) do
|
|
27
|
+
Autoload::EJS.compile(data)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|