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.
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,295 @@
1
+ # frozen_string_literal: true
2
+ require 'set'
3
+ require 'sprockets/http_utils'
4
+ require 'sprockets/path_dependency_utils'
5
+ require 'sprockets/uri_utils'
6
+
7
+ module Sprockets
8
+ module Resolve
9
+ include HTTPUtils, PathDependencyUtils, URIUtils
10
+
11
+ # Public: Find Asset URI for given a logical path by searching the
12
+ # environment's load paths.
13
+ #
14
+ # resolve("application.js")
15
+ # # => "file:///path/to/app/javascripts/application.js?type=application/javascript"
16
+ #
17
+ # An accept content type can be given if the logical path doesn't have a
18
+ # format extension.
19
+ #
20
+ # resolve("application", accept: "application/javascript")
21
+ # # => "file:///path/to/app/javascripts/application.coffee?type=application/javascript"
22
+ #
23
+ # The String Asset URI is returned or nil if no results are found.
24
+ def resolve(path, load_paths: config[:paths], accept: nil, pipeline: nil, base_path: nil)
25
+ paths = load_paths
26
+
27
+ if valid_asset_uri?(path)
28
+ uri, deps = resolve_asset_uri(path)
29
+ elsif absolute_path?(path)
30
+ filename, type, deps = resolve_absolute_path(paths, path, accept)
31
+ elsif relative_path?(path)
32
+ filename, type, path_pipeline, deps, index_alias = resolve_relative_path(paths, path, base_path, accept)
33
+ else
34
+ filename, type, path_pipeline, deps, index_alias = resolve_logical_path(paths, path, accept)
35
+ end
36
+
37
+ if filename
38
+ uri = build_asset_uri(filename, type: type, pipeline: pipeline || path_pipeline, index_alias: index_alias)
39
+ end
40
+
41
+ return uri, deps
42
+ end
43
+
44
+ # Public: Same as resolve() but raises a FileNotFound exception instead of
45
+ # nil if no assets are found.
46
+ def resolve!(path, **kargs)
47
+ uri, deps = resolve(path, **kargs)
48
+
49
+ unless uri
50
+ message = +"couldn't find file '#{path}'"
51
+
52
+ if relative_path?(path) && kargs[:base_path]
53
+ load_path, _ = paths_split(config[:paths], kargs[:base_path])
54
+ message << " under '#{load_path}'"
55
+ end
56
+
57
+ message << " with type '#{kargs[:accept]}'" if kargs[:accept]
58
+
59
+ load_paths = kargs[:load_paths] || config[:paths]
60
+ message << "\nChecked in these paths: \n #{ load_paths.join("\n ") }"
61
+
62
+ raise FileNotFound, message
63
+ end
64
+
65
+ return uri, deps
66
+ end
67
+
68
+ protected
69
+
70
+ # Internal: Finds an asset given a URI
71
+ #
72
+ # uri - String. Contains file:// scheme, absolute path to
73
+ # file.
74
+ # e.g. "file:///Users/schneems/sprockets/test/fixtures/default/gallery.js?type=application/javascript"
75
+ #
76
+ # Returns Array. Contains a String uri and Set of dependencies
77
+ def resolve_asset_uri(uri)
78
+ filename, _ = URIUtils.parse_asset_uri(uri)
79
+ return uri, Set.new( [URIUtils.build_file_digest_uri(filename)] )
80
+ end
81
+
82
+ # Internal: Finds a file in a set of given paths
83
+ #
84
+ # paths - Array of Strings.
85
+ # filename - String containing absolute path to a file including extension.
86
+ # e.g. "/Users/schneems/sprockets/test/fixtures/asset/application.js"
87
+ # accept - String. A Quality value incoded set of
88
+ # mime types that we are looking for. Can be nil.
89
+ # e.g. "application/javascript" or "text/css, */*"
90
+ #
91
+ # Returns Array. Filename, type, path_pipeline, deps, index_alias
92
+ def resolve_absolute_path(paths, filename, accept)
93
+ deps = Set.new
94
+ filename = File.expand_path(filename)
95
+
96
+ # Ensure path is under load paths
97
+ return nil, nil, deps unless PathUtils.paths_split(paths, filename)
98
+
99
+ _, mime_type = PathUtils.match_path_extname(filename, config[:mime_exts])
100
+ type = resolve_transform_type(mime_type, accept)
101
+ return nil, nil, deps if accept && !type
102
+
103
+ return nil, nil, deps unless file?(filename)
104
+
105
+ deps << URIUtils.build_file_digest_uri(filename)
106
+ return filename, type, deps
107
+ end
108
+
109
+ # Internal: Finds a relative file in a set of given paths
110
+ #
111
+ # paths - Array of Strings.
112
+ # path - String. A relative filename with or without extension
113
+ # e.g. "./jquery" or "../foo.js"
114
+ # dirname - String. Base path where we start looking for the given file.
115
+ # accept - String. A Quality value incoded set of
116
+ # mime types that we are looking for. Can be nil.
117
+ # e.g. "application/javascript" or "text/css, */*"
118
+ #
119
+ # Returns Array. Filename, type, path_pipeline, deps, index_alias
120
+ def resolve_relative_path(paths, path, dirname, accept)
121
+ filename = File.expand_path(path, dirname)
122
+ load_path, _ = PathUtils.paths_split(paths, dirname)
123
+ if load_path && logical_path = PathUtils.split_subpath(load_path, filename)
124
+ resolve_logical_path([load_path], logical_path, accept)
125
+ else
126
+ return nil, nil, nil, Set.new
127
+ end
128
+ end
129
+
130
+ # Internal: Finds a file in a set of given paths
131
+ #
132
+ # paths - Array of Strings.
133
+ # logical_path - String. A filename with extension
134
+ # e.g. "coffee/foo.js" or "foo.js"
135
+ # accept - String. A Quality value incoded set of
136
+ # mime types that we are looking for. Can be nil.
137
+ # e.g. "application/javascript" or "text/css, */*"
138
+ #
139
+ # Finds a file on the given paths.
140
+ #
141
+ # Returns Array. Filename, type, path_pipeline, deps, index_alias
142
+ def resolve_logical_path(paths, logical_path, accept)
143
+ extname, mime_type = PathUtils.match_path_extname(logical_path, config[:mime_exts])
144
+ logical_name = logical_path.chomp(extname)
145
+
146
+ extname, pipeline = PathUtils.match_path_extname(logical_name, config[:pipeline_exts])
147
+ logical_name = logical_name.chomp(extname)
148
+
149
+ parsed_accept = parse_accept_options(mime_type, accept)
150
+ transformed_accepts = expand_transform_accepts(parsed_accept)
151
+
152
+ filename, mime_type, deps, index_alias = resolve_under_paths(paths, logical_name, transformed_accepts)
153
+
154
+ if filename
155
+ deps << build_file_digest_uri(filename)
156
+ type = resolve_transform_type(mime_type, parsed_accept)
157
+ return filename, type, pipeline, deps, index_alias
158
+ else
159
+ return nil, nil, nil, deps
160
+ end
161
+ end
162
+
163
+ # Internal: Finds a file in a set of given paths
164
+ #
165
+ # paths - Array of Strings.
166
+ # logical_name - String. A filename without extension
167
+ # e.g. "application" or "coffee/foo"
168
+ # accepts - Array of array containing mime/version pairs
169
+ # e.g. [["application/javascript", 1.0]]
170
+ #
171
+ # Finds a file with the same name as `logical_name` or "index" inside
172
+ # of the `logical_name` directory that matches a valid mime-type/version from
173
+ # `accepts`.
174
+ #
175
+ # Returns Array. Filename, type, dependencies, and index_alias
176
+ def resolve_under_paths(paths, logical_name, accepts)
177
+ deps = Set.new
178
+ return nil, nil, deps if accepts.empty?
179
+
180
+ # TODO: Allow new path resolves to be registered
181
+ @resolvers ||= [
182
+ method(:resolve_main_under_path),
183
+ method(:resolve_alts_under_path),
184
+ method(:resolve_index_under_path)
185
+ ]
186
+ mime_exts = config[:mime_exts]
187
+
188
+ paths.each do |load_path|
189
+ candidates = []
190
+ @resolvers.each do |fn|
191
+ result = fn.call(load_path, logical_name, mime_exts)
192
+ candidates.concat(result[0])
193
+ deps.merge(result[1])
194
+ end
195
+
196
+ candidate = HTTPUtils.find_best_q_match(accepts, candidates) do |c, matcher|
197
+ match_mime_type?(c[:type] || "application/octet-stream", matcher)
198
+ end
199
+ return candidate[:filename], candidate[:type], deps, candidate[:index_alias] if candidate
200
+ end
201
+
202
+ return nil, nil, deps
203
+ end
204
+
205
+ # Internal: Finds candidate files on a given path
206
+ #
207
+ # load_path - String. An absolute path to a directory
208
+ # logical_name - String. A filename without extension
209
+ # e.g. "application" or "coffee/foo"
210
+ # mime_exts - Hash of file extensions and their mime types
211
+ # e.g. {".xml.builder"=>"application/xml+builder"}
212
+ #
213
+ # Finds files that match a given `logical_name` with an acceptable
214
+ # mime type that is included in `mime_exts` on the `load_path`.
215
+ #
216
+ # Returns Array. First element is an Array of hashes or empty, second is a String
217
+ def resolve_main_under_path(load_path, logical_name, mime_exts)
218
+ dirname = File.dirname(File.join(load_path, logical_name))
219
+ candidates = self.find_matching_path_for_extensions(dirname, File.basename(logical_name), mime_exts)
220
+ candidates.map! do |c|
221
+ { filename: c[0], type: c[1] }
222
+ end
223
+ return candidates, [ URIUtils.build_file_digest_uri(dirname) ]
224
+ end
225
+
226
+
227
+ # Internal: Finds candidate index files in a given path
228
+ #
229
+ # load_path - String. An absolute path to a directory
230
+ # logical_name - String. A filename without extension
231
+ # e.g. "application" or "coffee/foo"
232
+ # mime_exts - Hash of file extensions and their mime types
233
+ # e.g. {".xml.builder"=>"application/xml+builder"}
234
+ #
235
+ # Looking in the given `load_path` this method will find all files under the `logical_name` directory
236
+ # that are named `index` and have a matching mime type in `mime_exts`.
237
+ #
238
+ # Returns Array. First element is an Array of hashes or empty, second is a String
239
+ def resolve_index_under_path(load_path, logical_name, mime_exts)
240
+ dirname = File.join(load_path, logical_name)
241
+
242
+ if self.directory?(dirname)
243
+ candidates = self.find_matching_path_for_extensions(dirname, "index".freeze, mime_exts)
244
+ else
245
+ candidates = []
246
+ end
247
+
248
+ candidates.map! do |c|
249
+ { filename: c[0],
250
+ type: c[1],
251
+ index_alias: compress_from_root(c[0].sub(/\/index(\.[^\/]+)$/, '\1')) }
252
+ end
253
+
254
+ return candidates, [ URIUtils.build_file_digest_uri(dirname) ]
255
+ end
256
+
257
+ def resolve_alts_under_path(load_path, logical_name, mime_exts)
258
+ filenames, deps = self.resolve_alternates(load_path, logical_name)
259
+ filenames.map! do |fn|
260
+ _, mime_type = PathUtils.match_path_extname(fn, mime_exts)
261
+ { filename: fn, type: mime_type }
262
+ end
263
+ return filenames, deps
264
+ end
265
+
266
+ # Internal: Converts mimetype into accept Array
267
+ #
268
+ # - mime_type - String, optional. e.g. "text/html"
269
+ # - explicit_type - String, optional. e.g. "application/javascript"
270
+ #
271
+ # When called with an explicit_type and a mime_type, only a mime_type
272
+ # that matches the given explicit_type will be accepted.
273
+ #
274
+ # Returns Array of Array
275
+ #
276
+ # [["application/javascript", 1.0]]
277
+ # [["*/*", 1.0]]
278
+ # []
279
+ def parse_accept_options(mime_type, explicit_type)
280
+ if mime_type
281
+ return [[mime_type, 1.0]] if explicit_type.nil?
282
+ return [[mime_type, 1.0]] if HTTPUtils.parse_q_values(explicit_type).any? { |accept, _| HTTPUtils.match_mime_type?(mime_type, accept) }
283
+ return []
284
+ end
285
+
286
+ accepts = HTTPUtils.parse_q_values(explicit_type)
287
+ accepts << ['*/*'.freeze, 1.0] if accepts.empty?
288
+ return accepts
289
+ end
290
+
291
+ def resolve_alternates(load_path, logical_name)
292
+ return [], Set.new
293
+ end
294
+ end
295
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ require 'sass'
3
+
4
+ module Sprockets
5
+ class SassProcessor
6
+ # Internal: Cache wrapper for Sprockets cache adapter.
7
+ class CacheStore < ::Sass::CacheStores::Base
8
+ VERSION = '1'
9
+
10
+ def initialize(cache, version)
11
+ @cache, @version = cache, "#{VERSION}/#{version}"
12
+ end
13
+
14
+ def _store(key, version, sha, contents)
15
+ @cache.set("#{@version}/#{version}/#{key}/#{sha}", contents, true)
16
+ end
17
+
18
+ def _retrieve(key, version, sha)
19
+ @cache.get("#{@version}/#{version}/#{key}/#{sha}", true)
20
+ end
21
+
22
+ def path_to(key)
23
+ key
24
+ end
25
+ end
26
+ end
27
+
28
+ # Deprecated: Use Sprockets::SassProcessor::CacheStore instead.
29
+ SassCacheStore = SassProcessor::CacheStore
30
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+ require 'sprockets/autoload'
3
+ require 'sprockets/digest_utils'
4
+ require 'sprockets/source_map_utils'
5
+
6
+ module Sprockets
7
+ # Public: Sass CSS minifier.
8
+ #
9
+ # To accept the default options
10
+ #
11
+ # environment.register_bundle_processor 'text/css',
12
+ # Sprockets::SassCompressor
13
+ #
14
+ # Or to pass options to the Sass::Engine class.
15
+ #
16
+ # environment.register_bundle_processor 'text/css',
17
+ # Sprockets::SassCompressor.new({ ... })
18
+ #
19
+ class SassCompressor
20
+ VERSION = '1'
21
+
22
+ # Public: Return singleton instance with default options.
23
+ #
24
+ # Returns SassCompressor object.
25
+ def self.instance
26
+ @instance ||= new
27
+ end
28
+
29
+ def self.call(input)
30
+ instance.call(input)
31
+ end
32
+
33
+ def self.cache_key
34
+ instance.cache_key
35
+ end
36
+
37
+ attr_reader :cache_key
38
+
39
+ def initialize(options = {})
40
+ @options = {
41
+ syntax: :scss,
42
+ cache: false,
43
+ read_cache: false,
44
+ style: :compressed
45
+ }.merge(options).freeze
46
+ @cache_key = "#{self.class.name}:#{Autoload::Sass::VERSION}:#{VERSION}:#{DigestUtils.digest(options)}".freeze
47
+ end
48
+
49
+ def call(input)
50
+ css, map = Autoload::Sass::Engine.new(
51
+ input[:data],
52
+ @options.merge(filename: input[:filename])
53
+ ).render_with_sourcemap('')
54
+
55
+ css = css.sub("/*# sourceMappingURL= */\n", '')
56
+
57
+ map = SourceMapUtils.format_source_map(JSON.parse(map.to_json(css_uri: '')), input)
58
+ map = SourceMapUtils.combine_source_maps(input[:metadata][:map], map)
59
+
60
+ { data: css, map: map }
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+ # Deprecated: Require sprockets/sass_processor instead
3
+ require 'sprockets/sass_processor'
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+ # Deprecated: Require sprockets/sass_processor instead
3
+ require 'sprockets/sass_processor'
@@ -0,0 +1,313 @@
1
+ # frozen_string_literal: true
2
+ require 'rack/utils'
3
+ require 'sprockets/autoload'
4
+ require 'sprockets/source_map_utils'
5
+ require 'uri'
6
+
7
+ module Sprockets
8
+ # Processor engine class for the SASS/SCSS compiler. Depends on the `sass` gem.
9
+ #
10
+ # For more infomation see:
11
+ #
12
+ # https://github.com/sass/sass
13
+ # https://github.com/rails/sass-rails
14
+ #
15
+ class SassProcessor
16
+ autoload :CacheStore, 'sprockets/sass_cache_store'
17
+
18
+ # Internal: Defines default sass syntax to use. Exposed so the ScssProcessor
19
+ # may override it.
20
+ def self.syntax
21
+ :sass
22
+ end
23
+
24
+ # Public: Return singleton instance with default options.
25
+ #
26
+ # Returns SassProcessor object.
27
+ def self.instance
28
+ @instance ||= new
29
+ end
30
+
31
+ def self.call(input)
32
+ instance.call(input)
33
+ end
34
+
35
+ def self.cache_key
36
+ instance.cache_key
37
+ end
38
+
39
+ attr_reader :cache_key
40
+
41
+ # Public: Initialize template with custom options.
42
+ #
43
+ # options - Hash
44
+ # cache_version - String custom cache version. Used to force a cache
45
+ # change after code changes are made to Sass Functions.
46
+ #
47
+ def initialize(options = {}, &block)
48
+ @cache_version = options[:cache_version]
49
+ @cache_key = "#{self.class.name}:#{VERSION}:#{Autoload::Sass::VERSION}:#{@cache_version}".freeze
50
+ @importer_class = options[:importer] || Sass::Importers::Filesystem
51
+ @sass_config = options[:sass_config] || {}
52
+ @functions = Module.new do
53
+ include Functions
54
+ include options[:functions] if options[:functions]
55
+ class_eval(&block) if block_given?
56
+ end
57
+ end
58
+
59
+ def call(input)
60
+ context = input[:environment].context_class.new(input)
61
+
62
+ engine_options = merge_options({
63
+ filename: input[:filename],
64
+ syntax: self.class.syntax,
65
+ cache_store: build_cache_store(input, @cache_version),
66
+ load_paths: context.environment.paths.map { |p| @importer_class.new(p.to_s) },
67
+ importer: @importer_class.new(Pathname.new(context.filename).to_s),
68
+ sprockets: {
69
+ context: context,
70
+ environment: input[:environment],
71
+ dependencies: context.metadata[:dependencies]
72
+ }
73
+ })
74
+
75
+ engine = Autoload::Sass::Engine.new(input[:data], engine_options)
76
+
77
+ css, map = Utils.module_include(Autoload::Sass::Script::Functions, @functions) do
78
+ engine.render_with_sourcemap('')
79
+ end
80
+
81
+ css = css.sub("\n/*# sourceMappingURL= */\n", '')
82
+
83
+ map = SourceMapUtils.format_source_map(JSON.parse(map.to_json(css_uri: '')), input)
84
+ map = SourceMapUtils.combine_source_maps(input[:metadata][:map], map)
85
+
86
+ # Track all imported files
87
+ sass_dependencies = Set.new([input[:filename]])
88
+ engine.dependencies.map do |dependency|
89
+ sass_dependencies << dependency.options[:filename]
90
+ context.metadata[:dependencies] << URIUtils.build_file_digest_uri(dependency.options[:filename])
91
+ end
92
+
93
+ context.metadata.merge(data: css, sass_dependencies: sass_dependencies, map: map)
94
+ end
95
+
96
+ private
97
+
98
+ # Public: Build the cache store to be used by the Sass engine.
99
+ #
100
+ # input - the input hash.
101
+ # version - the cache version.
102
+ #
103
+ # Override this method if you need to use a different cache than the
104
+ # Sprockets cache.
105
+ def build_cache_store(input, version)
106
+ CacheStore.new(input[:cache], version)
107
+ end
108
+
109
+ def merge_options(options)
110
+ defaults = @sass_config.dup
111
+
112
+ if load_paths = defaults.delete(:load_paths)
113
+ options[:load_paths] += load_paths
114
+ end
115
+
116
+ options.merge!(defaults)
117
+ options
118
+ end
119
+
120
+ # Public: Functions injected into Sass context during Sprockets evaluation.
121
+ #
122
+ # This module may be extended to add global functionality to all Sprockets
123
+ # Sass environments. Though, scoping your functions to just your environment
124
+ # is preferred.
125
+ #
126
+ # module Sprockets::SassProcessor::Functions
127
+ # def asset_path(path, options = {})
128
+ # end
129
+ # end
130
+ #
131
+ module Functions
132
+ # Public: Generate a url for asset path.
133
+ #
134
+ # Default implementation is deprecated. Currently defaults to
135
+ # Context#asset_path.
136
+ #
137
+ # Will raise NotImplementedError in the future. Users should provide their
138
+ # own base implementation.
139
+ #
140
+ # Returns a Sass::Script::String.
141
+ def asset_path(path, options = {})
142
+ path = path.value
143
+
144
+ path, _, query, fragment = URI.split(path)[5..8]
145
+ path = sprockets_context.asset_path(path, options)
146
+ query = "?#{query}" if query
147
+ fragment = "##{fragment}" if fragment
148
+
149
+ Autoload::Sass::Script::String.new("#{path}#{query}#{fragment}", :string)
150
+ end
151
+
152
+ # Public: Generate a asset url() link.
153
+ #
154
+ # path - Sass::Script::String URL path
155
+ #
156
+ # Returns a Sass::Script::String.
157
+ def asset_url(path, options = {})
158
+ Autoload::Sass::Script::String.new("url(#{asset_path(path, options).value})")
159
+ end
160
+
161
+ # Public: Generate url for image path.
162
+ #
163
+ # path - Sass::Script::String URL path
164
+ #
165
+ # Returns a Sass::Script::String.
166
+ def image_path(path)
167
+ asset_path(path, type: :image)
168
+ end
169
+
170
+ # Public: Generate a image url() link.
171
+ #
172
+ # path - Sass::Script::String URL path
173
+ #
174
+ # Returns a Sass::Script::String.
175
+ def image_url(path)
176
+ asset_url(path, type: :image)
177
+ end
178
+
179
+ # Public: Generate url for video path.
180
+ #
181
+ # path - Sass::Script::String URL path
182
+ #
183
+ # Returns a Sass::Script::String.
184
+ def video_path(path)
185
+ asset_path(path, type: :video)
186
+ end
187
+
188
+ # Public: Generate a video url() link.
189
+ #
190
+ # path - Sass::Script::String URL path
191
+ #
192
+ # Returns a Sass::Script::String.
193
+ def video_url(path)
194
+ asset_url(path, type: :video)
195
+ end
196
+
197
+ # Public: Generate url for audio path.
198
+ #
199
+ # path - Sass::Script::String URL path
200
+ #
201
+ # Returns a Sass::Script::String.
202
+ def audio_path(path)
203
+ asset_path(path, type: :audio)
204
+ end
205
+
206
+ # Public: Generate a audio url() link.
207
+ #
208
+ # path - Sass::Script::String URL path
209
+ #
210
+ # Returns a Sass::Script::String.
211
+ def audio_url(path)
212
+ asset_url(path, type: :audio)
213
+ end
214
+
215
+ # Public: Generate url for font path.
216
+ #
217
+ # path - Sass::Script::String URL path
218
+ #
219
+ # Returns a Sass::Script::String.
220
+ def font_path(path)
221
+ asset_path(path, type: :font)
222
+ end
223
+
224
+ # Public: Generate a font url() link.
225
+ #
226
+ # path - Sass::Script::String URL path
227
+ #
228
+ # Returns a Sass::Script::String.
229
+ def font_url(path)
230
+ asset_url(path, type: :font)
231
+ end
232
+
233
+ # Public: Generate url for javascript path.
234
+ #
235
+ # path - Sass::Script::String URL path
236
+ #
237
+ # Returns a Sass::Script::String.
238
+ def javascript_path(path)
239
+ asset_path(path, type: :javascript)
240
+ end
241
+
242
+ # Public: Generate a javascript url() link.
243
+ #
244
+ # path - Sass::Script::String URL path
245
+ #
246
+ # Returns a Sass::Script::String.
247
+ def javascript_url(path)
248
+ asset_url(path, type: :javascript)
249
+ end
250
+
251
+ # Public: Generate url for stylesheet path.
252
+ #
253
+ # path - Sass::Script::String URL path
254
+ #
255
+ # Returns a Sass::Script::String.
256
+ def stylesheet_path(path)
257
+ asset_path(path, type: :stylesheet)
258
+ end
259
+
260
+ # Public: Generate a stylesheet url() link.
261
+ #
262
+ # path - Sass::Script::String URL path
263
+ #
264
+ # Returns a Sass::Script::String.
265
+ def stylesheet_url(path)
266
+ asset_url(path, type: :stylesheet)
267
+ end
268
+
269
+ # Public: Generate a data URI for asset path.
270
+ #
271
+ # path - Sass::Script::String logical asset path
272
+ #
273
+ # Returns a Sass::Script::String.
274
+ def asset_data_url(path)
275
+ url = sprockets_context.asset_data_uri(path.value)
276
+ Autoload::Sass::Script::String.new("url(" + url + ")")
277
+ end
278
+
279
+ protected
280
+ # Public: The Environment.
281
+ #
282
+ # Returns Sprockets::Environment.
283
+ def sprockets_environment
284
+ options[:sprockets][:environment]
285
+ end
286
+
287
+ # Public: Mutatable set of dependencies.
288
+ #
289
+ # Returns a Set.
290
+ def sprockets_dependencies
291
+ options[:sprockets][:dependencies]
292
+ end
293
+
294
+ # Deprecated: Get the Context instance. Use APIs on
295
+ # sprockets_environment or sprockets_dependencies directly.
296
+ #
297
+ # Returns a Context instance.
298
+ def sprockets_context
299
+ options[:sprockets][:context]
300
+ end
301
+
302
+ end
303
+ end
304
+
305
+ class ScssProcessor < SassProcessor
306
+ def self.syntax
307
+ :scss
308
+ end
309
+ end
310
+
311
+ # Deprecated: Use Sprockets::SassProcessor::Functions instead.
312
+ SassFunctions = SassProcessor::Functions
313
+ end