sassc-embedded 1.63.0 → 1.78.0
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 +266 -188
- 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,16 +128,16 @@ 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
|
139
|
+
remove_method(:setup) if public_method_defined?(:setup, false)
|
140
|
+
|
143
141
|
def setup(_native_options, functions: Script::Functions)
|
144
142
|
@callbacks = {}
|
145
143
|
|
@@ -150,7 +148,7 @@ module SassC
|
|
150
148
|
end.new
|
151
149
|
functions_wrapper.options = @options
|
152
150
|
|
153
|
-
Script.custom_functions(functions:
|
151
|
+
Script.custom_functions(functions:).each do |custom_function|
|
154
152
|
callback = lambda do |native_argument_list|
|
155
153
|
function_arguments = arguments_from_native_list(native_argument_list)
|
156
154
|
begin
|
@@ -164,7 +162,7 @@ module SassC
|
|
164
162
|
raise e
|
165
163
|
end
|
166
164
|
|
167
|
-
@callbacks[Script.formatted_function_name(custom_function, functions:
|
165
|
+
@callbacks[Script.formatted_function_name(custom_function, functions:)] = callback
|
168
166
|
end
|
169
167
|
|
170
168
|
@callbacks
|
@@ -172,40 +170,66 @@ module SassC
|
|
172
170
|
|
173
171
|
private
|
174
172
|
|
173
|
+
remove_method(:arguments_from_native_list) if private_method_defined?(:arguments_from_native_list, false)
|
174
|
+
|
175
175
|
def arguments_from_native_list(native_argument_list)
|
176
176
|
native_argument_list.filter_map do |native_value|
|
177
177
|
Script::ValueConversion.from_native(native_value, @options)
|
178
178
|
end
|
179
179
|
end
|
180
|
+
end
|
180
181
|
|
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
|
182
|
+
module NoopImporter
|
183
|
+
module_function
|
184
|
+
|
185
|
+
def canonicalize(...); end
|
186
|
+
|
187
|
+
def load(...); end
|
201
188
|
end
|
202
189
|
|
190
|
+
private_constant :NoopImporter
|
191
|
+
|
203
192
|
class ImportHandler
|
193
|
+
remove_method(:setup) if public_method_defined?(:setup, false)
|
194
|
+
|
204
195
|
def setup(_native_options)
|
205
|
-
|
196
|
+
if @importer
|
197
|
+
import_cache = ImportCache.new(@importer)
|
198
|
+
[Importer.new(import_cache), FileImporter.new(import_cache)]
|
199
|
+
else
|
200
|
+
[]
|
201
|
+
end
|
206
202
|
end
|
207
203
|
|
204
|
+
class Importer
|
205
|
+
def initialize(import_cache)
|
206
|
+
@import_cache = import_cache
|
207
|
+
end
|
208
|
+
|
209
|
+
def canonicalize(...)
|
210
|
+
@import_cache.canonicalize(...)
|
211
|
+
end
|
212
|
+
|
213
|
+
def load(...)
|
214
|
+
@import_cache.load(...)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
private_constant :Importer
|
219
|
+
|
208
220
|
class FileImporter
|
221
|
+
def initialize(import_cache)
|
222
|
+
@import_cache = import_cache
|
223
|
+
end
|
224
|
+
|
225
|
+
def find_file_url(...)
|
226
|
+
@import_cache.find_file_url(...)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
private_constant :FileImporter
|
231
|
+
|
232
|
+
module FileSystemImporter
|
209
233
|
class << self
|
210
234
|
def resolve_path(path, from_import)
|
211
235
|
ext = File.extname(path)
|
@@ -217,15 +241,6 @@ module SassC
|
|
217
241
|
return exactly_one(try_path(path))
|
218
242
|
end
|
219
243
|
|
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
244
|
if from_import
|
230
245
|
result = exactly_one(try_path_with_ext("#{path}.import"))
|
231
246
|
return result unless result.nil?
|
@@ -253,7 +268,7 @@ module SassC
|
|
253
268
|
end
|
254
269
|
|
255
270
|
def try_path_as_dir(path, from_import)
|
256
|
-
return unless dir_exist?
|
271
|
+
return unless dir_exist?(path)
|
257
272
|
|
258
273
|
if from_import
|
259
274
|
result = exactly_one(try_path_with_ext(File.join(path, 'index.import')))
|
@@ -265,7 +280,7 @@ module SassC
|
|
265
280
|
|
266
281
|
def exactly_one(paths)
|
267
282
|
return if paths.empty?
|
268
|
-
return paths.first if paths.
|
283
|
+
return paths.first if paths.one?
|
269
284
|
|
270
285
|
raise "It's not clear which file to import. Found:\n#{paths.map { |path| " #{path}" }.join("\n")}"
|
271
286
|
end
|
@@ -285,79 +300,63 @@ module SassC
|
|
285
300
|
end
|
286
301
|
end
|
287
302
|
|
288
|
-
private_constant :
|
303
|
+
private_constant :FileSystemImporter
|
289
304
|
|
290
|
-
class
|
305
|
+
class ImportCache
|
291
306
|
def initialize(importer)
|
292
307
|
@importer = importer
|
293
|
-
|
294
|
-
@canonical_urls = {}
|
295
|
-
@id = 0
|
296
308
|
@importer_results = {}
|
297
|
-
@
|
309
|
+
@importer_result = nil
|
310
|
+
@file_url = nil
|
298
311
|
end
|
299
312
|
|
300
|
-
def canonicalize(url,
|
301
|
-
|
302
|
-
|
313
|
+
def canonicalize(url, context)
|
314
|
+
return unless context.containing_url&.start_with?('file:')
|
315
|
+
|
316
|
+
containing_url = context.containing_url
|
317
|
+
|
318
|
+
path = Uri.decode_uri_component(url)
|
319
|
+
parent_path = Uri.file_url_to_path(containing_url)
|
320
|
+
parent_dir = File.dirname(parent_path)
|
321
|
+
|
322
|
+
if containing_url.include?('?')
|
323
|
+
canonical_url = Uri.path_to_file_url(File.absolute_path(path, parent_dir))
|
303
324
|
unless @importer_results.key?(canonical_url)
|
304
|
-
|
325
|
+
@file_url = resolve_file_url(path, parent_dir, context.from_import)
|
326
|
+
return
|
305
327
|
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))
|
328
|
+
else
|
329
|
+
imports = [*@importer.imports(path, parent_path)]
|
330
|
+
canonical_url = imports_to_native(imports, parent_dir, context.from_import, url, containing_url)
|
331
|
+
unless @importer_results.key?(canonical_url)
|
332
|
+
@file_url = canonical_url
|
333
|
+
return
|
317
334
|
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
335
|
end
|
336
|
+
|
337
|
+
@importer_result = @importer_results.delete(canonical_url)
|
338
|
+
canonical_url
|
327
339
|
end
|
328
340
|
|
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
|
341
|
+
def load(_canonical_url)
|
342
|
+
importer_result = @importer_result
|
343
|
+
@importer_result = nil
|
344
|
+
importer_result
|
345
345
|
end
|
346
346
|
|
347
|
-
|
347
|
+
def find_file_url(_url, context)
|
348
|
+
return if context.containing_url.nil? || @file_url.nil?
|
348
349
|
|
349
|
-
|
350
|
-
@
|
350
|
+
canonical_url = @file_url
|
351
|
+
@file_url = nil
|
352
|
+
canonical_url
|
351
353
|
end
|
352
354
|
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
return URL.path_to_file_url(resolved) unless resolved.nil?
|
359
|
-
end
|
360
|
-
nil
|
355
|
+
private
|
356
|
+
|
357
|
+
def resolve_file_url(path, parent_dir, from_import)
|
358
|
+
resolved = FileSystemImporter.resolve_path(File.absolute_path(path, parent_dir), from_import)
|
359
|
+
Uri.path_to_file_url(resolved) unless resolved.nil?
|
361
360
|
end
|
362
361
|
|
363
362
|
def syntax(path)
|
@@ -371,47 +370,55 @@ module SassC
|
|
371
370
|
end
|
372
371
|
end
|
373
372
|
|
374
|
-
def
|
375
|
-
|
373
|
+
def import_to_native(import, parent_dir, from_import, canonicalize)
|
374
|
+
if import.source
|
375
|
+
canonical_url = Uri.path_to_file_url(File.absolute_path(import.path, parent_dir))
|
376
|
+
@importer_results[canonical_url] = if import.source.is_a?(Hash)
|
377
|
+
{
|
378
|
+
contents: import.source[:contents],
|
379
|
+
syntax: import.source[:syntax],
|
380
|
+
source_map_url: canonical_url
|
381
|
+
}
|
382
|
+
else
|
383
|
+
{
|
384
|
+
contents: import.source,
|
385
|
+
syntax: syntax(import.path),
|
386
|
+
source_map_url: canonical_url
|
387
|
+
}
|
388
|
+
end
|
389
|
+
return canonical_url if canonicalize
|
390
|
+
elsif canonicalize
|
391
|
+
return resolve_file_url(import.path, parent_dir, from_import)
|
392
|
+
end
|
393
|
+
|
394
|
+
Uri.encode_uri_path_component(import.path)
|
395
|
+
end
|
396
|
+
|
397
|
+
def imports_to_native(imports, parent_dir, from_import, url, containing_url)
|
398
|
+
return import_to_native(imports.first, parent_dir, from_import, true) if imports.one?
|
399
|
+
|
400
|
+
canonical_url = "#{containing_url}?url=#{Uri.encode_uri_query_component(url)}&from_import=#{from_import}"
|
401
|
+
@importer_results[canonical_url] = {
|
376
402
|
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
|
-
]
|
403
|
+
at_rule = from_import ? '@import' : '@forward'
|
404
|
+
url = import_to_native(import, parent_dir, from_import, false)
|
405
|
+
"#{at_rule} #{Script::Value::String.quote(url)};"
|
399
406
|
end.join("\n"),
|
400
407
|
syntax: :scss
|
401
408
|
}
|
402
|
-
end
|
403
409
|
|
404
|
-
|
405
|
-
id = @id
|
406
|
-
@id = id.next
|
407
|
-
id.to_s
|
410
|
+
canonical_url
|
408
411
|
end
|
409
412
|
end
|
410
413
|
|
411
|
-
private_constant :
|
414
|
+
private_constant :ImportCache
|
412
415
|
end
|
413
416
|
|
414
417
|
class Sass2Scss
|
418
|
+
class << self
|
419
|
+
remove_method(:convert) if public_method_defined?(:convert, false)
|
420
|
+
end
|
421
|
+
|
415
422
|
def self.convert(sass)
|
416
423
|
{
|
417
424
|
contents: sass,
|
@@ -421,7 +428,38 @@ module SassC
|
|
421
428
|
end
|
422
429
|
|
423
430
|
module Script
|
431
|
+
class Value
|
432
|
+
class String
|
433
|
+
class << self
|
434
|
+
remove_method(:quote) if public_method_defined?(:quote, false)
|
435
|
+
end
|
436
|
+
|
437
|
+
# Returns the quoted string representation of `contents`.
|
438
|
+
#
|
439
|
+
# @options opts :quote [String]
|
440
|
+
# The preferred quote style for quoted strings. If `:none`, strings are
|
441
|
+
# always emitted unquoted. If `nil`, quoting is determined automatically.
|
442
|
+
# @options opts :sass [String]
|
443
|
+
# Whether to quote strings for Sass source, as opposed to CSS. Defaults to `false`.
|
444
|
+
def self.quote(contents, opts = {})
|
445
|
+
contents = ::Sass::Value::String.new(contents, quoted: opts[:quote] != :none).to_s
|
446
|
+
opts[:sass] ? contents.gsub('#', '\#') : contents
|
447
|
+
end
|
448
|
+
|
449
|
+
remove_method(:to_s) if public_method_defined?(:to_s, false)
|
450
|
+
|
451
|
+
def to_s(opts = {})
|
452
|
+
opts = { quote: :none }.merge!(opts) if @type == :identifier
|
453
|
+
self.class.quote(@value, opts)
|
454
|
+
end
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
424
458
|
module ValueConversion
|
459
|
+
class << self
|
460
|
+
remove_method(:from_native) if public_method_defined?(:from_native, false)
|
461
|
+
end
|
462
|
+
|
425
463
|
def self.from_native(value, options)
|
426
464
|
case value
|
427
465
|
when ::Sass::Value::Null::NULL
|
@@ -477,6 +515,10 @@ module SassC
|
|
477
515
|
end
|
478
516
|
end
|
479
517
|
|
518
|
+
class << self
|
519
|
+
remove_method(:to_native) if public_method_defined?(:to_native, false)
|
520
|
+
end
|
521
|
+
|
480
522
|
def self.to_native(value)
|
481
523
|
case value
|
482
524
|
when nil
|
@@ -537,48 +579,84 @@ module SassC
|
|
537
579
|
end
|
538
580
|
end
|
539
581
|
|
540
|
-
module
|
541
|
-
|
542
|
-
IMPORT = 'sassc-embedded-import:'
|
543
|
-
LOADED = 'sassc-embedded-loaded:'
|
544
|
-
end
|
582
|
+
module Uri
|
583
|
+
module_function
|
545
584
|
|
546
|
-
|
585
|
+
def parse(...)
|
586
|
+
::URI::RFC3986_PARSER.parse(...)
|
587
|
+
end
|
547
588
|
|
548
|
-
|
549
|
-
|
589
|
+
encode_uri_hash = {}
|
590
|
+
decode_uri_hash = {}
|
591
|
+
256.times do |i|
|
592
|
+
c = -[i].pack('C')
|
593
|
+
h = c.unpack1('H')
|
594
|
+
l = c.unpack1('h')
|
595
|
+
pdd = -"%#{h}#{l}"
|
596
|
+
pdu = -"%#{h}#{l.upcase}"
|
597
|
+
pud = -"%#{h.upcase}#{l}"
|
598
|
+
puu = -pdd.upcase
|
599
|
+
encode_uri_hash[c] = puu
|
600
|
+
decode_uri_hash[pdd] = c
|
601
|
+
decode_uri_hash[pdu] = c
|
602
|
+
decode_uri_hash[pud] = c
|
603
|
+
decode_uri_hash[puu] = c
|
604
|
+
end.freeze
|
605
|
+
encode_uri_hash.freeze
|
606
|
+
decode_uri_hash.freeze
|
607
|
+
|
608
|
+
{
|
609
|
+
uri_path_component: "!$&'()*+,;=:/@",
|
610
|
+
uri_query_component: "!$&'()*+,;=:/?@",
|
611
|
+
uri_component: nil,
|
612
|
+
uri: "!$&'()*+,;=:/?#[]@"
|
613
|
+
}
|
614
|
+
.each do |symbol, unescaped|
|
615
|
+
encode_regexp = Regexp.new("[^0-9A-Za-z#{Regexp.escape("-._~#{unescaped}")}]", Regexp::NOENCODING)
|
616
|
+
|
617
|
+
define_method(:"encode_#{symbol}") do |str|
|
618
|
+
str.b.gsub(encode_regexp, encode_uri_hash).force_encoding(str.encoding)
|
619
|
+
end
|
550
620
|
|
551
|
-
|
621
|
+
next if symbol.match?(/_.+_/o)
|
552
622
|
|
553
|
-
|
623
|
+
decode_regexp = /%[0-9A-Fa-f]{2}/o
|
624
|
+
decode_uri_hash_with_preserve_escaped = if unescaped.nil? || unescaped.empty?
|
625
|
+
decode_uri_hash
|
626
|
+
else
|
627
|
+
decode_uri_hash.to_h do |key, value|
|
628
|
+
[key, unescaped.include?(value) ? key : value]
|
629
|
+
end.freeze
|
630
|
+
end
|
554
631
|
|
555
|
-
|
556
|
-
|
557
|
-
|
632
|
+
define_method(:"decode_#{symbol}") do |str|
|
633
|
+
str.gsub(decode_regexp, decode_uri_hash_with_preserve_escaped).force_encoding(str.encoding)
|
634
|
+
end
|
635
|
+
end
|
558
636
|
|
559
|
-
def
|
560
|
-
|
637
|
+
def file_urls_to_relative_url(url, from_url)
|
638
|
+
parse(url).route_from(from_url).to_s
|
561
639
|
end
|
562
640
|
|
563
|
-
def
|
564
|
-
|
641
|
+
def file_urls_to_relative_path(url, from_url)
|
642
|
+
decode_uri_component(file_urls_to_relative_url(url, from_url))
|
565
643
|
end
|
566
644
|
|
567
645
|
def file_url_to_path(url)
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
646
|
+
path = decode_uri_component(parse(url).path)
|
647
|
+
if path.start_with?('/')
|
648
|
+
windows_path = path[1..]
|
649
|
+
path = windows_path if File.absolute_path?(windows_path)
|
650
|
+
end
|
572
651
|
path
|
573
652
|
end
|
574
653
|
|
575
654
|
def path_to_file_url(path)
|
576
|
-
return if path.nil?
|
577
|
-
|
578
655
|
path = "/#{path}" unless path.start_with?('/')
|
579
|
-
|
656
|
+
|
657
|
+
"file://#{encode_uri_path_component(path)}"
|
580
658
|
end
|
581
659
|
end
|
582
660
|
|
583
|
-
private_constant :
|
661
|
+
private_constant :Uri
|
584
662
|
end
|