sprockets 4.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/CHANGELOG.md +72 -0
- data/README.md +665 -0
- data/bin/sprockets +93 -0
- data/lib/rake/sprocketstask.rb +153 -0
- data/lib/sprockets.rb +229 -0
- data/lib/sprockets/add_source_map_comment_to_asset_processor.rb +60 -0
- data/lib/sprockets/asset.rb +202 -0
- data/lib/sprockets/autoload.rb +16 -0
- data/lib/sprockets/autoload/babel.rb +8 -0
- data/lib/sprockets/autoload/closure.rb +8 -0
- data/lib/sprockets/autoload/coffee_script.rb +8 -0
- data/lib/sprockets/autoload/eco.rb +8 -0
- data/lib/sprockets/autoload/ejs.rb +8 -0
- data/lib/sprockets/autoload/jsminc.rb +8 -0
- data/lib/sprockets/autoload/sass.rb +8 -0
- data/lib/sprockets/autoload/sassc.rb +8 -0
- data/lib/sprockets/autoload/uglifier.rb +8 -0
- data/lib/sprockets/autoload/yui.rb +8 -0
- data/lib/sprockets/autoload/zopfli.rb +7 -0
- data/lib/sprockets/babel_processor.rb +66 -0
- data/lib/sprockets/base.rb +147 -0
- data/lib/sprockets/bower.rb +61 -0
- data/lib/sprockets/bundle.rb +105 -0
- data/lib/sprockets/cache.rb +271 -0
- data/lib/sprockets/cache/file_store.rb +208 -0
- data/lib/sprockets/cache/memory_store.rb +75 -0
- data/lib/sprockets/cache/null_store.rb +54 -0
- data/lib/sprockets/cached_environment.rb +64 -0
- data/lib/sprockets/closure_compressor.rb +48 -0
- data/lib/sprockets/coffee_script_processor.rb +39 -0
- data/lib/sprockets/compressing.rb +134 -0
- data/lib/sprockets/configuration.rb +79 -0
- data/lib/sprockets/context.rb +304 -0
- data/lib/sprockets/dependencies.rb +74 -0
- data/lib/sprockets/digest_utils.rb +200 -0
- data/lib/sprockets/directive_processor.rb +414 -0
- data/lib/sprockets/eco_processor.rb +33 -0
- data/lib/sprockets/ejs_processor.rb +32 -0
- data/lib/sprockets/encoding_utils.rb +262 -0
- data/lib/sprockets/environment.rb +46 -0
- data/lib/sprockets/erb_processor.rb +37 -0
- data/lib/sprockets/errors.rb +12 -0
- data/lib/sprockets/exporters/base.rb +71 -0
- data/lib/sprockets/exporters/file_exporter.rb +24 -0
- data/lib/sprockets/exporters/zlib_exporter.rb +33 -0
- data/lib/sprockets/exporters/zopfli_exporter.rb +14 -0
- data/lib/sprockets/exporting.rb +73 -0
- data/lib/sprockets/file_reader.rb +16 -0
- data/lib/sprockets/http_utils.rb +135 -0
- data/lib/sprockets/jsminc_compressor.rb +32 -0
- data/lib/sprockets/jst_processor.rb +50 -0
- data/lib/sprockets/loader.rb +345 -0
- data/lib/sprockets/manifest.rb +338 -0
- data/lib/sprockets/manifest_utils.rb +48 -0
- data/lib/sprockets/mime.rb +96 -0
- data/lib/sprockets/npm.rb +52 -0
- data/lib/sprockets/path_dependency_utils.rb +77 -0
- data/lib/sprockets/path_digest_utils.rb +48 -0
- data/lib/sprockets/path_utils.rb +367 -0
- data/lib/sprockets/paths.rb +82 -0
- data/lib/sprockets/preprocessors/default_source_map.rb +49 -0
- data/lib/sprockets/processing.rb +228 -0
- data/lib/sprockets/processor_utils.rb +169 -0
- data/lib/sprockets/resolve.rb +295 -0
- data/lib/sprockets/sass_cache_store.rb +30 -0
- data/lib/sprockets/sass_compressor.rb +63 -0
- data/lib/sprockets/sass_functions.rb +3 -0
- data/lib/sprockets/sass_importer.rb +3 -0
- data/lib/sprockets/sass_processor.rb +313 -0
- data/lib/sprockets/sassc_compressor.rb +56 -0
- data/lib/sprockets/sassc_processor.rb +297 -0
- data/lib/sprockets/server.rb +295 -0
- data/lib/sprockets/source_map_processor.rb +66 -0
- data/lib/sprockets/source_map_utils.rb +483 -0
- data/lib/sprockets/transformers.rb +173 -0
- data/lib/sprockets/uglifier_compressor.rb +66 -0
- data/lib/sprockets/unloaded_asset.rb +139 -0
- data/lib/sprockets/uri_tar.rb +99 -0
- data/lib/sprockets/uri_utils.rb +191 -0
- data/lib/sprockets/utils.rb +202 -0
- data/lib/sprockets/utils/gzip.rb +99 -0
- data/lib/sprockets/version.rb +4 -0
- data/lib/sprockets/yui_compressor.rb +56 -0
- metadata +444 -0
@@ -0,0 +1,191 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module Sprockets
|
5
|
+
# Internal: Asset URI related parsing utilities. Mixed into Environment.
|
6
|
+
#
|
7
|
+
# An Asset URI identifies the compiled Asset result. It shares the file:
|
8
|
+
# scheme and requires an absolute path.
|
9
|
+
#
|
10
|
+
# Other query parameters
|
11
|
+
#
|
12
|
+
# type - String output content type. Otherwise assumed from file extension.
|
13
|
+
# This maybe different than the extension if the asset is transformed
|
14
|
+
# from one content type to another. For an example .coffee -> .js.
|
15
|
+
#
|
16
|
+
# id - Unique fingerprint of the entire asset and all its metadata. Assets
|
17
|
+
# will only have the same id if they serialize to an identical value.
|
18
|
+
#
|
19
|
+
# pipeline - String name of pipeline.
|
20
|
+
#
|
21
|
+
module URIUtils
|
22
|
+
extend self
|
23
|
+
|
24
|
+
# Internal: Parse URI into component parts.
|
25
|
+
#
|
26
|
+
# uri - String uri
|
27
|
+
#
|
28
|
+
# Returns Array of components.
|
29
|
+
def split_uri(uri)
|
30
|
+
URI.split(uri)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Internal: Join URI component parts into String.
|
34
|
+
#
|
35
|
+
# Returns String.
|
36
|
+
def join_uri(scheme, userinfo, host, port, registry, path, opaque, query, fragment)
|
37
|
+
URI::Generic.new(scheme, userinfo, host, port, registry, path, opaque, query, fragment).to_s
|
38
|
+
end
|
39
|
+
|
40
|
+
# Internal: Parse file: URI into component parts.
|
41
|
+
#
|
42
|
+
# uri - String uri
|
43
|
+
#
|
44
|
+
# Returns [scheme, host, path, query].
|
45
|
+
def split_file_uri(uri)
|
46
|
+
scheme, _, host, _, _, path, _, query, _ = URI.split(uri)
|
47
|
+
|
48
|
+
path = URI::Generic::DEFAULT_PARSER.unescape(path)
|
49
|
+
path.force_encoding(Encoding::UTF_8)
|
50
|
+
|
51
|
+
# Hack for parsing Windows "/C:/Users/IEUser" paths
|
52
|
+
if File::ALT_SEPARATOR && path[2] == ':'
|
53
|
+
path = path[1..-1]
|
54
|
+
end
|
55
|
+
|
56
|
+
[scheme, host, path, query]
|
57
|
+
end
|
58
|
+
|
59
|
+
# Internal: Join file: URI component parts into String.
|
60
|
+
#
|
61
|
+
# Returns String.
|
62
|
+
def join_file_uri(scheme, host, path, query)
|
63
|
+
str = +"#{scheme}://"
|
64
|
+
str << host if host
|
65
|
+
path = "/#{path}" unless path.start_with?("/".freeze)
|
66
|
+
str << URI::Generic::DEFAULT_PARSER.escape(path)
|
67
|
+
str << "?#{query}" if query
|
68
|
+
str
|
69
|
+
end
|
70
|
+
|
71
|
+
# Internal: Check if String is a valid Asset URI.
|
72
|
+
#
|
73
|
+
# str - Possible String asset URI.
|
74
|
+
#
|
75
|
+
# Returns true or false.
|
76
|
+
def valid_asset_uri?(str)
|
77
|
+
# Quick prefix check before attempting a full parse
|
78
|
+
str.start_with?("file://".freeze) && parse_asset_uri(str) ? true : false
|
79
|
+
rescue URI::InvalidURIError
|
80
|
+
false
|
81
|
+
end
|
82
|
+
|
83
|
+
# Internal: Parse Asset URI.
|
84
|
+
#
|
85
|
+
# Examples
|
86
|
+
#
|
87
|
+
# parse("file:///tmp/js/application.coffee?type=application/javascript")
|
88
|
+
# # => "/tmp/js/application.coffee", {type: "application/javascript"}
|
89
|
+
#
|
90
|
+
# uri - String asset URI
|
91
|
+
#
|
92
|
+
# Returns String path and Hash of symbolized parameters.
|
93
|
+
def parse_asset_uri(uri)
|
94
|
+
scheme, _, path, query = split_file_uri(uri)
|
95
|
+
|
96
|
+
unless scheme == 'file'
|
97
|
+
raise URI::InvalidURIError, "expected file:// scheme: #{uri}"
|
98
|
+
end
|
99
|
+
|
100
|
+
return path, parse_uri_query_params(query)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Internal: Build Asset URI.
|
104
|
+
#
|
105
|
+
# Examples
|
106
|
+
#
|
107
|
+
# build("/tmp/js/application.coffee", type: "application/javascript")
|
108
|
+
# # => "file:///tmp/js/application.coffee?type=application/javascript"
|
109
|
+
#
|
110
|
+
# path - String file path
|
111
|
+
# params - Hash of optional parameters
|
112
|
+
#
|
113
|
+
# Returns String URI.
|
114
|
+
def build_asset_uri(path, params = {})
|
115
|
+
join_file_uri("file", nil, path, encode_uri_query_params(params))
|
116
|
+
end
|
117
|
+
|
118
|
+
# Internal: Parse file-digest dependency URI.
|
119
|
+
#
|
120
|
+
# Examples
|
121
|
+
#
|
122
|
+
# parse("file-digest:/tmp/js/application.js")
|
123
|
+
# # => "/tmp/js/application.js"
|
124
|
+
#
|
125
|
+
# uri - String file-digest URI
|
126
|
+
#
|
127
|
+
# Returns String path.
|
128
|
+
def parse_file_digest_uri(uri)
|
129
|
+
scheme, _, path, _ = split_file_uri(uri)
|
130
|
+
|
131
|
+
unless scheme == 'file-digest'.freeze
|
132
|
+
raise URI::InvalidURIError, "expected file-digest scheme: #{uri}"
|
133
|
+
end
|
134
|
+
|
135
|
+
path
|
136
|
+
end
|
137
|
+
|
138
|
+
# Internal: Build file-digest dependency URI.
|
139
|
+
#
|
140
|
+
# Examples
|
141
|
+
#
|
142
|
+
# build("/tmp/js/application.js")
|
143
|
+
# # => "file-digest:/tmp/js/application.js"
|
144
|
+
#
|
145
|
+
# path - String file path
|
146
|
+
#
|
147
|
+
# Returns String URI.
|
148
|
+
def build_file_digest_uri(path)
|
149
|
+
join_file_uri('file-digest'.freeze, nil, path, nil)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Internal: Serialize hash of params into query string.
|
153
|
+
#
|
154
|
+
# params - Hash of params to serialize
|
155
|
+
#
|
156
|
+
# Returns String query or nil if empty.
|
157
|
+
def encode_uri_query_params(params)
|
158
|
+
query = []
|
159
|
+
|
160
|
+
params.each do |key, value|
|
161
|
+
case value
|
162
|
+
when Integer
|
163
|
+
query << "#{key}=#{value}"
|
164
|
+
when String, Symbol
|
165
|
+
query << "#{key}=#{URI::Generic::DEFAULT_PARSER.escape(value.to_s)}"
|
166
|
+
when TrueClass
|
167
|
+
query << "#{key}"
|
168
|
+
when FalseClass, NilClass
|
169
|
+
else
|
170
|
+
raise TypeError, "unexpected type: #{value.class}"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
"#{query.join('&'.freeze)}" if query.any?
|
175
|
+
end
|
176
|
+
|
177
|
+
# Internal: Parse query string into hash of params
|
178
|
+
#
|
179
|
+
# query - String query string
|
180
|
+
#
|
181
|
+
# Return Hash of params.
|
182
|
+
def parse_uri_query_params(query)
|
183
|
+
query.to_s.split('&'.freeze).reduce({}) do |h, p|
|
184
|
+
k, v = p.split('='.freeze, 2)
|
185
|
+
v = URI::Generic::DEFAULT_PARSER.unescape(v) if v
|
186
|
+
h[k.to_sym] = v || true
|
187
|
+
h
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
module Sprockets
|
5
|
+
# Internal: Utils, we didn't know where else to put it! Functions may
|
6
|
+
# eventually be shuffled into more specific drawers.
|
7
|
+
module Utils
|
8
|
+
extend self
|
9
|
+
|
10
|
+
# Internal: Check if object can safely be .dup'd.
|
11
|
+
#
|
12
|
+
# Similar to ActiveSupport #duplicable? check.
|
13
|
+
#
|
14
|
+
# obj - Any Object
|
15
|
+
#
|
16
|
+
# Returns false if .dup would raise a TypeError, otherwise true.
|
17
|
+
def duplicable?(obj)
|
18
|
+
case obj
|
19
|
+
when NilClass, FalseClass, TrueClass, Symbol, Numeric
|
20
|
+
false
|
21
|
+
else
|
22
|
+
true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Internal: Duplicate and store key/value on new frozen hash.
|
27
|
+
#
|
28
|
+
# Seperated for recursive calls, always use hash_reassoc(hash, *keys).
|
29
|
+
#
|
30
|
+
# hash - Hash
|
31
|
+
# key - Object key
|
32
|
+
#
|
33
|
+
# Returns Hash.
|
34
|
+
def hash_reassoc1(hash, key)
|
35
|
+
hash = hash.dup if hash.frozen?
|
36
|
+
old_value = hash[key]
|
37
|
+
old_value = old_value.dup if duplicable?(old_value)
|
38
|
+
new_value = yield old_value
|
39
|
+
new_value.freeze if duplicable?(new_value)
|
40
|
+
hash.store(key, new_value)
|
41
|
+
hash.freeze
|
42
|
+
end
|
43
|
+
|
44
|
+
# Internal: Duplicate and store key/value on new frozen hash.
|
45
|
+
#
|
46
|
+
# Similar to Hash#store for nested frozen hashes.
|
47
|
+
#
|
48
|
+
# hash - Hash
|
49
|
+
# key_a - Object key. Use multiple keys for nested hashes.
|
50
|
+
# key_b - Object key. Use multiple keys for nested hashes.
|
51
|
+
# block - Receives current value at key.
|
52
|
+
#
|
53
|
+
# Examples
|
54
|
+
#
|
55
|
+
# config = {paths: ["/bin", "/sbin"]}.freeze
|
56
|
+
# new_config = hash_reassoc(config, :paths) do |paths|
|
57
|
+
# paths << "/usr/local/bin"
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# Returns duplicated frozen Hash.
|
61
|
+
def hash_reassoc(hash, key_a, key_b = nil, &block)
|
62
|
+
if key_b
|
63
|
+
hash_reassoc1(hash, key_a) do |value|
|
64
|
+
hash_reassoc(value, key_b, &block)
|
65
|
+
end
|
66
|
+
else
|
67
|
+
hash_reassoc1(hash, key_a, &block)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
WHITESPACE_ORDINALS = {0x0A => "\n", 0x20 => " ", 0x09 => "\t"}
|
72
|
+
private_constant :WHITESPACE_ORDINALS
|
73
|
+
|
74
|
+
# Internal: Check if string has a trailing semicolon.
|
75
|
+
#
|
76
|
+
# str - String
|
77
|
+
#
|
78
|
+
# Returns true or false.
|
79
|
+
def string_end_with_semicolon?(str)
|
80
|
+
i = str.size - 1
|
81
|
+
while i >= 0
|
82
|
+
c = str[i].ord
|
83
|
+
i -= 1
|
84
|
+
|
85
|
+
next if WHITESPACE_ORDINALS[c]
|
86
|
+
|
87
|
+
return c === 0x3B
|
88
|
+
end
|
89
|
+
|
90
|
+
true
|
91
|
+
end
|
92
|
+
|
93
|
+
# Internal: Accumulate asset source to buffer and append a trailing
|
94
|
+
# semicolon if necessary.
|
95
|
+
#
|
96
|
+
# buf - String buffer to append to
|
97
|
+
# source - String source to append
|
98
|
+
#
|
99
|
+
# Returns buf String.
|
100
|
+
def concat_javascript_sources(buf, source)
|
101
|
+
return buf if source.bytesize <= 0
|
102
|
+
|
103
|
+
buf << source
|
104
|
+
# If the source contains non-ASCII characters, indexing on it becomes O(N).
|
105
|
+
# This will lead to O(N^2) performance in string_end_with_semicolon?, so we should use 32 bit encoding to make sure indexing stays O(1)
|
106
|
+
source = source.encode(Encoding::UTF_32LE) unless source.ascii_only?
|
107
|
+
return buf if string_end_with_semicolon?(source)
|
108
|
+
|
109
|
+
# If the last character in the string was whitespace,
|
110
|
+
# such as a newline, then we want to put the semicolon
|
111
|
+
# before the whitespace. Otherwise append a semicolon.
|
112
|
+
if whitespace = WHITESPACE_ORDINALS[source[-1].ord]
|
113
|
+
buf[-1] = ";#{whitespace}"
|
114
|
+
else
|
115
|
+
buf << ";"
|
116
|
+
end
|
117
|
+
|
118
|
+
buf
|
119
|
+
end
|
120
|
+
|
121
|
+
# Internal: Inject into target module for the duration of the block.
|
122
|
+
#
|
123
|
+
# mod - Module
|
124
|
+
#
|
125
|
+
# Returns result of block.
|
126
|
+
def module_include(base, mod)
|
127
|
+
old_methods = {}
|
128
|
+
|
129
|
+
mod.instance_methods.each do |sym|
|
130
|
+
old_methods[sym] = base.instance_method(sym) if base.method_defined?(sym)
|
131
|
+
end
|
132
|
+
|
133
|
+
mod.instance_methods.each do |sym|
|
134
|
+
method = mod.instance_method(sym)
|
135
|
+
base.send(:define_method, sym, method)
|
136
|
+
end
|
137
|
+
|
138
|
+
yield
|
139
|
+
ensure
|
140
|
+
mod.instance_methods.each do |sym|
|
141
|
+
base.send(:undef_method, sym) if base.method_defined?(sym)
|
142
|
+
end
|
143
|
+
old_methods.each do |sym, method|
|
144
|
+
base.send(:define_method, sym, method)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Internal: Post-order Depth-First search algorithm.
|
149
|
+
#
|
150
|
+
# Used for resolving asset dependencies.
|
151
|
+
#
|
152
|
+
# initial - Initial Array of nodes to traverse.
|
153
|
+
# block -
|
154
|
+
# node - Current node to get children of
|
155
|
+
#
|
156
|
+
# Returns a Set of nodes.
|
157
|
+
def dfs(initial)
|
158
|
+
nodes, seen = Set.new, Set.new
|
159
|
+
stack = Array(initial).reverse
|
160
|
+
|
161
|
+
while node = stack.pop
|
162
|
+
if seen.include?(node)
|
163
|
+
nodes.add(node)
|
164
|
+
else
|
165
|
+
seen.add(node)
|
166
|
+
stack.push(node)
|
167
|
+
stack.concat(Array(yield node).reverse)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
nodes
|
172
|
+
end
|
173
|
+
|
174
|
+
# Internal: Post-order Depth-First search algorithm that gathers all paths
|
175
|
+
# along the way.
|
176
|
+
#
|
177
|
+
# TODO: Rename function.
|
178
|
+
#
|
179
|
+
# path - Initial Array node path
|
180
|
+
# block -
|
181
|
+
# node - Current node to get children of
|
182
|
+
#
|
183
|
+
# Returns an Array of node Arrays.
|
184
|
+
def dfs_paths(path)
|
185
|
+
paths = []
|
186
|
+
stack = [path]
|
187
|
+
seen = Set.new
|
188
|
+
|
189
|
+
while path = stack.pop
|
190
|
+
seen.add(path.last)
|
191
|
+
paths << path
|
192
|
+
|
193
|
+
children = yield path.last
|
194
|
+
children.reverse_each do |node|
|
195
|
+
stack.push(path + [node]) unless seen.include?(node)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
paths
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Sprockets
|
3
|
+
module Utils
|
4
|
+
class Gzip
|
5
|
+
# Private: Generates a gzipped file based off of reference asset.
|
6
|
+
#
|
7
|
+
# ZlibArchiver.call(file, source, mtime)
|
8
|
+
#
|
9
|
+
# Compresses a given `source` using stdlib Zlib algorithm
|
10
|
+
# writes contents to the `file` passed in. Sets `mtime` of
|
11
|
+
# written file to passed in `mtime`
|
12
|
+
module ZlibArchiver
|
13
|
+
def self.call(file, source, mtime)
|
14
|
+
gz = Zlib::GzipWriter.new(file, Zlib::BEST_COMPRESSION)
|
15
|
+
gz.mtime = mtime
|
16
|
+
gz.write(source)
|
17
|
+
gz.close
|
18
|
+
|
19
|
+
File.utime(mtime, mtime, file.path)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Private: Generates a gzipped file based off of reference asset.
|
24
|
+
#
|
25
|
+
# ZopfliArchiver.call(file, source, mtime)
|
26
|
+
#
|
27
|
+
# Compresses a given `source` using the zopfli gem
|
28
|
+
# writes contents to the `file` passed in. Sets `mtime` of
|
29
|
+
# written file to passed in `mtime`
|
30
|
+
module ZopfliArchiver
|
31
|
+
def self.call(file, source, mtime)
|
32
|
+
compressed_source = Autoload::Zopfli.deflate(source, format: :gzip, mtime: mtime)
|
33
|
+
file.write(compressed_source)
|
34
|
+
file.close
|
35
|
+
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
attr_reader :content_type, :source, :charset, :archiver
|
41
|
+
|
42
|
+
# Private: Generates a gzipped file based off of reference file.
|
43
|
+
def initialize(asset, archiver: ZlibArchiver)
|
44
|
+
@content_type = asset.content_type
|
45
|
+
@source = asset.source
|
46
|
+
@charset = asset.charset
|
47
|
+
@archiver = archiver
|
48
|
+
end
|
49
|
+
|
50
|
+
# What non-text mime types should we compress? This list comes from:
|
51
|
+
# https://www.fastly.com/blog/new-gzip-settings-and-deciding-what-compress
|
52
|
+
COMPRESSABLE_MIME_TYPES = {
|
53
|
+
"application/vnd.ms-fontobject" => true,
|
54
|
+
"application/x-font-opentype" => true,
|
55
|
+
"application/x-font-ttf" => true,
|
56
|
+
"image/x-icon" => true,
|
57
|
+
"image/svg+xml" => true
|
58
|
+
}
|
59
|
+
|
60
|
+
# Private: Returns whether or not an asset can be compressed.
|
61
|
+
#
|
62
|
+
# We want to compress any file that is text based.
|
63
|
+
# You do not want to compress binary
|
64
|
+
# files as they may already be compressed and running them
|
65
|
+
# through a compression algorithm would make them larger.
|
66
|
+
#
|
67
|
+
# Return Boolean.
|
68
|
+
def can_compress?
|
69
|
+
# The "charset" of a mime type is present if the value is
|
70
|
+
# encoded text. We can check this value to see if the asset
|
71
|
+
# can be compressed.
|
72
|
+
#
|
73
|
+
# We also check against our list of non-text compressible mime types
|
74
|
+
@charset || COMPRESSABLE_MIME_TYPES.include?(@content_type)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Private: Opposite of `can_compress?`.
|
78
|
+
#
|
79
|
+
# Returns Boolean.
|
80
|
+
def cannot_compress?
|
81
|
+
!can_compress?
|
82
|
+
end
|
83
|
+
|
84
|
+
# Private: Generates a gzipped file based off of reference asset.
|
85
|
+
#
|
86
|
+
# Compresses the target asset's contents and puts it into a file with
|
87
|
+
# the same name plus a `.gz` extension in the same folder as the original.
|
88
|
+
# Does not modify the target asset.
|
89
|
+
#
|
90
|
+
# Returns nothing.
|
91
|
+
def compress(file, target)
|
92
|
+
mtime = Sprockets::PathUtils.stat(target).mtime
|
93
|
+
archiver.call(file, source, mtime)
|
94
|
+
|
95
|
+
nil
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|