sass-embedded 1.6.2 → 1.83.1

Sign up to get free protection for your applications and to get access to all the features.
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