sass-embedded 1.54.6-x86-mingw32

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 (43) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +20 -0
  3. data/README.md +42 -0
  4. data/ext/sass/embedded.rb +9 -0
  5. data/ext/sass/embedded_sass_pb.rb +349 -0
  6. data/ext/sass/sass_embedded/dart-sass-embedded.bat +7 -0
  7. data/ext/sass/sass_embedded/src/LICENSE +1476 -0
  8. data/ext/sass/sass_embedded/src/dart-sass-embedded.snapshot +0 -0
  9. data/ext/sass/sass_embedded/src/dart.exe +0 -0
  10. data/lib/sass/compile_error.rb +28 -0
  11. data/lib/sass/compile_result.rb +23 -0
  12. data/lib/sass/embedded/async.rb +65 -0
  13. data/lib/sass/embedded/channel.rb +61 -0
  14. data/lib/sass/embedded/compiler.rb +60 -0
  15. data/lib/sass/embedded/dispatcher.rb +90 -0
  16. data/lib/sass/embedded/host/function_registry.rb +90 -0
  17. data/lib/sass/embedded/host/importer_registry.rb +108 -0
  18. data/lib/sass/embedded/host/logger_registry.rb +50 -0
  19. data/lib/sass/embedded/host/value_protofier.rb +241 -0
  20. data/lib/sass/embedded/host.rb +141 -0
  21. data/lib/sass/embedded/protofier.rb +78 -0
  22. data/lib/sass/embedded/structifier.rb +36 -0
  23. data/lib/sass/embedded/varint.rb +35 -0
  24. data/lib/sass/embedded/version.rb +7 -0
  25. data/lib/sass/embedded.rb +245 -0
  26. data/lib/sass/logger/silent.rb +26 -0
  27. data/lib/sass/logger/source_location.rb +21 -0
  28. data/lib/sass/logger/source_span.rb +27 -0
  29. data/lib/sass/script_error.rb +6 -0
  30. data/lib/sass/value/argument_list.rb +30 -0
  31. data/lib/sass/value/boolean.rb +52 -0
  32. data/lib/sass/value/color.rb +253 -0
  33. data/lib/sass/value/function.rb +54 -0
  34. data/lib/sass/value/fuzzy_math.rb +81 -0
  35. data/lib/sass/value/list.rb +79 -0
  36. data/lib/sass/value/map.rb +71 -0
  37. data/lib/sass/value/null.rb +48 -0
  38. data/lib/sass/value/number/unit.rb +186 -0
  39. data/lib/sass/value/number.rb +358 -0
  40. data/lib/sass/value/string.rb +55 -0
  41. data/lib/sass/value.rb +132 -0
  42. data/lib/sass-embedded.rb +4 -0
  43. metadata +186 -0
Binary file
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ # An exception thrown because a Sass compilation failed.
5
+ class CompileError < StandardError
6
+ # @return [String, nil]
7
+ attr_accessor :sass_stack
8
+
9
+ # @return [Logger::SourceSpan, nil]
10
+ attr_accessor :span
11
+
12
+ def initialize(message, full_message, sass_stack, span)
13
+ super(message)
14
+ @full_message = full_message == '' ? nil : full_message.dup
15
+ @sass_stack = sass_stack == '' ? nil : sass_stack
16
+ @span = span
17
+ end
18
+
19
+ # @return [String]
20
+ def full_message(*args, **kwargs)
21
+ if @full_message.nil?
22
+ super(*args, **kwargs)
23
+ else
24
+ @full_message
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ # The result of compiling Sass to CSS. Returned by {Sass.compile} and {Sass.compile_string}.
5
+ #
6
+ # @see https://sass-lang.com/documentation/js-api/interfaces/CompileResult
7
+ class CompileResult
8
+ # @return [String]
9
+ attr_reader :css
10
+
11
+ # @return [String, nil]
12
+ attr_reader :source_map
13
+
14
+ # @return [Array<String>]
15
+ attr_reader :loaded_urls
16
+
17
+ def initialize(css, source_map, loaded_urls)
18
+ @css = css
19
+ @source_map = source_map == '' ? nil : source_map
20
+ @loaded_urls = loaded_urls
21
+ end
22
+ end
23
+ end
@@ -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
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ class Embedded
5
+ # The {Channel} class.
6
+ #
7
+ # It establishes connection between {Host} and {Dispatcher}.
8
+ class Channel
9
+ def initialize
10
+ @dispatcher = Dispatcher.new
11
+ @mutex = Mutex.new
12
+ end
13
+
14
+ def close
15
+ @mutex.synchronize do
16
+ @dispatcher.close
17
+ end
18
+ end
19
+
20
+ def closed?
21
+ @mutex.synchronize do
22
+ @dispatcher.closed?
23
+ end
24
+ end
25
+
26
+ def connect(observer)
27
+ @mutex.synchronize do
28
+ begin
29
+ id = @dispatcher.subscribe(observer)
30
+ rescue EOFError
31
+ @dispatcher = Dispatcher.new
32
+ id = @dispatcher.subscribe(observer)
33
+ end
34
+ Connection.new(@dispatcher, id)
35
+ end
36
+ end
37
+
38
+ # The {Connection} between {Host} to {Dispatcher}.
39
+ class Connection
40
+ attr_reader :id
41
+
42
+ def initialize(dispatcher, id)
43
+ @dispatcher = dispatcher
44
+ @id = id
45
+ end
46
+
47
+ def disconnect
48
+ @dispatcher.unsubscribe(id)
49
+ end
50
+
51
+ def send_message(message)
52
+ @dispatcher.send_message(message)
53
+ end
54
+ end
55
+
56
+ private_constant :Connection
57
+ end
58
+
59
+ private_constant :Channel
60
+ end
61
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open3'
4
+
5
+ module Sass
6
+ class Embedded
7
+ # The {Compiler} class.
8
+ #
9
+ # It runs the `dart-sass-embedded` process.
10
+ class Compiler
11
+ def initialize
12
+ @stdin, @stdout, @stderr, @wait_thread = Open3.popen3(PATH, chdir: __dir__)
13
+ @stdin.binmode
14
+ @stdout.binmode
15
+ @stdin_mutex = Mutex.new
16
+ @stdout_mutex = Mutex.new
17
+
18
+ Thread.new do
19
+ loop do
20
+ warn(@stderr.readline, uplevel: 1)
21
+ rescue IOError, Errno::EBADF
22
+ break
23
+ end
24
+ end
25
+ end
26
+
27
+ def close
28
+ @stdin_mutex.synchronize do
29
+ @stdin.close unless @stdin.closed?
30
+ @stdout.close unless @stdout.closed?
31
+ @stderr.close unless @stderr.closed?
32
+ end
33
+
34
+ @wait_thread.value
35
+ end
36
+
37
+ def closed?
38
+ @stdin_mutex.synchronize do
39
+ @stdin.closed?
40
+ end
41
+ end
42
+
43
+ def write(payload)
44
+ @stdin_mutex.synchronize do
45
+ Varint.write(@stdin, payload.length)
46
+ @stdin.write(payload)
47
+ end
48
+ end
49
+
50
+ def read
51
+ @stdout_mutex.synchronize do
52
+ length = Varint.read(@stdout)
53
+ @stdout.read(length)
54
+ end
55
+ end
56
+ end
57
+
58
+ private_constant :Compiler
59
+ end
60
+ end
@@ -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 = 0xffffffff
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, Errno::EBADF => e
21
+ @mutex.synchronize do
22
+ @id = PROTOCOL_ERROR_ID
23
+ @observers.values
24
+ end.each do |observer|
25
+ observer.error e
26
+ end
27
+ break
28
+ end
29
+ end
30
+ end
31
+
32
+ def subscribe(observer)
33
+ @mutex.synchronize do
34
+ raise EOFError if @id == PROTOCOL_ERROR_ID
35
+
36
+ id = @id
37
+ @id = id.next
38
+ @observers[id] = observer
39
+ id
40
+ end
41
+ end
42
+
43
+ def unsubscribe(id)
44
+ @mutex.synchronize do
45
+ @observers.delete(id)
46
+
47
+ close if @id == PROTOCOL_ERROR_ID && @observers.empty?
48
+ end
49
+ end
50
+
51
+ def close
52
+ @compiler.close
53
+ end
54
+
55
+ def closed?
56
+ @compiler.closed?
57
+ end
58
+
59
+ def send_message(inbound_message)
60
+ @compiler.write(inbound_message.to_proto)
61
+ end
62
+
63
+ private
64
+
65
+ def receive_message(outbound_message)
66
+ oneof = outbound_message.message
67
+ message = outbound_message.public_send(oneof)
68
+ case oneof
69
+ when :error
70
+ @mutex.synchronize do
71
+ @id = PROTOCOL_ERROR_ID
72
+ message.id == PROTOCOL_ERROR_ID ? @observers.values : [@observers[message.id]]
73
+ end.each do |observer|
74
+ observer.public_send(oneof, message)
75
+ end
76
+ when :compile_response, :version_response
77
+ @mutex.synchronize { @observers[message.id] }.public_send(oneof, message)
78
+ when :log_event, :canonicalize_request, :import_request, :file_import_request, :function_call_request
79
+ Thread.new(@mutex.synchronize { @observers[message.compilation_id] }) do |observer|
80
+ observer.public_send(oneof, message)
81
+ end
82
+ else
83
+ raise ArgumentError, "Unknown OutboundMessage.message #{message}"
84
+ end
85
+ end
86
+ end
87
+
88
+ private_constant :Dispatcher
89
+ end
90
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ class Embedded
5
+ class Host
6
+ # The {FunctionRegistry} class.
7
+ #
8
+ # It stores sass custom functions and handles function calls.
9
+ class FunctionRegistry
10
+ attr_reader :global_functions
11
+
12
+ def initialize(functions, alert_color:)
13
+ functions = functions.transform_keys(&:to_s)
14
+
15
+ @global_functions = functions.keys
16
+ @functions_by_name = functions.transform_keys do |signature|
17
+ signature = signature.chomp
18
+ index = signature.index('(')
19
+ if index
20
+ signature.slice(0, index)
21
+ else
22
+ signature
23
+ end
24
+ end
25
+
26
+ @id = 0
27
+ @functions_by_id = {}
28
+ @ids_by_function = {}
29
+
30
+ @highlight = alert_color
31
+ end
32
+
33
+ def register(function)
34
+ return if @ids_by_function.key?(function)
35
+
36
+ id = @id
37
+ @id = id.next
38
+
39
+ @ids_by_function[function] = id
40
+ @functions_by_id[id] = function
41
+
42
+ id
43
+ end
44
+
45
+ def function_call(function_call_request)
46
+ arguments = function_call_request.arguments.map do |argument|
47
+ value_protofier.from_proto(argument)
48
+ end
49
+
50
+ success = value_protofier.to_proto(get(function_call_request).call(arguments))
51
+ accessed_argument_lists = arguments
52
+ .select do |argument|
53
+ argument.is_a?(Sass::Value::ArgumentList) && argument.instance_eval do
54
+ @keywords_accessed
55
+ end
56
+ end
57
+ .map { |argument| argument.instance_eval { @id } }
58
+
59
+ EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
60
+ id: function_call_request.id,
61
+ success: success,
62
+ accessed_argument_lists: accessed_argument_lists
63
+ )
64
+ rescue StandardError => e
65
+ EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
66
+ id: function_call_request.id,
67
+ error: e.full_message(highlight: @highlight, order: :top)
68
+ )
69
+ end
70
+
71
+ private
72
+
73
+ def get(function_call_request)
74
+ case function_call_request.identifier
75
+ when :name
76
+ @functions_by_name[function_call_request.name]
77
+ when :function_id
78
+ @functions_by_id[function_call_request.function_id]
79
+ end
80
+ end
81
+
82
+ def value_protofier
83
+ @value_protofier ||= ValueProtofier.new(self)
84
+ end
85
+ end
86
+
87
+ private_constant :FunctionRegistry
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ class Embedded
5
+ class Host
6
+ # The {ImporterRegistry} class.
7
+ #
8
+ # It stores importers and handles import requests.
9
+ class ImporterRegistry
10
+ attr_reader :importers
11
+
12
+ def initialize(importers, load_paths, alert_color:)
13
+ @id = 0
14
+ @importers_by_id = {}
15
+ @importers = importers
16
+ .map { |importer| register(importer) }
17
+ .concat(
18
+ load_paths.map do |load_path|
19
+ EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
20
+ path: File.absolute_path(load_path)
21
+ )
22
+ end
23
+ )
24
+
25
+ @highlight = alert_color
26
+ end
27
+
28
+ def register(importer)
29
+ importer = Structifier.to_struct(importer)
30
+
31
+ is_importer = importer.respond_to?(:canonicalize) && importer.respond_to?(:load)
32
+ is_file_importer = importer.respond_to?(:find_file_url)
33
+
34
+ raise ArgumentError, 'importer must be an Importer or a FileImporter' if is_importer == is_file_importer
35
+
36
+ id = @id
37
+ @id = id.next
38
+
39
+ @importers_by_id[id] = importer
40
+ if is_importer
41
+ EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
42
+ importer_id: id
43
+ )
44
+ else
45
+ EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
46
+ file_importer_id: id
47
+ )
48
+ end
49
+ end
50
+
51
+ def canonicalize(canonicalize_request)
52
+ importer = @importers_by_id[canonicalize_request.importer_id]
53
+ url = importer.canonicalize(canonicalize_request.url, from_import: canonicalize_request.from_import)&.to_s
54
+
55
+ EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
56
+ id: canonicalize_request.id,
57
+ url: url
58
+ )
59
+ rescue StandardError => e
60
+ EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
61
+ id: canonicalize_request.id,
62
+ error: e.full_message(highlight: @highlight, order: :top)
63
+ )
64
+ end
65
+
66
+ def import(import_request)
67
+ importer = @importers_by_id[import_request.importer_id]
68
+ importer_result = Structifier.to_struct importer.load(import_request.url)
69
+
70
+ EmbeddedProtocol::InboundMessage::ImportResponse.new(
71
+ id: import_request.id,
72
+ success: EmbeddedProtocol::InboundMessage::ImportResponse::ImportSuccess.new(
73
+ contents: importer_result.contents,
74
+ syntax: Protofier.to_proto_syntax(importer_result.syntax),
75
+ source_map_url: (importer_result.source_map_url&.to_s if importer_result.respond_to?(:source_map_url))
76
+ )
77
+ )
78
+ rescue StandardError => e
79
+ EmbeddedProtocol::InboundMessage::ImportResponse.new(
80
+ id: import_request.id,
81
+ error: e.full_message(highlight: @highlight, order: :top)
82
+ )
83
+ end
84
+
85
+ def file_import(file_import_request)
86
+ importer = @importers_by_id[file_import_request.importer_id]
87
+ file_url = importer.find_file_url(file_import_request.url, from_import: file_import_request.from_import)&.to_s
88
+
89
+ if !file_url.nil? && !file_url.start_with?('file:')
90
+ raise "file_url must be a file: URL, was #{file_url.inspect}"
91
+ end
92
+
93
+ EmbeddedProtocol::InboundMessage::FileImportResponse.new(
94
+ id: file_import_request.id,
95
+ file_url: file_url
96
+ )
97
+ rescue StandardError => e
98
+ EmbeddedProtocol::InboundMessage::FileImportResponse.new(
99
+ id: file_import_request.id,
100
+ error: e.full_message(highlight: @highlight, order: :top)
101
+ )
102
+ end
103
+ end
104
+
105
+ private_constant :ImporterRegistry
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ class Embedded
5
+ class Host
6
+ # The {LoggerRegistry} class.
7
+ #
8
+ # It stores logger and handles log events.
9
+ class LoggerRegistry
10
+ attr_reader :logger
11
+
12
+ def initialize(logger)
13
+ @logger = Structifier.to_struct(logger)
14
+ end
15
+
16
+ def log(event)
17
+ case event.type
18
+ when :DEBUG
19
+ if logger.respond_to? :debug
20
+ logger.debug(event.message,
21
+ span: Protofier.from_proto_source_span(event.span))
22
+ else
23
+ warn(event.formatted)
24
+ end
25
+ when :DEPRECATION_WARNING
26
+ if logger.respond_to? :warn
27
+ logger.warn(event.message,
28
+ deprecation: true,
29
+ span: Protofier.from_proto_source_span(event.span),
30
+ stack: event.stack_trace)
31
+ else
32
+ warn(event.formatted)
33
+ end
34
+ when :WARNING
35
+ if logger.respond_to? :warn
36
+ logger.warn(event.message,
37
+ deprecation: false,
38
+ span: Protofier.from_proto_source_span(event.span),
39
+ stack: event.stack_trace)
40
+ else
41
+ warn(event.formatted)
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ private_constant :LoggerRegistry
48
+ end
49
+ end
50
+ end