sprockets-sass 1.3.1 → 2.0.0.beta1

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 (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