sass-embedded 0.15.0 → 0.16.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.
@@ -0,0 +1,329 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ class Embedded
5
+ # The {Protofier} between Pure Ruby types and Protobuf Ruby types.
6
+ class Protofier
7
+ ONEOF_MESSAGE = EmbeddedProtocol::InboundMessage
8
+ .descriptor
9
+ .lookup_oneof('message')
10
+ .to_h do |field_descriptor|
11
+ [field_descriptor.subtype, field_descriptor.name]
12
+ end
13
+
14
+ private_constant :ONEOF_MESSAGE
15
+
16
+ def initialize(function_registry)
17
+ @function_registry = function_registry
18
+ end
19
+
20
+ def to_proto_value(obj)
21
+ case obj
22
+ when Sass::Value::String
23
+ Sass::EmbeddedProtocol::Value.new(
24
+ string: Sass::EmbeddedProtocol::Value::String.new(
25
+ text: obj.text,
26
+ quoted: obj.quoted?
27
+ )
28
+ )
29
+ when Sass::Value::Number
30
+ Sass::EmbeddedProtocol::Value.new(
31
+ number: Sass::EmbeddedProtocol::Value::Number.new(
32
+ value: obj.value.to_f,
33
+ numerators: obj.numerator_units,
34
+ denominators: obj.denominator_units
35
+ )
36
+ )
37
+ when Sass::Value::Color
38
+ if obj.instance_eval { @hue.nil? }
39
+ Sass::EmbeddedProtocol::Value.new(
40
+ rgb_color: Sass::EmbeddedProtocol::Value::RgbColor.new(
41
+ red: obj.red,
42
+ green: obj.green,
43
+ blue: obj.blue,
44
+ alpha: obj.alpha.to_f
45
+ )
46
+ )
47
+ elsif obj.instance_eval { @saturation.nil? }
48
+ Sass::EmbeddedProtocol::Value.new(
49
+ hwb_color: Sass::EmbeddedProtocol::Value::HwbColor.new(
50
+ hue: obj.hue.to_f,
51
+ whiteness: obj.whiteness.to_f,
52
+ blackness: obj.blackness.to_f,
53
+ alpha: obj.alpha.to_f
54
+ )
55
+ )
56
+ else
57
+ Sass::EmbeddedProtocol::Value.new(
58
+ hsl_color: Sass::EmbeddedProtocol::Value::HslColor.new(
59
+ hue: obj.hue.to_f,
60
+ saturation: obj.saturation.to_f,
61
+ lightness: obj.lightness.to_f,
62
+ alpha: obj.alpha.to_f
63
+ )
64
+ )
65
+ end
66
+ when Sass::Value::ArgumentList
67
+ Sass::EmbeddedProtocol::Value.new(
68
+ argument_list: Sass::EmbeddedProtocol::Value::ArgumentList.new(
69
+ id: obj.instance_eval { @id },
70
+ contents: obj.contents.map { |element| to_proto_value(element) },
71
+ keywords: obj.keywords.transform_values { |value| to_proto_value(value) },
72
+ separator: to_proto_separator(obj.separator)
73
+ )
74
+ )
75
+ when Sass::Value::List
76
+ Sass::EmbeddedProtocol::Value.new(
77
+ list: Sass::EmbeddedProtocol::Value::List.new(
78
+ contents: obj.contents.map { |element| to_proto_value(element) },
79
+ separator: to_proto_separator(obj.separator),
80
+ has_brackets: obj.bracketed?
81
+ )
82
+ )
83
+ when Sass::Value::Map
84
+ Sass::EmbeddedProtocol::Value.new(
85
+ map: Sass::EmbeddedProtocol::Value::Map.new(
86
+ entries: obj.contents.map do |key, value|
87
+ Sass::EmbeddedProtocol::Value::Map::Entry.new(
88
+ key: to_proto_value(key),
89
+ value: to_proto_value(value)
90
+ )
91
+ end
92
+ )
93
+ )
94
+ when Sass::Value::Function
95
+ if obj.id
96
+ Sass::EmbeddedProtocol::Value.new(
97
+ compiler_function: Sass::EmbeddedProtocol::Value::CompilerFunction.new(
98
+ id: obj.id
99
+ )
100
+ )
101
+ else
102
+ Sass::EmbeddedProtocol::Value.new(
103
+ host_function: Sass::EmbeddedProtocol::Value::HostFunction.new(
104
+ id: @function_registry.register(obj.callback),
105
+ signature: obj.signature
106
+ )
107
+ )
108
+ end
109
+ when Sass::Value::Boolean
110
+ Sass::EmbeddedProtocol::Value.new(
111
+ singleton: obj.value ? :TRUE : :FALSE
112
+ )
113
+ when Sass::Value::Null
114
+ Sass::EmbeddedProtocol::Value.new(
115
+ singleton: :NULL
116
+ )
117
+ else
118
+ raise Sass::ScriptError, "Unknown Sass::Value #{obj}"
119
+ end
120
+ end
121
+
122
+ def from_proto_value(proto)
123
+ value = proto.method(proto.value).call
124
+ case proto.value
125
+ when :string
126
+ Sass::Value::String.new(
127
+ value.text,
128
+ quoted: value.quoted
129
+ )
130
+ when :number
131
+ Sass::Value::Number.new(
132
+ value.value,
133
+ value.numerators,
134
+ value.denominators
135
+ )
136
+ when :rgb_color
137
+ Sass::Value::Color.new(
138
+ red: value.red,
139
+ green: value.green,
140
+ blue: value.blue,
141
+ alpha: value.alpha
142
+ )
143
+ when :hsl_color
144
+ Sass::Value::Color.new(
145
+ hue: value.hue,
146
+ saturation: value.saturation,
147
+ lightness: value.lightness,
148
+ alpha: value.alpha
149
+ )
150
+ when :hwb_color
151
+ Sass::Value::Color.new(
152
+ hue: value.hue,
153
+ whiteness: value.whiteness,
154
+ blackness: value.blackness,
155
+ alpha: value.alpha
156
+ )
157
+ when :argument_list
158
+ Sass::Value::ArgumentList.new(
159
+ value.contents.map do |i|
160
+ from_proto_value(i)
161
+ end,
162
+ value.keywords.entries.to_h do |entry|
163
+ [entry.first, from_proto_value(entry.last)]
164
+ end,
165
+ from_proto_separator(value.separator)
166
+ ).instance_eval do
167
+ @id = value.id
168
+ self
169
+ end
170
+ when :list
171
+ Sass::Value::List.new(
172
+ value.contents.map do |element|
173
+ from_proto_value(element)
174
+ end,
175
+ separator: from_proto_separator(value.separator),
176
+ bracketed: value.has_brackets
177
+ )
178
+ when :map
179
+ Sass::Value::Map.new(
180
+ value.entries.to_h do |entry|
181
+ [from_proto_value(entry.key), from_proto_value(entry.value)]
182
+ end
183
+ )
184
+ when :compiler_function
185
+ Sass::Value::Function.new(value.id)
186
+ when :host_function
187
+ raise ProtocolError, 'The compiler may not send Value.host_function to host'
188
+ when :singleton
189
+ case value
190
+ when :TRUE
191
+ Sass::Value::Boolean::TRUE
192
+ when :FALSE
193
+ Sass::Value::Boolean::FALSE
194
+ when :NULL
195
+ Sass::Value::Null::NULL
196
+ else
197
+ raise Sass::ScriptError "Unknown Value.singleton #{value}"
198
+ end
199
+ else
200
+ raise Sass::ScriptError, "Unknown Value.value #{value}"
201
+ end
202
+ end
203
+
204
+ private
205
+
206
+ def to_proto_separator(separator)
207
+ case separator
208
+ when ','
209
+ :COMMA
210
+ when ' '
211
+ :SPACE
212
+ when '/'
213
+ :SLASH
214
+ when nil
215
+ :UNDECIDED
216
+ else
217
+ raise Sass::ScriptError, "Unknown ListSeparator #{separator}"
218
+ end
219
+ end
220
+
221
+ def from_proto_separator(separator)
222
+ case separator
223
+ when :COMMA
224
+ ','
225
+ when :SPACE
226
+ ' '
227
+ when :SLASH
228
+ '/'
229
+ when :UNDECIDED
230
+ nil
231
+ else
232
+ raise Sass::ScriptError, "Unknown ListSeparator #{separator}"
233
+ end
234
+ end
235
+
236
+ class << self
237
+ def from_proto_compile_response(compile_response)
238
+ if compile_response.result == :failure
239
+ raise CompileError.new(
240
+ compile_response.failure.formatted || compile_response.failure.message,
241
+ compile_response.failure.message,
242
+ compile_response.failure.stack_trace,
243
+ from_proto_source_span(compile_response.failure.span)
244
+ )
245
+ end
246
+
247
+ CompileResult.new(
248
+ compile_response.success.css,
249
+ compile_response.success.source_map,
250
+ compile_response.success.loaded_urls
251
+ )
252
+ end
253
+
254
+ def from_proto_source_span(source_span)
255
+ return nil if source_span.nil?
256
+
257
+ Logger::SourceSpan.new(from_proto_source_location(source_span.start),
258
+ from_proto_source_location(source_span.end),
259
+ source_span.text,
260
+ source_span.url,
261
+ source_span.context)
262
+ end
263
+
264
+ def from_proto_source_location(source_location)
265
+ return nil if source_location.nil?
266
+
267
+ Logger::SourceLocation.new(source_location.offset,
268
+ source_location.line,
269
+ source_location.column)
270
+ end
271
+
272
+ def from_proto_message(proto)
273
+ message = EmbeddedProtocol::OutboundMessage.decode(proto)
274
+ message.method(message.message).call
275
+ end
276
+
277
+ def to_proto_message(message)
278
+ EmbeddedProtocol::InboundMessage.new(
279
+ ONEOF_MESSAGE[message.class.descriptor] => message
280
+ ).to_proto
281
+ end
282
+
283
+ def to_proto_syntax(syntax)
284
+ case syntax&.to_sym
285
+ when :scss
286
+ EmbeddedProtocol::Syntax::SCSS
287
+ when :indented
288
+ EmbeddedProtocol::Syntax::INDENTED
289
+ when :css
290
+ EmbeddedProtocol::Syntax::CSS
291
+ else
292
+ raise ArgumentError, 'syntax must be one of :scss, :indented, :css'
293
+ end
294
+ end
295
+
296
+ def to_proto_output_style(style)
297
+ case style&.to_sym
298
+ when :expanded
299
+ EmbeddedProtocol::OutputStyle::EXPANDED
300
+ when :compressed
301
+ EmbeddedProtocol::OutputStyle::COMPRESSED
302
+ else
303
+ raise ArgumentError, 'style must be one of :expanded, :compressed'
304
+ end
305
+ end
306
+
307
+ def to_struct(obj)
308
+ return obj unless obj.is_a? Hash
309
+
310
+ struct = Object.new
311
+ obj.each do |key, value|
312
+ if value.respond_to? :call
313
+ struct.define_singleton_method key.to_sym do |*args, **kwargs|
314
+ value.call(*args, **kwargs)
315
+ end
316
+ else
317
+ struct.define_singleton_method key.to_sym do
318
+ value
319
+ end
320
+ end
321
+ end
322
+ struct
323
+ end
324
+ end
325
+ end
326
+
327
+ private_constant :Protofier
328
+ end
329
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Sass
4
4
  class Embedded
5
- VERSION = '0.15.0'
5
+ VERSION = '0.16.0'
6
6
  end
7
7
  end
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../embedded_protocol'
4
- require_relative 'observer'
5
-
6
3
  module Sass
7
4
  class Embedded
8
5
  # The {Observer} for {Embedded#info}.
@@ -32,5 +29,7 @@ module Sass
32
29
  end
33
30
  end
34
31
  end
32
+
33
+ private_constant :VersionContext
35
34
  end
36
35
  end
data/lib/sass/embedded.rb CHANGED
@@ -1,17 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'compile_error'
4
- require_relative 'compile_result'
5
- require_relative 'embedded/channel'
6
- require_relative 'embedded/compile_context'
7
- require_relative 'embedded/render' # deprecated
8
- require_relative 'embedded/version'
9
- require_relative 'embedded/version_context'
10
- require_relative 'logger'
11
-
12
3
  module Sass
13
4
  # The {Embedded} host for using dart-sass-embedded. Each instance creates
14
- # its own {Channel}.
5
+ # its own communication {Channel} with a dedicated compiler process.
15
6
  #
16
7
  # @example
17
8
  # embedded = Sass::Embedded.new
@@ -46,27 +37,25 @@ module Sass
46
37
 
47
38
  raise ArgumentError, 'path must be set' if path.nil?
48
39
 
49
- message = CompileContext.new(@channel,
50
- path: path,
51
- source: nil,
52
- importer: nil,
53
- load_paths: load_paths,
54
- syntax: nil,
55
- url: nil,
56
- source_map: source_map,
57
- source_map_include_sources: source_map_include_sources,
58
- style: style,
59
- functions: functions,
60
- importers: importers,
61
- alert_color: alert_color,
62
- alert_ascii: alert_ascii,
63
- logger: logger,
64
- quiet_deps: quiet_deps,
65
- verbose: verbose).receive_message
66
-
67
- raise CompileError.from_proto(message.failure) if message.failure
68
-
69
- CompileResult.from_proto(message.success)
40
+ Protofier.from_proto_compile_response(
41
+ CompileContext.new(@channel,
42
+ path: path,
43
+ source: nil,
44
+ importer: nil,
45
+ load_paths: load_paths,
46
+ syntax: nil,
47
+ url: nil,
48
+ source_map: source_map,
49
+ source_map_include_sources: source_map_include_sources,
50
+ style: style,
51
+ functions: functions,
52
+ importers: importers,
53
+ alert_color: alert_color,
54
+ alert_ascii: alert_ascii,
55
+ logger: logger,
56
+ quiet_deps: quiet_deps,
57
+ verbose: verbose).receive_message
58
+ )
70
59
  end
71
60
 
72
61
  # The {Embedded#compile_string} method.
@@ -94,27 +83,25 @@ module Sass
94
83
  verbose: false)
95
84
  raise ArgumentError, 'source must be set' if source.nil?
96
85
 
97
- message = CompileContext.new(@channel,
98
- path: nil,
99
- source: source,
100
- importer: importer,
101
- load_paths: load_paths,
102
- syntax: syntax,
103
- url: url,
104
- source_map: source_map,
105
- source_map_include_sources: source_map_include_sources,
106
- style: style,
107
- functions: functions,
108
- importers: importers,
109
- alert_color: alert_color,
110
- alert_ascii: alert_ascii,
111
- logger: logger,
112
- quiet_deps: quiet_deps,
113
- verbose: verbose).receive_message
114
-
115
- raise CompileError.from_proto(message.failure) if message.failure
116
-
117
- CompileResult.from_proto(message.success)
86
+ Protofier.from_proto_compile_response(
87
+ CompileContext.new(@channel,
88
+ path: nil,
89
+ source: source,
90
+ importer: importer,
91
+ load_paths: load_paths,
92
+ syntax: syntax,
93
+ url: url,
94
+ source_map: source_map,
95
+ source_map_include_sources: source_map_include_sources,
96
+ style: style,
97
+ functions: functions,
98
+ importers: importers,
99
+ alert_color: alert_color,
100
+ alert_ascii: alert_ascii,
101
+ logger: logger,
102
+ quiet_deps: quiet_deps,
103
+ verbose: verbose).receive_message
104
+ )
118
105
  end
119
106
 
120
107
  # The {Embedded#info} method.
@@ -1,9 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../../ext/sass/embedded_sass_pb'
4
-
5
- module Sass
6
- module EmbeddedProtocol
7
- PROTOCOL_ERROR_ID = 4_294_967_295
8
- end
9
- end
@@ -2,7 +2,9 @@
2
2
 
3
3
  module Sass
4
4
  module Logger
5
- # The {SourceLocation} in {SourceSpan}.
5
+ # A specific location within a source file.
6
+ #
7
+ # This is always associated with a {SourceSpan} which indicates which file it refers to.
6
8
  class SourceLocation
7
9
  attr_reader :offset, :line, :column
8
10
 
@@ -11,14 +13,6 @@ module Sass
11
13
  @line = line
12
14
  @column = column
13
15
  end
14
-
15
- def self.from_proto(source_location)
16
- return nil if source_location.nil?
17
-
18
- SourceLocation.new(source_location.offset,
19
- source_location.line,
20
- source_location.column)
21
- end
22
16
  end
23
17
  end
24
18
  end
@@ -1,10 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'source_location'
4
-
5
3
  module Sass
6
4
  module Logger
7
- # The {SourceSpan} in {CompileError}.
5
+ # A span of text within a source file.
8
6
  class SourceSpan
9
7
  attr_reader :start, :end, :text, :url, :context
10
8
 
@@ -15,16 +13,6 @@ module Sass
15
13
  @url = url == '' ? nil : url
16
14
  @context = context == '' ? nil : context
17
15
  end
18
-
19
- def self.from_proto(source_span)
20
- return nil if source_span.nil?
21
-
22
- SourceSpan.new(SourceLocation.from_proto(source_span.start),
23
- SourceLocation.from_proto(source_span.end),
24
- source_span.text,
25
- source_span.url,
26
- source_span.context)
27
- end
28
16
  end
29
17
  end
30
18
  end
data/lib/sass/logger.rb CHANGED
@@ -1,16 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sass
4
- # The {Logger} module.
4
+ # A namespace for built-in Loggers.
5
5
  module Logger
6
6
  module_function
7
7
 
8
- # The instance of a silent {Logger}.
8
+ # A Logger that silently ignores all warnings and debug messages.
9
9
  def silent
10
10
  Silent
11
11
  end
12
12
 
13
- # The silent {Logger}.
13
+ # A Logger that silently ignores all warnings and debug messages.
14
14
  module Silent
15
15
  module_function
16
16
 
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ class ScriptError < StandardError; end
5
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ class Value
5
+ # Sass's argument list type.
6
+ #
7
+ # An argument list comes from a rest argument. It's distinct from a normal {List} in that it may contain a keyword
8
+ # map as well as the positional arguments.
9
+ class ArgumentList < Sass::Value::List
10
+ def initialize(contents = [], keywords = {}, separator = ',')
11
+ super(contents, separator: separator)
12
+
13
+ @id = 0
14
+ @keywords_accessed = false
15
+ @keywords = keywords.transform_keys(&:to_s).freeze
16
+ end
17
+
18
+ def keywords
19
+ @keywords_accessed = true
20
+ @keywords
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ class Value
5
+ # Sass's boolean type.
6
+ class Boolean < Sass::Value
7
+ def initialize(value) # rubocop:disable Lint/MissingSuper
8
+ @value = value
9
+ end
10
+
11
+ attr_reader :value
12
+
13
+ alias to_bool value
14
+
15
+ def assert_boolean(_name = nil)
16
+ self
17
+ end
18
+
19
+ def ==(other)
20
+ other.is_a?(Sass::Value::Boolean) && other.value == value
21
+ end
22
+
23
+ def hash
24
+ @hash ||= value.hash
25
+ end
26
+
27
+ def !
28
+ value ? Boolean::FALSE : Boolean::TRUE
29
+ end
30
+
31
+ # Sass's true value.
32
+ TRUE = Boolean.new(true)
33
+
34
+ # Sass's false value.
35
+ FALSE = Boolean.new(false)
36
+
37
+ def self.new(value)
38
+ value ? Boolean::TRUE : Boolean::FALSE
39
+ end
40
+ end
41
+ end
42
+ end