sass-embedded 1.77.5 → 1.100.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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +18 -17
  3. data/README.md +1 -1
  4. data/exe/sass +2 -10
  5. data/ext/sass/Rakefile +162 -385
  6. data/ext/sass/file_utils.rb +75 -0
  7. data/ext/sass/package.json +1 -1
  8. data/ext/sass/platform.rb +44 -0
  9. data/ext/sass/sass-1.100.0.tgz +0 -0
  10. data/ext/sass/sass_config.rb +183 -0
  11. data/ext/sass/utils.rb +39 -0
  12. data/lib/sass/compiler/channel.rb +6 -4
  13. data/lib/sass/compiler/connection.rb +17 -21
  14. data/lib/sass/compiler/dispatcher.rb +27 -1
  15. data/lib/sass/compiler/host/function_registry.rb +6 -6
  16. data/lib/sass/compiler/host/importer_registry.rb +17 -11
  17. data/lib/sass/compiler/host/logger_registry.rb +17 -20
  18. data/lib/sass/compiler/host/protofier.rb +59 -73
  19. data/lib/sass/compiler/host/struct.rb +36 -0
  20. data/lib/sass/compiler/host.rb +2 -2
  21. data/lib/sass/compiler.rb +4 -3
  22. data/lib/sass/elf.rb +282 -172
  23. data/lib/sass/embedded/version.rb +1 -1
  24. data/lib/sass/embedded.rb +2 -41
  25. data/lib/sass/embedded_protocol.rb +1 -1
  26. data/{ext → lib}/sass/embedded_sass_pb.rb +3 -5
  27. data/lib/sass/exception.rb +7 -2
  28. data/lib/sass/fork_tracker.rb +36 -28
  29. data/lib/sass/gem_package_importer.rb +19 -0
  30. data/lib/sass/serializer.rb +5 -11
  31. data/lib/sass/value/argument_list.rb +0 -8
  32. data/lib/sass/value/color/channel.rb +79 -0
  33. data/lib/sass/value/color/conversions.rb +473 -0
  34. data/lib/sass/value/color/gamut_map_method/clip.rb +45 -0
  35. data/lib/sass/value/color/gamut_map_method/local_minde.rb +94 -0
  36. data/lib/sass/value/color/gamut_map_method.rb +45 -0
  37. data/lib/sass/value/color/interpolation_method.rb +51 -0
  38. data/lib/sass/value/color/space/a98_rgb.rb +57 -0
  39. data/lib/sass/value/color/space/display_p3.rb +72 -0
  40. data/lib/sass/value/color/space/display_p3_linear.rb +72 -0
  41. data/lib/sass/value/color/space/hsl.rb +65 -0
  42. data/lib/sass/value/color/space/hwb.rb +70 -0
  43. data/lib/sass/value/color/space/lab.rb +77 -0
  44. data/lib/sass/value/color/space/lch.rb +53 -0
  45. data/lib/sass/value/color/space/lms.rb +129 -0
  46. data/lib/sass/value/color/space/oklab.rb +66 -0
  47. data/lib/sass/value/color/space/oklch.rb +54 -0
  48. data/lib/sass/value/color/space/prophoto_rgb.rb +59 -0
  49. data/lib/sass/value/color/space/rec2020.rb +69 -0
  50. data/lib/sass/value/color/space/rgb.rb +52 -0
  51. data/lib/sass/value/color/space/srgb.rb +140 -0
  52. data/lib/sass/value/color/space/srgb_linear.rb +72 -0
  53. data/lib/sass/value/color/space/utils.rb +86 -0
  54. data/lib/sass/value/color/space/xyz_d50.rb +100 -0
  55. data/lib/sass/value/color/space/xyz_d65.rb +57 -0
  56. data/lib/sass/value/color/space.rb +201 -0
  57. data/lib/sass/value/color.rb +539 -162
  58. data/lib/sass/value/function.rb +9 -6
  59. data/lib/sass/value/fuzzy_math.rb +34 -30
  60. data/lib/sass/value/mixin.rb +5 -2
  61. data/lib/sass/value/null.rb +1 -1
  62. data/lib/sass/value/number/unit.rb +5 -4
  63. data/lib/sass/value/number.rb +15 -17
  64. data/lib/sass/value/string.rb +1 -1
  65. data/lib/sass/value.rb +1 -1
  66. metadata +42 -21
  67. data/ext/sass/expand-archive.ps1 +0 -1
  68. data/lib/sass/compiler/host/structifier.rb +0 -37
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The {Platform} module.
4
+ module Platform
5
+ HOST_CPU = RbConfig::CONFIG['host_cpu'].downcase
6
+
7
+ CPU = case HOST_CPU
8
+ when /amd64|x86_64|x64/
9
+ 'x86_64'
10
+ when /i\d86|x86|i86pc/
11
+ 'i386'
12
+ when /arm64|aarch64/
13
+ 'aarch64'
14
+ when /arm/
15
+ 'arm'
16
+ when /ppc64le|powerpc64le/
17
+ 'ppc64le'
18
+ else
19
+ HOST_CPU
20
+ end
21
+
22
+ HOST_OS = RbConfig::CONFIG['host_os'].downcase
23
+
24
+ OS = case HOST_OS
25
+ when /darwin/
26
+ 'darwin'
27
+ when /linux-android/
28
+ 'linux-android'
29
+ when /linux-musl/
30
+ 'linux-musl'
31
+ when /linux-none/
32
+ 'linux-none'
33
+ when /linux-uclibc/
34
+ 'linux-uclibc'
35
+ when /linux/
36
+ 'linux'
37
+ when *Gem::WIN_PATTERNS
38
+ 'windows'
39
+ else
40
+ HOST_OS
41
+ end
42
+
43
+ ARCH = "#{CPU}-#{OS}".freeze
44
+ end
Binary file
@@ -0,0 +1,183 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'platform'
4
+
5
+ # The {SassConfig} module.
6
+ module SassConfig
7
+ module_function
8
+
9
+ def package_json(path = '.')
10
+ require 'json'
11
+
12
+ JSON.parse(File.read(File.absolute_path('package.json', path)))
13
+ end
14
+
15
+ def dart_sass_version
16
+ package_json(__dir__)['dependencies']['sass']
17
+ # TODO: remove after https://github.com/sass/dart-sass/pull/2413
18
+ .delete_prefix('file:sass-').delete_suffix('.tgz')
19
+ end
20
+
21
+ def dart_sass
22
+ repo = 'https://github.com/sass/dart-sass'
23
+
24
+ tag_name = dart_sass_version
25
+
26
+ message = "dart-sass for #{Platform::ARCH} not available at #{repo}/releases/tag/#{tag_name}"
27
+
28
+ env = ''
29
+
30
+ os = case Platform::OS
31
+ when 'darwin'
32
+ 'macos'
33
+ when 'linux'
34
+ 'linux'
35
+ when 'linux-android'
36
+ 'android'
37
+ when 'linux-musl'
38
+ env = '-musl'
39
+ 'linux'
40
+ when 'windows'
41
+ 'windows'
42
+ else
43
+ raise NotImplementedError, message
44
+ end
45
+
46
+ cpu = case Platform::CPU
47
+ when 'x86_64'
48
+ 'x64'
49
+ when 'aarch64'
50
+ 'arm64'
51
+ when 'arm'
52
+ 'arm'
53
+ when 'riscv64'
54
+ 'riscv64'
55
+ else
56
+ raise NotImplementedError, message
57
+ end
58
+
59
+ ext = Platform::OS == 'windows' ? 'zip' : 'tar.gz'
60
+
61
+ "#{repo}/releases/download/#{tag_name}/dart-sass-#{tag_name}-#{os}-#{cpu}#{env}.#{ext}"
62
+ end
63
+
64
+ def protoc
65
+ repo = 'https://repo.maven.apache.org/maven2/com/google/protobuf/protoc'
66
+
67
+ dependency = Gem::Dependency.new('google-protobuf')
68
+
69
+ spec = dependency.to_spec
70
+
71
+ version = spec.version
72
+
73
+ message = "protoc for #{Platform::ARCH} not available at #{repo}/#{version}"
74
+
75
+ os = case Platform::OS
76
+ when 'darwin'
77
+ 'osx'
78
+ when 'linux', 'linux-android', 'linux-musl', 'linux-none', 'linux-uclibc'
79
+ 'linux'
80
+ when 'windows'
81
+ 'windows'
82
+ else
83
+ raise NotImplementedError, message
84
+ end
85
+
86
+ cpu = case Platform::CPU
87
+ when 'i386'
88
+ 'x86_32'
89
+ when 'x86_64'
90
+ 'x86_64'
91
+ when 'aarch64'
92
+ Platform::OS == 'windows' ? 'x86_64' : 'aarch_64'
93
+ when 'ppc64le'
94
+ 'ppcle_64'
95
+ when 's390x'
96
+ 's390_64'
97
+ else
98
+ raise NotImplementedError, message
99
+ end
100
+
101
+ uri = "#{repo}/#{version}/protoc-#{version}-#{os}-#{cpu}.exe"
102
+
103
+ Utils.fetch_https("#{uri}.sha1")
104
+
105
+ uri
106
+ rescue Gem::RemoteFetcher::FetchError
107
+ dependency_request = Gem::Resolver::DependencyRequest.new(dependency, nil)
108
+
109
+ versions = Gem::Resolver::BestSet.new.find_all(dependency_request).filter_map do |s|
110
+ s.version if s.platform == Gem::Platform::RUBY
111
+ end
112
+
113
+ versions.sort.reverse_each do |v|
114
+ uri = "#{repo}/#{v}/protoc-#{v}-#{os}-#{cpu}.exe"
115
+
116
+ Utils.fetch_https("#{uri}.sha1")
117
+
118
+ return uri
119
+ rescue Gem::RemoteFetcher::FetchError
120
+ next
121
+ end
122
+
123
+ raise NotImplementedError, message
124
+ end
125
+
126
+ def embedded_sass_protocol
127
+ require 'json'
128
+
129
+ rubyarchdir = ENV.fetch('RUBYARCHDIR', nil)
130
+
131
+ rubylibdir = ENV.fetch('RUBYLIBDIR', nil)
132
+
133
+ version = Utils.capture(RbConfig.ruby,
134
+ "-I#{File.absolute_path('../../lib', __dir__)}",
135
+ *("-I#{rubyarchdir}" if rubyarchdir),
136
+ *("-I#{rubylibdir}" if rubylibdir),
137
+ File.absolute_path('../../exe/sass', __dir__),
138
+ '--embedded',
139
+ '--version')
140
+
141
+ tag_name = JSON.parse(version)['protocolVersion']
142
+
143
+ "https://github.com/sass/sass/raw/embedded-protocol-#{tag_name}/spec/embedded_sass.proto"
144
+ end
145
+
146
+ def development?
147
+ File.exist?('../../Gemfile')
148
+ end
149
+
150
+ def gem_version
151
+ require_relative '../../lib/sass/embedded/version'
152
+
153
+ development? ? dart_sass_version : Sass::Embedded::VERSION
154
+ end
155
+
156
+ def gem_platform
157
+ platform = Gem::Platform.new("#{Platform::CPU}-#{Platform::HOST_OS}")
158
+ case Platform::OS
159
+ when 'darwin'
160
+ case platform.cpu
161
+ when 'aarch64'
162
+ Gem::Platform.new(['arm64', platform.os])
163
+ else
164
+ platform
165
+ end
166
+ when 'linux'
167
+ if platform.version&.start_with?('gnu')
168
+ platform
169
+ else
170
+ Gem::Platform.new([platform.cpu, platform.os, "gnu#{platform.version}"])
171
+ end
172
+ when 'windows'
173
+ case platform.cpu
174
+ when 'x86_64'
175
+ Gem::Platform.new('x64-mingw-ucrt')
176
+ else
177
+ Gem::Platform.new([platform.cpu, 'mingw', 'ucrt'])
178
+ end
179
+ else
180
+ platform
181
+ end
182
+ end
183
+ end
data/ext/sass/utils.rb ADDED
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The {Utils} module.
4
+ module Utils
5
+ module_function
6
+
7
+ def capture(...)
8
+ require 'open3'
9
+
10
+ stdout, stderr, status = Open3.capture3(...)
11
+
12
+ raise stderr unless status.success?
13
+
14
+ stdout
15
+ end
16
+
17
+ def fetch_https(source_uri)
18
+ require 'rubygems/remote_fetcher'
19
+
20
+ source_uri = begin
21
+ Gem::Uri.parse!(source_uri)
22
+ rescue NoMethodError
23
+ URI.parse(source_uri)
24
+ end
25
+
26
+ Gem::RemoteFetcher.fetcher.fetch_https(source_uri)
27
+ end
28
+
29
+ def windows_system_directory
30
+ path = capture('powershell.exe',
31
+ '-NoLogo',
32
+ '-NoProfile',
33
+ '-NonInteractive',
34
+ '-Command',
35
+ '[Environment]::GetFolderPath([Environment+SpecialFolder]::System) | Write-Host -NoNewline')
36
+
37
+ File.absolute_path(path)
38
+ end
39
+ end
@@ -6,9 +6,11 @@ module Sass
6
6
  #
7
7
  # It manages the lifecycle of {Dispatcher}.
8
8
  class Channel
9
- def initialize(dispatcher_class)
10
- @dispatcher_class = dispatcher_class
11
- @dispatcher = @dispatcher_class.new
9
+ def initialize(*args, **kwargs, &block)
10
+ @args = args
11
+ @kwargs = kwargs
12
+ @block = block
13
+ @dispatcher = Dispatcher.new(*@args, **@kwargs, &@block)
12
14
  @mutex = Mutex.new
13
15
  end
14
16
 
@@ -33,7 +35,7 @@ module Sass
33
35
 
34
36
  Stream.new(@dispatcher, host)
35
37
  rescue Errno::EBUSY
36
- @dispatcher = @dispatcher_class.new
38
+ @dispatcher = Dispatcher.new(*@args, **@kwargs, &@block)
37
39
  Stream.new(@dispatcher, host)
38
40
  end
39
41
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'open3'
4
4
 
5
- require_relative '../../../ext/sass/cli'
5
+ require 'sass/cli'
6
6
 
7
7
  module Sass
8
8
  class Compiler
@@ -12,33 +12,29 @@ module Sass
12
12
  class Connection
13
13
  def initialize
14
14
  @mutex = Mutex.new
15
- @stdin, @stdout, @stderr, @wait_thread = begin
16
- Open3.popen3(*CLI::COMMAND, '--embedded', chdir: __dir__)
17
- rescue Errno::ENOENT
18
- require_relative '../elf'
15
+ @stdin, @stdout, @stderr, @wait_thread = Open3.popen3(*CLI::COMMAND, '--embedded', chdir: __dir__)
19
16
 
20
- raise if ELF::INTERPRETER.nil?
17
+ @stdin.binmode
21
18
 
22
- Open3.popen3(ELF::INTERPRETER, *CLI::COMMAND, '--embedded', chdir: __dir__)
23
- end
19
+ # # https://dart.dev/tools/dart-devtools
20
+ # if %w[dart dartvm].include?(File.basename(CLI::COMMAND.first, '.exe')) &&
21
+ # %w[--enable-vm-service --observe].intersect?(CLI::COMMAND.map { |argument| argument.partition('=').first })
22
+ # Kernel.warn(@stdout.readline, uplevel: 0)
23
+ # Kernel.warn(@stdout.readline, uplevel: 0)
24
+ # end
24
25
 
25
- @stdin.binmode
26
+ @stdout.binmode
27
+
28
+ @wait_thread.name = "sass-embedded-process-waiter-#{id}"
29
+ end
26
30
 
27
- @wait_thread.name = "sass-embedded-process-waiter-#{@wait_thread.pid}"
31
+ def id
32
+ @wait_thread.pid
28
33
  end
29
34
 
30
35
  def listen(dispatcher)
31
36
  Thread.new do
32
- Thread.current.name = "sass-embedded-process-stdout-poller-#{@wait_thread.pid}"
33
-
34
- # # https://dart.dev/tools/dart-devtools
35
- # if 'dart' == File.basename(CLI::COMMAND.first, '.exe') && CLI::COMMAND.include?('--observe')
36
- # Kernel.warn(@stdout.readline, uplevel: 0)
37
- # Kernel.warn(@stdout.readline, uplevel: 0)
38
- # end
39
-
40
- @stdout.binmode
41
-
37
+ Thread.current.name = "sass-embedded-process-stdout-poller-#{id}"
42
38
  loop do
43
39
  length = Varint.read(@stdout)
44
40
  id = Varint.read(@stdout)
@@ -53,7 +49,7 @@ module Sass
53
49
  end
54
50
 
55
51
  Thread.new do
56
- Thread.current.name = "sass-embedded-process-stderr-poller-#{@wait_thread.pid}"
52
+ Thread.current.name = "sass-embedded-process-stderr-poller-#{id}"
57
53
  loop do
58
54
  Kernel.warn(@stderr.readline, uplevel: 0)
59
55
  end
@@ -6,13 +6,33 @@ module Sass
6
6
  #
7
7
  # It dispatches messages between multiple instances of {Host} and a single {Connection} to the compiler.
8
8
  class Dispatcher
9
- def initialize
9
+ def initialize(idle_timeout: 0)
10
10
  @id = 1
11
11
  @observers = {}.compare_by_identity
12
12
  @mutex = Mutex.new
13
13
  @connection = Connection.new
14
14
  @connection.listen(self)
15
15
  ForkTracker.add(self)
16
+
17
+ return unless idle_timeout.positive?
18
+
19
+ @last_accessed_time = current_time
20
+ Thread.new do
21
+ Thread.current.name = "sass-embedded-connection-reaper-#{@connection.id}"
22
+ duration = idle_timeout
23
+ loop do
24
+ sleep(duration.negative? ? idle_timeout : duration)
25
+ break if @mutex.synchronize do
26
+ raise Errno::EBUSY if _closed?
27
+
28
+ duration = idle_timeout - (current_time - @last_accessed_time)
29
+ duration.negative? && _idle? && _close
30
+ end
31
+ end
32
+ close
33
+ rescue Errno::EBUSY
34
+ # do nothing
35
+ end
16
36
  end
17
37
 
18
38
  def subscribe(observer)
@@ -94,6 +114,10 @@ module Sass
94
114
 
95
115
  private
96
116
 
117
+ def current_time
118
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
119
+ end
120
+
97
121
  def _close
98
122
  @id = 0xffffffff
99
123
  end
@@ -103,6 +127,8 @@ module Sass
103
127
  end
104
128
 
105
129
  def _idle
130
+ @last_accessed_time = current_time if defined?(@last_accessed_time)
131
+
106
132
  @id = 1
107
133
  end
108
134
 
@@ -7,13 +7,13 @@ module Sass
7
7
  #
8
8
  # It stores sass custom functions and handles function calls.
9
9
  class FunctionRegistry
10
- attr_reader :global_functions
10
+ attr_reader :compile_context, :global_functions
11
11
 
12
12
  def initialize(functions, alert_color:)
13
- functions = functions.transform_keys(&:to_s)
14
-
15
- @global_functions = functions.keys
13
+ @compile_context = Object.new
14
+ @global_functions = functions.keys.map!(&:to_s)
16
15
  @functions_by_name = functions.transform_keys do |signature|
16
+ signature = signature.to_s
17
17
  index = signature.index('(')
18
18
  if index
19
19
  signature.slice(0, index)
@@ -57,8 +57,8 @@ module Sass
57
57
 
58
58
  success = protofier.to_proto(function.call(arguments))
59
59
  accessed_argument_lists = arguments.filter_map do |argument|
60
- if argument.is_a?(Sass::Value::ArgumentList) && argument.instance_eval { @keywords_accessed }
61
- argument.instance_eval { @id }
60
+ if argument.is_a?(Sass::Value::ArgumentList) && argument.instance_variable_get(:@keywords_accessed)
61
+ argument.instance_variable_get(:@id)
62
62
  end
63
63
  end
64
64
 
@@ -25,15 +25,21 @@ module Sass
25
25
  @highlight = alert_color
26
26
  end
27
27
 
28
+ IMPORTER_ATTRS = %i[non_canonical_scheme].freeze
29
+
30
+ IMPORTER_METHODS = %i[canonicalize load find_file_url].freeze
31
+
32
+ private_constant :IMPORTER_ATTRS, :IMPORTER_METHODS
33
+
28
34
  def register(importer)
29
35
  if importer.is_a?(Sass::NodePackageImporter)
30
36
  EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
31
37
  node_package_importer: EmbeddedProtocol::NodePackageImporter.new(
32
- entry_point_directory: importer.instance_eval { @entry_point_directory }
38
+ entry_point_directory: importer.instance_variable_get(:@entry_point_directory)
33
39
  )
34
40
  )
35
41
  else
36
- importer = Structifier.to_struct(importer, :canonicalize, :load, :non_canonical_scheme, :find_file_url)
42
+ importer = Struct.new(importer, attrs: IMPORTER_ATTRS, methods: IMPORTER_METHODS) if importer.is_a?(::Hash)
37
43
 
38
44
  is_importer = importer.respond_to?(:canonicalize) && importer.respond_to?(:load)
39
45
  is_file_importer = importer.respond_to?(:find_file_url)
@@ -48,12 +54,7 @@ module Sass
48
54
  EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
49
55
  importer_id: id,
50
56
  non_canonical_scheme: if importer.respond_to?(:non_canonical_scheme)
51
- non_canonical_scheme = importer.non_canonical_scheme
52
- if non_canonical_scheme.is_a?(String)
53
- [non_canonical_scheme]
54
- else
55
- non_canonical_scheme || []
56
- end
57
+ Array(importer.non_canonical_scheme)
57
58
  else
58
59
  []
59
60
  end
@@ -75,7 +76,7 @@ module Sass
75
76
  EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
76
77
  id: canonicalize_request.id,
77
78
  url:,
78
- containing_url_unused: canonicalize_context.instance_eval { @containing_url_unused }
79
+ containing_url_unused: canonicalize_context.instance_variable_get(:@containing_url_unused)
79
80
  )
80
81
  rescue StandardError => e
81
82
  EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
@@ -84,9 +85,14 @@ module Sass
84
85
  )
85
86
  end
86
87
 
88
+ IMPORTER_RESULT_ATTRS = %i[contents syntax source_map_url].freeze
89
+
90
+ private_constant :IMPORTER_RESULT_ATTRS
91
+
87
92
  def import(import_request)
88
93
  importer = @importers_by_id[import_request.importer_id]
89
- importer_result = Structifier.to_struct importer.load(import_request.url), :contents, :syntax, :source_map_url
94
+ importer_result = importer.load(import_request.url)
95
+ importer_result = Struct.new(importer_result, attrs: IMPORTER_RESULT_ATTRS) if importer_result.is_a?(::Hash)
90
96
 
91
97
  EmbeddedProtocol::InboundMessage::ImportResponse.new(
92
98
  id: import_request.id,
@@ -112,7 +118,7 @@ module Sass
112
118
  EmbeddedProtocol::InboundMessage::FileImportResponse.new(
113
119
  id: file_import_request.id,
114
120
  file_url:,
115
- containing_url_unused: canonicalize_context.instance_eval { @containing_url_unused }
121
+ containing_url_unused: canonicalize_context.instance_variable_get(:@containing_url_unused)
116
122
  )
117
123
  rescue StandardError => e
118
124
  EmbeddedProtocol::InboundMessage::FileImportResponse.new(
@@ -7,39 +7,36 @@ module Sass
7
7
  #
8
8
  # It stores logger and handles log events.
9
9
  class LoggerRegistry
10
- def initialize(logger)
11
- logger = Structifier.to_struct(logger, :debug, :warn)
10
+ LOGGER_METHODS = %i[debug warn].freeze
12
11
 
13
- { debug: DebugContext, warn: WarnContext }.each do |symbol, context_class|
14
- next unless logger.respond_to?(symbol)
12
+ private_constant :LOGGER_METHODS
15
13
 
16
- define_singleton_method(symbol) do |event|
17
- logger.public_send(symbol, event.message, context_class.new(event))
18
- end
19
- end
14
+ def initialize(logger)
15
+ logger = Struct.new(logger, methods: LOGGER_METHODS) if logger.is_a?(::Hash)
16
+ @logger = logger
17
+ @logger_respond_to_debug = logger.respond_to?(:debug)
18
+ @logger_respond_to_warn = logger.respond_to?(:warn)
20
19
  end
21
20
 
22
21
  def log(event)
23
22
  case event.type
24
23
  when :DEBUG
25
- debug(event)
24
+ if @logger_respond_to_debug
25
+ @logger.debug(event.message, DebugContext.new(event))
26
+ else
27
+ Kernel.warn(event.formatted)
28
+ end
26
29
  when :DEPRECATION_WARNING, :WARNING
27
- warn(event)
30
+ if @logger_respond_to_warn
31
+ @logger.warn(event.message, WarnContext.new(event))
32
+ else
33
+ Kernel.warn(event.formatted)
34
+ end
28
35
  else
29
36
  raise ArgumentError, "Unknown LogEvent.type #{event.type}"
30
37
  end
31
38
  end
32
39
 
33
- private
34
-
35
- def debug(event)
36
- Kernel.warn(event.formatted)
37
- end
38
-
39
- def warn(event)
40
- Kernel.warn(event.formatted)
41
- end
42
-
43
40
  # Contextual information passed to `debug`.
44
41
  class DebugContext
45
42
  # @return [Logger::SourceSpan, nil]