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/mime.rb
CHANGED
@@ -1,49 +1,130 @@
|
|
1
|
-
require '
|
1
|
+
require 'sprockets/encoding_utils'
|
2
2
|
|
3
3
|
module Sprockets
|
4
4
|
module Mime
|
5
|
-
|
6
|
-
|
7
|
-
#
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
5
|
+
include HTTPUtils
|
6
|
+
|
7
|
+
# Public: Mapping of MIME type Strings to properties Hash.
|
8
|
+
#
|
9
|
+
# key - MIME Type String
|
10
|
+
# value - Hash
|
11
|
+
# extensions - Array of extnames
|
12
|
+
# charset - Default Encoding or function to detect encoding
|
13
|
+
#
|
14
|
+
# Returns Hash.
|
15
|
+
attr_reader :mime_types
|
16
|
+
|
17
|
+
# Internal: Mapping of MIME extension Strings to MIME type Strings.
|
18
|
+
#
|
19
|
+
# Used for internal fast lookup purposes.
|
20
|
+
#
|
21
|
+
# Examples:
|
22
|
+
#
|
23
|
+
# mime_exts['.js'] #=> 'application/javascript'
|
24
|
+
#
|
25
|
+
# key - MIME extension String
|
26
|
+
# value - MIME Type String
|
27
|
+
#
|
28
|
+
# Returns Hash.
|
29
|
+
attr_reader :mime_exts
|
30
|
+
|
31
|
+
# Public: Register a new mime type.
|
32
|
+
#
|
33
|
+
# mime_type - String MIME Type
|
34
|
+
# options - Hash
|
35
|
+
# extensions: Array of String extnames
|
36
|
+
# charset: Proc/Method that detects the charset of a file.
|
37
|
+
# See EncodingUtils.
|
38
|
+
#
|
39
|
+
# Returns nothing.
|
40
|
+
def register_mime_type(mime_type, options = {})
|
41
|
+
# Legacy extension argument, will be removed from 4.x
|
42
|
+
if options.is_a?(String)
|
43
|
+
options = { extensions: [options] }
|
15
44
|
end
|
16
|
-
end
|
17
45
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
46
|
+
extnames = Array(options[:extensions]).map { |extname|
|
47
|
+
Sprockets::Utils.normalize_extension(extname)
|
48
|
+
}
|
22
49
|
|
23
|
-
|
24
|
-
|
25
|
-
|
50
|
+
charset = options[:charset]
|
51
|
+
charset ||= EncodingUtils::DETECT if mime_type.start_with?('text/')
|
52
|
+
|
53
|
+
mutate_config(:mime_exts) do |mime_exts|
|
54
|
+
extnames.each do |extname|
|
55
|
+
mime_exts[extname] = mime_type
|
56
|
+
end
|
57
|
+
mime_exts
|
26
58
|
end
|
27
|
-
|
28
|
-
|
29
|
-
|
59
|
+
|
60
|
+
mutate_config(:mime_types) do |mime_types|
|
61
|
+
type = { extensions: extnames }
|
62
|
+
type[:charset] = charset if charset
|
63
|
+
mime_types.merge(mime_type => type)
|
30
64
|
end
|
31
65
|
end
|
32
66
|
|
33
|
-
#
|
34
|
-
|
35
|
-
|
36
|
-
|
67
|
+
# Public: Read file on disk with MIME type specific encoding.
|
68
|
+
#
|
69
|
+
# filename - String path
|
70
|
+
# content_type - String MIME type
|
71
|
+
#
|
72
|
+
# Returns String file contents transcoded to UTF-8 or in its external
|
73
|
+
# encoding.
|
74
|
+
def read_file(filename, content_type = nil)
|
75
|
+
data = File.open(filename, 'rb') { |f| f.read }
|
76
|
+
|
77
|
+
if type = mime_types[content_type]
|
78
|
+
if charset = type[:charset]
|
79
|
+
data = charset.call(data).encode(Encoding::UTF_8)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
data
|
37
84
|
end
|
38
85
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
86
|
+
# Public: Mapping of supported HTTP Content/Transfer encodings
|
87
|
+
#
|
88
|
+
# key - String name
|
89
|
+
# value - Method/Proc to encode data
|
90
|
+
#
|
91
|
+
# Returns Hash.
|
92
|
+
attr_reader :encodings
|
93
|
+
|
94
|
+
# Public: Register a new encoding.
|
95
|
+
#
|
96
|
+
# Examples
|
97
|
+
#
|
98
|
+
# register_encoding :gzip, EncodingUtils::GZIP
|
99
|
+
#
|
100
|
+
# key - String name
|
101
|
+
# encode - Method/Proc to encode data
|
102
|
+
#
|
103
|
+
# Returns nothing.
|
104
|
+
def register_encoding(name, encode)
|
105
|
+
mutate_config(:encodings) do |encodings|
|
106
|
+
encodings.merge(name.to_s => encode)
|
46
107
|
end
|
47
108
|
end
|
109
|
+
|
110
|
+
private
|
111
|
+
def read_input(input)
|
112
|
+
read_file(input[:filename], input[:content_type])
|
113
|
+
end
|
114
|
+
|
115
|
+
# Internal: Get a postprocessor to perform the encoding.
|
116
|
+
#
|
117
|
+
# encoding - String encoding.
|
118
|
+
#
|
119
|
+
# Returns an Array of Processors.
|
120
|
+
def unwrap_encoding_processors(encoding)
|
121
|
+
processors = []
|
122
|
+
if encoder = self.encodings[encoding]
|
123
|
+
processors << lambda do |input|
|
124
|
+
{ data: encoder.call(input[:data]), encoding: encoding }
|
125
|
+
end
|
126
|
+
end
|
127
|
+
processors
|
128
|
+
end
|
48
129
|
end
|
49
130
|
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Sprockets
|
4
|
+
# Internal: File and path related utilities. Mixed into Environment.
|
5
|
+
#
|
6
|
+
# Probably would be called FileUtils, but that causes namespace annoyances
|
7
|
+
# when code actually wants to reference ::FileUtils.
|
8
|
+
module PathUtils
|
9
|
+
extend self
|
10
|
+
|
11
|
+
# Internal: Like `File.stat`.
|
12
|
+
#
|
13
|
+
# path - String file or directory path
|
14
|
+
#
|
15
|
+
# Returns nil if the file does not exist.
|
16
|
+
def stat(path)
|
17
|
+
if File.exist?(path)
|
18
|
+
File.stat(path.to_s)
|
19
|
+
else
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Internal: Like `File.file?`.
|
25
|
+
#
|
26
|
+
# path - String file path.
|
27
|
+
#
|
28
|
+
# Returns true path exists and is a file.
|
29
|
+
def file?(path)
|
30
|
+
if stat = self.stat(path)
|
31
|
+
stat.file?
|
32
|
+
else
|
33
|
+
false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Internal: A version of `Dir.entries` that filters out `.` files and `~`
|
38
|
+
# swap files.
|
39
|
+
#
|
40
|
+
# path - String directory path
|
41
|
+
#
|
42
|
+
# Returns an empty `Array` if the directory does not exist.
|
43
|
+
def entries(path)
|
44
|
+
if File.directory?(path)
|
45
|
+
Dir.entries(path).reject { |entry| entry =~ /^\.|~$|^\#.*\#$/ }.sort
|
46
|
+
else
|
47
|
+
[]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Internal: Check if path is absolute or relative.
|
52
|
+
#
|
53
|
+
# path - String path.
|
54
|
+
#
|
55
|
+
# Returns true if path is absolute, otherwise false.
|
56
|
+
if File::ALT_SEPARATOR
|
57
|
+
# On Windows, ALT_SEPARATOR is \
|
58
|
+
def absolute_path?(path)
|
59
|
+
path[0] == File::SEPARATOR || path[0] == File::ALT_SEPARATOR
|
60
|
+
end
|
61
|
+
else
|
62
|
+
def absolute_path?(path)
|
63
|
+
path[0] == File::SEPARATOR
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Internal: Check if path is explicitly relative.
|
68
|
+
# Starts with "./" or "../".
|
69
|
+
#
|
70
|
+
# path - String path.
|
71
|
+
#
|
72
|
+
# Returns true if path is relative, otherwise false.
|
73
|
+
def relative_path?(path)
|
74
|
+
path =~ /^\.\.?($|\/)/ ? true : false
|
75
|
+
end
|
76
|
+
|
77
|
+
# Internal: Get relative path for root path and subpath.
|
78
|
+
#
|
79
|
+
# path - String path
|
80
|
+
# subpath - String subpath of path
|
81
|
+
#
|
82
|
+
# Returns relative String path if subpath is a subpath of path, or nil if
|
83
|
+
# subpath is outside of path.
|
84
|
+
def split_subpath(path, subpath)
|
85
|
+
path = File.join(path, '')
|
86
|
+
if subpath.start_with?(path)
|
87
|
+
subpath[path.length..-1]
|
88
|
+
else
|
89
|
+
nil
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Internal: Detect root path and base for file in a set of paths.
|
94
|
+
#
|
95
|
+
# paths - Array of String paths
|
96
|
+
# filename - String path of file expected to be in one of the paths.
|
97
|
+
#
|
98
|
+
# Returns [String root, String path]
|
99
|
+
def paths_split(paths, filename)
|
100
|
+
paths.each do |path|
|
101
|
+
if subpath = split_subpath(path, filename)
|
102
|
+
return path, subpath
|
103
|
+
end
|
104
|
+
end
|
105
|
+
nil
|
106
|
+
end
|
107
|
+
|
108
|
+
# Internal: Get path's extensions.
|
109
|
+
#
|
110
|
+
# path - String
|
111
|
+
#
|
112
|
+
# Returns an Array of String extnames.
|
113
|
+
def path_extnames(path)
|
114
|
+
File.basename(path).scan(/\.[^.]+/)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Internal: Stat all the files under a directory.
|
118
|
+
#
|
119
|
+
# dir - A String directory
|
120
|
+
#
|
121
|
+
# Returns an Enumerator of [path, stat].
|
122
|
+
def stat_directory(dir)
|
123
|
+
return to_enum(__method__, dir) unless block_given?
|
124
|
+
|
125
|
+
self.entries(dir).each do |entry|
|
126
|
+
path = File.join(dir, entry)
|
127
|
+
if stat = self.stat(path)
|
128
|
+
yield path, stat
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
nil
|
133
|
+
end
|
134
|
+
|
135
|
+
# Internal: Recursive stat all the files under a directory.
|
136
|
+
#
|
137
|
+
# dir - A String directory
|
138
|
+
#
|
139
|
+
# Returns an Enumerator of [path, stat].
|
140
|
+
def stat_tree(dir, &block)
|
141
|
+
return to_enum(__method__, dir) unless block_given?
|
142
|
+
|
143
|
+
self.stat_directory(dir) do |path, stat|
|
144
|
+
yield path, stat
|
145
|
+
|
146
|
+
if stat.directory?
|
147
|
+
stat_tree(path, &block)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
nil
|
152
|
+
end
|
153
|
+
|
154
|
+
# Internal: Write to a file atomically. Useful for situations where you
|
155
|
+
# don't want other processes or threads to see half-written files.
|
156
|
+
#
|
157
|
+
# Utils.atomic_write('important.file') do |file|
|
158
|
+
# file.write('hello')
|
159
|
+
# end
|
160
|
+
#
|
161
|
+
# Returns nothing.
|
162
|
+
def atomic_write(filename)
|
163
|
+
tmpname = [
|
164
|
+
File.dirname(filename),
|
165
|
+
Thread.current.object_id,
|
166
|
+
Process.pid,
|
167
|
+
rand(1000000)
|
168
|
+
].join('.')
|
169
|
+
|
170
|
+
File.open(tmpname, 'wb+') do |f|
|
171
|
+
yield f
|
172
|
+
end
|
173
|
+
|
174
|
+
FileUtils.mv(tmpname, filename)
|
175
|
+
ensure
|
176
|
+
FileUtils.rm(tmpname) if File.exist?(tmpname)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
data/lib/sprockets/paths.rb
CHANGED
@@ -4,33 +4,31 @@ module Sprockets
|
|
4
4
|
#
|
5
5
|
# All relative paths are expanded with root as its base. To be
|
6
6
|
# useful set this to your applications root directory. (`Rails.root`)
|
7
|
-
|
8
|
-
@trail.root.dup
|
9
|
-
end
|
7
|
+
attr_reader :root
|
10
8
|
|
11
9
|
# Returns an `Array` of path `String`s.
|
12
10
|
#
|
13
11
|
# These paths will be used for asset logical path lookups.
|
14
|
-
|
15
|
-
# Note that a copy of the `Array` is returned so mutating will
|
16
|
-
# have no affect on the environment. See `append_path`,
|
17
|
-
# `prepend_path`, and `clear_paths`.
|
18
|
-
def paths
|
19
|
-
@trail.paths.dup
|
20
|
-
end
|
12
|
+
attr_reader :paths
|
21
13
|
|
22
14
|
# Prepend a `path` to the `paths` list.
|
23
15
|
#
|
24
16
|
# Paths at the end of the `Array` have the least priority.
|
25
17
|
def prepend_path(path)
|
26
|
-
|
18
|
+
mutate_config(:paths) do |paths|
|
19
|
+
path = File.expand_path(path, root).dup.freeze
|
20
|
+
paths.unshift(path)
|
21
|
+
end
|
27
22
|
end
|
28
23
|
|
29
24
|
# Append a `path` to the `paths` list.
|
30
25
|
#
|
31
26
|
# Paths at the beginning of the `Array` have a higher priority.
|
32
27
|
def append_path(path)
|
33
|
-
|
28
|
+
mutate_config(:paths) do |paths|
|
29
|
+
path = File.expand_path(path, root).dup.freeze
|
30
|
+
paths.push(path)
|
31
|
+
end
|
34
32
|
end
|
35
33
|
|
36
34
|
# Clear all paths and start fresh.
|
@@ -39,20 +37,9 @@ module Sprockets
|
|
39
37
|
# completely wipe the paths list and reappend them in the order
|
40
38
|
# you want.
|
41
39
|
def clear_paths
|
42
|
-
|
40
|
+
mutate_config(:paths) do |paths|
|
41
|
+
paths.clear
|
42
|
+
end
|
43
43
|
end
|
44
|
-
|
45
|
-
# Returns an `Array` of extensions.
|
46
|
-
#
|
47
|
-
# These extensions maybe omitted from logical path searches.
|
48
|
-
#
|
49
|
-
# # => [".js", ".css", ".coffee", ".sass", ...]
|
50
|
-
#
|
51
|
-
def extensions
|
52
|
-
@trail.extensions.dup
|
53
|
-
end
|
54
|
-
|
55
|
-
protected
|
56
|
-
attr_reader :trail
|
57
44
|
end
|
58
45
|
end
|
data/lib/sprockets/processing.rb
CHANGED
@@ -1,64 +1,43 @@
|
|
1
1
|
require 'sprockets/engines'
|
2
|
+
require 'sprockets/lazy_processor'
|
3
|
+
require 'sprockets/legacy_proc_processor'
|
4
|
+
require 'sprockets/legacy_tilt_processor'
|
2
5
|
require 'sprockets/mime'
|
3
|
-
require 'sprockets/processor'
|
4
6
|
require 'sprockets/utils'
|
5
7
|
|
6
8
|
module Sprockets
|
7
9
|
# `Processing` is an internal mixin whose public methods are exposed on
|
8
|
-
# the `Environment` and `
|
10
|
+
# the `Environment` and `CachedEnvironment` classes.
|
9
11
|
module Processing
|
10
|
-
# Returns an `Array` of format extension `String`s.
|
11
|
-
#
|
12
|
-
# format_extensions
|
13
|
-
# # => ['.js', '.css']
|
14
|
-
#
|
15
|
-
def format_extensions
|
16
|
-
@trail.extensions - @engines.keys
|
17
|
-
end
|
18
|
-
|
19
|
-
# Deprecated alias for `preprocessors`.
|
20
|
-
def processors(*args)
|
21
|
-
preprocessors(*args)
|
22
|
-
end
|
23
|
-
|
24
|
-
# Returns an `Array` of `Processor` classes. If a `mime_type`
|
25
|
-
# argument is supplied, the processors registered under that
|
26
|
-
# extension will be returned.
|
27
|
-
#
|
28
12
|
# Preprocessors are ran before Postprocessors and Engine
|
29
13
|
# processors.
|
14
|
+
attr_reader :preprocessors
|
15
|
+
|
16
|
+
# Internal: Find and load preprocessors by mime type.
|
30
17
|
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
deep_copy_hash(@preprocessors)
|
18
|
+
# mime_type - String MIME type.
|
19
|
+
#
|
20
|
+
# Returns Array of Procs.
|
21
|
+
def unwrap_preprocessors(mime_type)
|
22
|
+
preprocessors[mime_type].map do |processor|
|
23
|
+
unwrap_processor(processor)
|
38
24
|
end
|
39
25
|
end
|
40
26
|
|
41
|
-
# Returns an `Array` of `Processor` classes. If a `mime_type`
|
42
|
-
# argument is supplied, the processors registered under that
|
43
|
-
# extension will be returned.
|
44
|
-
#
|
45
27
|
# Postprocessors are ran after Preprocessors and Engine processors.
|
28
|
+
attr_reader :postprocessors
|
29
|
+
|
30
|
+
# Internal: Find and load postprocessors by mime type.
|
46
31
|
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
deep_copy_hash(@postprocessors)
|
32
|
+
# mime_type - String MIME type.
|
33
|
+
#
|
34
|
+
# Returns Array of Procs.
|
35
|
+
def unwrap_postprocessors(mime_type)
|
36
|
+
postprocessors[mime_type].map do |processor|
|
37
|
+
unwrap_processor(processor)
|
54
38
|
end
|
55
39
|
end
|
56
40
|
|
57
|
-
# Deprecated alias for `register_preprocessor`.
|
58
|
-
def register_processor(*args, &block)
|
59
|
-
register_preprocessor(*args, &block)
|
60
|
-
end
|
61
|
-
|
62
41
|
# Registers a new Preprocessor `klass` for `mime_type`.
|
63
42
|
#
|
64
43
|
# register_preprocessor 'text/css', Sprockets::DirectiveProcessor
|
@@ -70,42 +49,28 @@ module Sprockets
|
|
70
49
|
# end
|
71
50
|
#
|
72
51
|
def register_preprocessor(mime_type, klass, &block)
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
@name = name
|
77
|
-
@processor = block
|
78
|
-
end
|
52
|
+
mutate_hash_config(:preprocessors, mime_type) do |processors|
|
53
|
+
processors.push(wrap_processor(klass, block))
|
54
|
+
processors
|
79
55
|
end
|
80
|
-
|
81
|
-
@preprocessors[mime_type].push(klass)
|
82
56
|
end
|
83
57
|
|
84
58
|
# Registers a new Postprocessor `klass` for `mime_type`.
|
85
59
|
#
|
86
|
-
# register_postprocessor '
|
60
|
+
# register_postprocessor 'application/javascript', Sprockets::DirectiveProcessor
|
87
61
|
#
|
88
62
|
# A block can be passed for to create a shorthand processor.
|
89
63
|
#
|
90
|
-
# register_postprocessor '
|
64
|
+
# register_postprocessor 'application/javascript', :my_processor do |context, data|
|
91
65
|
# data.gsub(...)
|
92
66
|
# end
|
93
67
|
#
|
94
|
-
def register_postprocessor(mime_type, klass, &block)
|
95
|
-
|
96
|
-
|
97
|
-
klass
|
98
|
-
|
99
|
-
@processor = block
|
100
|
-
end
|
68
|
+
def register_postprocessor(mime_type, klass, proc = nil, &block)
|
69
|
+
proc ||= block
|
70
|
+
mutate_hash_config(:postprocessors, mime_type) do |processors|
|
71
|
+
processors.push(wrap_processor(klass, proc))
|
72
|
+
processors
|
101
73
|
end
|
102
|
-
|
103
|
-
@postprocessors[mime_type].push(klass)
|
104
|
-
end
|
105
|
-
|
106
|
-
# Deprecated alias for `unregister_preprocessor`.
|
107
|
-
def unregister_processor(*args)
|
108
|
-
unregister_preprocessor(*args)
|
109
74
|
end
|
110
75
|
|
111
76
|
# Remove Preprocessor `klass` for `mime_type`.
|
@@ -114,13 +79,15 @@ module Sprockets
|
|
114
79
|
#
|
115
80
|
def unregister_preprocessor(mime_type, klass)
|
116
81
|
if klass.is_a?(String) || klass.is_a?(Symbol)
|
117
|
-
klass =
|
118
|
-
cls.respond_to?(:name) &&
|
119
|
-
cls.name == "Sprockets::Processor (#{klass})"
|
82
|
+
klass = preprocessors[mime_type].detect { |cls|
|
83
|
+
cls.respond_to?(:name) && cls.name == "Sprockets::LegacyProcProcessor (#{klass})"
|
120
84
|
}
|
121
85
|
end
|
122
86
|
|
123
|
-
|
87
|
+
mutate_hash_config(:preprocessors, mime_type) do |processors|
|
88
|
+
processors.delete(klass)
|
89
|
+
processors
|
90
|
+
end
|
124
91
|
end
|
125
92
|
|
126
93
|
# Remove Postprocessor `klass` for `mime_type`.
|
@@ -129,78 +96,202 @@ module Sprockets
|
|
129
96
|
#
|
130
97
|
def unregister_postprocessor(mime_type, klass)
|
131
98
|
if klass.is_a?(String) || klass.is_a?(Symbol)
|
132
|
-
klass =
|
133
|
-
cls.respond_to?(:name) &&
|
134
|
-
cls.name == "Sprockets::Processor (#{klass})"
|
99
|
+
klass = postprocessors[mime_type].detect { |cls|
|
100
|
+
cls.respond_to?(:name) && cls.name == "Sprockets::LegacyProcProcessor (#{klass})"
|
135
101
|
}
|
136
102
|
end
|
137
103
|
|
138
|
-
|
104
|
+
mutate_hash_config(:postprocessors, mime_type) do |processors|
|
105
|
+
processors.delete(klass)
|
106
|
+
processors
|
107
|
+
end
|
139
108
|
end
|
140
109
|
|
141
|
-
# Returns an `Array` of `Processor` classes. If a `mime_type`
|
142
|
-
# argument is supplied, the processors registered under that
|
143
|
-
# extension will be returned.
|
144
|
-
#
|
145
110
|
# Bundle Processors are ran on concatenated assets rather than
|
146
111
|
# individual files.
|
112
|
+
attr_reader :bundle_processors
|
113
|
+
|
114
|
+
# Internal: Find and load bundle processors by mime type.
|
147
115
|
#
|
148
|
-
#
|
149
|
-
#
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
deep_copy_hash(@bundle_processors)
|
116
|
+
# mime_type - String MIME type.
|
117
|
+
#
|
118
|
+
# Returns Array of Procs.
|
119
|
+
def unwrap_bundle_processors(mime_type)
|
120
|
+
bundle_processors[mime_type].map do |processor|
|
121
|
+
unwrap_processor(processor)
|
155
122
|
end
|
156
123
|
end
|
157
124
|
|
158
125
|
# Registers a new Bundle Processor `klass` for `mime_type`.
|
159
126
|
#
|
160
|
-
# register_bundle_processor '
|
127
|
+
# register_bundle_processor 'application/javascript', Sprockets::DirectiveProcessor
|
161
128
|
#
|
162
129
|
# A block can be passed for to create a shorthand processor.
|
163
130
|
#
|
164
|
-
# register_bundle_processor '
|
131
|
+
# register_bundle_processor 'application/javascript', :my_processor do |context, data|
|
165
132
|
# data.gsub(...)
|
166
133
|
# end
|
167
134
|
#
|
168
135
|
def register_bundle_processor(mime_type, klass, &block)
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
@name = name
|
173
|
-
@processor = block
|
174
|
-
end
|
136
|
+
mutate_hash_config(:bundle_processors, mime_type) do |processors|
|
137
|
+
processors.push(wrap_processor(klass, block))
|
138
|
+
processors
|
175
139
|
end
|
176
|
-
|
177
|
-
@bundle_processors[mime_type].push(klass)
|
178
140
|
end
|
179
141
|
|
180
142
|
# Remove Bundle Processor `klass` for `mime_type`.
|
181
143
|
#
|
182
|
-
# unregister_bundle_processor '
|
144
|
+
# unregister_bundle_processor 'application/javascript', Sprockets::DirectiveProcessor
|
183
145
|
#
|
184
146
|
def unregister_bundle_processor(mime_type, klass)
|
185
147
|
if klass.is_a?(String) || klass.is_a?(Symbol)
|
186
|
-
klass =
|
187
|
-
cls.respond_to?(:name) &&
|
188
|
-
cls.name == "Sprockets::Processor (#{klass})"
|
148
|
+
klass = bundle_processors[mime_type].detect { |cls|
|
149
|
+
cls.respond_to?(:name) && cls.name == "Sprockets::LegacyProcProcessor (#{klass})"
|
189
150
|
}
|
190
151
|
end
|
191
152
|
|
192
|
-
|
153
|
+
mutate_hash_config(:bundle_processors, mime_type) do |processors|
|
154
|
+
processors.delete(klass)
|
155
|
+
processors
|
156
|
+
end
|
193
157
|
end
|
194
158
|
|
195
|
-
|
196
|
-
|
197
|
-
|
159
|
+
# Internal: Run processors on filename and data.
|
160
|
+
#
|
161
|
+
# Returns Hash.
|
162
|
+
def process(processors, uri, filename, load_path, name, content_type)
|
163
|
+
data, metadata = nil, {}
|
164
|
+
|
165
|
+
input = {
|
166
|
+
environment: self,
|
167
|
+
cache: cache,
|
168
|
+
uri: uri,
|
169
|
+
filename: filename,
|
170
|
+
load_path: load_path,
|
171
|
+
name: name,
|
172
|
+
content_type: content_type,
|
173
|
+
metadata: metadata
|
174
|
+
}
|
198
175
|
|
199
|
-
|
200
|
-
|
201
|
-
|
176
|
+
processors.each do |processor|
|
177
|
+
begin
|
178
|
+
result = processor.call(input.merge(data: data, metadata: metadata))
|
179
|
+
case result
|
180
|
+
when NilClass
|
181
|
+
# noop
|
182
|
+
when Hash
|
183
|
+
data = result[:data]
|
184
|
+
metadata = metadata.merge(result)
|
185
|
+
metadata.delete(:data)
|
186
|
+
when String
|
187
|
+
data = result
|
188
|
+
else
|
189
|
+
raise Error, "invalid processor return type: #{result.class}"
|
202
190
|
end
|
203
191
|
end
|
204
192
|
end
|
193
|
+
|
194
|
+
{
|
195
|
+
source: data,
|
196
|
+
charset: data.encoding.name.downcase,
|
197
|
+
length: data.bytesize,
|
198
|
+
digest: digest_class.hexdigest(data),
|
199
|
+
metadata: metadata
|
200
|
+
}
|
201
|
+
end
|
202
|
+
|
203
|
+
# Internal: Two dimensional Hash of reducer functions for a given mime type
|
204
|
+
# and asset metadata key.
|
205
|
+
attr_reader :bundle_reducers
|
206
|
+
|
207
|
+
# Public: Register bundle reducer function.
|
208
|
+
#
|
209
|
+
# Examples
|
210
|
+
#
|
211
|
+
# Sprockets.register_bundle_reducer 'application/javascript', :jshint_errors, [], :+
|
212
|
+
#
|
213
|
+
# Sprockets.register_bundle_reducer 'text/css', :selector_count, 0 { |total, count|
|
214
|
+
# total + count
|
215
|
+
# }
|
216
|
+
#
|
217
|
+
# mime_type - String MIME Type. Use '*/*' applies to all types.
|
218
|
+
# key - Symbol metadata key
|
219
|
+
# initial - Initial memo to pass to the reduce funciton (default: nil)
|
220
|
+
# block - Proc accepting the memo accumulator and current value
|
221
|
+
#
|
222
|
+
# Returns nothing.
|
223
|
+
def register_bundle_reducer(mime_type, key, *args, &block)
|
224
|
+
case args.size
|
225
|
+
when 0
|
226
|
+
reducer = block
|
227
|
+
when 1
|
228
|
+
if block_given?
|
229
|
+
initial = args[0]
|
230
|
+
reducer = block
|
231
|
+
else
|
232
|
+
initial = nil
|
233
|
+
reducer = args[0].to_proc
|
234
|
+
end
|
235
|
+
when 2
|
236
|
+
initial = args[0]
|
237
|
+
reducer = args[1].to_proc
|
238
|
+
else
|
239
|
+
raise ArgumentError, "wrong number of arguments (#{args.size} for 0..2)"
|
240
|
+
end
|
241
|
+
|
242
|
+
mutate_hash_config(:bundle_reducers, mime_type) do |reducers|
|
243
|
+
reducers.merge(key => [initial, reducer])
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
# Internal: Gather all bundle reducer functions for MIME type.
|
248
|
+
#
|
249
|
+
# mime_type - String MIME type
|
250
|
+
#
|
251
|
+
# Returns an Array of [initial, reducer_proc] pairs.
|
252
|
+
def unwrap_bundle_reducers(mime_type)
|
253
|
+
self.bundle_reducers['*/*'].merge(self.bundle_reducers[mime_type])
|
254
|
+
end
|
255
|
+
|
256
|
+
# Internal: Run bundle reducers on set of Assets producing a reduced
|
257
|
+
# metadata Hash.
|
258
|
+
#
|
259
|
+
# assets - Array of Assets
|
260
|
+
# reducers - Array of [initial, reducer_proc] pairs
|
261
|
+
#
|
262
|
+
# Returns reduced asset metadata Hash.
|
263
|
+
def process_bundle_reducers(assets, reducers)
|
264
|
+
initial = {}
|
265
|
+
reducers.each do |k, (v, _)|
|
266
|
+
initial[k] = v if v
|
267
|
+
end
|
268
|
+
|
269
|
+
assets.reduce(initial) do |h, asset|
|
270
|
+
reducers.each do |k, (_, block)|
|
271
|
+
value = k == :data ? asset.source : asset.metadata[k]
|
272
|
+
h[k] = h.key?(k) ? block.call(h[k], value) : value
|
273
|
+
end
|
274
|
+
h
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
private
|
279
|
+
def wrap_processor(klass, proc)
|
280
|
+
if !proc
|
281
|
+
if klass.class == Sprockets::LazyProcessor || klass.respond_to?(:call)
|
282
|
+
klass
|
283
|
+
else
|
284
|
+
LegacyTiltProcessor.new(klass)
|
285
|
+
end
|
286
|
+
elsif proc.respond_to?(:arity) && proc.arity == 2
|
287
|
+
LegacyProcProcessor.new(klass.to_s, proc)
|
288
|
+
else
|
289
|
+
proc
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def unwrap_processor(processor)
|
294
|
+
processor.respond_to?(:unwrap) ? processor.unwrap : processor
|
295
|
+
end
|
205
296
|
end
|
206
297
|
end
|