sass-embedded 0.8.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/sass/embedded.rb CHANGED
@@ -2,10 +2,17 @@
2
2
 
3
3
  require 'base64'
4
4
  require 'json'
5
+ require_relative 'embedded/channel'
6
+ require_relative 'embedded/compile_context'
7
+ require_relative 'embedded/error'
8
+ require_relative 'embedded/result'
9
+ require_relative 'embedded/util'
10
+ require_relative 'embedded/version'
11
+ require_relative 'embedded/version_context'
5
12
 
6
13
  module Sass
7
14
  # The {Embedded} host for using dart-sass-embedded. Each instance creates
8
- # its own {Transport}.
15
+ # its own {Channel}.
9
16
  #
10
17
  # @example
11
18
  # embedded = Sass::Embedded.new
@@ -13,17 +20,23 @@ module Sass
13
20
  # result = embedded.render(file: 'style.css')
14
21
  # embedded.close
15
22
  class Embedded
23
+ def self.include_paths
24
+ @include_paths ||= if ENV['SASS_PATH']
25
+ ENV['SASS_PATH'].split(File::PATH_SEPARATOR)
26
+ else
27
+ []
28
+ end
29
+ end
30
+
16
31
  def initialize
17
- @transport = Transport.new
18
- @id_semaphore = Mutex.new
19
- @id = 0
32
+ @channel = Channel.new
20
33
  end
21
34
 
22
35
  # The {Embedded#info} method.
23
36
  #
24
37
  # @raise [ProtocolError]
25
38
  def info
26
- @info ||= VersionContext.new(@transport, next_id).receive_message
39
+ @info ||= VersionContext.new(@channel).receive_message
27
40
  end
28
41
 
29
42
  # The {Embedded#render} method.
@@ -55,7 +68,7 @@ module Sass
55
68
  indent_width = parse_indent_width(indent_width)
56
69
  linefeed = parse_linefeed(linefeed)
57
70
 
58
- message = CompileContext.new(@transport, next_id,
71
+ message = CompileContext.new(@channel,
59
72
  data: data,
60
73
  file: file,
61
74
  indented_syntax: indented_syntax,
@@ -109,11 +122,11 @@ module Sass
109
122
  end
110
123
 
111
124
  def close
112
- @transport.close
125
+ @channel.close
113
126
  end
114
127
 
115
128
  def closed?
116
- @transport.closed?
129
+ @channel.closed?
117
130
  end
118
131
 
119
132
  private
@@ -239,13 +252,5 @@ module Sass
239
252
  raise ArgumentError, 'linefeed must be one of :lf, :lfcr, :cr, :crlf'
240
253
  end
241
254
  end
242
-
243
- def next_id
244
- @id_semaphore.synchronize do
245
- @id += 1
246
- @id = 0 if @id == Compiler::PROTOCOL_ERROR_ID
247
- @id
248
- end
249
- end
250
255
  end
251
256
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
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
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'sass'
data/lib/sass.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'sass/embedded'
4
+
3
5
  # The Sass module. This communicates with Embedded Dart Sass using
4
6
  # the Embedded Sass protocol.
5
7
  module Sass
@@ -19,11 +21,7 @@ module Sass
19
21
  # Sass.include_paths << File.dirname(__FILE__) + '/sass'
20
22
  # @return [Array]
21
23
  def include_paths
22
- @include_paths ||= if ENV['SASS_PATH']
23
- ENV['SASS_PATH'].split(File::PATH_SEPARATOR)
24
- else
25
- []
26
- end
24
+ Embedded.include_paths
27
25
  end
28
26
 
29
27
  # The global {.info} method. This instantiates a global {Embedded} instance
@@ -31,7 +29,7 @@ module Sass
31
29
  #
32
30
  # @raise [ProtocolError]
33
31
  def info
34
- embedded.info
32
+ instance.info
35
33
  end
36
34
 
37
35
  # The global {.render} method. This instantiates a global {Embedded} instance
@@ -47,28 +45,21 @@ module Sass
47
45
  # @raise [ProtocolError]
48
46
  # @raise [RenderError]
49
47
  def render(**kwargs)
50
- embedded.render(**kwargs)
48
+ instance.render(**kwargs)
51
49
  end
52
50
 
53
51
  private
54
52
 
55
- def embedded
56
- return @embedded if defined?(@embedded) && !@embedded.closed?
57
-
58
- @embedded = Sass::Embedded.new
53
+ def instance
54
+ if @instance.nil?
55
+ @instance = Embedded.new
56
+ at_exit do
57
+ @instance.close
58
+ end
59
+ elsif @instance.closed?
60
+ @instance = Embedded.new
61
+ end
62
+ @instance
59
63
  end
60
64
  end
61
65
  end
62
-
63
- require_relative 'sass/version'
64
- require_relative 'sass/platform'
65
- require_relative 'sass/compiler'
66
- require_relative 'sass/util'
67
- require_relative 'sass/struct'
68
- require_relative 'sass/result'
69
- require_relative 'sass/error'
70
- require_relative 'sass/transport'
71
- require_relative 'sass/observer'
72
- require_relative 'sass/info'
73
- require_relative 'sass/compile'
74
- require_relative 'sass/embedded'
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.8.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - なつき
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-23 00:00:00.000000000 Z
11
+ date: 2021-09-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-protobuf
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.15.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-performance
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 1.11.5
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 1.11.5
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: rubocop-rake
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -122,25 +136,29 @@ files:
122
136
  - ext/sass/Makefile
123
137
  - ext/sass/extconf.rb
124
138
  - ext/sass/unzip.vbs
139
+ - lib/sass-embedded.rb
125
140
  - lib/sass.rb
126
- - lib/sass/compile.rb
127
- - lib/sass/compiler.rb
128
141
  - lib/sass/embedded.rb
129
- - lib/sass/error.rb
130
- - lib/sass/info.rb
131
- - lib/sass/observer.rb
132
- - lib/sass/platform.rb
133
- - lib/sass/result.rb
134
- - lib/sass/struct.rb
135
- - lib/sass/transport.rb
136
- - lib/sass/util.rb
137
- - lib/sass/version.rb
142
+ - lib/sass/embedded/channel.rb
143
+ - lib/sass/embedded/compile_context.rb
144
+ - lib/sass/embedded/compiler.rb
145
+ - lib/sass/embedded/compiler/path.rb
146
+ - lib/sass/embedded/compiler/requirements.rb
147
+ - lib/sass/embedded/error.rb
148
+ - lib/sass/embedded/observer.rb
149
+ - lib/sass/embedded/platform.rb
150
+ - lib/sass/embedded/result.rb
151
+ - lib/sass/embedded/struct.rb
152
+ - lib/sass/embedded/util.rb
153
+ - lib/sass/embedded/version.rb
154
+ - lib/sass/embedded/version_context.rb
155
+ - lib/sass/embedded_protocol.rb
138
156
  homepage: https://github.com/ntkme/sass-embedded-host-ruby
139
157
  licenses:
140
158
  - MIT
141
159
  metadata:
142
- documentation_uri: https://www.rubydoc.info/gems/sass-embedded/0.8.0
143
- source_code_uri: https://github.com/ntkme/sass-embedded-host-ruby/tree/v0.8.0
160
+ documentation_uri: https://www.rubydoc.info/gems/sass-embedded/0.9.1
161
+ source_code_uri: https://github.com/ntkme/sass-embedded-host-ruby/tree/v0.9.1
144
162
  funding_uri: https://github.com/sponsors/ntkme
145
163
  post_install_message:
146
164
  rdoc_options: []
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