sass-embedded 1.6.2 → 1.83.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.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -3
  3. data/exe/sass +13 -0
  4. data/ext/sass/Rakefile +352 -76
  5. data/ext/sass/embedded_sass_pb.rb +61 -0
  6. data/ext/sass/expand-archive.ps1 +1 -0
  7. data/ext/sass/package.json +1 -1
  8. data/lib/sass/calculation_value/calculation_operation.rb +49 -0
  9. data/lib/sass/calculation_value.rb +22 -0
  10. data/lib/sass/canonicalize_context.rb +25 -0
  11. data/lib/sass/compile_result.rb +3 -2
  12. data/lib/sass/compiler/channel.rb +68 -0
  13. data/lib/sass/compiler/connection.rb +89 -0
  14. data/lib/sass/compiler/dispatcher.rb +116 -0
  15. data/lib/sass/{embedded → compiler}/host/function_registry.rb +31 -34
  16. data/lib/sass/compiler/host/importer_registry.rb +141 -0
  17. data/lib/sass/compiler/host/logger_registry.rb +80 -0
  18. data/lib/sass/compiler/host/protofier.rb +360 -0
  19. data/lib/sass/compiler/host/structifier.rb +37 -0
  20. data/lib/sass/compiler/host.rb +226 -0
  21. data/lib/sass/{embedded → compiler}/varint.rb +9 -5
  22. data/lib/sass/compiler.rb +212 -0
  23. data/lib/sass/elf.rb +222 -0
  24. data/lib/sass/embedded/version.rb +2 -2
  25. data/lib/sass/embedded.rb +76 -204
  26. data/lib/sass/embedded_protocol.rb +10 -0
  27. data/lib/sass/exception.rb +74 -0
  28. data/lib/sass/fork_tracker.rb +51 -0
  29. data/lib/sass/logger/silent.rb +5 -3
  30. data/lib/sass/logger/source_location.rb +6 -5
  31. data/lib/sass/logger/source_span.rb +8 -7
  32. data/lib/sass/node_package_importer.rb +17 -0
  33. data/lib/sass/serializer.rb +30 -0
  34. data/lib/sass/value/argument_list.rb +13 -6
  35. data/lib/sass/value/boolean.rb +1 -1
  36. data/lib/sass/value/calculation.rb +90 -0
  37. data/lib/sass/value/color/channel.rb +79 -0
  38. data/lib/sass/value/color/conversions.rb +473 -0
  39. data/lib/sass/value/color/gamut_map_method/clip.rb +45 -0
  40. data/lib/sass/value/color/gamut_map_method/local_minde.rb +94 -0
  41. data/lib/sass/value/color/gamut_map_method.rb +45 -0
  42. data/lib/sass/value/color/interpolation_method.rb +51 -0
  43. data/lib/sass/value/color/space/a98_rgb.rb +57 -0
  44. data/lib/sass/value/color/space/display_p3.rb +57 -0
  45. data/lib/sass/value/color/space/hsl.rb +65 -0
  46. data/lib/sass/value/color/space/hwb.rb +70 -0
  47. data/lib/sass/value/color/space/lab.rb +77 -0
  48. data/lib/sass/value/color/space/lch.rb +53 -0
  49. data/lib/sass/value/color/space/lms.rb +129 -0
  50. data/lib/sass/value/color/space/oklab.rb +66 -0
  51. data/lib/sass/value/color/space/oklch.rb +54 -0
  52. data/lib/sass/value/color/space/prophoto_rgb.rb +59 -0
  53. data/lib/sass/value/color/space/rec2020.rb +69 -0
  54. data/lib/sass/value/color/space/rgb.rb +52 -0
  55. data/lib/sass/value/color/space/srgb.rb +140 -0
  56. data/lib/sass/value/color/space/srgb_linear.rb +72 -0
  57. data/lib/sass/value/color/space/utils.rb +86 -0
  58. data/lib/sass/value/color/space/xyz_d50.rb +100 -0
  59. data/lib/sass/value/color/space/xyz_d65.rb +57 -0
  60. data/lib/sass/value/color/space.rb +198 -0
  61. data/lib/sass/value/color.rb +538 -163
  62. data/lib/sass/value/function.rb +11 -16
  63. data/lib/sass/value/fuzzy_math.rb +24 -21
  64. data/lib/sass/value/list.rb +7 -7
  65. data/lib/sass/value/map.rb +6 -6
  66. data/lib/sass/value/mixin.rb +34 -0
  67. data/lib/sass/value/null.rb +1 -1
  68. data/lib/sass/value/number/unit.rb +7 -6
  69. data/lib/sass/value/number.rb +34 -26
  70. data/lib/sass/value/string.rb +9 -3
  71. data/lib/sass/value.rb +20 -16
  72. metadata +67 -103
  73. data/ext/sass/unzip.vbs +0 -13
  74. data/lib/sass/compile_error.rb +0 -28
  75. data/lib/sass/embedded/async.rb +0 -65
  76. data/lib/sass/embedded/channel.rb +0 -61
  77. data/lib/sass/embedded/compiler.rb +0 -60
  78. data/lib/sass/embedded/dispatcher.rb +0 -90
  79. data/lib/sass/embedded/host/importer_registry.rb +0 -107
  80. data/lib/sass/embedded/host/logger_registry.rb +0 -50
  81. data/lib/sass/embedded/host/value_protofier.rb +0 -241
  82. data/lib/sass/embedded/host.rb +0 -139
  83. data/lib/sass/embedded/protofier.rb +0 -78
  84. data/lib/sass/embedded/structifier.rb +0 -36
  85. data/lib/sass/script_error.rb +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f4302072559a2d7fe8548932c6d860e5acc4a5270c2f2a7c429166cfc7c838ea
4
- data.tar.gz: 1a489d71a7ea6c7ce3d7acd1e40f0546d01df683ba6dff52409f6f552a97d8d2
3
+ metadata.gz: e195e5414c096b69ed749c06fa18abceb7183b9210589eac6ecbe4567e6ca062
4
+ data.tar.gz: 7db43c7cde6beac01612d5c0cb06e08ed7e3df66054319a6f327a0e3ce8de608
5
5
  SHA512:
6
- metadata.gz: 2a632cf28ec8df7a914139acd1ba4ba790d142e8816b726c98f3f96a77b2137e9719de4959f70bd723ff348797bab2513feebf278b8c6946b91b69394ff3ce12
7
- data.tar.gz: 4ee90b0c45ce7d44789fe689390cdaf70c1e93a840d48ab8ce90eb0e750c91c8244447f04442f8354ccebbc5bfe8f91abcc1e86cd0623ad43ce2cd215e9757b2
6
+ metadata.gz: 60933b74969f9fc1237b22531bf0f46690564f0556bfbfe26519402970e45c68e1fbd8be03217206ea7b1f833c8563b65078b3d44e28743375bd2798c619c049
7
+ data.tar.gz: bcc7c53bf5452b3130d119fe0950450d329522c48cafabef5aa1aecb8732e232c5975739a161445fe0a3aa396120b0b1764fbba72a6518f644b5a40efa7ba801
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # Embedded Sass Host for Ruby
2
2
 
3
- [![build](https://github.com/ntkme/sass-embedded-host-ruby/actions/workflows/build.yml/badge.svg)](https://github.com/ntkme/sass-embedded-host-ruby/actions/workflows/build.yml)
3
+ [![build](https://github.com/sass-contrib/sass-embedded-host-ruby/actions/workflows/build.yml/badge.svg)](https://github.com/sass-contrib/sass-embedded-host-ruby/actions/workflows/build.yml)
4
4
  [![gem](https://badge.fury.io/rb/sass-embedded.svg)](https://rubygems.org/gems/sass-embedded)
5
5
 
6
- This is a Ruby library that implements the host side of the [Embedded Sass protocol](https://github.com/sass/sass-embedded-protocol).
6
+ This is a Ruby library that implements the host side of the [Embedded Sass protocol](https://github.com/sass/sass/blob/HEAD/spec/embedded-protocol.md).
7
7
 
8
8
  It exposes a Ruby API for Sass that's backed by a native [Dart Sass](https://sass-lang.com/dart-sass) executable.
9
9
 
@@ -24,6 +24,9 @@ require 'sass-embedded'
24
24
 
25
25
  result = Sass.compile('style.scss')
26
26
  puts result.css
27
+
28
+ compressed = Sass.compile('style.scss', style: :compressed)
29
+ puts compressed.css
27
30
  ```
28
31
 
29
32
  - `Sass.compile_string` takes a string that represents the contents of a Sass file and return the result of compiling that file to CSS.
@@ -33,9 +36,12 @@ require 'sass-embedded'
33
36
 
34
37
  result = Sass.compile_string('h1 { font-size: 40px; }')
35
38
  puts result.css
39
+
40
+ compressed = Sass.compile_string('h1 { font-size: 40px; }', style: :compressed)
41
+ puts compressed.css
36
42
  ```
37
43
 
38
- See [rubydoc.info/gems/sass-embedded](https://rubydoc.info/gems/sass-embedded) for full API documentation.
44
+ See [rubydoc.info/gems/sass-embedded/Sass](https://rubydoc.info/gems/sass-embedded/Sass) for full API documentation.
39
45
 
40
46
  ---
41
47
 
data/exe/sass ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../ext/sass/cli'
5
+
6
+ module Sass
7
+ # The `sass` command line interface
8
+ module CLI
9
+ Kernel.exec(*COMMAND, *ARGV)
10
+ end
11
+
12
+ private_constant :CLI
13
+ end
data/ext/sass/Rakefile CHANGED
@@ -4,44 +4,154 @@ require 'rake/clean'
4
4
 
5
5
  task default: %i[install clean]
6
6
 
7
- task install: %w[sass_embedded embedded.rb embedded_sass_pb.rb]
8
-
9
- CLEAN.include %w[protoc.exe *.proto *.tar.gz *.zip]
7
+ task install: %w[cli.rb] do
8
+ Rake::Task['embedded_sass_pb.rb'].invoke unless File.exist?('embedded_sass_pb.rb')
9
+ end
10
10
 
11
- CLOBBER.include %w[sass_embedded embedded.rb embedded_sass_pb.rb]
11
+ CLEAN.include %w[
12
+ protoc.exe
13
+ ruby
14
+ *.proto
15
+ *.tar.gz
16
+ *.zip
17
+ ]
18
+
19
+ CLOBBER.include %w[
20
+ dart-sass
21
+ cli.rb
22
+ embedded_sass_pb.rb
23
+ node_modules
24
+ bun.lockb
25
+ package-lock.json
26
+ pnpm-lock.yaml
27
+ yarn.lock
28
+ ]
12
29
 
13
30
  file 'protoc.exe' do |t|
14
- fetch(ENV.fetch('PROTOC_BIN') { Configuration.default_protoc }, t.name)
31
+ fetch(SassConfig.protoc, t.name)
32
+ chmod 'a+x', t.name
33
+ rescue NotImplementedError
34
+ File.write(t.name, <<~PROTOC_EXE)
35
+ #!#{RbConfig.ruby}
36
+ # frozen_string_literal: true
37
+ Kernel.exec('protoc', *ARGV)
38
+ PROTOC_EXE
15
39
  chmod 'a+x', t.name
16
40
  end
17
41
 
18
- file 'sass_embedded' do |t|
19
- archive = fetch(ENV.fetch(t.name.upcase) { Configuration.default_sass_embedded })
42
+ file 'dart-sass/sass' do |t|
43
+ gem_install 'sass-embedded', SassConfig.gem_version, SassConfig.gem_platform do |dir|
44
+ mv File.absolute_path("ext/sass/#{t.name}", dir), t.name
45
+ end
46
+ rescue StandardError
47
+ archive = fetch(SassConfig.dart_sass)
20
48
  unarchive archive
21
49
  rm archive
22
50
  end
23
51
 
24
- file 'embedded.rb' => %w[sass_embedded] do |t|
25
- path = 'sass_embedded/dart-sass-embedded'
26
- path = "#{path}#{['.exe', '.bat'].find { |ext| File.exist? "#{path}#{ext}" }}" if Gem.win_platform?
52
+ file 'node_modules/sass' do
53
+ sh 'npm', 'install'
54
+ rescue StandardError
55
+ begin
56
+ sh 'yarn', 'install'
57
+ rescue StandardError
58
+ begin
59
+ sh 'pnpm', 'install'
60
+ rescue StandardError
61
+ sh 'bun', 'install'
62
+ end
63
+ end
64
+ end
27
65
 
28
- raise "#{path} not found" unless File.exist? path
66
+ task 'dart-sass' do
67
+ Rake::Task['dart-sass/sass'].invoke
68
+ rescue NotImplementedError
69
+ Rake::Task['node_modules/sass'].invoke
70
+ end
29
71
 
30
- File.write(t.name, <<~EMBEDDED_RB)
31
- # frozen_string_literal: true
72
+ file 'cli.rb' => %w[dart-sass] do |t|
73
+ require_relative '../../lib/sass/elf'
74
+
75
+ begin
76
+ exe = 'dart-sass/sass'
77
+ exe = "#{exe}#{['', '.bat', '.exe'].find { |ext| File.exist?("#{exe}#{ext}") }}"
78
+
79
+ raise Errno::ENOENT, exe unless File.exist?(exe)
80
+
81
+ runtime = 'dart-sass/src/dart'
82
+ runtime = "#{runtime}#{['', '.exe'].find { |ext| File.exist?("#{runtime}#{ext}") }}"
83
+ snapshot = 'dart-sass/src/sass.snapshot'
32
84
 
33
- module Sass
34
- class Embedded
35
- class Compiler
36
- PATH = File.absolute_path('#{path}', __dir__)
85
+ command = if File.exist?(runtime) && File.exist?(snapshot)
86
+ [runtime, snapshot]
87
+ else
88
+ [exe]
89
+ end
90
+
91
+ interpreter = File.open(command[0], 'rb') do |file|
92
+ Sass.const_get(:ELF).new(file).interpreter
93
+ rescue ArgumentError
94
+ nil
95
+ end
96
+
97
+ command_source = command.map do |argument|
98
+ "File.absolute_path('#{argument}', __dir__).freeze"
99
+ end.join(',
100
+ ')
101
+ rescue Errno::ENOENT
102
+ package = 'node_modules/sass'
103
+
104
+ script = File.join(package, SassConfig.package_json(package)['bin']['sass'])
105
+
106
+ interpreter = nil
107
+
108
+ command_source = [
109
+ "'node'",
110
+ "File.absolute_path('#{script}', __dir__).freeze"
111
+ ].join(',
112
+ ')
113
+ end
114
+
115
+ if interpreter.nil?
116
+ File.write(t.name, <<~CLI_RB)
117
+ # frozen_string_literal: true
118
+
119
+ module Sass
120
+ module CLI
121
+ COMMAND = [
122
+ #{command_source}
123
+ ].freeze
37
124
  end
125
+
126
+ private_constant :CLI
38
127
  end
39
- end
40
- EMBEDDED_RB
128
+ CLI_RB
129
+ else
130
+ File.write(t.name, <<~CLI_RB)
131
+ # frozen_string_literal: true
132
+
133
+ require_relative '../../lib/sass/elf'
134
+
135
+ module Sass
136
+ module CLI
137
+ INTERPRETER = '#{interpreter}'
138
+
139
+ INTERPRETER_SUFFIX = '/#{File.basename(interpreter)}'
140
+
141
+ COMMAND = [
142
+ *(ELF::INTERPRETER if ELF::INTERPRETER != INTERPRETER && ELF::INTERPRETER&.end_with?(INTERPRETER_SUFFIX)),
143
+ #{command_source}
144
+ ].freeze
145
+ end
146
+
147
+ private_constant :CLI
148
+ end
149
+ CLI_RB
150
+ end
41
151
  end
42
152
 
43
- file 'embedded_sass.proto' => %w[embedded.rb] do |t|
44
- fetch(ENV.fetch('SASS_EMBEDDED_PROTOCOL') { Configuration.default_sass_embedded_protocol }, t.name)
153
+ file 'embedded_sass.proto' => %w[cli.rb] do |t|
154
+ fetch(SassConfig.embedded_sass_protocol, t.name)
45
155
  end
46
156
 
47
157
  rule '_pb.rb' => %w[.proto protoc.exe] do |t|
@@ -51,14 +161,59 @@ end
51
161
  # This is a FileUtils extension that defines several additional commands to be
52
162
  # added to the FileUtils utility functions.
53
163
  module FileUtils
164
+ # PowerShell quirks:
165
+ # - `powershell -Command -`:
166
+ # Arguments must be part of command, thus cannot pass arguments safely without escaping.
167
+ # - `powershell -Command <script-block> [-args <arg-array>]`:
168
+ # This only works when invoking powershell subshell in powershell.
169
+ # - `powershell -Command <string> [<CommandParameters>]`:
170
+ # CommandParameters are joined with command and then parsed, thus cannot pass arguments safely without escaping.
171
+ # - `powershell -File -`:
172
+ # Arguments must be part of file, thus cannot pass arguments safely without escaping.
173
+ # - `powershell -File <filePath> <args>`:
174
+ # This is the only way to pass arguments safely without escaping.
175
+ def powershell(file, *args)
176
+ sh 'powershell', '-NoLogo', '-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-File', file, *args
177
+ end
178
+
179
+ def junzip(archive, dest = '.')
180
+ require 'java'
181
+
182
+ Rake.rake_output_message "Archive: #{archive}" if Rake::FileUtilsExt.verbose_flag
183
+
184
+ current_directory = java.nio.file.Paths.get(org.jruby.Ruby.getGlobalRuntime.getCurrentDirectory)
185
+ zip_file = java.util.zip.ZipFile.new(current_directory.resolve(archive).toFile)
186
+ dest_path = current_directory.resolve(dest).normalize
187
+ entries = zip_file.entries
188
+ while entries.hasMoreElements
189
+ entry = entries.nextElement
190
+ name = entry.getName
191
+ path = dest_path.resolve(name).normalize
192
+ raise SecurityError unless path.startsWith(dest_path)
193
+
194
+ Rake.rake_output_message " inflating: #{name}" if Rake::FileUtilsExt.verbose_flag
195
+
196
+ if entry.isDirectory
197
+ java.nio.file.Files.createDirectories(path)
198
+ else
199
+ java.nio.file.Files.createDirectories(path.getParent)
200
+ java.nio.file.Files.copy(zip_file.getInputStream(entry), path)
201
+ end
202
+ end
203
+ ensure
204
+ zip_file&.close
205
+ end
206
+
54
207
  def unarchive(archive, dest = '.')
55
208
  case archive.downcase
56
209
  when ->(name) { name.include?('.tar.') || name.end_with?('.tar') }
57
210
  mkdir_p dest
58
- sh 'tar', '-vxC', dest, '-f', archive
211
+ sh 'tar', '-vxC', dest, '-f', archive, '--no-same-owner', '--no-same-permissions'
59
212
  when ->(name) { name.end_with?('.zip') }
60
- if Gem.win_platform?
61
- sh 'cscript', 'unzip.vbs', '//B', '//Nologo', archive, dest
213
+ if RUBY_PLATFORM == 'java'
214
+ junzip archive, dest
215
+ elsif Gem.win_platform?
216
+ powershell 'expand-archive.ps1', '-Force', '-LiteralPath', archive, '-DestinationPath', dest
62
217
  else
63
218
  sh 'unzip', '-od', dest, archive
64
219
  end
@@ -70,58 +225,95 @@ module FileUtils
70
225
  def fetch(source_uri, dest_path = nil)
71
226
  require 'rubygems/remote_fetcher'
72
227
 
73
- unless source_uri.is_a?(URI::Generic)
228
+ source_uri = "/#{source_uri}" if !source_uri.start_with?('/') && File.absolute_path?(source_uri)
229
+
230
+ source_uri = begin
231
+ Gem::Uri.parse!(source_uri)
232
+ rescue NoMethodError
74
233
  begin
75
- source_uri = URI.parse(source_uri)
234
+ URI.parse(source_uri)
76
235
  rescue StandardError
77
- source_uri = URI.parse(URI::DEFAULT_PARSER.escape(source_uri.to_s))
236
+ URI.parse(URI::DEFAULT_PARSER.escape(source_uri.to_s))
78
237
  end
79
238
  end
80
239
 
81
240
  scheme = source_uri.scheme
82
- source_path = URI::DEFAULT_PARSER.unescape(source_uri.path || source_uri.opaque)
83
-
84
- if Gem.win_platform? && scheme =~ /^[a-z]$/i && !source_path.include?(':')
85
- source_path = "#{scheme}:#{source_path}"
86
- scheme = nil
87
- end
241
+ source_path = begin
242
+ Gem::URI::DEFAULT_PARSER
243
+ rescue NameError
244
+ URI::DEFAULT_PARSER
245
+ end.unescape(source_uri.path)
88
246
 
89
247
  dest_path = File.basename(source_path) if dest_path.nil?
90
248
 
91
- case scheme
92
- when nil, 'file'
93
- if Gem.win_platform? && source_path[0].chr == '/' && source_path[1].chr =~ /[a-z]/i && source_path[2].chr == ':'
94
- source_path = source_path[1..]
95
- end
96
- cp source_path, dest_path
97
- else
98
- fetcher = Gem::RemoteFetcher.fetcher
99
- symbol = "fetch_#{scheme}".to_sym
100
- raise ArgumentError, "Unsupported URI scheme #{scheme}" unless fetcher.respond_to?(symbol)
249
+ fetcher = Gem::RemoteFetcher.fetcher
250
+ symbol = :"fetch_#{scheme.nil? ? 'file' : scheme}"
251
+ raise ArgumentError, "Unsupported URI scheme #{scheme}" unless fetcher.respond_to?(symbol)
101
252
 
102
- if Rake::FileUtilsExt.verbose_flag
103
- redacted_uri = Gem::RemoteFetcher::FetchError.new('', source_uri).uri
104
- Rake.rake_output_message "fetch #{redacted_uri}"
105
- end
253
+ Rake.rake_output_message "fetch #{Gem::Uri.new(source_uri).redacted}" if Rake::FileUtilsExt.verbose_flag
106
254
 
107
- unless Rake::FileUtilsExt.nowrite_flag
108
- data = fetcher.public_send(symbol, source_uri)
109
- Gem.write_binary(dest_path, data)
110
- end
255
+ unless Rake::FileUtilsExt.nowrite_flag
256
+ data = fetcher.public_send(symbol, source_uri)
257
+ Gem.write_binary(dest_path, data)
111
258
  end
112
259
 
113
260
  dest_path
114
261
  end
262
+
263
+ def gem_install(name, version, platform)
264
+ require 'rubygems/remote_fetcher'
265
+
266
+ install_dir = File.absolute_path('ruby')
267
+
268
+ if Rake::FileUtilsExt.verbose_flag
269
+ Rake.rake_output_message [
270
+ 'gem', 'install',
271
+ '--force',
272
+ '--install-dir', install_dir,
273
+ '--no-document', '--ignore-dependencies',
274
+ '--platform', platform,
275
+ '--version', version,
276
+ 'sass-embedded'
277
+ ].join(' ')
278
+ end
279
+
280
+ dependency = Gem::Dependency.new(name, version)
281
+
282
+ dependency_request = Gem::Resolver::DependencyRequest.new(dependency, nil)
283
+
284
+ resolver_spec = Gem::Resolver::BestSet.new.find_all(dependency_request).find do |s|
285
+ s.platform == platform
286
+ end
287
+
288
+ raise Gem::UnsatisfiableDependencyError, dependency_request if resolver_spec.nil?
289
+
290
+ options = { force: true, install_dir: }
291
+ if Rake::FileUtilsExt.nowrite_flag
292
+ installer = Gem::Installer.for_spec(resolver_spec.spec, options)
293
+ else
294
+ path = resolver_spec.download(options)
295
+ installer = Gem::Installer.at(path, options)
296
+ installer.install
297
+ end
298
+
299
+ yield installer.dir
300
+ ensure
301
+ rm_rf install_dir unless Rake::FileUtilsExt.nowrite_flag
302
+ end
115
303
  end
116
304
 
117
- # The {Configuration} module.
118
- module Configuration
305
+ # The {SassConfig} module.
306
+ module SassConfig
119
307
  module Platform
120
308
  OS = case RbConfig::CONFIG['host_os'].downcase
121
309
  when /darwin/
122
310
  'darwin'
311
+ when /linux-android/
312
+ 'linux-android'
123
313
  when /linux-musl/
124
314
  'linux-musl'
315
+ when /linux-uclibc/
316
+ 'linux-uclibc'
125
317
  when /linux/
126
318
  'linux'
127
319
  when *Gem::WIN_PATTERNS
@@ -134,43 +326,53 @@ module Configuration
134
326
  when /amd64|x86_64|x64/
135
327
  'x86_64'
136
328
  when /i\d86|x86|i86pc/
137
- 'i386'
329
+ 'x86'
138
330
  when /arm64|aarch64/
139
331
  'aarch64'
140
332
  when /arm/
141
- # Ruby before 3.0 reports "arm" instead of "arm64" as host_cpu on darwin
142
- OS == 'darwin' ? 'aarch64' : 'arm'
333
+ 'arm'
143
334
  when /ppc64le|powerpc64le/
144
335
  'powerpc64le'
145
- when /s390x/
146
- 's390x'
147
336
  else
148
337
  RbConfig::CONFIG['host_cpu']
149
338
  end
150
339
 
151
- ARCH = "#{CPU}-#{OS}"
340
+ ARCH = "#{CPU}-#{OS}".freeze
152
341
  end
153
342
 
154
343
  private_constant :Platform
155
344
 
156
345
  module_function
157
346
 
158
- def default_sass_embedded
347
+ def package_json(path = '.')
159
348
  require 'json'
160
349
 
161
- repo = 'https://github.com/sass/dart-sass-embedded'
350
+ JSON.parse(File.read(File.absolute_path('package.json', path)))
351
+ end
352
+
353
+ def dart_sass_version
354
+ package_json['dependencies']['sass']
355
+ end
356
+
357
+ def dart_sass
358
+ repo = 'https://github.com/sass/dart-sass'
162
359
 
163
- spec = JSON.parse(File.read(File.absolute_path('package.json', __dir__)))
360
+ tag_name = dart_sass_version
164
361
 
165
- tag_name = spec['dependencies']['sass-embedded']
362
+ message = "dart-sass for #{Platform::ARCH} not available at #{repo}/releases/tag/#{tag_name}"
166
363
 
167
- message = "sass_embedded for #{Platform::ARCH} not available at #{repo}/releases/tag/#{tag_name}"
364
+ env = ''
168
365
 
169
366
  os = case Platform::OS
170
367
  when 'darwin'
171
368
  'macos'
172
369
  when 'linux'
173
370
  'linux'
371
+ when 'linux-android'
372
+ 'android'
373
+ when 'linux-musl'
374
+ env = '-musl'
375
+ 'linux'
174
376
  when 'windows'
175
377
  'windows'
176
378
  else
@@ -178,32 +380,42 @@ module Configuration
178
380
  end
179
381
 
180
382
  cpu = case Platform::CPU
181
- when 'i386'
383
+ when 'x86'
182
384
  'ia32'
183
385
  when 'x86_64'
184
386
  'x64'
185
387
  when 'aarch64'
186
388
  'arm64'
389
+ when 'arm'
390
+ 'arm'
391
+ when 'riscv64'
392
+ 'riscv64'
187
393
  else
188
394
  raise NotImplementedError, message
189
395
  end
190
396
 
191
- ext = Gem.win_platform? ? 'zip' : 'tar.gz'
397
+ ext = Platform::OS == 'windows' ? 'zip' : 'tar.gz'
192
398
 
193
- "#{repo}/releases/download/#{tag_name}/sass_embedded-#{tag_name}-#{os}-#{cpu}.#{ext}"
399
+ "#{repo}/releases/download/#{tag_name}/dart-sass-#{tag_name}-#{os}-#{cpu}#{env}.#{ext}"
194
400
  end
195
401
 
196
- def default_protoc
402
+ def protoc
403
+ require 'rubygems/remote_fetcher'
404
+
197
405
  repo = 'https://repo.maven.apache.org/maven2/com/google/protobuf/protoc'
198
406
 
199
- version = Gem::Dependency.new('google-protobuf').to_spec.version
407
+ dependency = Gem::Dependency.new('google-protobuf')
408
+
409
+ spec = dependency.to_spec
410
+
411
+ version = spec.version
200
412
 
201
413
  message = "protoc for #{Platform::ARCH} not available at #{repo}/#{version}"
202
414
 
203
415
  os = case Platform::OS
204
416
  when 'darwin'
205
417
  'osx'
206
- when 'linux'
418
+ when 'linux', 'linux-android', 'linux-musl', 'linux-uclibc'
207
419
  'linux'
208
420
  when 'windows'
209
421
  'windows'
@@ -212,7 +424,7 @@ module Configuration
212
424
  end
213
425
 
214
426
  cpu = case Platform::CPU
215
- when 'i386'
427
+ when 'x86'
216
428
  'x86_32'
217
429
  when 'x86_64'
218
430
  'x86_64'
@@ -226,20 +438,84 @@ module Configuration
226
438
  raise NotImplementedError, message
227
439
  end
228
440
 
229
- "#{repo}/#{version}/protoc-#{version}-#{os}-#{cpu}.exe"
441
+ uri = "#{repo}/#{version}/protoc-#{version}-#{os}-#{cpu}.exe"
442
+
443
+ Gem::RemoteFetcher.fetcher.fetch_https(Gem::Uri.new("#{uri}.sha1"))
444
+
445
+ uri
446
+ rescue Gem::RemoteFetcher::FetchError
447
+ dependency_request = Gem::Resolver::DependencyRequest.new(dependency, nil)
448
+
449
+ versions = Gem::Resolver::BestSet.new.find_all(dependency_request).filter_map do |s|
450
+ s.version if s.platform == Gem::Platform::RUBY
451
+ end
452
+
453
+ versions.sort.reverse_each do |v|
454
+ uri = "#{repo}/#{v}/protoc-#{v}-#{os}-#{cpu}.exe"
455
+
456
+ Gem::RemoteFetcher.fetcher.fetch_https(Gem::Uri.new("#{uri}.sha1"))
457
+
458
+ return uri
459
+ rescue Gem::RemoteFetcher::FetchError
460
+ next
461
+ end
462
+
463
+ raise NotImplementedError, message
230
464
  end
231
465
 
232
- def default_sass_embedded_protocol
466
+ def embedded_sass_protocol
233
467
  require 'json'
234
468
  require 'open3'
235
- require_relative 'embedded'
236
469
 
237
- stdout, stderr, status = Open3.capture3(Sass::Embedded::Compiler::PATH, '--version')
470
+ stdout, stderr, status = Open3.capture3(RbConfig.ruby,
471
+ File.absolute_path('../../exe/sass', __dir__),
472
+ '--embedded',
473
+ '--version')
238
474
 
239
475
  raise stderr unless status.success?
240
476
 
241
477
  tag_name = JSON.parse(stdout)['protocolVersion']
242
478
 
243
- "https://github.com/sass/embedded-protocol/raw/#{tag_name}/embedded_sass.proto"
479
+ "https://github.com/sass/sass/raw/embedded-protocol-#{tag_name}/spec/embedded_sass.proto"
480
+ rescue StandardError # TODO: remove after https://github.com/sass/dart-sass/pull/2413
481
+ 'https://github.com/sass/sass/raw/HEAD/spec/embedded_sass.proto'
482
+ end
483
+
484
+ def development?
485
+ File.exist?('../../Gemfile')
486
+ end
487
+
488
+ def gem_version
489
+ require_relative '../../lib/sass/embedded/version'
490
+
491
+ development? ? dart_sass_version : Sass::Embedded::VERSION
492
+ end
493
+
494
+ def gem_platform
495
+ platform = Gem::Platform.new("#{Platform::CPU}-#{RbConfig::CONFIG['host_os']}")
496
+ case Platform::OS
497
+ when 'darwin'
498
+ case platform.cpu
499
+ when 'aarch64'
500
+ Gem::Platform.new(['arm64', platform.os])
501
+ else
502
+ platform
503
+ end
504
+ when 'linux'
505
+ if platform.version&.start_with?('gnu')
506
+ platform
507
+ else
508
+ Gem::Platform.new([platform.cpu, platform.os, "gnu#{platform.version}"])
509
+ end
510
+ when 'windows'
511
+ case platform.cpu
512
+ when 'x86_64'
513
+ Gem::Platform.new('x64-mingw-ucrt')
514
+ else
515
+ Gem::Platform.new([platform.cpu, 'mingw', 'ucrt'])
516
+ end
517
+ else
518
+ platform
519
+ end
244
520
  end
245
521
  end