sprockets-sass 1.3.1 → 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/.reek +12 -0
  3. data/.rubocop.yml +77 -0
  4. data/.travis.yml +16 -0
  5. data/Appraisals +32 -15
  6. data/Gemfile +5 -0
  7. data/README.md +41 -4
  8. data/Rakefile +15 -3
  9. data/gemfiles/compass_0.11.gemfile +1 -1
  10. data/gemfiles/sass_3.1.gemfile +1 -1
  11. data/gemfiles/sass_3.3.gemfile +8 -0
  12. data/gemfiles/sass_3.4.gemfile +8 -0
  13. data/gemfiles/sprockets_2.10.gemfile +1 -1
  14. data/gemfiles/sprockets_2.11.gemfile +1 -1
  15. data/gemfiles/sprockets_2.2.gemfile +1 -1
  16. data/gemfiles/sprockets_2.3.gemfile +1 -1
  17. data/gemfiles/sprockets_2.4.gemfile +1 -1
  18. data/gemfiles/sprockets_2.5.gemfile +1 -1
  19. data/gemfiles/sprockets_2.6.gemfile +1 -1
  20. data/gemfiles/sprockets_2.7.gemfile +1 -1
  21. data/gemfiles/sprockets_2.8.gemfile +1 -1
  22. data/gemfiles/sprockets_2.9.gemfile +1 -1
  23. data/gemfiles/sprockets_3.7.gemfile +9 -0
  24. data/gemfiles/sprockets_4.0.gemfile +10 -0
  25. data/gemfiles/sprockets_4.0_beta2.gemfile +9 -0
  26. data/lib/sprockets-sass.rb +1 -0
  27. data/lib/sprockets/sass.rb +37 -12
  28. data/lib/sprockets/sass/functions.rb +24 -159
  29. data/lib/sprockets/sass/registration.rb +126 -0
  30. data/lib/sprockets/sass/utils.rb +115 -0
  31. data/lib/sprockets/sass/v2/cache_store.rb +26 -0
  32. data/lib/sprockets/sass/v2/compressor.rb +31 -0
  33. data/lib/sprockets/sass/v2/functions.rb +142 -0
  34. data/lib/sprockets/sass/v2/importer.rb +209 -0
  35. data/lib/sprockets/sass/v2/sass_template.rb +221 -0
  36. data/lib/sprockets/sass/v2/scss_template.rb +14 -0
  37. data/lib/sprockets/sass/v3/cache_store.rb +28 -0
  38. data/lib/sprockets/sass/v3/compressor.rb +97 -0
  39. data/lib/sprockets/sass/v3/functions.rb +12 -0
  40. data/lib/sprockets/sass/v3/importer.rb +212 -0
  41. data/lib/sprockets/sass/v3/sass_template.rb +37 -0
  42. data/lib/sprockets/sass/v3/scss_template.rb +15 -0
  43. data/lib/sprockets/sass/v4/cache_store.rb +11 -0
  44. data/lib/sprockets/sass/v4/compressor.rb +11 -0
  45. data/lib/sprockets/sass/v4/functions.rb +12 -0
  46. data/lib/sprockets/sass/v4/importer.rb +105 -0
  47. data/lib/sprockets/sass/v4/sass_template.rb +27 -0
  48. data/lib/sprockets/sass/v4/scss_template.rb +16 -0
  49. data/lib/sprockets/sass/version.rb +2 -1
  50. data/spec/custom_importer_spec.rb +4 -6
  51. data/spec/spec_helper.rb +30 -3
  52. data/spec/sprockets-sass_spec.rb +101 -61
  53. data/spec/support/be_fresh_matcher.rb +10 -6
  54. data/spec/support/dummy_importer.rb +1 -1
  55. data/spec/support/fail_postprocessor.rb +23 -0
  56. data/spec/support/sass_template.rb +11 -0
  57. data/sprockets-sass.gemspec +27 -8
  58. metadata +92 -95
  59. data/gemfiles/compass_0.12.gemfile +0 -7
  60. data/gemfiles/sass_3.2.gemfile +0 -7
  61. data/gemfiles/sprockets_2.0.gemfile +0 -7
  62. data/gemfiles/sprockets_2.1.gemfile +0 -9
  63. data/lib/sprockets/sass/cache_store.rb +0 -27
  64. data/lib/sprockets/sass/compressor.rb +0 -22
  65. data/lib/sprockets/sass/importer.rb +0 -142
  66. data/lib/sprockets/sass/sass_template.rb +0 -115
  67. data/lib/sprockets/sass/scss_template.rb +0 -12
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+ module Sprockets
3
+ module Sass
4
+ module V2
5
+ # Class used to compress CSS files
6
+ class Compressor
7
+ def self.instance
8
+ @instance ||= new
9
+ end
10
+
11
+ def self.compress(input)
12
+ instance.compress(input)
13
+ end
14
+
15
+ # Compresses the given CSS using Sass::Engine's
16
+ # :compressed output style.
17
+ def compress(css)
18
+ if css.count("\n") >= 2
19
+ ::Sass::Engine.new(css,
20
+ syntax: :scss,
21
+ cache: false,
22
+ read_cache: false,
23
+ style: :compressed).render
24
+ else
25
+ css
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+ module Sprockets
3
+ module Sass
4
+ module V2
5
+ # Module used to inject helpers into SASS engine
6
+ module Functions
7
+ # Using Sprockets::Context#asset_data_uri return a Base64-encoded `data:`
8
+ # URI with the contents of the asset at the specified path.
9
+ #
10
+ # === Examples
11
+ #
12
+ # background: asset-data-uri("image.jpg"); // background: url(data:image/jpeg;base64,...);
13
+ #
14
+ def asset_data_uri(source)
15
+ ::Sass::Script::String.new "url(#{sprockets_context.asset_data_uri(source.value)})"
16
+ end
17
+
18
+ # Using Sprockets::Helpers#asset_path, return the full path
19
+ # for the given +source+ as a Sass String. This supports keyword
20
+ # arguments that mirror the +options+.
21
+ #
22
+ # === Examples
23
+ #
24
+ # background: url(asset-path("image.jpg")); // background: url("/assets/image.jpg");
25
+ # background: url(asset-path("image.jpg", $digest: true)); // background: url("/assets/image-27a8f1f96afd8d4c67a59eb9447f45bd.jpg");
26
+ #
27
+ def asset_path(source, options = {})
28
+ # Work with the Sass::Rails #asset_path API
29
+ if options.respond_to? :value
30
+ kind = options.value
31
+ options = {}
32
+ end
33
+
34
+ if kind && sprockets_context.respond_to?("#{kind}_path")
35
+ ::Sass::Script::String.new sprockets_context.send("#{kind}_path", source.value), :string
36
+ else
37
+ ::Sass::Script::String.new sprockets_context.asset_path(source.value, map_options(options)).to_s, :string
38
+ end
39
+ end
40
+
41
+ # Using Sprockets::Helpers#asset_path, return the url CSS
42
+ # for the given +source+ as a Sass String. This supports keyword
43
+ # arguments that mirror the +options+.
44
+ #
45
+ # === Examples
46
+ #
47
+ # background: asset-url("image.jpg"); // background: url("/assets/image.jpg");
48
+ # background: asset-url("image.jpg", $digest: true); // background: url("/assets/image-27a8f1f96afd8d4c67a59eb9447f45bd.jpg");
49
+ #
50
+ def asset_url(source, options = {})
51
+ ::Sass::Script::String.new "url(#{asset_path(source, options)})"
52
+ end
53
+
54
+ # Using Sprockets::Helpers#image_path, return the full path
55
+ # for the given +source+ as a Sass String. This supports keyword
56
+ # arguments that mirror the +options+.
57
+ #
58
+ # === Examples
59
+ #
60
+ # background: url(image-path("image.jpg")); // background: url("/assets/image.jpg");
61
+ # background: url(image-path("image.jpg", $digest: true)); // background: url("/assets/image-27a8f1f96afd8d4c67a59eb9447f45bd.jpg");
62
+ #
63
+ def image_path(source, options = {})
64
+ ::Sass::Script::String.new sprockets_context.image_path(source.value, map_options(options)).to_s, :string
65
+ end
66
+
67
+ # Using Sprockets::Helpers#image_path, return the url CSS
68
+ # for the given +source+ as a Sass String. This supports keyword
69
+ # arguments that mirror the +options+.
70
+ #
71
+ # === Examples
72
+ #
73
+ # background: image-url("image.jpg"); // background: url("/assets/image.jpg");
74
+ # background: image-url("image.jpg", $digest: true); // background: url("/assets/image-27a8f1f96afd8d4c67a59eb9447f45bd.jpg");
75
+ #
76
+ def image_url(source, options = {}, _cache_buster = nil)
77
+ # Work with the Compass #image_url API
78
+ if options.respond_to? :value
79
+ case options.value
80
+ when true
81
+ return image_path source
82
+ else
83
+ options = {}
84
+ end
85
+ end
86
+ ::Sass::Script::String.new "url(#{image_path(source, options)})"
87
+ end
88
+
89
+ # Using Sprockets::Helpers#font_path, return the full path
90
+ # for the given +source+ as a Sass String. This supports keyword
91
+ # arguments that mirror the +options+.
92
+ #
93
+ # === Examples
94
+ #
95
+ # src: url(font-path("font.ttf")); // src: url("/assets/font.ttf");
96
+ # src: url(font-path("font.ttf", $digest: true)); // src: url("/assets/font-27a8f1f96afd8d4c67a59eb9447f45bd.ttf");
97
+ #
98
+ def font_path(source, options = {})
99
+ ::Sass::Script::String.new sprockets_context.font_path(source.value, map_options(options)).to_s, :string
100
+ end
101
+
102
+ # Using Sprockets::Helpers#font_path, return the url CSS
103
+ # for the given +source+ as a Sass String. This supports keyword
104
+ # arguments that mirror the +options+.
105
+ #
106
+ # === Examples
107
+ #
108
+ # src: font-url("font.ttf"); // src: url("/assets/font.ttf");
109
+ # src: font-url("image.jpg", $digest: true); // src: url("/assets/font-27a8f1f96afd8d4c67a59eb9447f45bd.ttf");
110
+ #
111
+ def font_url(source, options = {})
112
+ # Work with the Compass #font_url API
113
+ if options.respond_to? :value
114
+ case options.value
115
+ when true
116
+ return font_path source
117
+ else
118
+ options = {}
119
+ end
120
+ end
121
+ ::Sass::Script::String.new "url(#{font_path(source, options)})"
122
+ end
123
+
124
+ protected
125
+
126
+ # Returns a reference to the Sprocket's context through
127
+ # the importer.
128
+ def sprockets_context # :nodoc:
129
+ options[:custom][:sprockets_context]
130
+ end
131
+
132
+ # Returns an options hash where the keys are symbolized
133
+ # and the values are unwrapped Sass literals.
134
+ def map_options(options = {}) # :nodoc:
135
+ ::Sass::Util.map_hash(options) do |key, value|
136
+ [key.to_sym, value.respond_to?(:value) ? value.value : value]
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,209 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sprockets
4
+ module Sass
5
+ module V2
6
+ # class used for importing files from SCCS and SASS files
7
+ class Importer < ::Sass::Importers::Base
8
+ GLOB = /\*|\[.+\]/
9
+
10
+ # @see Sass::Importers::Base#find_relative
11
+ def find_relative(path, base_path, options)
12
+ if path.to_s =~ GLOB
13
+ engine_from_glob(path, base_path, options)
14
+ else
15
+ engine_from_path(path, base_path, options)
16
+ end
17
+ end
18
+
19
+ # @see Sass::Importers::Base#find
20
+ def find(path, options)
21
+ engine_from_path(path, nil, options)
22
+ end
23
+
24
+ # @see Sass::Importers::Base#mtime
25
+ def mtime(path, _options)
26
+ if pathname = resolve(path)
27
+ pathname.mtime
28
+ end
29
+ rescue Errno::ENOENT
30
+ nil
31
+ end
32
+
33
+ # @see Sass::Importers::Base#key
34
+ def key(path, _options)
35
+ path = Pathname.new(path)
36
+ ["#{self.class.name}:#{path.dirname.expand_path}", path.basename]
37
+ end
38
+
39
+ # @see Sass::Importers::Base#to_s
40
+ def to_s
41
+ inspect
42
+ end
43
+
44
+ protected
45
+
46
+ # Create a Sass::Engine from the given path.
47
+ def engine_from_path(path, base_path, options)
48
+ context = options[:custom][:sprockets_context]
49
+ (pathname = resolve(context, path, base_path)) || (return nil)
50
+ context.depend_on pathname
51
+ ::Sass::Engine.new evaluate(context, pathname), options.merge(
52
+ filename: pathname.to_s,
53
+ syntax: syntax(pathname),
54
+ importer: self,
55
+ custom: { sprockets_context: context }
56
+ )
57
+ end
58
+
59
+ # Create a Sass::Engine that will handle importing
60
+ # a glob of files.
61
+ def engine_from_glob(glob, base_path, options)
62
+ context = options[:custom][:sprockets_context]
63
+ engine_imports = resolve_glob(context, glob, base_path).reduce(''.dup) do |imports, path|
64
+ context.depend_on path
65
+ relative_path = path.relative_path_from Pathname.new(base_path).dirname
66
+ imports << %(@import "#{relative_path}";\n)
67
+ end
68
+ return nil if engine_imports.empty?
69
+ ::Sass::Engine.new engine_imports, options.merge(
70
+ filename: base_path.to_s,
71
+ syntax: syntax(base_path.to_s),
72
+ importer: self,
73
+ custom: { sprockets_context: context }
74
+ )
75
+ end
76
+
77
+ # Finds an asset from the given path. This is where
78
+ # we make Sprockets behave like Sass, and import partial
79
+ # style paths.
80
+ def resolve(context, path, base_path)
81
+ paths, _root_path = possible_files(context, path, base_path)
82
+ paths.each do |file|
83
+ context.resolve(file.to_s) do |found|
84
+ return found if context.asset_requirable?(found)
85
+ end
86
+ end
87
+ nil
88
+ end
89
+
90
+ # Finds all of the assets using the given glob.
91
+ def resolve_glob(context, glob, base_path)
92
+ base_path = Pathname.new(base_path)
93
+ path_with_glob = base_path.dirname.join(glob).to_s
94
+
95
+ Pathname.glob(path_with_glob).sort.select do |path|
96
+ asset_requirable = context.asset_requirable?(path)
97
+ path != context.pathname && asset_requirable
98
+ end
99
+ end
100
+
101
+ def context_root_path(context)
102
+ Pathname.new(context.root_path)
103
+ end
104
+
105
+ def context_load_pathnames(context)
106
+ context.environment.paths.map { |p| Pathname.new(p) }
107
+ end
108
+
109
+ # Returns all of the possible paths (including partial variations)
110
+ # to attempt to resolve with the given path.
111
+ def possible_files(context, path, base_path)
112
+ path = Pathname.new(path)
113
+ base_path = Pathname.new(base_path).dirname
114
+ partial_path = partialize_path(path)
115
+ additional_paths = [Pathname.new("#{path}.css"), Pathname.new("#{partial_path}.css"), Pathname.new("#{path}.css.#{syntax(path)}"), Pathname.new("#{partial_path}.css.#{syntax(path)}")]
116
+ paths = additional_paths.concat([path, partial_path])
117
+
118
+ # Find base_path's root
119
+ paths, root_path = add_root_to_possible_files(context, base_path, path, paths)
120
+ [paths.compact, root_path]
121
+ end
122
+
123
+ def add_root_to_possible_files(context, base_path, path, paths)
124
+ env_root_paths = context_load_pathnames(context)
125
+ root_path = env_root_paths.find do |env_root_path|
126
+ base_path.to_s.start_with?(env_root_path.to_s)
127
+ end
128
+ root_path ||= context_root_path(context)
129
+ # Add the relative path from the root, if necessary
130
+ if path.relative? && base_path != root_path
131
+ relative_path = base_path.relative_path_from(root_path).join path
132
+ paths.unshift(relative_path, partialize_path(relative_path))
133
+ end
134
+ [paths, root_path]
135
+ end
136
+
137
+ # Returns the partialized version of the given path.
138
+ # Returns nil if the path is already to a partial.
139
+ def partialize_path(path)
140
+ return unless path.basename.to_s !~ /\A_/
141
+ Pathname.new path.to_s.sub(/([^\/]+)\Z/, '_\1')
142
+ end
143
+
144
+ # Returns the Sass syntax of the given path.
145
+ def syntax(path)
146
+ path.to_s.include?('.sass') ? :sass : :scss
147
+ end
148
+
149
+ def syntax_mime_type(_path)
150
+ 'text/css'
151
+ end
152
+
153
+ def filtered_processor_classes
154
+ classes = [Sprockets::Sass::Utils.get_class_by_version('SassTemplate'), Sprockets::Sass::Utils.get_class_by_version('ScssTemplate')]
155
+ classes << Sprockets::SassProcessor if defined?(Sprockets::SassProcessor)
156
+ classes << Sprockets::SasscProcessor if defined?(Sprockets::SasscProcessor)
157
+ classes
158
+ end
159
+
160
+ def content_type_of_path(context, path)
161
+ attributes = context.environment.attributes_for(path)
162
+ content_type = attributes.content_type
163
+ [content_type, attributes]
164
+ end
165
+
166
+ def get_context_preprocessors(context, content_type)
167
+ context.environment.preprocessors(content_type)
168
+ end
169
+
170
+ def get_context_transformers(_context, _content_type, _path)
171
+ []
172
+ end
173
+
174
+ def get_engines_from_attributes(attributes)
175
+ attributes.engines
176
+ end
177
+
178
+ def get_all_processors_for_evaluate(context, content_type, attributes, path)
179
+ engines = get_engines_from_attributes(attributes)
180
+ preprocessors = get_context_preprocessors(context, content_type)
181
+ additional_transformers = get_context_transformers(context, content_type, path)
182
+ additional_transformers.reverse + preprocessors + engines.reverse
183
+ end
184
+
185
+ def filter_all_processors(processors)
186
+ processors.delete_if do |processor|
187
+ filtered_processor_classes.include?(processor) || filtered_processor_classes.any? do |filtered_processor|
188
+ !processor.is_a?(Proc) && processor < filtered_processor
189
+ end
190
+ end
191
+ end
192
+
193
+ def evaluate_path_from_context(context, path, processors)
194
+ context.evaluate(path, processors: processors)
195
+ end
196
+
197
+ # Returns the string to be passed to the Sass engine. We use
198
+ # Sprockets to process the file, but we remove any Sass processors
199
+ # because we need to let the Sass::Engine handle that.
200
+ def evaluate(context, path)
201
+ content_type, attributes = content_type_of_path(context, path)
202
+ processors = get_all_processors_for_evaluate(context, content_type, attributes, path)
203
+ filter_all_processors(processors)
204
+ evaluate_path_from_context(context, path, processors)
205
+ end
206
+ end
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,221 @@
1
+ # frozen_string_literal: true
2
+ module Sprockets
3
+ module Sass
4
+ module V2
5
+ # Preprocessor for SASS files
6
+ class SassTemplate
7
+ VERSION = '1'
8
+
9
+ def self.default_mime_type
10
+ 'text/css'
11
+ end
12
+
13
+ # Internal: Defines default sass syntax to use. Exposed so the ScssProcessor
14
+ # may override it.
15
+ def self.syntax
16
+ :sass
17
+ end
18
+
19
+ # Public: Return singleton instance with default options.
20
+ #
21
+ # Returns SassProcessor object.
22
+ def self.instance
23
+ @instance ||= new
24
+ end
25
+
26
+ def self.call(input)
27
+ instance.call(input)
28
+ end
29
+
30
+ def self.cache_key
31
+ instance.cache_key
32
+ end
33
+
34
+ attr_reader :cache_key, :filename, :source, :context, :options
35
+
36
+ def initialize(options = {}, &block)
37
+ @default_options = { default_encoding: Encoding.default_external || 'utf-8' }
38
+ initialize_engine
39
+ if options.is_a?(Hash)
40
+ instantiate_with_options(options, &block)
41
+ else
42
+ instantiate_with_filename_and_source(options, &block)
43
+ end
44
+ end
45
+
46
+ def instantiate_with_filename_and_source(options)
47
+ @filename = options
48
+ @source = block_given? ? yield : nil
49
+ @options = @default_options
50
+ @cache_version = VERSION
51
+ @cache_key = "#{self.class.name}:#{::Sass::VERSION}:#{VERSION}:#{Sprockets::Sass::Utils.digest(options)}"
52
+ @functions = Module.new do
53
+ include Sprockets::Helpers if defined?(Sprockets::Helpers)
54
+ include Sprockets::Sass::Utils.get_class_by_version('Functions')
55
+ end
56
+ end
57
+
58
+ def instantiate_with_options(options, &block)
59
+ @cache_version = options[:cache_version] || VERSION
60
+ @cache_key = "#{self.class.name}:#{::Sass::VERSION}:#{@cache_version}:#{Sprockets::Sass::Utils.digest(options)}"
61
+ @filename = options[:filename]
62
+ @source = options[:data]
63
+ @options = options.merge(@default_options)
64
+ @importer_class = options[:importer]
65
+ @sass_config = options[:sass_config] || {}
66
+ @input = options
67
+ @functions = Module.new do
68
+ include Sprockets::Helpers if defined?(Sprockets::Helpers)
69
+ include Sprockets::Sass::Utils.get_class_by_version('Functions')
70
+ include options[:functions] if options[:functions]
71
+ class_eval(&block) if block_given?
72
+ end
73
+ end
74
+
75
+ @sass_functions_initialized = false
76
+ class << self
77
+ attr_accessor :sass_functions_initialized
78
+ alias sass_functions_initialized? sass_functions_initialized
79
+ # Templates are initialized once the functions are added.
80
+ def engine_initialized?
81
+ sass_functions_initialized?
82
+ end
83
+ end
84
+
85
+ # Add the Sass functions if they haven't already been added.
86
+ def initialize_engine
87
+ return if self.class.engine_initialized?
88
+
89
+ if Sass.add_sass_functions != false
90
+ begin
91
+ require 'sprockets/helpers'
92
+ require 'sprockets/sass/functions'
93
+ self.class.sass_functions_initialized = true
94
+ rescue LoadError; end
95
+ end
96
+ end
97
+
98
+ def call(input)
99
+ @input = input
100
+ @filename = input[:filename]
101
+ @source = input[:data]
102
+ @context = input[:environment].context_class.new(input)
103
+ run
104
+ end
105
+
106
+ def render(context, _empty_hash_wtf)
107
+ @context = context
108
+ run
109
+ end
110
+
111
+ def run
112
+ data = Sprockets::Sass::Utils.read_file_binary(filename, options)
113
+
114
+ engine = ::Sass::Engine.new(data, sass_options)
115
+ css = Sprockets::Sass::Utils.module_include(::Sass::Script::Functions, @functions) do
116
+ css = engine.render
117
+ end
118
+
119
+ sass_dependencies = Set.new([filename])
120
+ if context.respond_to?(:metadata)
121
+ engine.dependencies.map do |dependency|
122
+ sass_dependencies << dependency.options[:filename]
123
+ context.metadata[:dependencies] << Sprockets::URIUtils.build_file_digest_uri(dependency.options[:filename])
124
+ end
125
+ context.metadata.merge(data: css, sass_dependencies: sass_dependencies)
126
+ else
127
+ css
128
+ end
129
+
130
+ # Tilt::SassTemplate.new(filename, sass_options(filename, context)).render(self)
131
+ rescue => e
132
+ # Annotates exception message with parse line number
133
+ # context.__LINE__ = e.sass_backtrace.first[:line]
134
+ raise [e, e.backtrace].join("\n")
135
+ end
136
+
137
+ def merge_sass_options(options, other_options)
138
+ if (load_paths = options[:load_paths]) && (other_paths = other_options[:load_paths])
139
+ other_options[:load_paths] = other_paths + load_paths
140
+ end
141
+ options = options.merge(other_options)
142
+ options[:load_paths] = options[:load_paths].is_a?(Array) ? options[:load_paths] : []
143
+ options[:load_paths] = options[:load_paths].concat(context.environment.paths)
144
+ options
145
+ end
146
+
147
+ def default_sass_config
148
+ if defined?(Compass)
149
+ merge_sass_options Compass.sass_engine_options.dup, Sprockets::Sass.options
150
+ else
151
+ Sprockets::Sass.options.dup
152
+ end
153
+ end
154
+
155
+ def default_sass_options
156
+ sass = default_sass_config
157
+ sass = merge_sass_options(sass.dup, @sass_config) if defined?(@sass_config) && @sass_config.is_a?(Hash)
158
+ sass
159
+ end
160
+
161
+ def build_cache_store(context)
162
+ return nil if context.environment.cache.nil?
163
+ if defined?(Sprockets::SassProcessor::CacheStore)
164
+ Sprockets::SassProcessor::CacheStore.new(context.environment)
165
+ else
166
+ custom_cache_store(context.environment)
167
+ end
168
+ end
169
+
170
+ def custom_cache_store(*args)
171
+ Sprockets::Sass::V2::CacheStore.new(*args)
172
+ end
173
+
174
+ # Allow the use of custom SASS importers, making sure the
175
+ # custom importer is a `Sprockets::Sass::Importer`
176
+ def fetch_importer_class
177
+ if defined?(@importer_class) && !@importer_class.nil?
178
+ @importer_class
179
+ elsif default_sass_options.key?(:importer) && default_sass_options[:importer].is_a?(Importer)
180
+ default_sass_options[:importer]
181
+ else
182
+ custom_importer_class
183
+ end
184
+ end
185
+
186
+ def custom_importer_class(*_args)
187
+ Sprockets::Sass::V2::Importer.new
188
+ end
189
+
190
+ def fetch_sprockets_options
191
+ sprockets_options = {
192
+ context: context,
193
+ environment: context.environment,
194
+ dependencies: context.respond_to?(:metadata) ? context.metadata[:dependencies] : []
195
+ }
196
+ if context.respond_to?(:metadata)
197
+ sprockets_options.merge(load_paths: context.environment.paths + default_sass_options[:load_paths])
198
+ end
199
+ sprockets_options
200
+ end
201
+
202
+ def sass_options
203
+ importer = fetch_importer_class
204
+ sprockets_options = fetch_sprockets_options
205
+
206
+ sass = merge_sass_options(default_sass_options, options).merge(
207
+ filename: filename,
208
+ line: 1,
209
+ syntax: self.class.syntax,
210
+ cache: true,
211
+ cache_store: build_cache_store(context),
212
+ importer: importer,
213
+ custom: { sprockets_context: context },
214
+ sprockets: sprockets_options
215
+ )
216
+ sass
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end