sass-embedded 0.18.4 → 0.19.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: 25068693aab079cc3ec673b99407a0b9edfcf905c8afea7985ee06f9bbc3bb87
4
- data.tar.gz: 6af725ccc88495167bf0704d6a1789355e6d0a85280176342499e92e965cc35c
3
+ metadata.gz: 573a157ee6e0c3fa51cefec5c011649717718133d934e031a339d32a84838a13
4
+ data.tar.gz: ef27dd3177b8f58f3dd19180340686901597e9ac05efa77e2f9cc12b7784dbbb
5
5
  SHA512:
6
- metadata.gz: 577d34e39cf3adb245f39bf49ea2e621558e9d8714dc39efa8a4584f8728aed5ddb944251c9d82ffcc101d4e4788f795cade2e70a5729e84b9628a10538e22ab
7
- data.tar.gz: 3d4b4a936b6fe3d5bcb200e54e990ddb15cc668b98b6cb11db4ee93058ad469c77879dceae45dd2ba32c6bc6902b0adee120b8fb71a4908f391fc4bb0faafb68
6
+ metadata.gz: 538de1728de2da841ce66648d669acec38a4a3c3f15357e5d33e1d5dac773f246b43f29d244ec39076fc3d18504f6935374f9a5277baac7a1c400548b44aef5b
7
+ data.tar.gz: 26db551dd98592327a0c7e4fc9ee39c5917b1aff92431bfc7cdac6eea3c79899439c976512c7bed393493f564fd00e0ccafe735fe8cd8a514827d7a42b689d58
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ class Embedded
5
+ # The {Async} class.
6
+ #
7
+ # It awaits until the promise is resolved or rejected.
8
+ class Async
9
+ module State
10
+ PENDING = 0
11
+ FULFILLED = 1
12
+ REJECTED = 2
13
+ end
14
+
15
+ private_constant :State
16
+
17
+ def initialize
18
+ @error = nil
19
+ @result = nil
20
+ @state = State::PENDING
21
+
22
+ @condition_variable = ConditionVariable.new
23
+ @mutex = Mutex.new
24
+
25
+ begin
26
+ yield if block_given?
27
+ rescue StandardError => e
28
+ reject e
29
+ end
30
+ end
31
+
32
+ def resolve(value)
33
+ @mutex.synchronize do
34
+ return unless @state == State::PENDING
35
+
36
+ @state = State::FULFILLED
37
+ @result = value
38
+ @condition_variable.broadcast
39
+ end
40
+ end
41
+
42
+ def reject(reason)
43
+ @mutex.synchronize do
44
+ return unless @state == State::PENDING
45
+
46
+ @state = State::REJECTED
47
+ @error = reason
48
+ @condition_variable.broadcast
49
+ end
50
+ end
51
+
52
+ def await
53
+ @mutex.synchronize do
54
+ @condition_variable.wait(@mutex) if @state == State::PENDING
55
+
56
+ raise @error if @state == State::REJECTED
57
+
58
+ @result
59
+ end
60
+ end
61
+ end
62
+
63
+ private_constant :Async
64
+ end
65
+ end
@@ -2,59 +2,58 @@
2
2
 
3
3
  module Sass
4
4
  class Embedded
5
- # The {Channel} for {Compiler} calls. Each instance creates its own
6
- # {Compiler}. A new {Compiler} is automatically created when the existing
7
- # {Compiler} runs out of unique request id.
5
+ # The {Channel} class.
6
+ #
7
+ # It establishes connection between {Host} and {Dispatcher}.
8
8
  class Channel
9
9
  def initialize
10
10
  @mutex = Mutex.new
11
- @compiler = Compiler.new
11
+ @dispatcher = Dispatcher.new
12
12
  end
13
13
 
14
14
  def close
15
15
  @mutex.synchronize do
16
- @compiler.close
16
+ @dispatcher.close
17
17
  end
18
18
  end
19
19
 
20
20
  def closed?
21
21
  @mutex.synchronize do
22
- @compiler.closed?
22
+ @dispatcher.closed?
23
23
  end
24
24
  end
25
25
 
26
- def subscribe(observer)
26
+ def connect(observer)
27
27
  @mutex.synchronize do
28
28
  begin
29
- id = @compiler.add_observer(observer)
30
- rescue ProtocolError
31
- @compiler = Compiler.new
32
- id = @compiler.add_observer(observer)
29
+ id = @dispatcher.subscribe(observer)
30
+ rescue EOFError
31
+ @dispatcher = Dispatcher.new
32
+ id = @dispatcher.subscribe(observer)
33
33
  end
34
- Subscription.new @compiler, observer, id
34
+ Connection.new(@dispatcher, id)
35
35
  end
36
36
  end
37
37
 
38
- # The {Subscription} between {Compiler} and {Observer}.
39
- class Subscription
38
+ # The {Connection} between {Host} to {Dispatcher}.
39
+ class Connection
40
40
  attr_reader :id
41
41
 
42
- def initialize(compiler, observer, id)
43
- @compiler = compiler
44
- @observer = observer
42
+ def initialize(dispatcher, id)
43
+ @dispatcher = dispatcher
45
44
  @id = id
46
45
  end
47
46
 
48
- def unsubscribe
49
- @compiler.delete_observer(@observer)
47
+ def disconnect
48
+ @dispatcher.unsubscribe(id)
50
49
  end
51
50
 
52
- def send_message(*args)
53
- @compiler.send_message(*args)
51
+ def send_message(message)
52
+ @dispatcher.send_message(message)
54
53
  end
55
54
  end
56
55
 
57
- private_constant :Subscription
56
+ private_constant :Connection
58
57
  end
59
58
 
60
59
  private_constant :Channel
@@ -1,65 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'observer'
4
3
  require 'open3'
5
4
 
6
5
  module Sass
7
6
  class Embedded
8
- # The {::Observable} {Compiler} for low level communication with
9
- # `dart-sass-embedded` using protocol buffers via stdio. Received messages
10
- # can be observed by an {Observer}.
7
+ # The {Compiler} class.
8
+ #
9
+ # It runs the `dart-sass-embedded` process.
11
10
  class Compiler
12
- include Observable
13
-
14
11
  PATH = File.absolute_path(
15
12
  "../../../ext/sass/sass_embedded/dart-sass-embedded#{Gem.win_platform? ? '.bat' : ''}", __dir__
16
13
  )
17
14
 
18
- PROTOCOL_ERROR_ID = 4_294_967_295
19
-
20
15
  def initialize
21
- @observerable_mutex = Mutex.new
22
- @id = 0
23
16
  @stdin_mutex = Mutex.new
17
+ @stdout_mutex = Mutex.new
24
18
  @stdin, @stdout, @stderr, @wait_thread = Open3.popen3(PATH)
25
19
 
26
20
  [@stdin, @stdout].each(&:binmode)
27
21
 
28
- poll do
29
- warn(@stderr.readline, uplevel: 1)
30
- end
31
- poll do
32
- receive_message Protofier.from_proto_message read
33
- end
34
- end
35
-
36
- def add_observer(*)
37
- @observerable_mutex.synchronize do
38
- raise ProtocolError, 'half-closed compiler' if half_closed?
39
-
40
- super
41
-
42
- id = @id
43
- @id = @id.next
44
- id
45
- end
46
- end
47
-
48
- def delete_observer(*)
49
- @observerable_mutex.synchronize do
50
- super
51
-
52
- close if half_closed? && count_observers.zero?
22
+ Thread.new do
23
+ loop do
24
+ warn(@stderr.readline, uplevel: 1)
25
+ rescue IOError
26
+ break
27
+ end
53
28
  end
54
29
  end
55
30
 
56
- def send_message(message)
57
- write Protofier.to_proto_message message
58
- end
59
-
60
31
  def close
61
- delete_observers
62
-
63
32
  @stdin_mutex.synchronize do
64
33
  @stdin.close unless @stdin.closed?
65
34
  @stdout.close unless @stdout.closed?
@@ -75,54 +44,19 @@ module Sass
75
44
  end
76
45
  end
77
46
 
78
- private
79
-
80
- def half_closed?
81
- @id == PROTOCOL_ERROR_ID
82
- end
83
-
84
- def poll
85
- Thread.new do
86
- loop do
87
- yield
88
- rescue StandardError
89
- break
90
- end
91
- end
92
- end
93
-
94
- def notify_observers(*args)
95
- @observerable_mutex.synchronize do
96
- changed
97
- super(*args)
98
- end
99
- end
100
-
101
- def receive_message(message)
102
- case message
103
- when EmbeddedProtocol::ProtocolError
104
- notify_observers(ProtocolError.new(message.message), nil)
105
- close
106
- else
107
- notify_observers(nil, message)
108
- end
109
- end
110
-
111
- def read
112
- length = Varint.read(@stdout)
113
- @stdout.read(length)
114
- rescue IOError => e
115
- notify_observers(e, nil)
116
- close
117
- raise e
118
- end
119
-
120
47
  def write(payload)
121
48
  @stdin_mutex.synchronize do
122
49
  Varint.write(@stdin, payload.length)
123
50
  @stdin.write(payload)
124
51
  end
125
52
  end
53
+
54
+ def read
55
+ @stdout_mutex.synchronize do
56
+ length = Varint.read(@stdout)
57
+ @stdout.read(length)
58
+ end
59
+ end
126
60
  end
127
61
 
128
62
  private_constant :Compiler
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ class Embedded
5
+ # The {Dispatcher} class.
6
+ #
7
+ # It dispatches messages between mutliple instances of {Host} and a single {Compiler}.
8
+ class Dispatcher
9
+ PROTOCOL_ERROR_ID = 4_294_967_295
10
+
11
+ def initialize
12
+ @compiler = Compiler.new
13
+ @observers = {}
14
+ @id = 0
15
+ @mutex = Mutex.new
16
+
17
+ Thread.new do
18
+ loop do
19
+ receive_message EmbeddedProtocol::OutboundMessage.decode @compiler.read
20
+ rescue IOError => e
21
+ half_close
22
+ @observers.each_value do |observer|
23
+ observer.error e
24
+ end
25
+ break
26
+ end
27
+ end
28
+ end
29
+
30
+ def subscribe(observer)
31
+ @mutex.synchronize do
32
+ raise EOFError if half_closed?
33
+
34
+ id = @id
35
+ @id = id.next
36
+ @observers.store(id, observer)
37
+ id
38
+ end
39
+ end
40
+
41
+ def unsubscribe(id)
42
+ @observers.delete(id)
43
+
44
+ close if half_closed? && @observers.empty?
45
+ end
46
+
47
+ def close
48
+ @compiler.close
49
+ end
50
+
51
+ def closed?
52
+ @compiler.closed?
53
+ end
54
+
55
+ def send_message(inbound_message)
56
+ @compiler.write(inbound_message.to_proto)
57
+ end
58
+
59
+ private
60
+
61
+ def half_close
62
+ @mutex.synchronize do
63
+ @id = PROTOCOL_ERROR_ID
64
+ end
65
+ end
66
+
67
+ def half_closed?
68
+ @id == PROTOCOL_ERROR_ID
69
+ end
70
+
71
+ def receive_message(outbound_message)
72
+ message = outbound_message.send(outbound_message.message)
73
+
74
+ case outbound_message.message
75
+ when :error
76
+ half_close
77
+ @observers[message.id]&.send(outbound_message.message, message)
78
+ when :compile_response, :version_response
79
+ @observers[message.id]&.send(outbound_message.message, message)
80
+ when :log_event, :canonicalize_request, :import_request, :file_import_request, :function_call_request
81
+ @observers[message.compilation_id]&.send(outbound_message.message, message)
82
+ else
83
+ raise ArgumentError, "Unknown OutboundMessage.message #{message}"
84
+ end
85
+ end
86
+ end
87
+
88
+ private_constant :Dispatcher
89
+ end
90
+ end
@@ -2,12 +2,14 @@
2
2
 
3
3
  module Sass
4
4
  class Embedded
5
- class CompileContext
6
- # The {FunctionRegistry} for {CompileContext}.
5
+ class Host
6
+ # The {FunctionRegistry} class.
7
+ #
8
+ # It stores sass custom functions and handles function calls.
7
9
  class FunctionRegistry
8
10
  attr_reader :global_functions
9
11
 
10
- def initialize(functions, highlight:)
12
+ def initialize(functions, alert_color:)
11
13
  functions = functions.transform_keys(&:to_s)
12
14
 
13
15
  @global_functions = functions.keys
@@ -25,7 +27,7 @@ module Sass
25
27
  @functions_by_id = {}
26
28
  @ids_by_function = {}
27
29
 
28
- @highlight = highlight
30
+ @highlight = alert_color
29
31
  end
30
32
 
31
33
  def register(function)
@@ -2,12 +2,14 @@
2
2
 
3
3
  module Sass
4
4
  class Embedded
5
- class CompileContext
6
- # The {ImporterRegistry} for {CompileContext}.
5
+ class Host
6
+ # The {ImporterRegistry} class.
7
+ #
8
+ # It stores importers and handles import requests.
7
9
  class ImporterRegistry
8
10
  attr_reader :importers
9
11
 
10
- def initialize(importers, load_paths, highlight:)
12
+ def initialize(importers, load_paths, alert_color:)
11
13
  @id = 0
12
14
  @importers_by_id = {}
13
15
  @importers = importers
@@ -20,7 +22,7 @@ module Sass
20
22
  end
21
23
  )
22
24
 
23
- @highlight = highlight
25
+ @highlight = alert_color
24
26
  end
25
27
 
26
28
  def register(importer)
@@ -2,8 +2,10 @@
2
2
 
3
3
  module Sass
4
4
  class Embedded
5
- class CompileContext
6
- # The {LoggerRegistry} for {CompileContext}.
5
+ class Host
6
+ # The {LoggerRegistry} class.
7
+ #
8
+ # It stores logger and handles log events.
7
9
  class LoggerRegistry
8
10
  attr_reader :logger
9
11
 
@@ -2,8 +2,10 @@
2
2
 
3
3
  module Sass
4
4
  class Embedded
5
- class CompileContext
6
- # The {ValueProtofier} between Pure Ruby types and Protobuf Ruby types.
5
+ class Host
6
+ # The {ValueProtofier} class.
7
+ #
8
+ # It converts Pure Ruby types and Protobuf Ruby types.
7
9
  class ValueProtofier
8
10
  def initialize(function_registry)
9
11
  @function_registry = function_registry
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ class Embedded
5
+ # The {Host} class.
6
+ #
7
+ # It communicates with {Dispatcher} and handles the host logic.
8
+ class Host
9
+ def initialize(channel)
10
+ @channel = channel
11
+ @mutex = Mutex.new
12
+ end
13
+
14
+ def id
15
+ @connection.id
16
+ end
17
+
18
+ def send_message(message)
19
+ @connection.send_message(message)
20
+ end
21
+
22
+ def compile_request(path:,
23
+ source:,
24
+ importer:,
25
+ load_paths:,
26
+ syntax:,
27
+ url:,
28
+ source_map:,
29
+ source_map_include_sources:,
30
+ style:,
31
+ functions:,
32
+ importers:,
33
+ alert_ascii:,
34
+ alert_color:,
35
+ logger:,
36
+ quiet_deps:,
37
+ verbose:)
38
+ async do
39
+ @function_registry = FunctionRegistry.new(functions, alert_color: alert_color)
40
+ @importer_registry = ImporterRegistry.new(importers, load_paths, alert_color: alert_color)
41
+ @logger_registry = LoggerRegistry.new(logger)
42
+
43
+ send_message EmbeddedProtocol::InboundMessage.new(
44
+ compile_request: EmbeddedProtocol::InboundMessage::CompileRequest.new(
45
+ id: id,
46
+ string: unless source.nil?
47
+ EmbeddedProtocol::InboundMessage::CompileRequest::StringInput.new(
48
+ source: source,
49
+ url: url&.to_s,
50
+ syntax: Protofier.to_proto_syntax(syntax),
51
+ importer: importer.nil? ? nil : @importer_registry.register(importer)
52
+ )
53
+ end,
54
+ path: path,
55
+ style: Protofier.to_proto_output_style(style),
56
+ source_map: source_map,
57
+ source_map_include_sources: source_map_include_sources,
58
+ importers: @importer_registry.importers,
59
+ global_functions: @function_registry.global_functions,
60
+ alert_ascii: alert_ascii,
61
+ alert_color: alert_color,
62
+ quiet_deps: quiet_deps,
63
+ verbose: verbose
64
+ )
65
+ )
66
+ end
67
+ end
68
+
69
+ def version_request
70
+ async do
71
+ send_message EmbeddedProtocol::InboundMessage.new(
72
+ version_request: EmbeddedProtocol::InboundMessage::VersionRequest.new(
73
+ id: id
74
+ )
75
+ )
76
+ end
77
+ end
78
+
79
+ def log_event(message)
80
+ @logger_registry.log(message)
81
+ end
82
+
83
+ def compile_response(message)
84
+ @async.resolve(message)
85
+ end
86
+
87
+ def version_response(message)
88
+ @async.resolve(message)
89
+ end
90
+
91
+ def canonicalize_request(message)
92
+ send_message EmbeddedProtocol::InboundMessage.new(
93
+ canonicalize_response: @importer_registry.canonicalize(message)
94
+ )
95
+ end
96
+
97
+ def import_request(message)
98
+ send_message EmbeddedProtocol::InboundMessage.new(
99
+ import_response: @importer_registry.import(message)
100
+ )
101
+ end
102
+
103
+ def file_import_request(message)
104
+ send_message EmbeddedProtocol::InboundMessage.new(
105
+ file_import_response: @importer_registry.file_import(message)
106
+ )
107
+ end
108
+
109
+ def function_call_request(message)
110
+ send_message EmbeddedProtocol::InboundMessage.new(
111
+ function_call_response: @function_registry.function_call(message)
112
+ )
113
+ end
114
+
115
+ def error(message)
116
+ @async.reject(CompileError.new(message.message, nil, nil, nil))
117
+ end
118
+
119
+ private
120
+
121
+ def async
122
+ @mutex.synchronize do
123
+ @connection = @channel.connect(self)
124
+ @async = Async.new
125
+ yield
126
+ @async.await
127
+ ensure
128
+ @connection.disconnect
129
+ end
130
+ end
131
+ end
132
+
133
+ private_constant :Host
134
+ end
135
+ end
@@ -40,7 +40,6 @@ module Sass
40
40
  # @example
41
41
  # Sass.render(file: 'style.css')
42
42
  # @return [Result]
43
- # @raise [ProtocolError]
44
43
  # @raise [RenderError]
45
44
  def render(**kwargs)
46
45
  instance.render(**kwargs)
@@ -71,7 +70,6 @@ module Sass
71
70
  # See {file:README.md#options} for supported options.
72
71
  #
73
72
  # @return [RenderResult]
74
- # @raise [ProtocolError]
75
73
  # @raise [RenderError]
76
74
  def render(data: nil,
77
75
  file: nil,
@@ -2,17 +2,10 @@
2
2
 
3
3
  module Sass
4
4
  class Embedded
5
- # The {Protofier} between Pure Ruby types and Protobuf Ruby types.
5
+ # The {Protofier} module.
6
+ #
7
+ # It converts Pure Ruby types and Protobuf Ruby types.
6
8
  module 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
9
  module_function
17
10
 
18
11
  def from_proto_compile_response(compile_response)
@@ -50,17 +43,6 @@ module Sass
50
43
  source_location.column)
51
44
  end
52
45
 
53
- def from_proto_message(proto)
54
- message = EmbeddedProtocol::OutboundMessage.decode(proto)
55
- message.send(message.message)
56
- end
57
-
58
- def to_proto_message(message)
59
- EmbeddedProtocol::InboundMessage.new(
60
- ONEOF_MESSAGE[message.class.descriptor] => message
61
- ).to_proto
62
- end
63
-
64
46
  def to_proto_syntax(syntax)
65
47
  case syntax&.to_sym
66
48
  when :scss
@@ -2,7 +2,9 @@
2
2
 
3
3
  module Sass
4
4
  class Embedded
5
- # The {Structifier} that convert {::Hash} to {Struct}-like object.
5
+ # The {Structifier} module.
6
+ #
7
+ # It converts {::Hash} to {Struct}-like objects.
6
8
  module Structifier
7
9
  module_function
8
10
 
@@ -2,7 +2,9 @@
2
2
 
3
3
  module Sass
4
4
  class Embedded
5
- # Read and write {Varint} from {::IO}.
5
+ # The {Varint} module.
6
+ #
7
+ # It reads and writes varints.
6
8
  module Varint
7
9
  module_function
8
10
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Sass
4
4
  class Embedded
5
- VERSION = '0.18.4'
5
+ VERSION = '0.19.0'
6
6
  end
7
7
  end
data/lib/sass/embedded.rb CHANGED
@@ -18,7 +18,6 @@ module Sass
18
18
  #
19
19
  # @return [CompileResult]
20
20
  # @raise [CompileError]
21
- # @raise [ProtocolError]
22
21
  def compile(path,
23
22
  load_paths: [],
24
23
 
@@ -38,23 +37,24 @@ module Sass
38
37
  raise ArgumentError, 'path must be set' if path.nil?
39
38
 
40
39
  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
40
+ Host.new(@channel).compile_request(
41
+ path: path,
42
+ source: nil,
43
+ importer: nil,
44
+ load_paths: load_paths,
45
+ syntax: nil,
46
+ url: nil,
47
+ source_map: source_map,
48
+ source_map_include_sources: source_map_include_sources,
49
+ style: style,
50
+ functions: functions,
51
+ importers: importers,
52
+ alert_color: alert_color,
53
+ alert_ascii: alert_ascii,
54
+ logger: logger,
55
+ quiet_deps: quiet_deps,
56
+ verbose: verbose
57
+ )
58
58
  )
59
59
  end
60
60
 
@@ -62,7 +62,6 @@ module Sass
62
62
  #
63
63
  # @return [CompileResult]
64
64
  # @raise [CompileError]
65
- # @raise [ProtocolError]
66
65
  def compile_string(source,
67
66
  importer: nil,
68
67
  load_paths: [],
@@ -84,31 +83,30 @@ module Sass
84
83
  raise ArgumentError, 'source must be set' if source.nil?
85
84
 
86
85
  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
86
+ Host.new(@channel).compile_request(
87
+ path: nil,
88
+ source: source,
89
+ importer: importer,
90
+ load_paths: load_paths,
91
+ syntax: syntax,
92
+ url: url,
93
+ source_map: source_map,
94
+ source_map_include_sources: source_map_include_sources,
95
+ style: style,
96
+ functions: functions,
97
+ importers: importers,
98
+ alert_color: alert_color,
99
+ alert_ascii: alert_ascii,
100
+ logger: logger,
101
+ quiet_deps: quiet_deps,
102
+ verbose: verbose
103
+ )
104
104
  )
105
105
  end
106
106
 
107
107
  # The {Embedded#info} method.
108
- #
109
- # @raise [ProtocolError]
110
108
  def info
111
- @info ||= "sass-embedded\t#{VersionContext.new(@channel).receive_message.implementation_version}"
109
+ @info ||= "sass-embedded\t#{Host.new(@channel).version_request.implementation_version}"
112
110
  end
113
111
 
114
112
  def close
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sass
4
- class Value
4
+ module Value
5
5
  # Sass's argument list type.
6
6
  #
7
7
  # An argument list comes from a rest argument. It's distinct from a normal {List} in that it may contain a keyword
8
8
  # map as well as the positional arguments.
9
- class ArgumentList < Sass::Value::List
9
+ class ArgumentList < Value::List
10
10
  def initialize(contents = [], keywords = {}, separator = ',')
11
11
  super(contents, separator: separator)
12
12
 
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sass
4
- class Value
4
+ module Value
5
5
  # Sass's boolean type.
6
- class Boolean < Sass::Value
7
- def initialize(value) # rubocop:disable Lint/MissingSuper
6
+ class Boolean
7
+ include Value
8
+
9
+ def initialize(value)
8
10
  @value = value
9
11
  end
10
12
 
@@ -1,14 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sass
4
- class Value
4
+ module Value
5
5
  # Sass's color type.
6
6
  #
7
7
  # No matter what representation was originally used to create this color, all of its channels are accessible.
8
- class Color < Sass::Value
9
- def initialize(red: nil, green: nil, blue: nil, # rubocop:disable Lint/MissingSuper
10
- hue: nil, saturation: nil, lightness: nil,
11
- whiteness: nil, blackness: nil,
8
+ class Color
9
+ include Value
10
+
11
+ def initialize(red: nil,
12
+ green: nil,
13
+ blue: nil,
14
+ hue: nil,
15
+ saturation: nil,
16
+ lightness: nil,
17
+ whiteness: nil,
18
+ blackness: nil,
12
19
  alpha: nil)
13
20
  @alpha = alpha.nil? ? 1 : FuzzyMath.assert_between(alpha, 0, 1, 'alpha')
14
21
  if red && green && blue
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sass
4
- class Value
4
+ module Value
5
5
  # Sass's function type.
6
- class Function < Sass::Value
7
- def initialize(id_or_signature, callback = nil) # rubocop:disable Lint/MissingSuper
6
+ class Function
7
+ include Value
8
+
9
+ def initialize(id_or_signature, callback = nil)
8
10
  if id_or_signature.is_a? Numeric
9
11
  @id = id_or_signature
10
12
  else
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sass
4
- class Value
4
+ module Value
5
5
  # Sass's {FuzzyMath} module.
6
6
  module FuzzyMath
7
7
  PRECISION = 10
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sass
4
- class Value
4
+ module Value
5
5
  # Sass's list type.
6
- class List < Sass::Value
7
- def initialize(contents = [], separator: ',', bracketed: false) # rubocop:disable Lint/MissingSuper
6
+ class List
7
+ include Value
8
+
9
+ def initialize(contents = [], separator: ',', bracketed: false)
8
10
  if separator.nil? && contents.length > 1
9
11
  raise error 'A list with more than one element must have an explicit separator'
10
12
  end
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sass
4
- class Value
4
+ module Value
5
5
  # Sass's map type.
6
- class Map < Sass::Value
7
- def initialize(contents = {}) # rubocop:disable Lint/MissingSuper
6
+ class Map
7
+ include Value
8
+
9
+ def initialize(contents = {})
8
10
  @contents = contents.freeze
9
11
  end
10
12
 
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sass
4
- class Value
4
+ module Value
5
5
  # Sass's null type.
6
- class Null < Sass::Value
7
- def initialize # rubocop:disable Lint/MissingSuper
6
+ class Null
7
+ include Value
8
+
9
+ def initialize
8
10
  @value = nil
9
11
  end
10
12
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sass
4
- class Value
4
+ module Value
5
5
  class Number
6
6
  # The {Unit} module.
7
7
  module Unit
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sass
4
- class Value
4
+ module Value
5
5
  # Sass's number type.
6
- class Number < Sass::Value
7
- def initialize(value, numerator_units = [], denominator_units = []) # rubocop:disable Lint/MissingSuper
6
+ class Number
7
+ include Value
8
+
9
+ def initialize(value, numerator_units = [], denominator_units = [])
8
10
  numerator_units = [numerator_units] if numerator_units.is_a?(::String)
9
11
  denominator_units = [denominator_units] if denominator_units.is_a?(::String)
10
12
 
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sass
4
- class Value
4
+ module Value
5
5
  # Sass's string type.
6
- class String < Sass::Value
7
- def initialize(text = '', quoted: true) # rubocop:disable Lint/MissingSuper
6
+ class String
7
+ include Value
8
+
9
+ def initialize(text = '', quoted: true)
8
10
  @text = text.freeze
9
11
  @quoted = quoted
10
12
  end
data/lib/sass/value.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Sass
4
4
  # The abstract base class of Sass's value types.
5
- class Value
5
+ module Value
6
6
  def to_a
7
7
  [self]
8
8
  end
data/lib/sass.rb CHANGED
@@ -3,22 +3,21 @@
3
3
  require_relative 'sass/compile_error'
4
4
  require_relative 'sass/compile_result'
5
5
  require_relative 'sass/embedded'
6
+ require_relative 'sass/embedded/async'
6
7
  require_relative 'sass/embedded/channel'
7
- require_relative 'sass/embedded/observer'
8
- require_relative 'sass/embedded/compile_context'
9
- require_relative 'sass/embedded/compile_context/function_registry'
10
- require_relative 'sass/embedded/compile_context/importer_registry'
11
- require_relative 'sass/embedded/compile_context/logger_registry'
12
- require_relative 'sass/embedded/compile_context/value_protofier'
13
8
  require_relative 'sass/embedded/compiler'
14
- require_relative 'sass/embedded_protocol'
9
+ require_relative 'sass/embedded/dispatcher'
10
+ require_relative 'sass/embedded/host'
11
+ require_relative 'sass/embedded/host/function_registry'
12
+ require_relative 'sass/embedded/host/importer_registry'
13
+ require_relative 'sass/embedded/host/logger_registry'
14
+ require_relative 'sass/embedded/host/value_protofier'
15
15
  require_relative 'sass/embedded/legacy'
16
- require_relative 'sass/embedded/protocol_error'
17
16
  require_relative 'sass/embedded/protofier'
18
17
  require_relative 'sass/embedded/structifier'
19
18
  require_relative 'sass/embedded/varint'
20
19
  require_relative 'sass/embedded/version'
21
- require_relative 'sass/embedded/version_context'
20
+ require_relative 'sass/embedded_protocol'
22
21
  require_relative 'sass/logger'
23
22
  require_relative 'sass/logger/source_location'
24
23
  require_relative 'sass/logger/source_span'
@@ -51,7 +50,6 @@ module Sass
51
50
  # Sass.compile('style.scss')
52
51
  # @return [CompileResult]
53
52
  # @raise [CompileError]
54
- # @raise [Embedded::ProtocolError]
55
53
  def compile(path, **kwargs)
56
54
  instance.compile(path, **kwargs)
57
55
  end
@@ -66,7 +64,6 @@ module Sass
66
64
  # Sass.compile_string('h1 { font-size: 40px; }')
67
65
  # @return [CompileResult]
68
66
  # @raise [CompileError]
69
- # @raise [Embedded::ProtocolError]
70
67
  def compile_string(source, **kwargs)
71
68
  instance.compile_string(source, **kwargs)
72
69
  end
@@ -74,8 +71,6 @@ module Sass
74
71
  # The global {.info} method.
75
72
  #
76
73
  # This instantiates a global {Embedded} instance and calls {Embedded#info}.
77
- #
78
- # @raise [Embedded::ProtocolError]
79
74
  def info
80
75
  instance.info
81
76
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sass-embedded
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.4
4
+ version: 0.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - なつき
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-21 00:00:00.000000000 Z
11
+ date: 2022-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-protobuf
@@ -128,21 +128,20 @@ files:
128
128
  - lib/sass/compile_error.rb
129
129
  - lib/sass/compile_result.rb
130
130
  - lib/sass/embedded.rb
131
+ - lib/sass/embedded/async.rb
131
132
  - lib/sass/embedded/channel.rb
132
- - lib/sass/embedded/compile_context.rb
133
- - lib/sass/embedded/compile_context/function_registry.rb
134
- - lib/sass/embedded/compile_context/importer_registry.rb
135
- - lib/sass/embedded/compile_context/logger_registry.rb
136
- - lib/sass/embedded/compile_context/value_protofier.rb
137
133
  - lib/sass/embedded/compiler.rb
134
+ - lib/sass/embedded/dispatcher.rb
135
+ - lib/sass/embedded/host.rb
136
+ - lib/sass/embedded/host/function_registry.rb
137
+ - lib/sass/embedded/host/importer_registry.rb
138
+ - lib/sass/embedded/host/logger_registry.rb
139
+ - lib/sass/embedded/host/value_protofier.rb
138
140
  - lib/sass/embedded/legacy.rb
139
- - lib/sass/embedded/observer.rb
140
- - lib/sass/embedded/protocol_error.rb
141
141
  - lib/sass/embedded/protofier.rb
142
142
  - lib/sass/embedded/structifier.rb
143
143
  - lib/sass/embedded/varint.rb
144
144
  - lib/sass/embedded/version.rb
145
- - lib/sass/embedded/version_context.rb
146
145
  - lib/sass/embedded_protocol.rb
147
146
  - lib/sass/logger.rb
148
147
  - lib/sass/logger/source_location.rb
@@ -164,8 +163,8 @@ homepage: https://github.com/ntkme/sass-embedded-host-ruby
164
163
  licenses:
165
164
  - MIT
166
165
  metadata:
167
- documentation_uri: https://www.rubydoc.info/gems/sass-embedded/0.18.4
168
- source_code_uri: https://github.com/ntkme/sass-embedded-host-ruby/tree/v0.18.4
166
+ documentation_uri: https://www.rubydoc.info/gems/sass-embedded/0.19.0
167
+ source_code_uri: https://github.com/ntkme/sass-embedded-host-ruby/tree/v0.19.0
169
168
  funding_uri: https://github.com/sponsors/ntkme
170
169
  post_install_message:
171
170
  rdoc_options: []
@@ -1,107 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sass
4
- class Embedded
5
- # The {Observer} for {Embedded#compile}.
6
- class CompileContext
7
- include Observer
8
-
9
- def initialize(channel,
10
- path:,
11
- source:,
12
-
13
- importer:,
14
- load_paths:,
15
- syntax:,
16
- url:,
17
-
18
- source_map:,
19
- source_map_include_sources:,
20
- style:,
21
-
22
- functions:,
23
- importers:,
24
-
25
- alert_ascii:,
26
- alert_color:,
27
- logger:,
28
- quiet_deps:,
29
- verbose:)
30
- @function_registery = FunctionRegistry.new(functions, highlight: alert_color)
31
- @importer_registery = ImporterRegistry.new(importers, load_paths, highlight: alert_color)
32
- @logger_registery = LoggerRegistry.new(logger)
33
-
34
- super(channel)
35
-
36
- send_message EmbeddedProtocol::InboundMessage::CompileRequest.new(
37
- id: id,
38
- string: unless source.nil?
39
- EmbeddedProtocol::InboundMessage::CompileRequest::StringInput.new(
40
- source: source,
41
- url: url&.to_s,
42
- syntax: Protofier.to_proto_syntax(syntax),
43
- importer: importer.nil? ? nil : @importer_registery.register(importer)
44
- )
45
- end,
46
- path: path,
47
- style: Protofier.to_proto_output_style(style),
48
- source_map: source_map,
49
- source_map_include_sources: source_map_include_sources,
50
- importers: @importer_registery.importers,
51
- global_functions: @function_registery.global_functions,
52
- alert_ascii: alert_ascii,
53
- alert_color: alert_color,
54
- quiet_deps: quiet_deps,
55
- verbose: verbose
56
- )
57
- end
58
-
59
- def update(error, message)
60
- raise error unless error.nil?
61
-
62
- case message
63
- when EmbeddedProtocol::OutboundMessage::CompileResponse
64
- return unless message.id == id
65
-
66
- Thread.new do
67
- super(nil, message)
68
- end
69
- when EmbeddedProtocol::OutboundMessage::LogEvent
70
- return unless message.compilation_id == id
71
-
72
- @logger_registery.log message
73
- when EmbeddedProtocol::OutboundMessage::CanonicalizeRequest
74
- return unless message.compilation_id == id
75
-
76
- Thread.new do
77
- send_message @importer_registery.canonicalize message
78
- end
79
- when EmbeddedProtocol::OutboundMessage::ImportRequest
80
- return unless message.compilation_id == id
81
-
82
- Thread.new do
83
- send_message @importer_registery.import message
84
- end
85
- when EmbeddedProtocol::OutboundMessage::FileImportRequest
86
- return unless message.compilation_id == id
87
-
88
- Thread.new do
89
- send_message @importer_registery.file_import message
90
- end
91
- when EmbeddedProtocol::OutboundMessage::FunctionCallRequest
92
- return unless message.compilation_id == id
93
-
94
- Thread.new do
95
- send_message @function_registery.function_call message
96
- end
97
- end
98
- rescue StandardError => e
99
- Thread.new do
100
- super(e, nil)
101
- end
102
- end
103
- end
104
-
105
- private_constant :CompileContext
106
- end
107
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sass
4
- class Embedded
5
- # The {Observer} module for communicating with {Compiler}.
6
- module Observer
7
- def initialize(channel)
8
- @mutex = Mutex.new
9
- @condition_variable = ConditionVariable.new
10
- @error = nil
11
- @message = nil
12
-
13
- @subscription = channel.subscribe(self)
14
- end
15
-
16
- def receive_message
17
- @mutex.synchronize do
18
- @condition_variable.wait(@mutex) if @error.nil? && @message.nil?
19
- end
20
-
21
- raise @error unless @error.nil?
22
-
23
- @message
24
- end
25
-
26
- def update(error, message)
27
- @subscription.unsubscribe
28
-
29
- @mutex.synchronize do
30
- @error = error
31
- @message = message
32
- @condition_variable.broadcast
33
- end
34
- end
35
-
36
- private
37
-
38
- def id
39
- @subscription.id
40
- end
41
-
42
- def send_message(*args)
43
- @subscription.send_message(*args)
44
- end
45
- end
46
-
47
- private_constant :Observer
48
- end
49
- end
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sass
4
- class Embedded
5
- class ProtocolError < StandardError; end
6
- end
7
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sass
4
- class Embedded
5
- # The {Observer} for {Embedded#info}.
6
- class VersionContext
7
- include Observer
8
-
9
- def initialize(channel)
10
- super(channel)
11
-
12
- send_message EmbeddedProtocol::InboundMessage::VersionRequest.new(id: id)
13
- end
14
-
15
- def update(error, message)
16
- raise error unless error.nil?
17
-
18
- case message
19
- when EmbeddedProtocol::OutboundMessage::VersionResponse
20
- return unless message.id == id
21
-
22
- Thread.new do
23
- super(nil, message)
24
- end
25
- end
26
- rescue StandardError => e
27
- Thread.new do
28
- super(e, nil)
29
- end
30
- end
31
- end
32
-
33
- private_constant :VersionContext
34
- end
35
- end