sass-embedded 0.14.0 → 0.16.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.
- checksums.yaml +4 -4
- data/lib/sass/compile_error.rb +1 -10
- data/lib/sass/compile_result.rb +1 -5
- data/lib/sass/embedded/channel.rb +2 -2
- data/lib/sass/embedded/compile_context/function_registry.rb +85 -0
- data/lib/sass/embedded/compile_context/importer_registry.rb +99 -0
- data/lib/sass/embedded/compile_context/logger_registry.rb +45 -0
- data/lib/sass/embedded/compile_context/value_protofier.rb +237 -0
- data/lib/sass/embedded/compile_context.rb +31 -238
- data/lib/sass/embedded/compiler/requirements.rb +1 -1
- data/lib/sass/embedded/compiler.rb +10 -43
- data/lib/sass/embedded/{render.rb → legacy.rb} +79 -3
- data/lib/sass/embedded/observer.rb +2 -0
- data/lib/sass/embedded/protofier.rb +91 -0
- data/lib/sass/embedded/structifier.rb +30 -0
- data/lib/sass/embedded/varint.rb +33 -0
- data/lib/sass/embedded/version.rb +1 -1
- data/lib/sass/embedded/version_context.rb +2 -3
- data/lib/sass/embedded.rb +39 -54
- data/lib/sass/embedded_protocol.rb +0 -6
- data/lib/sass/logger/source_location.rb +3 -9
- data/lib/sass/logger/source_span.rb +1 -13
- data/lib/sass/logger.rb +3 -3
- data/lib/sass/script_error.rb +5 -0
- data/lib/sass/value/argument_list.rb +24 -0
- data/lib/sass/value/boolean.rb +42 -0
- data/lib/sass/value/color.rb +213 -0
- data/lib/sass/value/function.rb +35 -0
- data/lib/sass/value/fuzzy_math.rb +81 -0
- data/lib/sass/value/list.rb +60 -0
- data/lib/sass/value/map.rb +57 -0
- data/lib/sass/value/null.rb +39 -0
- data/lib/sass/value/number/unit.rb +186 -0
- data/lib/sass/value/number.rb +272 -0
- data/lib/sass/value/string.rb +43 -0
- data/lib/sass/value.rb +92 -0
- data/lib/sass.rb +51 -48
- metadata +30 -56
- data/lib/sass/embedded/url.rb +0 -35
- data/lib/sass/file_importer.rb +0 -10
- data/lib/sass/importer.rb +0 -14
- data/lib/sass/importer_result.rb +0 -14
@@ -1,9 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../embedded_protocol'
|
4
|
-
require_relative '../logger/source_span'
|
5
|
-
require_relative 'observer'
|
6
|
-
|
7
3
|
module Sass
|
8
4
|
class Embedded
|
9
5
|
# The {Observer} for {Embedded#compile}.
|
@@ -31,38 +27,33 @@ module Sass
|
|
31
27
|
logger:,
|
32
28
|
quiet_deps:,
|
33
29
|
verbose:)
|
34
|
-
@
|
35
|
-
@
|
36
|
-
|
37
|
-
@importer = to_struct(importer)
|
38
|
-
@load_paths = load_paths
|
39
|
-
@syntax = syntax
|
40
|
-
@url = url
|
41
|
-
|
42
|
-
@source_map = source_map
|
43
|
-
@source_map_include_sources = source_map_include_sources
|
44
|
-
@style = style
|
45
|
-
|
46
|
-
@global_functions = functions.keys.map(&:to_s)
|
47
|
-
|
48
|
-
@functions = functions.transform_keys do |key|
|
49
|
-
key.to_s.split('(')[0].chomp
|
50
|
-
end
|
51
|
-
@importers = importers.map do |obj|
|
52
|
-
to_struct(obj)
|
53
|
-
end
|
54
|
-
|
55
|
-
@alert_ascii = alert_ascii
|
56
|
-
@alert_color = alert_color
|
57
|
-
|
58
|
-
@logger = to_struct(logger)
|
59
|
-
|
60
|
-
@quiet_deps = quiet_deps
|
61
|
-
@verbose = verbose
|
30
|
+
@function_registery = FunctionRegistry.new(functions)
|
31
|
+
@importer_registery = ImporterRegistry.new(importers, load_paths)
|
32
|
+
@logger_registery = LoggerRegistry.new(logger)
|
62
33
|
|
63
34
|
super(channel)
|
64
35
|
|
65
|
-
send_message
|
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
|
+
)
|
66
57
|
end
|
67
58
|
|
68
59
|
def update(error, message)
|
@@ -78,30 +69,30 @@ module Sass
|
|
78
69
|
when EmbeddedProtocol::OutboundMessage::LogEvent
|
79
70
|
return unless message.compilation_id == id
|
80
71
|
|
81
|
-
log message
|
72
|
+
@logger_registery.log message
|
82
73
|
when EmbeddedProtocol::OutboundMessage::CanonicalizeRequest
|
83
74
|
return unless message.compilation_id == id
|
84
75
|
|
85
76
|
Thread.new do
|
86
|
-
send_message
|
77
|
+
send_message @importer_registery.canonicalize message
|
87
78
|
end
|
88
79
|
when EmbeddedProtocol::OutboundMessage::ImportRequest
|
89
80
|
return unless message.compilation_id == id
|
90
81
|
|
91
82
|
Thread.new do
|
92
|
-
send_message
|
83
|
+
send_message @importer_registery.import message
|
93
84
|
end
|
94
85
|
when EmbeddedProtocol::OutboundMessage::FileImportRequest
|
95
86
|
return unless message.compilation_id == id
|
96
87
|
|
97
88
|
Thread.new do
|
98
|
-
send_message
|
89
|
+
send_message @importer_registery.file_import message
|
99
90
|
end
|
100
91
|
when EmbeddedProtocol::OutboundMessage::FunctionCallRequest
|
101
92
|
return unless message.compilation_id == id
|
102
93
|
|
103
94
|
Thread.new do
|
104
|
-
send_message
|
95
|
+
send_message @function_registery.function_call message
|
105
96
|
end
|
106
97
|
end
|
107
98
|
rescue StandardError => e
|
@@ -109,206 +100,8 @@ module Sass
|
|
109
100
|
super(e, nil)
|
110
101
|
end
|
111
102
|
end
|
112
|
-
|
113
|
-
private
|
114
|
-
|
115
|
-
def log(event)
|
116
|
-
case event.type
|
117
|
-
when :DEBUG
|
118
|
-
if @logger.respond_to? :debug
|
119
|
-
@logger.debug(event.message, span: Logger::SourceSpan.from_proto(event.span))
|
120
|
-
else
|
121
|
-
Kernel.warn(event.formatted)
|
122
|
-
end
|
123
|
-
when :DEPRECATION_WARNING
|
124
|
-
if @logger.respond_to? :warn
|
125
|
-
@logger.warn(event.message, deprecation: true,
|
126
|
-
span: Logger::SourceSpan.from_proto(event.span),
|
127
|
-
stack: event.stack_trace)
|
128
|
-
else
|
129
|
-
Kernel.warn(event.formatted)
|
130
|
-
end
|
131
|
-
when :WARNING
|
132
|
-
if @logger.respond_to? :warn
|
133
|
-
@logger.warn(event.message, deprecation: false,
|
134
|
-
span: Logger::SourceSpan.from_proto(event.span),
|
135
|
-
stack: event.stack_trace)
|
136
|
-
else
|
137
|
-
Kernel.warn(event.formatted)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def compile_request
|
143
|
-
EmbeddedProtocol::InboundMessage::CompileRequest.new(
|
144
|
-
id: id,
|
145
|
-
string: unless @source.nil?
|
146
|
-
EmbeddedProtocol::InboundMessage::CompileRequest::StringInput.new(
|
147
|
-
source: @source,
|
148
|
-
url: @url,
|
149
|
-
syntax: to_proto_syntax(@syntax),
|
150
|
-
importer: @importer.nil? ? nil : to_proto_importer(@importer, @importers.length)
|
151
|
-
)
|
152
|
-
end,
|
153
|
-
path: @path,
|
154
|
-
style: to_proto_output_style(@style),
|
155
|
-
source_map: @source_map,
|
156
|
-
source_map_include_sources: @source_map_include_sources,
|
157
|
-
importers: to_proto_importers(@importers, @load_paths),
|
158
|
-
global_functions: @global_functions,
|
159
|
-
alert_ascii: @alert_ascii,
|
160
|
-
alert_color: @alert_color
|
161
|
-
)
|
162
|
-
end
|
163
|
-
|
164
|
-
def canonicalize_response(canonicalize_request)
|
165
|
-
importer = importer_of_id canonicalize_request.importer_id
|
166
|
-
url = importer.canonicalize canonicalize_request.url,
|
167
|
-
from_import: canonicalize_request.from_import
|
168
|
-
|
169
|
-
EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
170
|
-
id: canonicalize_request.id,
|
171
|
-
url: url
|
172
|
-
)
|
173
|
-
rescue StandardError => e
|
174
|
-
EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
175
|
-
id: canonicalize_request.id,
|
176
|
-
error: e.message
|
177
|
-
)
|
178
|
-
end
|
179
|
-
|
180
|
-
def import_response(import_request)
|
181
|
-
importer = importer_of_id import_request.importer_id
|
182
|
-
importer_result = to_struct importer.load(import_request.url)
|
183
|
-
|
184
|
-
EmbeddedProtocol::InboundMessage::ImportResponse.new(
|
185
|
-
id: import_request.id,
|
186
|
-
success: EmbeddedProtocol::InboundMessage::ImportResponse::ImportSuccess.new(
|
187
|
-
contents: importer_result.contents,
|
188
|
-
syntax: to_proto_syntax(importer_result.syntax),
|
189
|
-
source_map_url: importer_result.respond_to?(:source_map_url) ? importer_result.source_map_url : nil
|
190
|
-
)
|
191
|
-
)
|
192
|
-
rescue StandardError => e
|
193
|
-
EmbeddedProtocol::InboundMessage::ImportResponse.new(
|
194
|
-
id: import_request.id,
|
195
|
-
error: e.message
|
196
|
-
)
|
197
|
-
end
|
198
|
-
|
199
|
-
def file_import_response(file_import_request)
|
200
|
-
importer = importer_of_id file_import_request.importer_id
|
201
|
-
file_url = importer.find_file_url file_import_request.url,
|
202
|
-
from_import: file_import_request.from_import
|
203
|
-
|
204
|
-
raise "file_url must be a file: URL, was \"#{file_url}\"" if !file_url.nil? && !file_url.start_with?('file:')
|
205
|
-
|
206
|
-
EmbeddedProtocol::InboundMessage::FileImportResponse.new(
|
207
|
-
id: file_import_request.id,
|
208
|
-
file_url: file_url
|
209
|
-
)
|
210
|
-
rescue StandardError => e
|
211
|
-
EmbeddedProtocol::InboundMessage::FileImportResponse.new(
|
212
|
-
id: file_import_request.id,
|
213
|
-
error: e.message
|
214
|
-
)
|
215
|
-
end
|
216
|
-
|
217
|
-
def function_call_response(function_call_request)
|
218
|
-
EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
|
219
|
-
id: function_call_request.id,
|
220
|
-
success: @functions[function_call_request.name].call(*function_call_request.arguments),
|
221
|
-
accessed_argument_lists: function_call_request.arguments
|
222
|
-
.filter { |argument| argument.value == :argument_list }
|
223
|
-
.map { |argument| argument.argument_list.id }
|
224
|
-
)
|
225
|
-
rescue StandardError => e
|
226
|
-
EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
|
227
|
-
id: function_call_request.id,
|
228
|
-
error: e.message
|
229
|
-
)
|
230
|
-
end
|
231
|
-
|
232
|
-
def to_proto_syntax(syntax)
|
233
|
-
case syntax&.to_sym
|
234
|
-
when :scss
|
235
|
-
EmbeddedProtocol::Syntax::SCSS
|
236
|
-
when :indented
|
237
|
-
EmbeddedProtocol::Syntax::INDENTED
|
238
|
-
when :css
|
239
|
-
EmbeddedProtocol::Syntax::CSS
|
240
|
-
else
|
241
|
-
raise ArgumentError, 'syntax must be one of :scss, :indented, :css'
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
def to_proto_output_style(style)
|
246
|
-
case style&.to_sym
|
247
|
-
when :expanded
|
248
|
-
EmbeddedProtocol::OutputStyle::EXPANDED
|
249
|
-
when :compressed
|
250
|
-
EmbeddedProtocol::OutputStyle::COMPRESSED
|
251
|
-
else
|
252
|
-
raise ArgumentError, 'style must be one of :expanded, :compressed'
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
def to_proto_importer(importer, id)
|
257
|
-
is_importer = importer.respond_to?(:canonicalize) && importer.respond_to?(:load)
|
258
|
-
is_file_importer = importer.respond_to?(:find_file_url)
|
259
|
-
|
260
|
-
if is_importer && !is_file_importer
|
261
|
-
EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
|
262
|
-
importer_id: id
|
263
|
-
)
|
264
|
-
elsif is_file_importer && !is_importer
|
265
|
-
EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
|
266
|
-
file_importer_id: id
|
267
|
-
)
|
268
|
-
else
|
269
|
-
raise ArgumentError, 'importer must be an Importer or a FileImporter'
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
def to_proto_importers(importers, load_paths)
|
274
|
-
proto_importers = importers.map.with_index do |importer, id|
|
275
|
-
to_proto_importer(importer, id)
|
276
|
-
end
|
277
|
-
|
278
|
-
load_paths.each do |load_path|
|
279
|
-
proto_importers << EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
|
280
|
-
path: File.absolute_path(load_path)
|
281
|
-
)
|
282
|
-
end
|
283
|
-
|
284
|
-
proto_importers
|
285
|
-
end
|
286
|
-
|
287
|
-
def importer_of_id(id)
|
288
|
-
if id == @importers.length
|
289
|
-
@importer
|
290
|
-
else
|
291
|
-
@importers[id]
|
292
|
-
end
|
293
|
-
end
|
294
|
-
|
295
|
-
def to_struct(obj)
|
296
|
-
return obj unless obj.is_a? Hash
|
297
|
-
|
298
|
-
struct = Object.new
|
299
|
-
obj.each do |key, value|
|
300
|
-
if value.respond_to? :call
|
301
|
-
struct.define_singleton_method key.to_sym do |*args, **kwargs|
|
302
|
-
value.call(*args, **kwargs)
|
303
|
-
end
|
304
|
-
else
|
305
|
-
struct.define_singleton_method key.to_sym do
|
306
|
-
value
|
307
|
-
end
|
308
|
-
end
|
309
|
-
end
|
310
|
-
struct
|
311
|
-
end
|
312
103
|
end
|
104
|
+
|
105
|
+
private_constant :CompileContext
|
313
106
|
end
|
314
107
|
end
|
@@ -2,9 +2,6 @@
|
|
2
2
|
|
3
3
|
require 'observer'
|
4
4
|
require 'open3'
|
5
|
-
require_relative '../embedded_protocol'
|
6
|
-
require_relative 'compiler/path'
|
7
|
-
require_relative 'protocol_error'
|
8
5
|
|
9
6
|
module Sass
|
10
7
|
class Embedded
|
@@ -14,14 +11,7 @@ module Sass
|
|
14
11
|
class Compiler
|
15
12
|
include Observable
|
16
13
|
|
17
|
-
|
18
|
-
.descriptor
|
19
|
-
.lookup_oneof('message')
|
20
|
-
.to_h do |field_descriptor|
|
21
|
-
[field_descriptor.subtype, field_descriptor.name]
|
22
|
-
end
|
23
|
-
|
24
|
-
private_constant :ONEOF_MESSAGE
|
14
|
+
PROTOCOL_ERROR_ID = 4_294_967_295
|
25
15
|
|
26
16
|
def initialize
|
27
17
|
@observerable_mutex = Mutex.new
|
@@ -35,7 +25,7 @@ module Sass
|
|
35
25
|
warn(@stderr.readline, uplevel: 1)
|
36
26
|
end
|
37
27
|
poll do
|
38
|
-
|
28
|
+
receive_message Protofier.from_proto_message read
|
39
29
|
end
|
40
30
|
end
|
41
31
|
|
@@ -60,9 +50,7 @@ module Sass
|
|
60
50
|
end
|
61
51
|
|
62
52
|
def send_message(message)
|
63
|
-
write
|
64
|
-
ONEOF_MESSAGE[message.class.descriptor] => message
|
65
|
-
).to_proto
|
53
|
+
write Protofier.to_proto_message message
|
66
54
|
end
|
67
55
|
|
68
56
|
def close
|
@@ -86,7 +74,7 @@ module Sass
|
|
86
74
|
private
|
87
75
|
|
88
76
|
def half_closed?
|
89
|
-
@id ==
|
77
|
+
@id == PROTOCOL_ERROR_ID
|
90
78
|
end
|
91
79
|
|
92
80
|
def poll
|
@@ -108,9 +96,7 @@ module Sass
|
|
108
96
|
end
|
109
97
|
end
|
110
98
|
|
111
|
-
def
|
112
|
-
payload = EmbeddedProtocol::OutboundMessage.decode(proto)
|
113
|
-
message = payload[payload.message.to_s]
|
99
|
+
def receive_message(message)
|
114
100
|
case message
|
115
101
|
when EmbeddedProtocol::ProtocolError
|
116
102
|
raise ProtocolError, message.message
|
@@ -120,37 +106,18 @@ module Sass
|
|
120
106
|
end
|
121
107
|
|
122
108
|
def read
|
123
|
-
length =
|
109
|
+
length = Varint.read(@stdout)
|
124
110
|
@stdout.read(length)
|
125
111
|
end
|
126
112
|
|
127
113
|
def write(payload)
|
128
114
|
@stdin_mutex.synchronize do
|
129
|
-
|
130
|
-
@stdin.write
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
def read_varint(readable)
|
135
|
-
value = bits = 0
|
136
|
-
loop do
|
137
|
-
byte = readable.readbyte
|
138
|
-
value |= (byte & 0x7f) << bits
|
139
|
-
bits += 7
|
140
|
-
break if byte < 0x80
|
115
|
+
Varint.write(@stdin, payload.length)
|
116
|
+
@stdin.write(payload)
|
141
117
|
end
|
142
|
-
value
|
143
|
-
end
|
144
|
-
|
145
|
-
def write_varint(writeable, value)
|
146
|
-
bytes = []
|
147
|
-
until value < 0x80
|
148
|
-
bytes << (0x80 | (value & 0x7f))
|
149
|
-
value >>= 7
|
150
|
-
end
|
151
|
-
bytes << value
|
152
|
-
writeable.write bytes.pack('C*')
|
153
118
|
end
|
154
119
|
end
|
120
|
+
|
121
|
+
private_constant :Compiler
|
155
122
|
end
|
156
123
|
end
|
@@ -3,9 +3,50 @@
|
|
3
3
|
require 'base64'
|
4
4
|
require 'json'
|
5
5
|
require 'pathname'
|
6
|
-
|
6
|
+
require 'uri'
|
7
7
|
|
8
|
+
# The Sass module.
|
9
|
+
#
|
10
|
+
# This communicates with Embedded Dart Sass using the Embedded Sass protocol.
|
8
11
|
module Sass
|
12
|
+
class << self
|
13
|
+
# @deprecated
|
14
|
+
# The global {.include_paths} for Sass files. This is meant for plugins and
|
15
|
+
# libraries to register the paths to their Sass stylesheets to that they may
|
16
|
+
# be included via `@import` or `@use`. This include path is used by every
|
17
|
+
# instance of {Sass::Embedded}. They are lower-precedence than any include
|
18
|
+
# paths passed in via the `include_paths` option.
|
19
|
+
#
|
20
|
+
# If the `SASS_PATH` environment variable is set,
|
21
|
+
# the initial value of `include_paths` will be initialized based on that.
|
22
|
+
# The variable should be a colon-separated list of path names
|
23
|
+
# (semicolon-separated on Windows).
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
# Sass.include_paths << File.dirname(__FILE__) + '/sass'
|
27
|
+
# @return [Array]
|
28
|
+
def include_paths
|
29
|
+
Embedded.include_paths
|
30
|
+
end
|
31
|
+
|
32
|
+
# @deprecated
|
33
|
+
# The global {.render} method. This instantiates a global {Embedded} instance
|
34
|
+
# and calls {Embedded#render}.
|
35
|
+
#
|
36
|
+
# See {Embedded#render} for supported options.
|
37
|
+
#
|
38
|
+
# @example
|
39
|
+
# Sass.render(data: 'h1 { font-size: 40px; }')
|
40
|
+
# @example
|
41
|
+
# Sass.render(file: 'style.css')
|
42
|
+
# @return [Result]
|
43
|
+
# @raise [ProtocolError]
|
44
|
+
# @raise [RenderError]
|
45
|
+
def render(**kwargs)
|
46
|
+
instance.render(**kwargs)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
9
50
|
# The {Embedded} host for using dart-sass-embedded. Each instance creates
|
10
51
|
# its own {Channel}.
|
11
52
|
#
|
@@ -309,11 +350,17 @@ module Sass
|
|
309
350
|
raise result if result.is_a? StandardError
|
310
351
|
|
311
352
|
if result&.key? :contents
|
312
|
-
@importer_results[canonical_url] =
|
353
|
+
@importer_results[canonical_url] = {
|
354
|
+
contents: result[:contents],
|
355
|
+
syntax: :scss
|
356
|
+
}
|
313
357
|
canonical_url
|
314
358
|
elsif result&.key? :file
|
315
359
|
canonical_url = Url.path_to_file_url(File.absolute_path(result[:file]))
|
316
|
-
@importer_results[canonical_url] =
|
360
|
+
@importer_results[canonical_url] = {
|
361
|
+
contents: File.read(result[:file]),
|
362
|
+
syntax: :scss
|
363
|
+
}
|
317
364
|
canonical_url
|
318
365
|
end
|
319
366
|
end
|
@@ -323,6 +370,35 @@ module Sass
|
|
323
370
|
end
|
324
371
|
end
|
325
372
|
|
373
|
+
# @deprecated
|
374
|
+
# The {Url} module.
|
375
|
+
module Url
|
376
|
+
# The {::URI::Parser} that is in consistent with RFC 2396 (URI Generic Syntax) and dart:core library.
|
377
|
+
URI_PARSER = URI::Parser.new({ RESERVED: ';/?:@&=+$,' })
|
378
|
+
|
379
|
+
FILE_SCHEME = 'file://'
|
380
|
+
|
381
|
+
private_constant :URI_PARSER, :FILE_SCHEME
|
382
|
+
|
383
|
+
module_function
|
384
|
+
|
385
|
+
def path_to_file_url(path)
|
386
|
+
if File.absolute_path? path
|
387
|
+
URI_PARSER.escape "#{FILE_SCHEME}#{Gem.win_platform? ? '/' : ''}#{path}"
|
388
|
+
else
|
389
|
+
URI_PARSER.escape path
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
def file_url_to_path(url)
|
394
|
+
if url.start_with? FILE_SCHEME
|
395
|
+
URI_PARSER.unescape url[(FILE_SCHEME.length + (Gem.win_platform? ? 1 : 0))..]
|
396
|
+
else
|
397
|
+
URI_PARSER.unescape url
|
398
|
+
end
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
326
402
|
private_constant :LegacyImporter
|
327
403
|
end
|
328
404
|
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sass
|
4
|
+
class Embedded
|
5
|
+
# The {Protofier} between Pure Ruby types and Protobuf Ruby types.
|
6
|
+
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
|
+
module_function
|
17
|
+
|
18
|
+
def from_proto_compile_response(compile_response)
|
19
|
+
if compile_response.result == :failure
|
20
|
+
raise CompileError.new(
|
21
|
+
compile_response.failure.formatted || compile_response.failure.message,
|
22
|
+
compile_response.failure.message,
|
23
|
+
compile_response.failure.stack_trace,
|
24
|
+
from_proto_source_span(compile_response.failure.span)
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
CompileResult.new(
|
29
|
+
compile_response.success.css,
|
30
|
+
compile_response.success.source_map,
|
31
|
+
compile_response.success.loaded_urls
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
def from_proto_source_span(source_span)
|
36
|
+
return nil if source_span.nil?
|
37
|
+
|
38
|
+
Logger::SourceSpan.new(from_proto_source_location(source_span.start),
|
39
|
+
from_proto_source_location(source_span.end),
|
40
|
+
source_span.text,
|
41
|
+
source_span.url,
|
42
|
+
source_span.context)
|
43
|
+
end
|
44
|
+
|
45
|
+
def from_proto_source_location(source_location)
|
46
|
+
return nil if source_location.nil?
|
47
|
+
|
48
|
+
Logger::SourceLocation.new(source_location.offset,
|
49
|
+
source_location.line,
|
50
|
+
source_location.column)
|
51
|
+
end
|
52
|
+
|
53
|
+
def from_proto_message(proto)
|
54
|
+
message = EmbeddedProtocol::OutboundMessage.decode(proto)
|
55
|
+
message.method(message.message).call
|
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
|
+
def to_proto_syntax(syntax)
|
65
|
+
case syntax&.to_sym
|
66
|
+
when :scss
|
67
|
+
EmbeddedProtocol::Syntax::SCSS
|
68
|
+
when :indented
|
69
|
+
EmbeddedProtocol::Syntax::INDENTED
|
70
|
+
when :css
|
71
|
+
EmbeddedProtocol::Syntax::CSS
|
72
|
+
else
|
73
|
+
raise ArgumentError, 'syntax must be one of :scss, :indented, :css'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def to_proto_output_style(style)
|
78
|
+
case style&.to_sym
|
79
|
+
when :expanded
|
80
|
+
EmbeddedProtocol::OutputStyle::EXPANDED
|
81
|
+
when :compressed
|
82
|
+
EmbeddedProtocol::OutputStyle::COMPRESSED
|
83
|
+
else
|
84
|
+
raise ArgumentError, 'style must be one of :expanded, :compressed'
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
private_constant :Protofier
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sass
|
4
|
+
class Embedded
|
5
|
+
# The {Structifier} that convert {::Hash} to {Struct}-like object.
|
6
|
+
module Structifier
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def to_struct(obj)
|
10
|
+
return obj unless obj.is_a? Hash
|
11
|
+
|
12
|
+
struct = Object.new
|
13
|
+
obj.each do |key, value|
|
14
|
+
if value.respond_to? :call
|
15
|
+
struct.define_singleton_method key.to_sym do |*args, **kwargs|
|
16
|
+
value.call(*args, **kwargs)
|
17
|
+
end
|
18
|
+
else
|
19
|
+
struct.define_singleton_method key.to_sym do
|
20
|
+
value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
struct
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private_constant :Structifier
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sass
|
4
|
+
class Embedded
|
5
|
+
# Read and write {Varint} from {::IO}.
|
6
|
+
module Varint
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def read(readable)
|
10
|
+
value = bits = 0
|
11
|
+
loop do
|
12
|
+
byte = readable.readbyte
|
13
|
+
value |= (byte & 0x7f) << bits
|
14
|
+
bits += 7
|
15
|
+
break if byte < 0x80
|
16
|
+
end
|
17
|
+
value
|
18
|
+
end
|
19
|
+
|
20
|
+
def write(writeable, value)
|
21
|
+
bytes = []
|
22
|
+
until value < 0x80
|
23
|
+
bytes << (0x80 | (value & 0x7f))
|
24
|
+
value >>= 7
|
25
|
+
end
|
26
|
+
bytes << value
|
27
|
+
writeable.write bytes.pack('C*')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private_constant :Varint
|
32
|
+
end
|
33
|
+
end
|