sass-embedded 0.8.1 → 0.8.2

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.
data/lib/sass/compile.rb DELETED
@@ -1,249 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sass
4
- # The {Observer} for {Embedded#render}.
5
- class CompileContext
6
- include Observer
7
-
8
- def initialize(transport, id,
9
- data:,
10
- file:,
11
- indented_syntax:,
12
- include_paths:,
13
- output_style:,
14
- source_map:,
15
- out_file:,
16
- functions:,
17
- importer:)
18
- raise ArgumentError, 'either data or file must be set' if file.nil? && data.nil?
19
-
20
- @id = id
21
- @data = data
22
- @file = file
23
- @indented_syntax = indented_syntax
24
- @include_paths = include_paths
25
- @output_style = output_style
26
- @source_map = source_map
27
- @out_file = out_file
28
- @global_functions = functions.keys
29
- @functions = functions.transform_keys do |key|
30
- key.to_s.split('(')[0].chomp
31
- end
32
- @importer = importer
33
- @import_responses = {}
34
-
35
- super(transport)
36
-
37
- send_message compile_request
38
- end
39
-
40
- def update(error, message)
41
- raise error unless error.nil?
42
-
43
- case message
44
- when EmbeddedProtocol::OutboundMessage::CompileResponse
45
- return unless message.id == @id
46
-
47
- Thread.new do
48
- super(nil, message)
49
- end
50
- when EmbeddedProtocol::OutboundMessage::LogEvent
51
- return unless message.compilation_id == @id && $stderr.tty?
52
-
53
- warn message.formatted
54
- when EmbeddedProtocol::OutboundMessage::CanonicalizeRequest
55
- return unless message.compilation_id == @id
56
-
57
- Thread.new do
58
- send_message canonicalize_response message
59
- end
60
- when EmbeddedProtocol::OutboundMessage::ImportRequest
61
- return unless message.compilation_id == @id
62
-
63
- Thread.new do
64
- send_message import_response message
65
- end
66
- when EmbeddedProtocol::OutboundMessage::FileImportRequest
67
- raise NotImplementedError, 'FileImportRequest is not implemented'
68
- when EmbeddedProtocol::OutboundMessage::FunctionCallRequest
69
- return unless message.compilation_id == @id
70
-
71
- Thread.new do
72
- send_message function_call_response message
73
- end
74
- end
75
- rescue StandardError => e
76
- Thread.new do
77
- super(e, nil)
78
- end
79
- end
80
-
81
- private
82
-
83
- def compile_request
84
- EmbeddedProtocol::InboundMessage::CompileRequest.new(
85
- id: @id,
86
- string: string,
87
- path: path,
88
- style: style,
89
- source_map: source_map,
90
- importers: importers,
91
- global_functions: global_functions,
92
- alert_color: $stderr.tty?,
93
- alert_ascii: Platform::OS == 'windows'
94
- )
95
- end
96
-
97
- def canonicalize_response(canonicalize_request)
98
- url = Util.file_uri_from_path(File.absolute_path(canonicalize_request.url, (@file.nil? ? 'stdin' : @file)))
99
-
100
- begin
101
- result = @importer[canonicalize_request.importer_id].call canonicalize_request.url, @file
102
- raise result if result.is_a? StandardError
103
- rescue StandardError => e
104
- return EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
105
- id: canonicalize_request.id,
106
- error: e.message
107
- )
108
- end
109
-
110
- if result&.key? :contents
111
- @import_responses[url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
112
- id: canonicalize_request.id,
113
- success: EmbeddedProtocol::InboundMessage::ImportResponse::ImportSuccess.new(
114
- contents: result[:contents],
115
- syntax: EmbeddedProtocol::Syntax::SCSS,
116
- source_map_url: nil
117
- )
118
- )
119
- EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
120
- id: canonicalize_request.id,
121
- url: url
122
- )
123
- elsif result&.key? :file
124
- canonicalized_url = Util.file_uri_from_path(File.absolute_path(result[:file]))
125
-
126
- # TODO: FileImportRequest is not supported yet.
127
- # Workaround by reading contents and return it when server asks
128
- @import_responses[canonicalized_url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
129
- id: canonicalize_request.id,
130
- success: EmbeddedProtocol::InboundMessage::ImportResponse::ImportSuccess.new(
131
- contents: File.read(result[:file]),
132
- syntax: EmbeddedProtocol::Syntax::SCSS,
133
- source_map_url: nil
134
- )
135
- )
136
-
137
- EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
138
- id: canonicalize_request.id,
139
- url: canonicalized_url
140
- )
141
- else
142
- EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
143
- id: canonicalize_request.id
144
- )
145
- end
146
- end
147
-
148
- def import_response(import_request)
149
- url = import_request.url
150
-
151
- if @import_responses.key? url
152
- @import_responses[url].id = import_request.id
153
- else
154
- @import_responses[url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
155
- id: import_request.id,
156
- error: "Failed to import: #{url}"
157
- )
158
- end
159
-
160
- @import_responses[url]
161
- end
162
-
163
- def function_call_response(function_call_request)
164
- # TODO: convert argument_list to **kwargs
165
- EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
166
- id: function_call_request.id,
167
- success: @functions[function_call_request.name].call(*function_call_request.arguments),
168
- accessed_argument_lists: function_call_request.arguments
169
- .filter { |argument| argument.value == :argument_list }
170
- .map { |argument| argument.argument_list.id }
171
- )
172
- rescue StandardError => e
173
- EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
174
- id: function_call_request.id,
175
- error: e.message
176
- )
177
- end
178
-
179
- def syntax
180
- if @indented_syntax == true
181
- EmbeddedProtocol::Syntax::INDENTED
182
- else
183
- EmbeddedProtocol::Syntax::SCSS
184
- end
185
- end
186
-
187
- def url
188
- return if @file.nil?
189
-
190
- Util.file_uri_from_path File.absolute_path @file
191
- end
192
-
193
- def string
194
- return if @data.nil?
195
-
196
- EmbeddedProtocol::InboundMessage::CompileRequest::StringInput.new(
197
- source: @data,
198
- url: url,
199
- syntax: syntax
200
- )
201
- end
202
-
203
- def path
204
- @file if @data.nil?
205
- end
206
-
207
- def style
208
- case @output_style&.to_sym
209
- when :expanded
210
- EmbeddedProtocol::OutputStyle::EXPANDED
211
- when :compressed
212
- EmbeddedProtocol::OutputStyle::COMPRESSED
213
- else
214
- raise ArgumentError, 'output_style must be one of :expanded, :compressed'
215
- end
216
- end
217
-
218
- def source_map
219
- @source_map.is_a?(String) || (@source_map == true && !@out_file.nil?)
220
- end
221
-
222
- attr_reader :global_functions
223
-
224
- # Order
225
- # 1. Loading a file relative to the file in which the @use or @import appeared.
226
- # 2. Each custom importer.
227
- # 3. Loading a file relative to the current working directory.
228
- # 4. Each load path in includePaths
229
- # 5. Each load path specified in the SASS_PATH environment variable, which should
230
- # be semicolon-separated on Windows and colon-separated elsewhere.
231
- def importers
232
- custom_importers = @importer.map.with_index do |_, id|
233
- EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
234
- importer_id: id
235
- )
236
- end
237
-
238
- include_path_importers = @include_paths
239
- .concat(Sass.include_paths)
240
- .map do |include_path|
241
- EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
242
- path: File.absolute_path(include_path)
243
- )
244
- end
245
-
246
- custom_importers.concat include_path_importers
247
- end
248
- end
249
- end
data/lib/sass/compiler.rb DELETED
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sass
4
- module Compiler
5
- DART_SASS_EMBEDDED = File.absolute_path(
6
- "../../ext/sass/sass_embedded/dart-sass-embedded#{Platform::OS == 'windows' ? '.bat' : ''}", __dir__
7
- )
8
-
9
- PROTOCOL_ERROR_ID = 4_294_967_295
10
-
11
- REQUIREMENTS = '~> 1.0.0-beta.11'
12
- end
13
- end
data/lib/sass/error.rb DELETED
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sass
4
- class Error < StandardError; end
5
-
6
- class ProtocolError < Error; end
7
-
8
- # The {Error} raised by {Embedded#render}.
9
- class RenderError < Error
10
- attr_reader :formatted, :file, :line, :column, :status
11
-
12
- def initialize(message, formatted, file, line, column, status)
13
- super(message)
14
- @formatted = formatted
15
- @file = file
16
- @line = line
17
- @column = column
18
- @status = status
19
- end
20
-
21
- def backtrace
22
- return nil if super.nil?
23
-
24
- ["#{@file}:#{@line}:#{@column}"] + super
25
- end
26
- end
27
- end
data/lib/sass/info.rb DELETED
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sass
4
- # The {Observer} for {Embedded#info}.
5
- class VersionContext
6
- include Observer
7
-
8
- def initialize(transport, id)
9
- @id = id
10
-
11
- super(transport)
12
-
13
- send_message EmbeddedProtocol::InboundMessage::VersionRequest.new(id: @id)
14
- end
15
-
16
- def update(error, message)
17
- raise error unless error.nil?
18
-
19
- case message
20
- when EmbeddedProtocol::OutboundMessage::VersionResponse
21
- return unless message.id == @id
22
-
23
- Thread.new do
24
- super(nil, message)
25
- end
26
- end
27
- rescue StandardError => e
28
- Thread.new do
29
- super(e, nil)
30
- end
31
- end
32
- end
33
- end
data/lib/sass/observer.rb DELETED
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sass
4
- # The {Observer} module for receiving messages from {Transport}.
5
- module Observer
6
- def initialize(transport)
7
- @transport = transport
8
- @mutex = Mutex.new
9
- @condition_variable = ConditionVariable.new
10
- @error = nil
11
- @message = nil
12
- @transport.add_observer self
13
- end
14
-
15
- def receive_message
16
- @mutex.synchronize do
17
- @condition_variable.wait(@mutex) if @error.nil? && @message.nil?
18
- end
19
-
20
- raise @error unless @error.nil?
21
-
22
- @message
23
- end
24
-
25
- def update(error, message)
26
- @transport.delete_observer self
27
- @mutex.synchronize do
28
- @error = error
29
- @message = message
30
- @condition_variable.broadcast
31
- end
32
- end
33
-
34
- private
35
-
36
- def send_message(message)
37
- @transport.send_message(message)
38
- end
39
- end
40
- end
data/lib/sass/platform.rb DELETED
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sass
4
- module Platform
5
- OS = case RbConfig::CONFIG['host_os'].downcase
6
- when /linux/
7
- 'linux'
8
- when /darwin/
9
- 'darwin'
10
- when /freebsd/
11
- 'freebsd'
12
- when /netbsd/
13
- 'netbsd'
14
- when /openbsd/
15
- 'openbsd'
16
- when /dragonfly/
17
- 'dragonflybsd'
18
- when /sunos|solaris/
19
- 'solaris'
20
- when /mingw|mswin/
21
- 'windows'
22
- else
23
- RbConfig::CONFIG['host_os'].downcase
24
- end
25
-
26
- OSVERSION = RbConfig::CONFIG['host_os'].gsub(/[^\d]/, '').to_i
27
-
28
- CPU = RbConfig::CONFIG['host_cpu']
29
-
30
- ARCH = case CPU.downcase
31
- when /amd64|x86_64|x64/
32
- 'x86_64'
33
- when /i\d86|x86|i86pc/
34
- 'i386'
35
- when /ppc64|powerpc64/
36
- 'powerpc64'
37
- when /ppc|powerpc/
38
- 'powerpc'
39
- when /sparcv9|sparc64/
40
- 'sparcv9'
41
- when /arm64|aarch64/ # MacOS calls it "arm64", other operating systems "aarch64"
42
- 'aarch64'
43
- when /^arm/
44
- if OS == 'darwin' # Ruby before 3.0 reports "arm" instead of "arm64" as host_cpu on darwin
45
- 'aarch64'
46
- else
47
- 'arm'
48
- end
49
- else
50
- RbConfig::CONFIG['host_cpu']
51
- end
52
- end
53
- end
data/lib/sass/result.rb DELETED
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sass
4
- # The {RenderResult} of {Embedded#render}.
5
- class RenderResult
6
- include Struct
7
-
8
- attr_reader :css, :map, :stats
9
-
10
- def initialize(css, map, stats)
11
- @css = css
12
- @map = map
13
- @stats = stats
14
- end
15
- end
16
-
17
- # The {RenderResultStats} of {Embedded#render}.
18
- class RenderResultStats
19
- include Struct
20
-
21
- attr_reader :entry, :start, :end, :duration
22
-
23
- def initialize(entry, start, finish, duration)
24
- @entry = entry
25
- @start = start
26
- @end = finish
27
- @duration = duration
28
- end
29
- end
30
- end
data/lib/sass/struct.rb DELETED
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sass
4
- # The {Struct} module.
5
- module Struct
6
- def [](key)
7
- instance_variable_get("@#{key}".to_sym)
8
- end
9
-
10
- def to_h
11
- instance_variables.map do |variable|
12
- [variable[1..].to_sym, instance_variable_get(variable)]
13
- end.to_h
14
- end
15
-
16
- def to_s
17
- to_h.to_s
18
- end
19
- end
20
- end
@@ -1,127 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'open3'
4
- require 'observer'
5
- require_relative '../../ext/sass/embedded_sass_pb'
6
-
7
- module Sass
8
- # The {::Observable} {Transport} for low level communication with
9
- # `dart-sass-embedded` using protocol buffers via stdio. Received messages
10
- # can be observed by an {Observer}.
11
- class Transport
12
- include Observable
13
-
14
- ONEOF_MESSAGE = EmbeddedProtocol::InboundMessage
15
- .descriptor
16
- .lookup_oneof('message')
17
- .collect do |field_descriptor|
18
- [field_descriptor.subtype, field_descriptor.name]
19
- end.to_h
20
-
21
- private_constant :ONEOF_MESSAGE
22
-
23
- def initialize
24
- @observerable_mutex = Mutex.new
25
- @stdin_mutex = Mutex.new
26
- @stdin, @stdout, @stderr, @wait_thread = Open3.popen3(Compiler::DART_SASS_EMBEDDED)
27
-
28
- [@stdin, @stdout].each(&:binmode)
29
-
30
- poll do
31
- warn(@stderr.readline, uplevel: 1)
32
- end
33
- poll do
34
- receive_proto read
35
- end
36
- end
37
-
38
- def add_observer(*args)
39
- @observerable_mutex.synchronize do
40
- super(*args)
41
- end
42
- end
43
-
44
- def send_message(message)
45
- write EmbeddedProtocol::InboundMessage.new(
46
- ONEOF_MESSAGE[message.class.descriptor] => message
47
- ).to_proto
48
- end
49
-
50
- def close
51
- delete_observers
52
- @stdin.close unless @stdin.closed?
53
- @stdout.close unless @stdout.closed?
54
- @stderr.close unless @stderr.closed?
55
- nil
56
- end
57
-
58
- def closed?
59
- @stdin.closed?
60
- end
61
-
62
- private
63
-
64
- def poll
65
- Thread.new do
66
- loop do
67
- yield
68
- rescue StandardError => e
69
- notify_observers(e, nil)
70
- close
71
- break
72
- end
73
- end
74
- end
75
-
76
- def notify_observers(*args)
77
- @observerable_mutex.synchronize do
78
- changed
79
- super(*args)
80
- end
81
- end
82
-
83
- def receive_proto(proto)
84
- payload = EmbeddedProtocol::OutboundMessage.decode(proto)
85
- message = payload[payload.message.to_s]
86
- case message
87
- when EmbeddedProtocol::ProtocolError
88
- raise ProtocolError, message.message
89
- else
90
- notify_observers(nil, message)
91
- end
92
- end
93
-
94
- def read
95
- length = read_varint(@stdout)
96
- @stdout.read(length)
97
- end
98
-
99
- def write(payload)
100
- @stdin_mutex.synchronize do
101
- write_varint(@stdin, payload.length)
102
- @stdin.write payload
103
- end
104
- end
105
-
106
- def read_varint(readable)
107
- value = bits = 0
108
- loop do
109
- byte = readable.readbyte
110
- value |= (byte & 0x7f) << bits
111
- bits += 7
112
- break if byte < 0x80
113
- end
114
- value
115
- end
116
-
117
- def write_varint(writeable, value)
118
- bytes = []
119
- until value < 0x80
120
- bytes << (0x80 | (value & 0x7f))
121
- value >>= 7
122
- end
123
- bytes << value
124
- writeable.write bytes.pack('C*')
125
- end
126
- end
127
- end
data/lib/sass/util.rb DELETED
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'pathname'
4
- require 'uri'
5
-
6
- module Sass
7
- # The {Util} module.
8
- module Util
9
- module_function
10
-
11
- URI_PARSER = URI::Parser.new({ RESERVED: ';/?:@&=+$,' })
12
-
13
- private_constant :URI_PARSER
14
-
15
- def file_uri_from_path(path)
16
- "file://#{Platform::OS == 'windows' ? File::SEPARATOR : ''}#{URI_PARSER.escape(path)}"
17
- end
18
-
19
- def path_from_file_uri(file_uri)
20
- URI_PARSER.unescape(file_uri[(Platform::OS == 'windows' ? 8 : 7)..])
21
- end
22
-
23
- def relative_path(from, to)
24
- Pathname.new(File.absolute_path(to)).relative_path_from(Pathname.new(File.absolute_path(from))).to_s
25
- end
26
-
27
- def now
28
- (Time.now.to_f * 1000).to_i
29
- end
30
- end
31
- end