sprockets-sass 1.3.1 → 2.0.0.beta2
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.
- checksums.yaml +7 -0
- data/.reek +12 -0
- data/.rspec +1 -0
- data/.rubocop.yml +77 -0
- data/.travis.yml +14 -0
- data/Appraisals +32 -15
- data/Gemfile +5 -0
- data/README.md +41 -4
- data/Rakefile +15 -3
- data/gemfiles/compass_0.11.gemfile +1 -1
- data/gemfiles/sass_3.1.gemfile +1 -1
- data/gemfiles/sass_3.3.gemfile +8 -0
- data/gemfiles/sass_3.4.gemfile +8 -0
- data/gemfiles/sprockets_2.10.gemfile +1 -1
- data/gemfiles/sprockets_2.11.gemfile +1 -1
- data/gemfiles/sprockets_2.2.gemfile +1 -1
- data/gemfiles/sprockets_2.3.gemfile +1 -1
- data/gemfiles/sprockets_2.4.gemfile +1 -1
- data/gemfiles/sprockets_2.5.gemfile +1 -1
- data/gemfiles/sprockets_2.6.gemfile +1 -1
- data/gemfiles/sprockets_2.7.gemfile +1 -1
- data/gemfiles/sprockets_2.8.gemfile +1 -1
- data/gemfiles/sprockets_2.9.gemfile +1 -1
- data/gemfiles/sprockets_3.7.gemfile +9 -0
- data/gemfiles/sprockets_4.0.gemfile +10 -0
- data/gemfiles/sprockets_4.0_beta2.gemfile +9 -0
- data/lib/sprockets/sass/functions.rb +24 -159
- data/lib/sprockets/sass/registration.rb +126 -0
- data/lib/sprockets/sass/utils.rb +115 -0
- data/lib/sprockets/sass/v2/cache_store.rb +26 -0
- data/lib/sprockets/sass/v2/compressor.rb +31 -0
- data/lib/sprockets/sass/v2/functions.rb +142 -0
- data/lib/sprockets/sass/v2/importer.rb +209 -0
- data/lib/sprockets/sass/v2/sass_template.rb +221 -0
- data/lib/sprockets/sass/v2/scss_template.rb +14 -0
- data/lib/sprockets/sass/v3/cache_store.rb +28 -0
- data/lib/sprockets/sass/v3/compressor.rb +97 -0
- data/lib/sprockets/sass/v3/functions.rb +12 -0
- data/lib/sprockets/sass/v3/importer.rb +224 -0
- data/lib/sprockets/sass/v3/sass_template.rb +37 -0
- data/lib/sprockets/sass/v3/scss_template.rb +15 -0
- data/lib/sprockets/sass/v4/cache_store.rb +11 -0
- data/lib/sprockets/sass/v4/compressor.rb +11 -0
- data/lib/sprockets/sass/v4/functions.rb +12 -0
- data/lib/sprockets/sass/v4/importer.rb +109 -0
- data/lib/sprockets/sass/v4/sass_template.rb +27 -0
- data/lib/sprockets/sass/v4/scss_template.rb +16 -0
- data/lib/sprockets/sass/version.rb +2 -1
- data/lib/sprockets/sass.rb +37 -12
- data/lib/sprockets-sass.rb +1 -0
- data/spec/custom_importer_spec.rb +4 -6
- data/spec/importer_spec.rb +44 -0
- data/spec/spec_helper.rb +39 -3
- data/spec/sprockets-sass_spec.rb +102 -62
- data/spec/support/be_fresh_matcher.rb +12 -8
- data/spec/support/dummy_importer.rb +1 -1
- data/spec/support/fail_postprocessor.rb +23 -0
- data/spec/support/fake_engine.rb +50 -0
- data/spec/support/sass_template.rb +11 -0
- data/spec/support/test_registration.rb +11 -0
- data/sprockets-sass.gemspec +28 -9
- metadata +100 -97
- data/gemfiles/compass_0.12.gemfile +0 -7
- data/gemfiles/sass_3.2.gemfile +0 -7
- data/gemfiles/sprockets_2.0.gemfile +0 -7
- data/gemfiles/sprockets_2.1.gemfile +0 -9
- data/lib/sprockets/sass/cache_store.rb +0 -27
- data/lib/sprockets/sass/compressor.rb +0 -22
- data/lib/sprockets/sass/importer.rb +0 -142
- data/lib/sprockets/sass/sass_template.rb +0 -115
- data/lib/sprockets/sass/scss_template.rb +0 -12
|
@@ -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
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Sprockets
|
|
3
|
+
module Sass
|
|
4
|
+
module V2
|
|
5
|
+
# Preprocessor for SCSS files
|
|
6
|
+
class ScssTemplate < Sprockets::Sass::V2::SassTemplate
|
|
7
|
+
# Define the expected syntax for the template
|
|
8
|
+
def self.syntax
|
|
9
|
+
:scss
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Sprockets
|
|
3
|
+
module Sass
|
|
4
|
+
module V3
|
|
5
|
+
# Internal: Cache wrapper for Sprockets cache adapter. (Sprockets >= 3)
|
|
6
|
+
class CacheStore < ::Sass::CacheStores::Base
|
|
7
|
+
VERSION = '1'
|
|
8
|
+
|
|
9
|
+
def initialize(cache, version)
|
|
10
|
+
@cache = cache
|
|
11
|
+
@version = "#{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
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sprockets
|
|
4
|
+
module Sass
|
|
5
|
+
module V3
|
|
6
|
+
# Class used to compress CSS files
|
|
7
|
+
class Compressor
|
|
8
|
+
VERSION = '1'
|
|
9
|
+
|
|
10
|
+
def self.default_mime_type
|
|
11
|
+
'text/css'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Public: Return singleton instance with default options.
|
|
15
|
+
#
|
|
16
|
+
# Returns SassCompressor object.
|
|
17
|
+
def self.instance
|
|
18
|
+
@instance ||= new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.call(input)
|
|
22
|
+
instance.call(input)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.cache_key
|
|
26
|
+
instance.cache_key
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
attr_reader :cache_key, :input, :filename, :source, :options, :context
|
|
30
|
+
|
|
31
|
+
def initialize(options = {})
|
|
32
|
+
@default_options = {
|
|
33
|
+
syntax: :scss,
|
|
34
|
+
cache: false,
|
|
35
|
+
read_cache: false,
|
|
36
|
+
style: :compressed,
|
|
37
|
+
default_encoding: Encoding.default_external || 'utf-8'
|
|
38
|
+
}
|
|
39
|
+
@options = @default_options
|
|
40
|
+
@cache_key = "#{self.class.name}:#{::Sass::VERSION}:#{VERSION}:#{Sprockets::Sass::Utils.digest(options)}"
|
|
41
|
+
if options.is_a?(Hash)
|
|
42
|
+
@input = options
|
|
43
|
+
@filename = options[:filename]
|
|
44
|
+
@source = options[:data]
|
|
45
|
+
@options = @options.merge(options)
|
|
46
|
+
else
|
|
47
|
+
@filename = options
|
|
48
|
+
@source = block_given? ? yield : nil
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def call(input)
|
|
53
|
+
@input = input
|
|
54
|
+
if input.is_a?(Hash)
|
|
55
|
+
@filename = input[:filename]
|
|
56
|
+
@source = input[:data]
|
|
57
|
+
@context = input[:environment].context_class.new(input)
|
|
58
|
+
end
|
|
59
|
+
data = filename || @input
|
|
60
|
+
run(data)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def render(context, _empty_hash_wtf)
|
|
64
|
+
@context = context
|
|
65
|
+
run(filename)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def self.compress(input)
|
|
69
|
+
call(input)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def run(string)
|
|
73
|
+
data = File.exist?(string.to_s) ? Sprockets::Sass::Utils.read_file_binary(string, options) : string
|
|
74
|
+
if data.count("\n") >= 2
|
|
75
|
+
engine = ::Sass::Engine.new(data, @options.merge(filename: filename))
|
|
76
|
+
css = engine.render
|
|
77
|
+
# this is defined when using sprockets environment,
|
|
78
|
+
# but is not defined when calling directly in tests
|
|
79
|
+
# unless using the manifest to compile the assets
|
|
80
|
+
if defined?(@context) && @context.respond_to?(:metadata)
|
|
81
|
+
sass_dependencies = Set.new([filename])
|
|
82
|
+
engine.dependencies.map do |dependency|
|
|
83
|
+
sass_dependencies << dependency.options[:filename]
|
|
84
|
+
context.metadata[:dependencies] << Sprockets::URIUtils.build_file_digest_uri(dependency.options[:filename])
|
|
85
|
+
end
|
|
86
|
+
context.metadata.merge(data: css, sass_dependencies: sass_dependencies)
|
|
87
|
+
else
|
|
88
|
+
css
|
|
89
|
+
end
|
|
90
|
+
else
|
|
91
|
+
data
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative '../v2/importer'
|
|
3
|
+
module Sprockets
|
|
4
|
+
module Sass
|
|
5
|
+
module V3
|
|
6
|
+
# class used for importing files from SCCS and SASS files
|
|
7
|
+
class Importer < Sprockets::Sass::V2::Importer
|
|
8
|
+
GLOB = /\*|\[.+\]/
|
|
9
|
+
|
|
10
|
+
protected
|
|
11
|
+
|
|
12
|
+
def resolve_path_with_load_paths(context, path, root_path, file)
|
|
13
|
+
context.resolve(file.to_s, load_paths: context.environment.paths, base_path: root_path, accept: syntax_mime_type(path))
|
|
14
|
+
rescue
|
|
15
|
+
nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Finds an asset from the given path. This is where
|
|
19
|
+
# we make Sprockets behave like Sass, and import partial
|
|
20
|
+
# style paths.
|
|
21
|
+
def resolve(context, path, base_path)
|
|
22
|
+
paths, root_path = possible_files(context, path, base_path)
|
|
23
|
+
paths.each do |file|
|
|
24
|
+
found_item = resolve_path_with_load_paths(context, path, root_path, file)
|
|
25
|
+
return found_item if !found_item.nil? && asset_requirable?(context, found_item)
|
|
26
|
+
end
|
|
27
|
+
nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def stat_of_pathname(context, _pathname, path)
|
|
31
|
+
context.environment.stat(path)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def available_content_types(path)
|
|
35
|
+
['text/css', syntax_mime_type(path), "text/#{syntax(path)}+ruby"].compact.uniq
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def check_context_content_types(context, path)
|
|
39
|
+
available_mimes = available_content_types(path)
|
|
40
|
+
path_content_type, _attributes = content_type_of_path(context, path)
|
|
41
|
+
context.content_type.nil? || available_mimes.include?(path_content_type) || available_mimes.include?(context.content_type)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def asset_requirable?(context, path)
|
|
45
|
+
pathname = begin
|
|
46
|
+
context.resolve(path)
|
|
47
|
+
rescue
|
|
48
|
+
nil
|
|
49
|
+
end
|
|
50
|
+
return false if pathname.nil?
|
|
51
|
+
stat = stat_of_pathname(context, pathname, path)
|
|
52
|
+
return false unless stat && stat.file?
|
|
53
|
+
check_context_content_types(context, path)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Finds all of the assets using the given glob.
|
|
57
|
+
def resolve_glob(context, glob, base_path)
|
|
58
|
+
base_path = Pathname.new(base_path)
|
|
59
|
+
path_with_glob = base_path.dirname.join(glob).to_s
|
|
60
|
+
|
|
61
|
+
Pathname.glob(path_with_glob).sort.select do |path|
|
|
62
|
+
asset_requirable = asset_requirable?(context, path)
|
|
63
|
+
path != context.pathname && asset_requirable
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Returns all of the possible paths (including partial variations)
|
|
68
|
+
# to attempt to resolve with the given path.
|
|
69
|
+
def possible_files(context, path, base_path)
|
|
70
|
+
paths, root_path = super(context, path, base_path)
|
|
71
|
+
paths = additional_paths_for_sprockets(context, paths, path, base_path)
|
|
72
|
+
[paths.compact, root_path]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def additional_paths_for_sprockets(context, paths, path, base_path)
|
|
76
|
+
relatives = paths.map { |path_detected| path_detected.to_s.start_with?('.') ? Pathname.new(path_detected) : Pathname.new(path_detected.to_s.prepend('./')) }
|
|
77
|
+
context.environment.paths.each do |load_path|
|
|
78
|
+
relative_path = Pathname.new(base_path).relative_path_from(Pathname.new(load_path)).join(path)
|
|
79
|
+
paths.unshift(relative_path, partialize_path(relative_path))
|
|
80
|
+
end
|
|
81
|
+
paths = paths.unshift(relatives)
|
|
82
|
+
paths
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def filtered_processor_classes
|
|
86
|
+
classes = super
|
|
87
|
+
classes << Sprockets::Preprocessors::DefaultSourceMap if defined?(Sprockets::Preprocessors::DefaultSourceMap)
|
|
88
|
+
classes << Sprockets::SourceMapProcessor if defined?(Sprockets::SourceMapProcessor)
|
|
89
|
+
classes
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def content_type_of_path(context, path)
|
|
93
|
+
attributes = context.environment.send(:parse_path_extnames, path.to_s)
|
|
94
|
+
content_type = attributes[1]
|
|
95
|
+
[content_type, attributes]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def build_input_for_process(context, path, data)
|
|
99
|
+
content_type, _attributes = content_type_of_path(context, path)
|
|
100
|
+
{
|
|
101
|
+
environment: context.environment,
|
|
102
|
+
cache: context.environment.cache,
|
|
103
|
+
uri: path.to_s,
|
|
104
|
+
filename: path.to_s,
|
|
105
|
+
load_path: context.environment.paths,
|
|
106
|
+
name: File.basename(path),
|
|
107
|
+
content_type: content_type,
|
|
108
|
+
data: data,
|
|
109
|
+
metadata: context.metadata
|
|
110
|
+
}
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def check_path_before_process(_context, path)
|
|
114
|
+
path
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def call_processor_input(processor, context, input, processors)
|
|
118
|
+
metadata = (input[:metadata] || {}).dup
|
|
119
|
+
metadata[:data] = input[:data]
|
|
120
|
+
result = processor.call(input)
|
|
121
|
+
processors.delete(processor)
|
|
122
|
+
handle_process_result(context, result, processors, metadata)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def handle_complex_process_result(context, result, processors)
|
|
126
|
+
data = result[:data] if result.key?(:data)
|
|
127
|
+
context.metadata.merge!(result)
|
|
128
|
+
context.metadata.delete(:data)
|
|
129
|
+
if result.key?(:required)
|
|
130
|
+
result[:required].each do |file|
|
|
131
|
+
file_asset = context.environment.load(file)
|
|
132
|
+
data += process(processors, context, file_asset.filename)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
data
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def handle_process_result(context, result, processors, metadata)
|
|
139
|
+
data = nil
|
|
140
|
+
case result
|
|
141
|
+
when NilClass
|
|
142
|
+
data = metadata[:data]
|
|
143
|
+
when Hash
|
|
144
|
+
data = handle_complex_process_result(context, result, processors)
|
|
145
|
+
when String
|
|
146
|
+
data = result
|
|
147
|
+
else
|
|
148
|
+
raise Error, "invalid processor return type: #{result.class}"
|
|
149
|
+
end
|
|
150
|
+
data
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Internal: Run processors on filename and data.
|
|
154
|
+
#
|
|
155
|
+
# Returns Hash.
|
|
156
|
+
def process(processors, context, path)
|
|
157
|
+
path = check_path_before_process(context, path)
|
|
158
|
+
data = Sprockets::Sass::Utils.read_template_file(path.to_s)
|
|
159
|
+
input = build_input_for_process(context, path, data)
|
|
160
|
+
processors.each do |processor|
|
|
161
|
+
data = call_processor_input(processor, context, input, processors)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
data
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def get_context_preprocessors(context, content_type)
|
|
168
|
+
context.environment.preprocessors[content_type].map { |a| a.class == Class ? a : a.class }
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def get_context_transformers(context, content_type, path)
|
|
172
|
+
available_transformers = context.environment.transformers[content_type]
|
|
173
|
+
additional_transformers = available_transformers.key?(syntax_mime_type(path)) ? available_transformers[syntax_mime_type(path)] : []
|
|
174
|
+
additional_transformers.is_a?(Array) ? additional_transformers : [additional_transformers]
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def get_engines_from_attributes(context, attributes)
|
|
178
|
+
engines = []
|
|
179
|
+
attributes[2].each do |extension|
|
|
180
|
+
ext = ::Sprockets::Utils.normalize_extension(extension)
|
|
181
|
+
ext_engines = context.environment.engines[ext]
|
|
182
|
+
ext_engines = ext_engines.is_a?(Array) ? ext_engines : [ext_engines]
|
|
183
|
+
engines.concat(ext_engines)
|
|
184
|
+
end
|
|
185
|
+
engines
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def get_all_processors_for_evaluate(context, content_type, attributes, path)
|
|
189
|
+
engines = get_engines_from_attributes(context, attributes)
|
|
190
|
+
preprocessors = get_context_preprocessors(context, content_type)
|
|
191
|
+
additional_transformers = get_context_transformers(context, content_type, path)
|
|
192
|
+
postprocessors = get_context_postprocessors(context, content_type)
|
|
193
|
+
engines.reverse + preprocessors + additional_transformers.reverse + postprocessors
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def get_context_postprocessors(context, content_type)
|
|
197
|
+
context.environment.postprocessors[content_type].map { |a| a.class == Class ? a : a.class }
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def filter_all_processors(processors)
|
|
201
|
+
processors.delete_if do |processor|
|
|
202
|
+
filtered_processor_classes.include?(processor) || filtered_processor_classes.any? do |filtered_processor|
|
|
203
|
+
!processor.is_a?(Proc) && processor < filtered_processor
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def evaluate_path_from_context(context, path, processors)
|
|
209
|
+
process(processors, context, path)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# Returns the string to be passed to the Sass engine. We use
|
|
213
|
+
# Sprockets to process the file, but we remove any Sass processors
|
|
214
|
+
# because we need to let the Sass::Engine handle that.
|
|
215
|
+
def evaluate(context, path)
|
|
216
|
+
content_type, attributes = content_type_of_path(context, path)
|
|
217
|
+
processors = get_all_processors_for_evaluate(context, content_type, attributes, path)
|
|
218
|
+
filter_all_processors(processors)
|
|
219
|
+
evaluate_path_from_context(context, path, processors)
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative '../v2/sass_template'
|
|
3
|
+
module Sprockets
|
|
4
|
+
module Sass
|
|
5
|
+
module V3
|
|
6
|
+
# Preprocessor for SASS files
|
|
7
|
+
class SassTemplate < Sprockets::Sass::V2::SassTemplate
|
|
8
|
+
def build_cache_store(context)
|
|
9
|
+
return nil if context.environment.cache.nil?
|
|
10
|
+
cache = @input[:cache]
|
|
11
|
+
version = @cache_version
|
|
12
|
+
if defined?(Sprockets::SassProcessor::CacheStore)
|
|
13
|
+
Sprockets::SassProcessor::CacheStore.new(cache, version)
|
|
14
|
+
else
|
|
15
|
+
custom_cache_store(cache, version)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def custom_cache_store(*args)
|
|
20
|
+
Sprockets::Sass::V3::CacheStore.new(*args)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Allow the use of custom SASS importers, making sure the
|
|
24
|
+
# custom importer is a `Sprockets::Sass::Importer`
|
|
25
|
+
def fetch_importer_class
|
|
26
|
+
if defined?(@importer_class) && !@importer_class.nil?
|
|
27
|
+
@importer_class
|
|
28
|
+
elsif default_sass_options.key?(:importer) && default_sass_options[:importer].is_a?(Importer)
|
|
29
|
+
default_sass_options[:importer]
|
|
30
|
+
else
|
|
31
|
+
Sprockets::Sass::V3::Importer.new
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative './sass_template'
|
|
3
|
+
module Sprockets
|
|
4
|
+
module Sass
|
|
5
|
+
module V3
|
|
6
|
+
# Preprocessor for SCSS files
|
|
7
|
+
class ScssTemplate < Sprockets::Sass::V3::SassTemplate
|
|
8
|
+
# Define the expected syntax for the template
|
|
9
|
+
def self.syntax
|
|
10
|
+
:scss
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative '../v3/cache_store'
|
|
3
|
+
module Sprockets
|
|
4
|
+
module Sass
|
|
5
|
+
module V4
|
|
6
|
+
# Internal: Cache wrapper for Sprockets cache adapter. (Sprockets >= 3)
|
|
7
|
+
class CacheStore < Sprockets::Sass::V3::CacheStore
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|