sprockets 4.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'sprockets/uri_utils'
|
3
|
+
require 'sprockets/path_utils'
|
4
|
+
|
5
|
+
module Sprockets
|
6
|
+
# This is a processor designed to add a source map "comment"
|
7
|
+
# to the bottom of a css or JS file that is serving a source
|
8
|
+
# map. An example of a comment might look like this
|
9
|
+
#
|
10
|
+
# //# application.js-80af0efcc960fc2ac93eda2f7b12e3db40ab360bf6ea269ceed3bea3678326f9.map
|
11
|
+
#
|
12
|
+
# As an asset is built it gets source map information added
|
13
|
+
# to the `asset.to_hash[:metadata][:map]` key. This contains all the
|
14
|
+
# information that is needed to build a source map file.
|
15
|
+
#
|
16
|
+
# To add this comment we must have an asset we can link to.
|
17
|
+
# To do this we ensure that the original aset is loaded, then
|
18
|
+
# we use a use a special mime type. For example `application/js-sourcemap+json`
|
19
|
+
# for a JS source map.
|
20
|
+
#
|
21
|
+
# This will trigger a new asset to be loaded and generated by the
|
22
|
+
# `SourceMapProcessor` processor.
|
23
|
+
#
|
24
|
+
# Finally once we have that file, we can generate a link to it
|
25
|
+
# with it's full fingerprint. This is done and then
|
26
|
+
# added to the original asset as a comment at the bottom.
|
27
|
+
#
|
28
|
+
class AddSourceMapCommentToAssetProcessor
|
29
|
+
def self.call(input)
|
30
|
+
|
31
|
+
case input[:content_type]
|
32
|
+
when "application/javascript"
|
33
|
+
comment = "\n//# sourceMappingURL=%s"
|
34
|
+
map_type = "application/js-sourcemap+json"
|
35
|
+
when "text/css"
|
36
|
+
comment = "\n/*# sourceMappingURL=%s */"
|
37
|
+
map_type = "application/css-sourcemap+json"
|
38
|
+
else
|
39
|
+
fail input[:content_type]
|
40
|
+
end
|
41
|
+
|
42
|
+
env = input[:environment]
|
43
|
+
|
44
|
+
uri, _ = env.resolve!(input[:filename], accept: input[:content_type])
|
45
|
+
asset = env.load(uri)
|
46
|
+
|
47
|
+
uri, _ = env.resolve!(input[:filename], accept: map_type)
|
48
|
+
map = env.load(uri)
|
49
|
+
|
50
|
+
uri, params = URIUtils.parse_asset_uri(input[:uri])
|
51
|
+
uri = env.expand_from_root(params[:index_alias]) if params[:index_alias]
|
52
|
+
path = PathUtils.relative_path_from(PathUtils.split_subpath(input[:load_path], uri), map.digest_path)
|
53
|
+
|
54
|
+
asset.metadata.merge(
|
55
|
+
data: asset.source + (comment % path) + "\n",
|
56
|
+
links: asset.links + [asset.uri, map.uri]
|
57
|
+
)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'fileutils'
|
3
|
+
require 'sprockets/digest_utils'
|
4
|
+
|
5
|
+
module Sprockets
|
6
|
+
class Asset
|
7
|
+
attr_reader :logical_path
|
8
|
+
|
9
|
+
# Private: Intialize Asset wrapper from attributes Hash.
|
10
|
+
#
|
11
|
+
# Asset wrappers should not be initialized directly, only
|
12
|
+
# Environment#find_asset should vend them.
|
13
|
+
#
|
14
|
+
# attributes - Hash of ivars
|
15
|
+
#
|
16
|
+
# Returns Asset.
|
17
|
+
def initialize(attributes = {})
|
18
|
+
@attributes = attributes
|
19
|
+
@content_type = attributes[:content_type]
|
20
|
+
@filename = attributes[:filename]
|
21
|
+
@id = attributes[:id]
|
22
|
+
@load_path = attributes[:load_path]
|
23
|
+
@logical_path = attributes[:logical_path]
|
24
|
+
@metadata = attributes[:metadata]
|
25
|
+
@name = attributes[:name]
|
26
|
+
@source = attributes[:source]
|
27
|
+
@uri = attributes[:uri]
|
28
|
+
end
|
29
|
+
|
30
|
+
# Internal: Return all internal instance variables as a hash.
|
31
|
+
#
|
32
|
+
# Returns a Hash.
|
33
|
+
def to_hash
|
34
|
+
@attributes
|
35
|
+
end
|
36
|
+
|
37
|
+
# Public: Metadata accumulated from pipeline process.
|
38
|
+
#
|
39
|
+
# The API status of the keys is dependent on the pipeline processors
|
40
|
+
# itself. So some values maybe considered public and others internal.
|
41
|
+
# See the pipeline proccessor documentation itself.
|
42
|
+
#
|
43
|
+
# Returns Hash.
|
44
|
+
attr_reader :metadata
|
45
|
+
|
46
|
+
# Public: Returns String path of asset.
|
47
|
+
attr_reader :filename
|
48
|
+
|
49
|
+
# Internal: Unique asset object ID.
|
50
|
+
#
|
51
|
+
# Returns a String.
|
52
|
+
attr_reader :id
|
53
|
+
|
54
|
+
# Public: Internal URI to lookup asset by.
|
55
|
+
#
|
56
|
+
# NOT a publically accessible URL.
|
57
|
+
#
|
58
|
+
# Returns URI.
|
59
|
+
attr_reader :uri
|
60
|
+
|
61
|
+
# Public: Return logical path with digest spliced in.
|
62
|
+
#
|
63
|
+
# "foo/bar-37b51d194a7513e45b56f6524f2d51f2.js"
|
64
|
+
#
|
65
|
+
# Returns String.
|
66
|
+
def digest_path
|
67
|
+
logical_path.sub(/\.(\w+)$/) { |ext| "-#{etag}#{ext}" }
|
68
|
+
end
|
69
|
+
|
70
|
+
# Public: Return load path + logical path with digest spliced in.
|
71
|
+
#
|
72
|
+
# Returns String.
|
73
|
+
def full_digest_path
|
74
|
+
File.join(@load_path, digest_path)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Public: Returns String MIME type of asset. Returns nil if type is unknown.
|
78
|
+
attr_reader :content_type
|
79
|
+
|
80
|
+
# Public: Get all externally linked asset filenames from asset.
|
81
|
+
#
|
82
|
+
# All linked assets should be compiled anytime this asset is.
|
83
|
+
#
|
84
|
+
# Returns Set of String asset URIs.
|
85
|
+
def links
|
86
|
+
metadata[:links] || Set.new
|
87
|
+
end
|
88
|
+
|
89
|
+
# Public: Return `String` of concatenated source.
|
90
|
+
#
|
91
|
+
# Returns String.
|
92
|
+
def source
|
93
|
+
if @source
|
94
|
+
@source
|
95
|
+
else
|
96
|
+
# File is read everytime to avoid memory bloat of large binary files
|
97
|
+
File.binread(filename)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Public: Alias for #source.
|
102
|
+
#
|
103
|
+
# Returns String.
|
104
|
+
def to_s
|
105
|
+
source
|
106
|
+
end
|
107
|
+
|
108
|
+
# Public: Get charset of source.
|
109
|
+
#
|
110
|
+
# Returns a String charset name or nil if binary.
|
111
|
+
def charset
|
112
|
+
metadata[:charset]
|
113
|
+
end
|
114
|
+
|
115
|
+
# Public: Returns Integer length of source.
|
116
|
+
def length
|
117
|
+
metadata[:length]
|
118
|
+
end
|
119
|
+
alias_method :bytesize, :length
|
120
|
+
|
121
|
+
# Public: Returns String byte digest of source.
|
122
|
+
def digest
|
123
|
+
metadata[:digest]
|
124
|
+
end
|
125
|
+
|
126
|
+
# Private: Return the version of the environment where the asset was generated.
|
127
|
+
def environment_version
|
128
|
+
metadata[:environment_version]
|
129
|
+
end
|
130
|
+
|
131
|
+
# Public: Returns String hexdigest of source.
|
132
|
+
def hexdigest
|
133
|
+
DigestUtils.pack_hexdigest(digest)
|
134
|
+
end
|
135
|
+
|
136
|
+
# Pubic: ETag String of Asset.
|
137
|
+
def etag
|
138
|
+
DigestUtils.pack_hexdigest(environment_version + digest)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Public: Returns String base64 digest of source.
|
142
|
+
def base64digest
|
143
|
+
DigestUtils.pack_base64digest(digest)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Public: A "named information" URL for subresource integrity.
|
147
|
+
def integrity
|
148
|
+
DigestUtils.integrity_uri(digest)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Public: Add enumerator to allow `Asset` instances to be used as Rack
|
152
|
+
# compatible body objects.
|
153
|
+
#
|
154
|
+
# block
|
155
|
+
# part - String body chunk
|
156
|
+
#
|
157
|
+
# Returns nothing.
|
158
|
+
def each
|
159
|
+
yield to_s
|
160
|
+
end
|
161
|
+
|
162
|
+
# Deprecated: Save asset to disk.
|
163
|
+
#
|
164
|
+
# filename - String target
|
165
|
+
#
|
166
|
+
# Returns nothing.
|
167
|
+
def write_to(filename)
|
168
|
+
FileUtils.mkdir_p File.dirname(filename)
|
169
|
+
|
170
|
+
PathUtils.atomic_write(filename) do |f|
|
171
|
+
f.write source
|
172
|
+
end
|
173
|
+
|
174
|
+
nil
|
175
|
+
end
|
176
|
+
|
177
|
+
# Public: Pretty inspect
|
178
|
+
#
|
179
|
+
# Returns String.
|
180
|
+
def inspect
|
181
|
+
"#<#{self.class}:#{object_id.to_s(16)} #{uri.inspect}>"
|
182
|
+
end
|
183
|
+
|
184
|
+
# Public: Implements Object#hash so Assets can be used as a Hash key or
|
185
|
+
# in a Set.
|
186
|
+
#
|
187
|
+
# Returns Integer hash of the id.
|
188
|
+
def hash
|
189
|
+
id.hash
|
190
|
+
end
|
191
|
+
|
192
|
+
# Public: Compare assets.
|
193
|
+
#
|
194
|
+
# Assets are equal if they share the same path and digest.
|
195
|
+
#
|
196
|
+
# Returns true or false.
|
197
|
+
def eql?(other)
|
198
|
+
self.class == other.class && self.id == other.id
|
199
|
+
end
|
200
|
+
alias_method :==, :eql?
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Sprockets
|
3
|
+
module Autoload
|
4
|
+
autoload :Babel, 'sprockets/autoload/babel'
|
5
|
+
autoload :Closure, 'sprockets/autoload/closure'
|
6
|
+
autoload :CoffeeScript, 'sprockets/autoload/coffee_script'
|
7
|
+
autoload :Eco, 'sprockets/autoload/eco'
|
8
|
+
autoload :EJS, 'sprockets/autoload/ejs'
|
9
|
+
autoload :JSMinC, 'sprockets/autoload/jsminc'
|
10
|
+
autoload :Sass, 'sprockets/autoload/sass'
|
11
|
+
autoload :SassC, 'sprockets/autoload/sassc'
|
12
|
+
autoload :Uglifier, 'sprockets/autoload/uglifier'
|
13
|
+
autoload :YUI, 'sprockets/autoload/yui'
|
14
|
+
autoload :Zopfli, 'sprockets/autoload/zopfli'
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'sprockets/autoload'
|
3
|
+
require 'sprockets/path_utils'
|
4
|
+
require 'sprockets/source_map_utils'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
module Sprockets
|
8
|
+
class BabelProcessor
|
9
|
+
VERSION = '1'
|
10
|
+
|
11
|
+
def self.instance
|
12
|
+
@instance ||= new
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.call(input)
|
16
|
+
instance.call(input)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.cache_key
|
20
|
+
instance.cache_key
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :cache_key
|
24
|
+
|
25
|
+
def initialize(options = {})
|
26
|
+
@options = options.merge({
|
27
|
+
'blacklist' => (options['blacklist'] || []) + ['useStrict'],
|
28
|
+
'sourceMap' => true
|
29
|
+
}).freeze
|
30
|
+
|
31
|
+
@cache_key = [
|
32
|
+
self.class.name,
|
33
|
+
Autoload::Babel::Transpiler::VERSION,
|
34
|
+
Autoload::Babel::Source::VERSION,
|
35
|
+
VERSION,
|
36
|
+
@options
|
37
|
+
].freeze
|
38
|
+
end
|
39
|
+
|
40
|
+
def call(input)
|
41
|
+
data = input[:data]
|
42
|
+
|
43
|
+
result = input[:cache].fetch(@cache_key + [input[:filename]] + [data]) do
|
44
|
+
opts = {
|
45
|
+
'moduleRoot' => nil,
|
46
|
+
'filename' => input[:filename],
|
47
|
+
'filenameRelative' => PathUtils.split_subpath(input[:load_path], input[:filename]),
|
48
|
+
'sourceFileName' => File.basename(input[:filename]),
|
49
|
+
'sourceMapTarget' => input[:filename]
|
50
|
+
}.merge(@options)
|
51
|
+
|
52
|
+
if opts['moduleIds'] && opts['moduleRoot']
|
53
|
+
opts['moduleId'] ||= File.join(opts['moduleRoot'], input[:name])
|
54
|
+
elsif opts['moduleIds']
|
55
|
+
opts['moduleId'] ||= input[:name]
|
56
|
+
end
|
57
|
+
Autoload::Babel::Transpiler.transform(data, opts)
|
58
|
+
end
|
59
|
+
|
60
|
+
map = SourceMapUtils.format_source_map(result["map"], input)
|
61
|
+
map = SourceMapUtils.combine_source_maps(input[:metadata][:map], map)
|
62
|
+
|
63
|
+
{ data: result['code'], map: map }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|