sassc-embedded 1.1.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 70c90e46b79aadd3b3ba316365eb9d45a854e75be4634a008f4e7e54cec17dd0
4
- data.tar.gz: 1991dc737c3739f2c9b497e904b5dda5dd734cdb55fdba6dd3e65fcacc81086e
3
+ metadata.gz: cdd5607c689b8388cf0c07abc26c3769ef50007ddd6b46432b277f7631bceb7f
4
+ data.tar.gz: 510835f24a3d66cf516bfd56acb0efd729d000cde730ef64908dfd5645f5aa12
5
5
  SHA512:
6
- metadata.gz: '09c1017da2a0fd5b1bbb35e9b60514b2f687de9a745f5540317582336c34c7b8a43e201cf5f2efe8a1fdb2e18f0123537690902db504576923a5df96b898ff7f'
7
- data.tar.gz: cb1e8fef114385a5e8cc622e88e1e42ea3763c3a378108067b341865de63f8add6103a7e0b7874ddd6b2981e78dc53ada984df1809056cc65621382ac8865957
6
+ metadata.gz: 93bbe6c1e4ff6e2fc4209e9390fd4775f029f0efb60606ab64cf9ee71a6afbc64d658c7572fd9c0719a134e8e192c5e8200d8ac2530e691cb84ae3fc14a31686
7
+ data.tar.gz: 1eed6fff6d57ac4ac56965de504ee876bd6dbbebb93880edefef2de604eb99536660487ae5c1ebcd6991270904f4700b42a54790dd7c233e303a66755120f01d
data/README.md CHANGED
@@ -51,6 +51,4 @@ See [rubydoc.info/gems/sassc](https://rubydoc.info/gems/sassc) for full API docu
51
51
 
52
52
  4. Option `:line_comments` is ignored.
53
53
 
54
- 5. Argument `parent_path` in `Importer#imports(path, parent_path)` is set to value of option `:filename`.
55
-
56
54
  See [the dart-sass documentation](https://github.com/sass/dart-sass#behavioral-differences-from-ruby-sass) for other differences.
@@ -2,6 +2,6 @@
2
2
 
3
3
  module SassC
4
4
  module Embedded
5
- VERSION = '1.1.0'
5
+ VERSION = '1.3.0'
6
6
  end
7
7
  end
@@ -17,7 +17,7 @@ module SassC
17
17
 
18
18
  result = ::Sass.compile_string(
19
19
  @template,
20
- importer: nil,
20
+ importer: import_handler.setup(nil),
21
21
  load_paths: load_paths,
22
22
  syntax: syntax,
23
23
  url: file_url,
@@ -26,8 +26,8 @@ module SassC
26
26
  source_map_include_sources: source_map_contents?,
27
27
  style: output_style,
28
28
 
29
- functions: FunctionsHandler.new(@options).setup(nil, functions: @functions),
30
- importers: ImportHandler.new(@options).setup(nil),
29
+ functions: functions_handler.setup(nil, functions: @functions),
30
+ importers: [],
31
31
 
32
32
  alert_ascii: @options.fetch(:alert_ascii, false),
33
33
  alert_color: @options.fetch(:alert_color, nil),
@@ -45,30 +45,25 @@ module SassC
45
45
  rescue ::Sass::CompileError => e
46
46
  line = e.span&.start&.line
47
47
  line += 1 unless line.nil?
48
- path = URL.file_url_to_path(e.span&.url)
48
+ url = e.span&.url
49
+ path = url&.start_with?('file:') ? URL.file_url_to_path(url) : nil
49
50
  path = relative_path(Dir.pwd, path) unless path.nil?
50
51
  raise SyntaxError.new(e.message, filename: path, line: line)
51
52
  end
52
53
 
53
54
  private
54
55
 
56
+ def file_url
57
+ @file_url ||= URL.path_to_file_url(File.absolute_path(filename || 'stdin'))
58
+ end
59
+
55
60
  def output_path
56
61
  @output_path ||= @options.fetch(
57
62
  :output_path,
58
- ("#{File.basename(filename, File.extname(filename))}.css" if filename)
63
+ ("#{filename.delete_suffix(File.extname(filename))}.css" if filename)
59
64
  )
60
65
  end
61
66
 
62
- def file_url
63
- @file_url ||= URL.path_to_file_url(filename || 'stdin')
64
- end
65
-
66
- def syntax
67
- syntax = @options.fetch(:syntax, :scss)
68
- syntax = :indented if syntax.to_sym == :sass
69
- syntax
70
- end
71
-
72
67
  def output_style
73
68
  @output_style ||= begin
74
69
  style = @options.fetch(:style, :sass_style_nested).to_s
@@ -87,8 +82,18 @@ module SassC
87
82
  end
88
83
  end
89
84
 
85
+ def syntax
86
+ syntax = @options.fetch(:syntax, :scss)
87
+ syntax = :indented if syntax.to_sym == :sass
88
+ syntax
89
+ end
90
+
90
91
  def load_paths
91
- @load_paths ||= (@options[:load_paths] || []) + SassC.load_paths
92
+ @load_paths ||= if @options[:importer].nil?
93
+ (@options[:load_paths] || []) + SassC.load_paths
94
+ else
95
+ []
96
+ end
92
97
  end
93
98
 
94
99
  def post_process_source_map(source_map)
@@ -163,8 +168,8 @@ module SassC
163
168
  private
164
169
 
165
170
  def arguments_from_native_list(native_argument_list)
166
- native_argument_list.map do |embedded_value|
167
- Script::ValueConversion.from_native embedded_value, @options
171
+ native_argument_list.map do |native_value|
172
+ Script::ValueConversion.from_native(native_value, @options)
168
173
  end.compact
169
174
  end
170
175
 
@@ -175,7 +180,7 @@ module SassC
175
180
  raise ::Sass::ScriptError
176
181
  end
177
182
  rescue StandardError => e
178
- unless e.full_message.include? e.cause.full_message
183
+ unless e.full_message.include?(e.cause.full_message)
179
184
  ::Sass::ScriptError.class_eval do
180
185
  def full_message(*args, **kwargs)
181
186
  full_message = super(*args, **kwargs)
@@ -192,86 +197,196 @@ module SassC
192
197
 
193
198
  class ImportHandler
194
199
  def setup(_native_options)
195
- if @importer
196
- [FileImporter.new, Importer.new(@importer)]
197
- else
198
- [FileImporter.new]
199
- end
200
+ Importer.new(@importer) if @importer
200
201
  end
201
202
 
202
203
  class FileImporter
203
- def find_file_url(url, **_kwargs)
204
- return url if url.start_with?('file:')
204
+ class << self
205
+ def resolve_path(path, from_import)
206
+ ext = File.extname(path)
207
+ if ['.sass', '.scss', '.css'].include?(ext)
208
+ if from_import
209
+ result = exactly_one(try_path("#{without_ext(path)}.import#{ext}"))
210
+ return result unless result.nil?
211
+ end
212
+ return exactly_one(try_path(path))
213
+ end
214
+
215
+ if from_import
216
+ result = exactly_one(try_path_with_ext("#{path}.import"))
217
+ return result unless result.nil?
218
+ end
219
+
220
+ result = exactly_one(try_path_with_ext(path))
221
+ return result unless result.nil?
222
+
223
+ try_path_as_dir(path, from_import)
224
+ end
225
+
226
+ private
227
+
228
+ def try_path_with_ext(path)
229
+ result = try_path("#{path}.sass") + try_path("#{path}.scss")
230
+ result.empty? ? try_path("#{path}.css") : result
231
+ end
232
+
233
+ def try_path(path)
234
+ partial = File.join(File.dirname(path), "_#{File.basename(path)}")
235
+ result = []
236
+ result.push(partial) if file_exist?(partial)
237
+ result.push(path) if file_exist?(path)
238
+ result
239
+ end
240
+
241
+ def try_path_as_dir(path, from_import)
242
+ return unless dir_exist? path
243
+
244
+ if from_import
245
+ result = exactly_one(try_path_with_ext(File.join(path, 'index.import')))
246
+ return result unless result.nil?
247
+ end
248
+
249
+ exactly_one(try_path_with_ext(File.join(path, 'index')))
250
+ end
251
+
252
+ def exactly_one(paths)
253
+ return if paths.empty?
254
+ return paths.first if paths.length == 1
255
+
256
+ raise "It's not clear which file to import. Found:\n#{paths.map { |path| " #{path}" }.join("\n")}"
257
+ end
258
+
259
+ def file_exist?(path)
260
+ File.exist?(path) && File.file?(path)
261
+ end
262
+
263
+ def dir_exist?(path)
264
+ File.exist?(path) && File.directory?(path)
265
+ end
266
+
267
+ def without_ext(path)
268
+ ext = File.extname(path)
269
+ path.delete_suffix(ext)
270
+ end
205
271
  end
206
272
  end
207
273
 
208
274
  private_constant :FileImporter
209
275
 
210
276
  class Importer
277
+ module Protocol
278
+ FILE = 'file:'
279
+ IMPORT = 'sassc-embedded-import:'
280
+ LOAD = 'sassc-embedded-load:'
281
+ LOADED = 'sassc-embedded-loaded:'
282
+ end
283
+
284
+ private_constant :Protocol
285
+
211
286
  def initialize(importer)
212
287
  @importer = importer
213
288
  @importer_results = {}
289
+ @base_url = URL.parse(URL.path_to_file_url("#{File.absolute_path('')}/"))
290
+ @parent_urls = [URL.parse(URL.path_to_file_url(File.absolute_path(@importer.options[:filename] || 'stdin')))]
214
291
  end
215
292
 
216
- def canonicalize(url, **)
217
- path = if url.start_with?('file:')
218
- URL.file_url_to_path(url)
219
- else
220
- URL.unescape(url)
221
- end
222
- canonical_url = URL.path_to_file_url(File.absolute_path(path))
293
+ def canonicalize(url, from_import:)
294
+ return url if url.start_with?(Protocol::IMPORT, Protocol::LOADED)
223
295
 
224
- if @importer_results.key?(canonical_url)
225
- return if @importer_results[canonical_url].nil?
296
+ if url.start_with?(Protocol::LOAD)
297
+ url = url.delete_prefix(Protocol::LOAD)
298
+ return url if @importer_results.key?(url)
226
299
 
227
- return canonical_url
300
+ path = URL.parse(url).route_from(@parent_urls.last).to_s
301
+ resolved = resolve_path(path, URL.file_url_to_path(@parent_urls.last.to_s), from_import)
302
+ return resolved.nil? ? nil : URL.path_to_file_url(resolved)
228
303
  end
229
304
 
230
- canonical_url = "sassc-embedded:#{canonical_url}"
305
+ return unless url.start_with?(Protocol::FILE)
231
306
 
232
- imports = @importer.imports path, @importer.options[:filename]
233
- unless imports.is_a? Array
234
- return if imports.path == path
307
+ path = URL.parse(url).route_from(@parent_urls.last).to_s
308
+ parent_path = @parent_urls.last.route_from(@base_url).to_s
235
309
 
236
- imports = [imports]
310
+ imports = @importer.imports(path, parent_path)
311
+ imports = [SassC::Importer::Import.new(path)] if imports.nil?
312
+ imports = [imports] unless imports.is_a?(Array)
313
+ imports.each do |import|
314
+ import.path = File.absolute_path(import.path, File.dirname(parent_path))
237
315
  end
238
316
 
239
- dirname = File.dirname(@importer.options.fetch(:filename, 'stdin'))
240
- contents = imports.map do |import|
241
- import_url = URL.path_to_file_url(File.absolute_path(import.path, dirname))
242
- @importer_results[import_url] = if import.source
243
- {
244
- contents: import.source,
245
- syntax: case import.path
246
- when /\.sass$/i
247
- :indented
248
- when /\.css$/i
249
- :css
250
- else
251
- :scss
252
- end,
253
- source_map_url: if import.source_map_path
254
- URL.path_to_file_url(
255
- File.absolute_path(
256
- import.source_map_path, dirname
257
- )
258
- )
259
- end
260
- }
261
- end
262
- "@import #{import_url.inspect};"
263
- end.join("\n")
264
-
265
- @importer_results[canonical_url] = {
266
- contents: contents,
267
- syntax: :scss
268
- }
269
-
317
+ import_url = URL.path_to_file_url(File.absolute_path(path, File.dirname(parent_path)))
318
+ canonical_url = "#{Protocol::IMPORT}#{import_url}"
319
+ @importer_results[canonical_url] = imports_to_native(imports)
270
320
  canonical_url
271
321
  end
272
322
 
273
323
  def load(canonical_url)
274
- @importer_results[canonical_url]
324
+ if canonical_url.start_with?(Protocol::IMPORT)
325
+ @importer_results.delete(canonical_url)
326
+ elsif canonical_url.start_with?(Protocol::FILE)
327
+ @parent_urls.push(URL.parse(canonical_url))
328
+ if @importer_results.key?(canonical_url)
329
+ @importer_results.delete(canonical_url)
330
+ else
331
+ path = URL.file_url_to_path(canonical_url)
332
+ {
333
+ contents: File.read(path),
334
+ syntax: syntax(path),
335
+ source_map_url: canonical_url
336
+ }
337
+ end
338
+ elsif canonical_url.start_with?(Protocol::LOADED)
339
+ @parent_urls.pop
340
+ {
341
+ contents: '',
342
+ syntax: 'scss'
343
+ }
344
+ end
345
+ end
346
+
347
+ private
348
+
349
+ def load_paths
350
+ @load_paths ||= (@importer.options[:load_paths] || []) + SassC.load_paths
351
+ end
352
+
353
+ def resolve_path(path, parent_path, from_import)
354
+ [File.dirname(parent_path)].concat(load_paths).each do |load_path|
355
+ resolved = FileImporter.resolve_path(File.absolute_path(path, load_path), from_import)
356
+ return resolved unless resolved.nil?
357
+ end
358
+ nil
359
+ end
360
+
361
+ def syntax(path)
362
+ case File.extname(path)
363
+ when '.sass'
364
+ :indented
365
+ when '.css'
366
+ :css
367
+ else
368
+ :scss
369
+ end
370
+ end
371
+
372
+ def imports_to_native(imports)
373
+ {
374
+ contents: imports.flat_map do |import|
375
+ file_url = URL.path_to_file_url(import.path)
376
+ if import.source
377
+ @importer_results[file_url] = {
378
+ contents: import.source,
379
+ syntax: syntax(import.path),
380
+ source_map_url: file_url
381
+ }
382
+ end
383
+ [
384
+ "@import #{"#{Protocol::LOAD}#{file_url}".inspect};",
385
+ "@import #{"#{Protocol::LOADED}#{file_url}".inspect};"
386
+ ]
387
+ end.join("\n"),
388
+ syntax: :scss
389
+ }
275
390
  end
276
391
  end
277
392
 
@@ -402,6 +517,10 @@ module SassC
402
517
 
403
518
  module_function
404
519
 
520
+ def parse(str)
521
+ PARSER.parse(str)
522
+ end
523
+
405
524
  def escape(str)
406
525
  PARSER.escape(str)
407
526
  end
@@ -413,7 +532,7 @@ module SassC
413
532
  def file_url_to_path(url)
414
533
  return if url.nil?
415
534
 
416
- path = unescape(URI.parse(url).path)
535
+ path = unescape(parse(url).path)
417
536
  path = path[1..] if Gem.win_platform? && path[0].chr == '/' && path[1].chr =~ /[a-z]/i && path[2].chr == ':'
418
537
  path
419
538
  end
@@ -421,9 +540,10 @@ module SassC
421
540
  def path_to_file_url(path)
422
541
  return if path.nil?
423
542
 
424
- path = File.absolute_path(path)
425
- path = "/#{path}" unless path.start_with? '/'
543
+ path = "/#{path}" unless path.start_with?('/')
426
544
  URI::File.build([nil, escape(path)]).to_s
427
545
  end
428
546
  end
547
+
548
+ private_constant :URL
429
549
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sassc-embedded
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - なつき
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-22 00:00:00.000000000 Z
11
+ date: 2022-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sassc
@@ -138,8 +138,8 @@ homepage: https://github.com/ntkme/sassc-embedded-polyfill-ruby
138
138
  licenses:
139
139
  - MIT
140
140
  metadata:
141
- documentation_uri: https://rubydoc.info/gems/sassc-embedded/1.1.0
142
- source_code_uri: https://github.com/ntkme/sassc-embedded-polyfill-ruby/tree/v1.1.0
141
+ documentation_uri: https://rubydoc.info/gems/sassc-embedded/1.3.0
142
+ source_code_uri: https://github.com/ntkme/sassc-embedded-polyfill-ruby/tree/v1.3.0
143
143
  funding_uri: https://github.com/sponsors/ntkme
144
144
  post_install_message:
145
145
  rdoc_options: []