sprockets 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +72 -0
  3. data/README.md +665 -0
  4. data/bin/sprockets +93 -0
  5. data/lib/rake/sprocketstask.rb +153 -0
  6. data/lib/sprockets.rb +229 -0
  7. data/lib/sprockets/add_source_map_comment_to_asset_processor.rb +60 -0
  8. data/lib/sprockets/asset.rb +202 -0
  9. data/lib/sprockets/autoload.rb +16 -0
  10. data/lib/sprockets/autoload/babel.rb +8 -0
  11. data/lib/sprockets/autoload/closure.rb +8 -0
  12. data/lib/sprockets/autoload/coffee_script.rb +8 -0
  13. data/lib/sprockets/autoload/eco.rb +8 -0
  14. data/lib/sprockets/autoload/ejs.rb +8 -0
  15. data/lib/sprockets/autoload/jsminc.rb +8 -0
  16. data/lib/sprockets/autoload/sass.rb +8 -0
  17. data/lib/sprockets/autoload/sassc.rb +8 -0
  18. data/lib/sprockets/autoload/uglifier.rb +8 -0
  19. data/lib/sprockets/autoload/yui.rb +8 -0
  20. data/lib/sprockets/autoload/zopfli.rb +7 -0
  21. data/lib/sprockets/babel_processor.rb +66 -0
  22. data/lib/sprockets/base.rb +147 -0
  23. data/lib/sprockets/bower.rb +61 -0
  24. data/lib/sprockets/bundle.rb +105 -0
  25. data/lib/sprockets/cache.rb +271 -0
  26. data/lib/sprockets/cache/file_store.rb +208 -0
  27. data/lib/sprockets/cache/memory_store.rb +75 -0
  28. data/lib/sprockets/cache/null_store.rb +54 -0
  29. data/lib/sprockets/cached_environment.rb +64 -0
  30. data/lib/sprockets/closure_compressor.rb +48 -0
  31. data/lib/sprockets/coffee_script_processor.rb +39 -0
  32. data/lib/sprockets/compressing.rb +134 -0
  33. data/lib/sprockets/configuration.rb +79 -0
  34. data/lib/sprockets/context.rb +304 -0
  35. data/lib/sprockets/dependencies.rb +74 -0
  36. data/lib/sprockets/digest_utils.rb +200 -0
  37. data/lib/sprockets/directive_processor.rb +414 -0
  38. data/lib/sprockets/eco_processor.rb +33 -0
  39. data/lib/sprockets/ejs_processor.rb +32 -0
  40. data/lib/sprockets/encoding_utils.rb +262 -0
  41. data/lib/sprockets/environment.rb +46 -0
  42. data/lib/sprockets/erb_processor.rb +37 -0
  43. data/lib/sprockets/errors.rb +12 -0
  44. data/lib/sprockets/exporters/base.rb +71 -0
  45. data/lib/sprockets/exporters/file_exporter.rb +24 -0
  46. data/lib/sprockets/exporters/zlib_exporter.rb +33 -0
  47. data/lib/sprockets/exporters/zopfli_exporter.rb +14 -0
  48. data/lib/sprockets/exporting.rb +73 -0
  49. data/lib/sprockets/file_reader.rb +16 -0
  50. data/lib/sprockets/http_utils.rb +135 -0
  51. data/lib/sprockets/jsminc_compressor.rb +32 -0
  52. data/lib/sprockets/jst_processor.rb +50 -0
  53. data/lib/sprockets/loader.rb +345 -0
  54. data/lib/sprockets/manifest.rb +338 -0
  55. data/lib/sprockets/manifest_utils.rb +48 -0
  56. data/lib/sprockets/mime.rb +96 -0
  57. data/lib/sprockets/npm.rb +52 -0
  58. data/lib/sprockets/path_dependency_utils.rb +77 -0
  59. data/lib/sprockets/path_digest_utils.rb +48 -0
  60. data/lib/sprockets/path_utils.rb +367 -0
  61. data/lib/sprockets/paths.rb +82 -0
  62. data/lib/sprockets/preprocessors/default_source_map.rb +49 -0
  63. data/lib/sprockets/processing.rb +228 -0
  64. data/lib/sprockets/processor_utils.rb +169 -0
  65. data/lib/sprockets/resolve.rb +295 -0
  66. data/lib/sprockets/sass_cache_store.rb +30 -0
  67. data/lib/sprockets/sass_compressor.rb +63 -0
  68. data/lib/sprockets/sass_functions.rb +3 -0
  69. data/lib/sprockets/sass_importer.rb +3 -0
  70. data/lib/sprockets/sass_processor.rb +313 -0
  71. data/lib/sprockets/sassc_compressor.rb +56 -0
  72. data/lib/sprockets/sassc_processor.rb +297 -0
  73. data/lib/sprockets/server.rb +295 -0
  74. data/lib/sprockets/source_map_processor.rb +66 -0
  75. data/lib/sprockets/source_map_utils.rb +483 -0
  76. data/lib/sprockets/transformers.rb +173 -0
  77. data/lib/sprockets/uglifier_compressor.rb +66 -0
  78. data/lib/sprockets/unloaded_asset.rb +139 -0
  79. data/lib/sprockets/uri_tar.rb +99 -0
  80. data/lib/sprockets/uri_utils.rb +191 -0
  81. data/lib/sprockets/utils.rb +202 -0
  82. data/lib/sprockets/utils/gzip.rb +99 -0
  83. data/lib/sprockets/version.rb +4 -0
  84. data/lib/sprockets/yui_compressor.rb +56 -0
  85. 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,8 @@
1
+ # frozen_string_literal: true
2
+ require 'babel/transpiler'
3
+
4
+ module Sprockets
5
+ module Autoload
6
+ Babel = ::Babel
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ require 'closure-compiler'
3
+
4
+ module Sprockets
5
+ module Autoload
6
+ Closure = ::Closure
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ require 'coffee_script'
3
+
4
+ module Sprockets
5
+ module Autoload
6
+ CoffeeScript = ::CoffeeScript
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ require 'eco'
3
+
4
+ module Sprockets
5
+ module Autoload
6
+ Eco = ::Eco
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ require 'ejs'
3
+
4
+ module Sprockets
5
+ module Autoload
6
+ EJS = ::EJS
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ require 'jsminc'
3
+
4
+ module Sprockets
5
+ module Autoload
6
+ JSMinC = ::JSMinC
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ require 'sass'
3
+
4
+ module Sprockets
5
+ module Autoload
6
+ Sass = ::Sass
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ require 'sassc'
3
+
4
+ module Sprockets
5
+ module Autoload
6
+ SassC = ::SassC
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ require 'uglifier'
3
+
4
+ module Sprockets
5
+ module Autoload
6
+ Uglifier = ::Uglifier
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ require 'yui/compressor'
3
+
4
+ module Sprockets
5
+ module Autoload
6
+ YUI = ::YUI
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ require 'zopfli'
2
+
3
+ module Sprockets
4
+ module Autoload
5
+ Zopfli = ::Zopfli
6
+ end
7
+ 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