sassc-embedded 1.63.0 → 1.80.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.
- checksums.yaml +4 -4
- data/README.md +89 -23
- data/lib/sassc/embedded/version.rb +1 -1
- data/lib/sassc/embedded.rb +282 -203
- data/vendor/github.com/sass/sassc-ruby/LICENSE.txt +22 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/dependency.rb +17 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/engine.rb +141 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/error.rb +37 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/functions_handler.rb +73 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/import_handler.rb +50 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/importer.rb +31 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/native/native_context_api.rb +147 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/native/native_functions_api.rb +159 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/native/sass2scss_api.rb +10 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/native/sass_input_style.rb +13 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/native/sass_output_style.rb +12 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/native/sass_value.rb +97 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/native/string_list.rb +10 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/native.rb +64 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/sass_2_scss.rb +9 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/functions.rb +8 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value/bool.rb +32 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value/color.rb +95 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value/list.rb +136 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value/map.rb +69 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value/number.rb +389 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value/string.rb +96 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value.rb +137 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value_conversion/base.rb +13 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value_conversion/bool.rb +13 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value_conversion/color.rb +18 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value_conversion/list.rb +25 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value_conversion/map.rb +21 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value_conversion/number.rb +13 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value_conversion/string.rb +17 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script/value_conversion.rb +69 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/script.rb +17 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/util/normalized_map.rb +117 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/util.rb +231 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc/version.rb +5 -0
- data/vendor/github.com/sass/sassc-ruby/lib/sassc.rb +64 -0
- metadata +49 -23
data/lib/sassc/embedded.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
require 'sassc'
|
4
4
|
require 'sass-embedded'
|
5
5
|
|
6
|
-
require 'base64'
|
7
6
|
require 'json'
|
8
7
|
require 'uri'
|
9
8
|
|
@@ -11,14 +10,16 @@ require_relative 'embedded/version'
|
|
11
10
|
|
12
11
|
module SassC
|
13
12
|
class Engine
|
13
|
+
remove_method(:render) if public_method_defined?(:render, false)
|
14
|
+
|
14
15
|
def render
|
15
16
|
return @template.dup if @template.empty?
|
16
17
|
|
17
18
|
result = ::Sass.compile_string(
|
18
19
|
@template,
|
19
|
-
importer:
|
20
|
-
load_paths
|
21
|
-
syntax
|
20
|
+
importer: (NoopImporter unless @options[:importer].nil?),
|
21
|
+
load_paths:,
|
22
|
+
syntax:,
|
22
23
|
url: file_url,
|
23
24
|
|
24
25
|
charset: @options.fetch(:charset, true),
|
@@ -27,28 +28,28 @@ module SassC
|
|
27
28
|
style: output_style,
|
28
29
|
|
29
30
|
functions: functions_handler.setup(nil, functions: @functions),
|
30
|
-
importers: @options.fetch(:importers, []),
|
31
|
+
importers: import_handler.setup(nil).concat(@options.fetch(:importers, [])),
|
31
32
|
|
32
33
|
alert_ascii: @options.fetch(:alert_ascii, false),
|
33
34
|
alert_color: @options.fetch(:alert_color, nil),
|
34
|
-
|
35
|
+
fatal_deprecations: @options.fetch(:fatal_deprecations, []),
|
36
|
+
future_deprecations: @options.fetch(:future_deprecations, []),
|
37
|
+
logger: quiet? ? ::Sass::Logger.silent : @options.fetch(:logger, nil),
|
35
38
|
quiet_deps: @options.fetch(:quiet_deps, false),
|
39
|
+
silence_deprecations: @options.fetch(:silence_deprecations, []),
|
36
40
|
verbose: @options.fetch(:verbose, false)
|
37
41
|
)
|
38
42
|
|
39
43
|
@loaded_urls = result.loaded_urls
|
40
44
|
@source_map = result.source_map
|
41
45
|
|
42
|
-
return if quiet?
|
43
|
-
|
44
46
|
css = result.css
|
45
47
|
css += "\n" unless css.empty?
|
46
48
|
unless @source_map.nil? || omit_source_map_url?
|
47
|
-
url = URL.parse(output_url || file_url)
|
48
49
|
source_mapping_url = if source_map_embed?
|
49
|
-
"data:application/json;base64,#{
|
50
|
+
"data:application/json;base64,#{[@source_map].pack('m0')}"
|
50
51
|
else
|
51
|
-
|
52
|
+
Uri.file_urls_to_relative_url(source_map_file_url, file_url)
|
52
53
|
end
|
53
54
|
css += "\n/*# sourceMappingURL=#{source_mapping_url} */"
|
54
55
|
end
|
@@ -59,27 +60,30 @@ module SassC
|
|
59
60
|
line = e.span&.start&.line
|
60
61
|
line += 1 unless line.nil?
|
61
62
|
url = e.span&.url
|
62
|
-
path = (
|
63
|
-
raise SyntaxError.new(e.full_message, filename: path, line:
|
63
|
+
path = (Uri.file_urls_to_relative_path(url, Uri.path_to_file_url("#{Dir.pwd}/")) if url&.start_with?('file:'))
|
64
|
+
raise SyntaxError.new(e.full_message, filename: path, line:)
|
64
65
|
end
|
65
66
|
|
67
|
+
remove_method(:dependencies) if public_method_defined?(:dependencies, false)
|
68
|
+
|
66
69
|
def dependencies
|
67
70
|
raise NotRenderedError unless @loaded_urls
|
68
71
|
|
69
|
-
Dependency.from_filenames(@loaded_urls
|
70
|
-
.
|
71
|
-
|
72
|
+
Dependency.from_filenames(@loaded_urls.filter_map do |url|
|
73
|
+
Uri.file_url_to_path(url) if url.start_with?('file:') && !url.include?('?') && url != file_url
|
74
|
+
end)
|
72
75
|
end
|
73
76
|
|
77
|
+
remove_method(:source_map) if public_method_defined?(:source_map, false)
|
78
|
+
|
74
79
|
def source_map
|
75
80
|
raise NotRenderedError unless @source_map
|
76
81
|
|
77
|
-
url =
|
82
|
+
url = Uri.parse(source_map_file_url || file_url)
|
78
83
|
data = JSON.parse(@source_map)
|
79
|
-
data['file'] = URL.parse(output_url).route_from(url).to_s if output_url
|
80
84
|
data['sources'].map! do |source|
|
81
|
-
if source.start_with?(
|
82
|
-
|
85
|
+
if source.start_with?('file:')
|
86
|
+
Uri.file_urls_to_relative_url(source, url)
|
83
87
|
else
|
84
88
|
source
|
85
89
|
end
|
@@ -91,35 +95,29 @@ module SassC
|
|
91
95
|
private
|
92
96
|
|
93
97
|
def file_url
|
94
|
-
@file_url ||=
|
95
|
-
end
|
96
|
-
|
97
|
-
def output_path
|
98
|
-
@output_path ||= @options.fetch(:output_path) do
|
99
|
-
"#{filename.delete_suffix(File.extname(filename))}.css" if filename
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
def output_url
|
104
|
-
@output_url ||= (URL.path_to_file_url(File.absolute_path(output_path)) if output_path)
|
98
|
+
@file_url ||= Uri.path_to_file_url(File.absolute_path(filename || 'stdin'))
|
105
99
|
end
|
106
100
|
|
107
101
|
def source_map_file_url
|
108
|
-
@source_map_file_url ||=
|
102
|
+
@source_map_file_url ||= if source_map_file
|
103
|
+
Uri.path_to_file_url(File.absolute_path(source_map_file))
|
104
|
+
.gsub('%3F', '?') # https://github.com/sass-contrib/sassc-embedded-shim-ruby/pull/69
|
105
|
+
end
|
109
106
|
end
|
110
107
|
|
108
|
+
remove_method(:output_style) if private_method_defined?(:output_style, false)
|
109
|
+
|
111
110
|
def output_style
|
112
111
|
@output_style ||= begin
|
113
|
-
style = @options.fetch(:style, :sass_style_nested).to_s
|
114
|
-
style = "sass_style_#{style}" unless style.start_with?('sass_style_')
|
115
|
-
raise InvalidStyleError unless OUTPUT_STYLES.include?(style.to_sym)
|
112
|
+
style = @options.fetch(:style, :sass_style_nested).to_s.delete_prefix('sass_style_').to_sym
|
116
113
|
|
117
|
-
style = style.delete_prefix('sass_style_').to_sym
|
118
114
|
case style
|
119
|
-
when :nested, :compact
|
115
|
+
when :nested, :compact, :expanded
|
120
116
|
:expanded
|
117
|
+
when :compressed
|
118
|
+
:compressed
|
121
119
|
else
|
122
|
-
|
120
|
+
raise InvalidStyleError
|
123
121
|
end
|
124
122
|
end
|
125
123
|
end
|
@@ -130,19 +128,17 @@ module SassC
|
|
130
128
|
syntax
|
131
129
|
end
|
132
130
|
|
131
|
+
remove_method(:load_paths) if private_method_defined?(:load_paths, false)
|
132
|
+
|
133
133
|
def load_paths
|
134
|
-
@load_paths ||=
|
135
|
-
(@options[:load_paths] || []) + SassC.load_paths
|
136
|
-
else
|
137
|
-
[]
|
138
|
-
end
|
134
|
+
@load_paths ||= (@options[:load_paths] || []) + SassC.load_paths
|
139
135
|
end
|
140
136
|
end
|
141
137
|
|
142
138
|
class FunctionsHandler
|
143
|
-
|
144
|
-
@callbacks = {}
|
139
|
+
remove_method(:setup) if public_method_defined?(:setup, false)
|
145
140
|
|
141
|
+
def setup(_native_options, functions: Script::Functions)
|
146
142
|
functions_wrapper = Class.new do
|
147
143
|
attr_accessor :options
|
148
144
|
|
@@ -150,7 +146,7 @@ module SassC
|
|
150
146
|
end.new
|
151
147
|
functions_wrapper.options = @options
|
152
148
|
|
153
|
-
Script.custom_functions(functions:
|
149
|
+
Script.custom_functions(functions:).each_with_object({}) do |custom_function, callbacks|
|
154
150
|
callback = lambda do |native_argument_list|
|
155
151
|
function_arguments = arguments_from_native_list(native_argument_list)
|
156
152
|
begin
|
@@ -164,48 +160,72 @@ module SassC
|
|
164
160
|
raise e
|
165
161
|
end
|
166
162
|
|
167
|
-
|
163
|
+
callbacks[Script.formatted_function_name(custom_function, functions:)] = callback
|
168
164
|
end
|
169
|
-
|
170
|
-
@callbacks
|
171
165
|
end
|
172
166
|
|
173
167
|
private
|
174
168
|
|
169
|
+
remove_method(:arguments_from_native_list) if private_method_defined?(:arguments_from_native_list, false)
|
170
|
+
|
175
171
|
def arguments_from_native_list(native_argument_list)
|
176
172
|
native_argument_list.filter_map do |native_value|
|
177
173
|
Script::ValueConversion.from_native(native_value, @options)
|
178
174
|
end
|
179
175
|
end
|
176
|
+
end
|
180
177
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
rescue StandardError => e
|
188
|
-
unless e.full_message.include?(e.cause.full_message)
|
189
|
-
::Sass::ScriptError.class_eval do
|
190
|
-
def full_message(...)
|
191
|
-
full_message = super(...)
|
192
|
-
if cause
|
193
|
-
"#{full_message}\n#{cause.full_message(...)}"
|
194
|
-
else
|
195
|
-
full_message
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|
178
|
+
module NoopImporter
|
179
|
+
module_function
|
180
|
+
|
181
|
+
def canonicalize(...); end
|
182
|
+
|
183
|
+
def load(...); end
|
201
184
|
end
|
202
185
|
|
186
|
+
private_constant :NoopImporter
|
187
|
+
|
203
188
|
class ImportHandler
|
189
|
+
remove_method(:setup) if public_method_defined?(:setup, false)
|
190
|
+
|
204
191
|
def setup(_native_options)
|
205
|
-
|
192
|
+
if @importer
|
193
|
+
import_cache = ImportCache.new(@importer)
|
194
|
+
[Importer.new(import_cache), FileImporter.new(import_cache)]
|
195
|
+
else
|
196
|
+
[]
|
197
|
+
end
|
206
198
|
end
|
207
199
|
|
200
|
+
class Importer
|
201
|
+
def initialize(import_cache)
|
202
|
+
@import_cache = import_cache
|
203
|
+
end
|
204
|
+
|
205
|
+
def canonicalize(...)
|
206
|
+
@import_cache.canonicalize(...)
|
207
|
+
end
|
208
|
+
|
209
|
+
def load(...)
|
210
|
+
@import_cache.load(...)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
private_constant :Importer
|
215
|
+
|
208
216
|
class FileImporter
|
217
|
+
def initialize(import_cache)
|
218
|
+
@import_cache = import_cache
|
219
|
+
end
|
220
|
+
|
221
|
+
def find_file_url(...)
|
222
|
+
@import_cache.find_file_url(...)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
private_constant :FileImporter
|
227
|
+
|
228
|
+
module FileSystemImporter
|
209
229
|
class << self
|
210
230
|
def resolve_path(path, from_import)
|
211
231
|
ext = File.extname(path)
|
@@ -217,15 +237,6 @@ module SassC
|
|
217
237
|
return exactly_one(try_path(path))
|
218
238
|
end
|
219
239
|
|
220
|
-
unless ext.empty?
|
221
|
-
if from_import
|
222
|
-
result = exactly_one(try_path("#{without_ext(path)}.import#{ext}"))
|
223
|
-
return result unless result.nil?
|
224
|
-
end
|
225
|
-
result = exactly_one(try_path(path))
|
226
|
-
return result unless result.nil?
|
227
|
-
end
|
228
|
-
|
229
240
|
if from_import
|
230
241
|
result = exactly_one(try_path_with_ext("#{path}.import"))
|
231
242
|
return result unless result.nil?
|
@@ -253,7 +264,7 @@ module SassC
|
|
253
264
|
end
|
254
265
|
|
255
266
|
def try_path_as_dir(path, from_import)
|
256
|
-
return unless dir_exist?
|
267
|
+
return unless dir_exist?(path)
|
257
268
|
|
258
269
|
if from_import
|
259
270
|
result = exactly_one(try_path_with_ext(File.join(path, 'index.import')))
|
@@ -265,7 +276,7 @@ module SassC
|
|
265
276
|
|
266
277
|
def exactly_one(paths)
|
267
278
|
return if paths.empty?
|
268
|
-
return paths.first if paths.
|
279
|
+
return paths.first if paths.one?
|
269
280
|
|
270
281
|
raise "It's not clear which file to import. Found:\n#{paths.map { |path| " #{path}" }.join("\n")}"
|
271
282
|
end
|
@@ -285,79 +296,63 @@ module SassC
|
|
285
296
|
end
|
286
297
|
end
|
287
298
|
|
288
|
-
private_constant :
|
299
|
+
private_constant :FileSystemImporter
|
289
300
|
|
290
|
-
class
|
301
|
+
class ImportCache
|
291
302
|
def initialize(importer)
|
292
303
|
@importer = importer
|
293
|
-
|
294
|
-
@canonical_urls = {}
|
295
|
-
@id = 0
|
296
304
|
@importer_results = {}
|
297
|
-
@
|
305
|
+
@importer_result = nil
|
306
|
+
@file_url = nil
|
298
307
|
end
|
299
308
|
|
300
|
-
def canonicalize(url,
|
301
|
-
|
302
|
-
|
309
|
+
def canonicalize(url, context)
|
310
|
+
return unless context.containing_url&.start_with?('file:')
|
311
|
+
|
312
|
+
containing_url = context.containing_url
|
313
|
+
|
314
|
+
path = Uri.decode_uri_component(url)
|
315
|
+
parent_path = Uri.file_url_to_path(containing_url)
|
316
|
+
parent_dir = File.dirname(parent_path)
|
317
|
+
|
318
|
+
if containing_url.include?('?')
|
319
|
+
canonical_url = Uri.path_to_file_url(File.absolute_path(path, parent_dir))
|
303
320
|
unless @importer_results.key?(canonical_url)
|
304
|
-
|
321
|
+
@file_url = resolve_file_url(path, parent_dir, context.from_import)
|
322
|
+
return
|
305
323
|
end
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
imports = @importer.imports(path, parent_path)
|
313
|
-
imports = [SassC::Importer::Import.new(path)] if imports.nil?
|
314
|
-
imports = [imports] unless imports.is_a?(Array)
|
315
|
-
imports.each do |import|
|
316
|
-
import.path = File.absolute_path(import.path, File.dirname(parent_path))
|
324
|
+
else
|
325
|
+
imports = [*@importer.imports(path, parent_path)]
|
326
|
+
canonical_url = imports_to_native(imports, parent_dir, context.from_import, url, containing_url)
|
327
|
+
unless @importer_results.key?(canonical_url)
|
328
|
+
@file_url = canonical_url
|
329
|
+
return
|
317
330
|
end
|
318
|
-
|
319
|
-
canonical_url = "#{Protocol::IMPORT}#{next_id}"
|
320
|
-
@importer_results[canonical_url] = imports_to_native(imports)
|
321
|
-
canonical_url
|
322
|
-
elsif url.start_with?(Protocol::LOADED)
|
323
|
-
canonical_url = Protocol::LOADED
|
324
|
-
@parent_urls.pop
|
325
|
-
canonical_url
|
326
331
|
end
|
332
|
+
|
333
|
+
@importer_result = @importer_results.delete(canonical_url)
|
334
|
+
canonical_url
|
327
335
|
end
|
328
336
|
|
329
|
-
def load(
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
path = URL.file_url_to_path(canonical_url)
|
334
|
-
{
|
335
|
-
contents: File.read(path),
|
336
|
-
syntax: syntax(path),
|
337
|
-
source_map_url: canonical_url
|
338
|
-
}
|
339
|
-
elsif canonical_url.start_with?(Protocol::LOADED)
|
340
|
-
{
|
341
|
-
contents: '',
|
342
|
-
syntax: :scss
|
343
|
-
}
|
344
|
-
end
|
337
|
+
def load(_canonical_url)
|
338
|
+
importer_result = @importer_result
|
339
|
+
@importer_result = nil
|
340
|
+
importer_result
|
345
341
|
end
|
346
342
|
|
347
|
-
|
343
|
+
def find_file_url(_url, context)
|
344
|
+
return if context.containing_url.nil? || @file_url.nil?
|
348
345
|
|
349
|
-
|
350
|
-
@
|
346
|
+
canonical_url = @file_url
|
347
|
+
@file_url = nil
|
348
|
+
canonical_url
|
351
349
|
end
|
352
350
|
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
return URL.path_to_file_url(resolved) unless resolved.nil?
|
359
|
-
end
|
360
|
-
nil
|
351
|
+
private
|
352
|
+
|
353
|
+
def resolve_file_url(path, parent_dir, from_import)
|
354
|
+
resolved = FileSystemImporter.resolve_path(File.absolute_path(path, parent_dir), from_import)
|
355
|
+
Uri.path_to_file_url(resolved) unless resolved.nil?
|
361
356
|
end
|
362
357
|
|
363
358
|
def syntax(path)
|
@@ -371,47 +366,55 @@ module SassC
|
|
371
366
|
end
|
372
367
|
end
|
373
368
|
|
374
|
-
def
|
375
|
-
|
369
|
+
def import_to_native(import, parent_dir, from_import, canonicalize)
|
370
|
+
if import.source
|
371
|
+
canonical_url = Uri.path_to_file_url(File.absolute_path(import.path, parent_dir))
|
372
|
+
@importer_results[canonical_url] = if import.source.is_a?(Hash)
|
373
|
+
{
|
374
|
+
contents: import.source[:contents],
|
375
|
+
syntax: import.source[:syntax],
|
376
|
+
source_map_url: canonical_url
|
377
|
+
}
|
378
|
+
else
|
379
|
+
{
|
380
|
+
contents: import.source,
|
381
|
+
syntax: syntax(import.path),
|
382
|
+
source_map_url: canonical_url
|
383
|
+
}
|
384
|
+
end
|
385
|
+
return canonical_url if canonicalize
|
386
|
+
elsif canonicalize
|
387
|
+
return resolve_file_url(import.path, parent_dir, from_import)
|
388
|
+
end
|
389
|
+
|
390
|
+
Uri.encode_uri_path_component(import.path)
|
391
|
+
end
|
392
|
+
|
393
|
+
def imports_to_native(imports, parent_dir, from_import, url, containing_url)
|
394
|
+
return import_to_native(imports.first, parent_dir, from_import, true) if imports.one?
|
395
|
+
|
396
|
+
canonical_url = "#{containing_url}?url=#{Uri.encode_uri_query_component(url)}&from_import=#{from_import}"
|
397
|
+
@importer_results[canonical_url] = {
|
376
398
|
contents: imports.flat_map do |import|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
if import.source
|
381
|
-
@importer_results[canonical_url] = if import.source.is_a?(Hash)
|
382
|
-
{
|
383
|
-
contents: import.source[:contents],
|
384
|
-
syntax: import.source[:syntax],
|
385
|
-
source_map_url: canonical_url
|
386
|
-
}
|
387
|
-
else
|
388
|
-
{
|
389
|
-
contents: import.source,
|
390
|
-
syntax: syntax(import.path),
|
391
|
-
source_map_url: canonical_url
|
392
|
-
}
|
393
|
-
end
|
394
|
-
end
|
395
|
-
[
|
396
|
-
"@import \"#{Protocol::IMPORT}#{id}\";",
|
397
|
-
"@import \"#{Protocol::LOADED}#{id}\";"
|
398
|
-
]
|
399
|
+
at_rule = from_import ? '@import' : '@forward'
|
400
|
+
url = import_to_native(import, parent_dir, from_import, false)
|
401
|
+
"#{at_rule} #{Script::Value::String.quote(url)};"
|
399
402
|
end.join("\n"),
|
400
403
|
syntax: :scss
|
401
404
|
}
|
402
|
-
end
|
403
405
|
|
404
|
-
|
405
|
-
id = @id
|
406
|
-
@id = id.next
|
407
|
-
id.to_s
|
406
|
+
canonical_url
|
408
407
|
end
|
409
408
|
end
|
410
409
|
|
411
|
-
private_constant :
|
410
|
+
private_constant :ImportCache
|
412
411
|
end
|
413
412
|
|
414
413
|
class Sass2Scss
|
414
|
+
class << self
|
415
|
+
remove_method(:convert) if public_method_defined?(:convert, false)
|
416
|
+
end
|
417
|
+
|
415
418
|
def self.convert(sass)
|
416
419
|
{
|
417
420
|
contents: sass,
|
@@ -421,7 +424,38 @@ module SassC
|
|
421
424
|
end
|
422
425
|
|
423
426
|
module Script
|
427
|
+
class Value
|
428
|
+
class String
|
429
|
+
class << self
|
430
|
+
remove_method(:quote) if public_method_defined?(:quote, false)
|
431
|
+
end
|
432
|
+
|
433
|
+
# Returns the quoted string representation of `contents`.
|
434
|
+
#
|
435
|
+
# @options opts :quote [String]
|
436
|
+
# The preferred quote style for quoted strings. If `:none`, strings are
|
437
|
+
# always emitted unquoted. If `nil`, quoting is determined automatically.
|
438
|
+
# @options opts :sass [String]
|
439
|
+
# Whether to quote strings for Sass source, as opposed to CSS. Defaults to `false`.
|
440
|
+
def self.quote(contents, opts = {})
|
441
|
+
contents = ::Sass::Value::String.new(contents, quoted: opts[:quote] != :none).to_s
|
442
|
+
opts[:sass] ? contents.gsub('#', '\#') : contents
|
443
|
+
end
|
444
|
+
|
445
|
+
remove_method(:to_s) if public_method_defined?(:to_s, false)
|
446
|
+
|
447
|
+
def to_s(opts = {})
|
448
|
+
opts = { quote: :none }.merge!(opts) if @type == :identifier
|
449
|
+
self.class.quote(@value, opts)
|
450
|
+
end
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
424
454
|
module ValueConversion
|
455
|
+
class << self
|
456
|
+
remove_method(:from_native) if public_method_defined?(:from_native, false)
|
457
|
+
end
|
458
|
+
|
425
459
|
def self.from_native(value, options)
|
426
460
|
case value
|
427
461
|
when ::Sass::Value::Null::NULL
|
@@ -429,18 +463,21 @@ module SassC
|
|
429
463
|
when ::Sass::Value::Boolean
|
430
464
|
::SassC::Script::Value::Bool.new(value.to_bool)
|
431
465
|
when ::Sass::Value::Color
|
432
|
-
|
466
|
+
case value.space
|
467
|
+
when 'hsl', 'hwb'
|
468
|
+
value = value.to_space('hsl')
|
433
469
|
::SassC::Script::Value::Color.new(
|
434
|
-
hue: value.hue,
|
435
|
-
saturation: value.saturation,
|
436
|
-
lightness: value.lightness,
|
470
|
+
hue: value.channel('hue'),
|
471
|
+
saturation: value.channel('saturation'),
|
472
|
+
lightness: value.channel('lightness'),
|
437
473
|
alpha: value.alpha
|
438
474
|
)
|
439
475
|
else
|
476
|
+
value = value.to_space('rgb')
|
440
477
|
::SassC::Script::Value::Color.new(
|
441
|
-
red: value.red,
|
442
|
-
green: value.green,
|
443
|
-
blue: value.blue,
|
478
|
+
red: value.channel('red'),
|
479
|
+
green: value.channel('green'),
|
480
|
+
blue: value.channel('blue'),
|
444
481
|
alpha: value.alpha
|
445
482
|
)
|
446
483
|
end
|
@@ -459,7 +496,7 @@ module SassC
|
|
459
496
|
)
|
460
497
|
when ::Sass::Value::Map
|
461
498
|
::SassC::Script::Value::Map.new(
|
462
|
-
value.contents.
|
499
|
+
value.contents.each_with_object({}) { |(k, v), h| h[from_native(k, options)] = from_native(v, options) }
|
463
500
|
)
|
464
501
|
when ::Sass::Value::Number
|
465
502
|
::SassC::Script::Value::Number.new(
|
@@ -477,6 +514,10 @@ module SassC
|
|
477
514
|
end
|
478
515
|
end
|
479
516
|
|
517
|
+
class << self
|
518
|
+
remove_method(:to_native) if public_method_defined?(:to_native, false)
|
519
|
+
end
|
520
|
+
|
480
521
|
def self.to_native(value)
|
481
522
|
case value
|
482
523
|
when nil
|
@@ -489,14 +530,16 @@ module SassC
|
|
489
530
|
red: value.red,
|
490
531
|
green: value.green,
|
491
532
|
blue: value.blue,
|
492
|
-
alpha: value.alpha
|
533
|
+
alpha: value.alpha,
|
534
|
+
space: 'rgb'
|
493
535
|
)
|
494
536
|
elsif value.hlsa?
|
495
537
|
::Sass::Value::Color.new(
|
496
538
|
hue: value.hue,
|
497
539
|
saturation: value.saturation,
|
498
540
|
lightness: value.lightness,
|
499
|
-
alpha: value.alpha
|
541
|
+
alpha: value.alpha,
|
542
|
+
space: 'hsl'
|
500
543
|
)
|
501
544
|
else
|
502
545
|
raise UnsupportedValue, "Sass color mode #{value.instance_eval { @mode }} unsupported"
|
@@ -516,7 +559,7 @@ module SassC
|
|
516
559
|
)
|
517
560
|
when ::SassC::Script::Value::Map
|
518
561
|
::Sass::Value::Map.new(
|
519
|
-
value.value.
|
562
|
+
value.value.each_with_object({}) { |(k, v), h| h[to_native(k)] = to_native(v) }
|
520
563
|
)
|
521
564
|
when ::SassC::Script::Value::Number
|
522
565
|
::Sass::Value::Number.new(
|
@@ -537,48 +580,84 @@ module SassC
|
|
537
580
|
end
|
538
581
|
end
|
539
582
|
|
540
|
-
module
|
541
|
-
|
542
|
-
IMPORT = 'sassc-embedded-import:'
|
543
|
-
LOADED = 'sassc-embedded-loaded:'
|
544
|
-
end
|
583
|
+
module Uri
|
584
|
+
module_function
|
545
585
|
|
546
|
-
|
586
|
+
def parse(...)
|
587
|
+
::URI::RFC3986_PARSER.parse(...)
|
588
|
+
end
|
547
589
|
|
548
|
-
|
549
|
-
|
590
|
+
encode_uri_hash = {}
|
591
|
+
decode_uri_hash = {}
|
592
|
+
256.times do |i|
|
593
|
+
c = -[i].pack('C')
|
594
|
+
h = c.unpack1('H')
|
595
|
+
l = c.unpack1('h')
|
596
|
+
pdd = -"%#{h}#{l}"
|
597
|
+
pdu = -"%#{h}#{l.upcase}"
|
598
|
+
pud = -"%#{h.upcase}#{l}"
|
599
|
+
puu = -pdd.upcase
|
600
|
+
encode_uri_hash[c] = puu
|
601
|
+
decode_uri_hash[pdd] = c
|
602
|
+
decode_uri_hash[pdu] = c
|
603
|
+
decode_uri_hash[pud] = c
|
604
|
+
decode_uri_hash[puu] = c
|
605
|
+
end.freeze
|
606
|
+
encode_uri_hash.freeze
|
607
|
+
decode_uri_hash.freeze
|
608
|
+
|
609
|
+
{
|
610
|
+
uri_path_component: "!$&'()*+,;=:/@",
|
611
|
+
uri_query_component: "!$&'()*+,;=:/?@",
|
612
|
+
uri_component: nil,
|
613
|
+
uri: "!$&'()*+,;=:/?#[]@"
|
614
|
+
}
|
615
|
+
.each do |symbol, unescaped|
|
616
|
+
encode_regexp = Regexp.new("[^0-9A-Za-z#{Regexp.escape("-._~#{unescaped}")}]", Regexp::NOENCODING)
|
617
|
+
|
618
|
+
define_method(:"encode_#{symbol}") do |str|
|
619
|
+
str.b.gsub(encode_regexp, encode_uri_hash).force_encoding(str.encoding)
|
620
|
+
end
|
550
621
|
|
551
|
-
|
622
|
+
next if symbol.match?(/_.+_/o)
|
552
623
|
|
553
|
-
|
624
|
+
decode_regexp = /%[0-9A-Fa-f]{2}/o
|
625
|
+
decode_uri_hash_with_preserve_escaped = if unescaped.nil? || unescaped.empty?
|
626
|
+
decode_uri_hash
|
627
|
+
else
|
628
|
+
decode_uri_hash.each_with_object({}) do |(key, value), hash|
|
629
|
+
hash[key] = unescaped.include?(value) ? key : value
|
630
|
+
end.freeze
|
631
|
+
end
|
554
632
|
|
555
|
-
|
556
|
-
|
557
|
-
|
633
|
+
define_method(:"decode_#{symbol}") do |str|
|
634
|
+
str.gsub(decode_regexp, decode_uri_hash_with_preserve_escaped).force_encoding(str.encoding)
|
635
|
+
end
|
636
|
+
end
|
558
637
|
|
559
|
-
def
|
560
|
-
|
638
|
+
def file_urls_to_relative_url(url, from_url)
|
639
|
+
parse(url).route_from(from_url).to_s
|
561
640
|
end
|
562
641
|
|
563
|
-
def
|
564
|
-
|
642
|
+
def file_urls_to_relative_path(url, from_url)
|
643
|
+
decode_uri_component(file_urls_to_relative_url(url, from_url))
|
565
644
|
end
|
566
645
|
|
567
646
|
def file_url_to_path(url)
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
647
|
+
path = decode_uri_component(parse(url).path)
|
648
|
+
if path.start_with?('/')
|
649
|
+
windows_path = path[1..]
|
650
|
+
path = windows_path if File.absolute_path?(windows_path)
|
651
|
+
end
|
572
652
|
path
|
573
653
|
end
|
574
654
|
|
575
655
|
def path_to_file_url(path)
|
576
|
-
return if path.nil?
|
577
|
-
|
578
656
|
path = "/#{path}" unless path.start_with?('/')
|
579
|
-
|
657
|
+
|
658
|
+
"file://#{encode_uri_path_component(path)}"
|
580
659
|
end
|
581
660
|
end
|
582
661
|
|
583
|
-
private_constant :
|
662
|
+
private_constant :Uri
|
584
663
|
end
|