sass-embedded 0.9.0 → 0.10.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: c5bcaee2299b4f0b9d4d1d23b25773fdad87d1a294a4a34eeec0028d1f89a25c
4
- data.tar.gz: 75ce2615300b0d59e73f715ae43007baf09a9818ea56d80b8be4d54b1f561c69
3
+ metadata.gz: e3c01d861dce5149bb56f25e6cb89e54d21a26bc4e50486298f860b2386198b7
4
+ data.tar.gz: 36f04488a3118b833f6210766e590a617fe7204dabb31b0908023b32a008ed21
5
5
  SHA512:
6
- metadata.gz: 93cf20b2df8d4c363797df90e459f52c6dedf5e540cb5b6eb1cd110dded76477adf82f6c0bc0652f1b5201f535265053f7838654952a4bcc7f338bcc69c9464a
7
- data.tar.gz: c4190c8fc8e60a37fa834dfdac6fe1842e66d39ac8d0ad9bc1c15ea5c18c16766f19e194be746fc963a5604c740f438c6371aa59c10dd59d452a526fea6cbf0d
6
+ metadata.gz: c7c15d96579e3dc1843c3dfc66709c9a3ae48bcbb7458f0defcc91c313cffb53dc43b01d114c35b13b8a7b8cfae516440037730283d52e5ea506fffa70a9bcac
7
+ data.tar.gz: ae089947ade94c0550e9a066860e89e1c774572ddc1ab7c5b42327f4a9f3fe6db41c4422ce96a9454d63b44ae8675091239278ebd8d6f524438c0f680a3e5e26
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2021, なつき
1
+ Copyright (c) 2022, なつき
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -16,32 +16,12 @@ gem install sass-embedded
16
16
  ## Usage
17
17
 
18
18
  ``` ruby
19
- require "sass"
19
+ require 'sass'
20
20
 
21
- Sass.render(file: "style.scss")
21
+ Sass.compile('style.scss')
22
+ Sass.compile_string('h1 { font-size: 40px; }')
22
23
  ```
23
24
 
24
- ## Options
25
-
26
- `Sass.render(**kwargs)` supports the following options:
27
-
28
- - [`data`](https://sass-lang.com/documentation/js-api#data)
29
- - [`file`](https://sass-lang.com/documentation/js-api#file)
30
- - [`indented_syntax`](https://sass-lang.com/documentation/js-api#indentedsyntax)
31
- - [`include_paths`](https://sass-lang.com/documentation/js-api#includepaths)
32
- - [`output_style`](https://sass-lang.com/documentation/js-api#outputstyle)
33
- - [`indent_type`](https://sass-lang.com/documentation/js-api#indenttype)
34
- - [`indent_width`](https://sass-lang.com/documentation/js-api#indentwidth)
35
- - [`linefeed`](https://sass-lang.com/documentation/js-api#linefeed)
36
- - [`source_map`](https://sass-lang.com/documentation/js-api#sourcemap)
37
- - [`out_file`](https://sass-lang.com/documentation/js-api#outfile)
38
- - [`omit_source_map_url`](https://sass-lang.com/documentation/js-api#omitsourcemapurl)
39
- - [`source_map_contents`](https://sass-lang.com/documentation/js-api#sourcemapcontents)
40
- - [`source_map_embed`](https://sass-lang.com/documentation/js-api#sourcemapembed)
41
- - [`source_map_root`](https://sass-lang.com/documentation/js-api#sourcemaproot)
42
- - [`functions`](https://sass-lang.com/documentation/js-api#functions)
43
- - [`importer`](https://sass-lang.com/documentation/js-api#importer)
44
-
45
25
  ---
46
26
 
47
27
  Disclaimer: this is not an official Google product.
data/ext/sass/extconf.rb CHANGED
@@ -62,9 +62,7 @@ module Sass
62
62
  elsif uri.respond_to? :open
63
63
  puts "curl -fsSLo #{path} -- #{uri}"
64
64
  uri.open do |source|
65
- File.open(path, 'wb') do |destination|
66
- destination.write source.read
67
- end
65
+ File.binwrite(path, source.read)
68
66
  end
69
67
  else
70
68
  raise
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'logger/source_span'
4
+
5
+ module Sass
6
+ # The {CompileError} raised by {Embedded#compile} or {Embedded#compile_string}.
7
+ class CompileError < StandardError
8
+ attr_accessor :sass_message, :sass_stack, :span
9
+
10
+ def initialize(message, sass_message, sass_stack, span)
11
+ super(message)
12
+ @sass_message = sass_message
13
+ @sass_stack = sass_stack
14
+ @span = span
15
+ end
16
+
17
+ def self.from_proto(compile_failure)
18
+ CompileError.new(compile_failure.formatted,
19
+ compile_failure.message,
20
+ compile_failure.stack_trace,
21
+ Logger::SourceSpan.from_proto(compile_failure.span))
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ # The {CompileResult} of {Embedded#compile} or {Embedded#compile_string}.
5
+ class CompileResult
6
+ attr_reader :css, :source_map, :loaded_urls
7
+
8
+ def initialize(css, source_map, loaded_urls)
9
+ @css = css
10
+ @source_map = source_map == '' ? nil : source_map
11
+ @loaded_urls = loaded_urls
12
+ end
13
+
14
+ def self.from_proto(compile_success)
15
+ CompileResult.new(compile_success.css, compile_success.source_map, compile_success.loaded_urls)
16
+ end
17
+ end
18
+ end
@@ -29,7 +29,7 @@ module Sass
29
29
  @mutex.synchronize do
30
30
  begin
31
31
  id = @compiler.add_observer(observer)
32
- rescue IOError
32
+ rescue ProtocolError
33
33
  @compiler = Compiler.new
34
34
  id = @compiler.add_observer(observer)
35
35
  end
@@ -1,40 +1,58 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../embedded_protocol'
4
+ require_relative '../logger/source_span'
4
5
  require_relative 'observer'
5
- require_relative 'util'
6
6
 
7
7
  module Sass
8
8
  class Embedded
9
- # The {Observer} for {Embedded#render}.
9
+ # The {Observer} for {Embedded#compile}.
10
10
  class CompileContext
11
11
  include Observer
12
12
 
13
13
  def initialize(channel,
14
- data:,
15
- file:,
16
- indented_syntax:,
17
- include_paths:,
18
- output_style:,
14
+ path:,
15
+ source:,
16
+
17
+ importer:,
18
+ load_paths:,
19
+ syntax:,
20
+ url:,
21
+
19
22
  source_map:,
20
- out_file:,
23
+ style:,
24
+
21
25
  functions:,
22
- importer:)
23
- raise ArgumentError, 'either data or file must be set' if file.nil? && data.nil?
24
-
25
- @data = data
26
- @file = file
27
- @indented_syntax = indented_syntax
28
- @include_paths = include_paths
29
- @output_style = output_style
26
+ importers:,
27
+
28
+ alert_ascii:,
29
+ alert_color:,
30
+ logger:,
31
+ quiet_deps:,
32
+ verbose:)
33
+ @path = path
34
+ @source = source
35
+
36
+ @importer = importer
37
+ @load_paths = load_paths
38
+ @syntax = syntax
39
+ @url = url
40
+
30
41
  @source_map = source_map
31
- @out_file = out_file
32
- @global_functions = functions.keys
42
+ @style = style
43
+
44
+ @global_functions = functions.keys.map(&:to_s)
45
+
33
46
  @functions = functions.transform_keys do |key|
34
47
  key.to_s.split('(')[0].chomp
35
48
  end
36
- @importer = importer
37
- @import_responses = {}
49
+ @importers = importers
50
+
51
+ @alert_ascii = alert_ascii
52
+ @alert_color = alert_color
53
+ @logger = logger
54
+ @quiet_deps = quiet_deps
55
+ @verbose = verbose
38
56
 
39
57
  super(channel)
40
58
 
@@ -52,9 +70,9 @@ module Sass
52
70
  super(nil, message)
53
71
  end
54
72
  when EmbeddedProtocol::OutboundMessage::LogEvent
55
- return unless message.compilation_id == id && $stderr.tty?
73
+ return unless message.compilation_id == id
56
74
 
57
- warn message.formatted
75
+ log message
58
76
  when EmbeddedProtocol::OutboundMessage::CanonicalizeRequest
59
77
  return unless message.compilation_id == id
60
78
 
@@ -68,7 +86,11 @@ module Sass
68
86
  send_message import_response message
69
87
  end
70
88
  when EmbeddedProtocol::OutboundMessage::FileImportRequest
71
- raise NotImplementedError, 'FileImportRequest is not implemented'
89
+ return unless message.compilation_id == id
90
+
91
+ Thread.new do
92
+ send_message file_import_response message
93
+ end
72
94
  when EmbeddedProtocol::OutboundMessage::FunctionCallRequest
73
95
  return unless message.compilation_id == id
74
96
 
@@ -84,94 +106,107 @@ module Sass
84
106
 
85
107
  private
86
108
 
109
+ def log(event)
110
+ case event.type
111
+ when :DEBUG
112
+ if @logger.respond_to? :debug
113
+ @logger.debug(event.message, span: Logger::SourceSpan.from_proto(event.span))
114
+ else
115
+ Kernel.warn(event.formatted)
116
+ end
117
+ when :DEPRECATION_WARNING
118
+ if @logger.respond_to? :warn
119
+ @logger.warn(event.message, deprecation: true, span: Logger::SourceSpan.from_proto(event.span),
120
+ stack: event.stack_trace)
121
+ else
122
+ Kernel.warn(event.formatted)
123
+ end
124
+ when :WARNING
125
+ if @logger.respond_to? :warn
126
+ @logger.warn(event.message, deprecation: false, span: Logger::SourceSpan.from_proto(event.span),
127
+ stack: event.stack_trace)
128
+ else
129
+ Kernel.warn(event.formatted)
130
+ end
131
+ end
132
+ end
133
+
87
134
  def compile_request
88
135
  EmbeddedProtocol::InboundMessage::CompileRequest.new(
89
136
  id: id,
90
- string: string,
91
- path: path,
92
- style: style,
93
- source_map: source_map,
94
- importers: importers,
95
- global_functions: global_functions,
96
- alert_color: $stderr.tty?,
97
- alert_ascii: Platform::OS == 'windows'
137
+ string: unless @source.nil?
138
+ EmbeddedProtocol::InboundMessage::CompileRequest::StringInput.new(
139
+ source: @source,
140
+ url: @url,
141
+ syntax: to_proto_syntax(@syntax),
142
+ importer: @importer.nil? ? nil : to_proto_importer(@importer, @importers.length)
143
+ )
144
+ end,
145
+ path: @path,
146
+ style: to_proto_output_style(@style),
147
+ source_map: @source_map,
148
+ importers: to_proto_importers(@importers, @load_paths),
149
+ global_functions: @global_functions,
150
+ alert_ascii: @alert_ascii,
151
+ alert_color: @alert_color
98
152
  )
99
153
  end
100
154
 
101
155
  def canonicalize_response(canonicalize_request)
102
- url = Util.file_uri_from_path(File.absolute_path(canonicalize_request.url, (@file.nil? ? 'stdin' : @file)))
103
-
104
- begin
105
- result = @importer[canonicalize_request.importer_id].call canonicalize_request.url, @file
106
- raise result if result.is_a? StandardError
107
- rescue StandardError => e
108
- return EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
109
- id: canonicalize_request.id,
110
- error: e.message
111
- )
112
- end
113
-
114
- if result&.key? :contents
115
- @import_responses[url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
116
- id: canonicalize_request.id,
117
- success: EmbeddedProtocol::InboundMessage::ImportResponse::ImportSuccess.new(
118
- contents: result[:contents],
119
- syntax: EmbeddedProtocol::Syntax::SCSS,
120
- source_map_url: nil
121
- )
122
- )
123
- EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
124
- id: canonicalize_request.id,
125
- url: url
126
- )
127
- elsif result&.key? :file
128
- canonicalized_url = Util.file_uri_from_path(File.absolute_path(result[:file]))
129
-
130
- # TODO: FileImportRequest is not supported yet.
131
- # Workaround by reading contents and return it when server asks
132
- @import_responses[canonicalized_url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
133
- id: canonicalize_request.id,
134
- success: EmbeddedProtocol::InboundMessage::ImportResponse::ImportSuccess.new(
135
- contents: File.read(result[:file]),
136
- syntax: EmbeddedProtocol::Syntax::SCSS,
137
- source_map_url: nil
138
- )
139
- )
156
+ url = importer_with_id(canonicalize_request.importer_id).canonicalize canonicalize_request.url
140
157
 
141
- EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
142
- id: canonicalize_request.id,
143
- url: canonicalized_url
144
- )
145
- else
146
- EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
147
- id: canonicalize_request.id
148
- )
149
- end
158
+ EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
159
+ id: canonicalize_request.id,
160
+ url: url
161
+ )
162
+ rescue StandardError => e
163
+ EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
164
+ id: canonicalize_request.id,
165
+ error: e.message
166
+ )
150
167
  end
151
168
 
152
169
  def import_response(import_request)
153
- url = import_request.url
154
-
155
- if @import_responses.key? url
156
- @import_responses[url].id = import_request.id
157
- else
158
- @import_responses[url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
159
- id: import_request.id,
160
- error: "Failed to import: #{url}"
170
+ importer_result = importer_with_id(import_request.importer_id).load import_request.url
171
+
172
+ EmbeddedProtocol::InboundMessage::ImportResponse.new(
173
+ id: import_request.id,
174
+ success: EmbeddedProtocol::InboundMessage::ImportResponse::ImportSuccess.new(
175
+ contents: importer_result.contents,
176
+ syntax: to_proto_syntax(importer_result.syntax),
177
+ source_map_url: importer_result.source_map_url
161
178
  )
162
- end
179
+ )
180
+ rescue StandardError => e
181
+ EmbeddedProtocol::InboundMessage::ImportResponse.new(
182
+ id: import_request.id,
183
+ error: e.message
184
+ )
185
+ end
163
186
 
164
- @import_responses[url]
187
+ def file_import_response(file_import_request)
188
+ file_importer = importer_with_id(file_import_request.importer_id)
189
+ file_url = file_importer.find_file_url file_import_request.url,
190
+ from_import: file_import_request.from_import
191
+
192
+ EmbeddedProtocol::InboundMessage::FileImportResponse.new(
193
+ id: file_import_request.id,
194
+ file_url: file_url
195
+ )
196
+ rescue StandardError => e
197
+ EmbeddedProtocol::InboundMessage::FileImportResponse.new(
198
+ id: file_import_request.id,
199
+ error: e.message
200
+ )
165
201
  end
166
202
 
167
203
  def function_call_response(function_call_request)
168
- # TODO: convert argument_list to **kwargs
169
204
  EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
170
205
  id: function_call_request.id,
171
206
  success: @functions[function_call_request.name].call(*function_call_request.arguments),
172
207
  accessed_argument_lists: function_call_request.arguments
173
- .filter { |argument| argument.value == :argument_list }
174
- .map { |argument| argument.argument_list.id }
208
+ .filter { |argument| argument.value == :argument_list }
209
+ .map { |argument| argument.argument_list.id }
175
210
  )
176
211
  rescue StandardError => e
177
212
  EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
@@ -180,36 +215,21 @@ module Sass
180
215
  )
181
216
  end
182
217
 
183
- def syntax
184
- if @indented_syntax == true
218
+ def to_proto_syntax(syntax)
219
+ case syntax&.to_sym
220
+ when :scss
221
+ EmbeddedProtocol::Syntax::SCSS
222
+ when :indented
185
223
  EmbeddedProtocol::Syntax::INDENTED
224
+ when :css
225
+ EmbeddedProtocol::Syntax::CSS
186
226
  else
187
- EmbeddedProtocol::Syntax::SCSS
227
+ raise ArgumentError, 'syntax must be one of :scss, :indented, :css'
188
228
  end
189
229
  end
190
230
 
191
- def url
192
- return if @file.nil?
193
-
194
- Util.file_uri_from_path File.absolute_path @file
195
- end
196
-
197
- def string
198
- return if @data.nil?
199
-
200
- EmbeddedProtocol::InboundMessage::CompileRequest::StringInput.new(
201
- source: @data,
202
- url: url,
203
- syntax: syntax
204
- )
205
- end
206
-
207
- def path
208
- @file if @data.nil?
209
- end
210
-
211
- def style
212
- case @output_style&.to_sym
231
+ def to_proto_output_style(style)
232
+ case style&.to_sym
213
233
  when :expanded
214
234
  EmbeddedProtocol::OutputStyle::EXPANDED
215
235
  when :compressed
@@ -219,35 +239,40 @@ module Sass
219
239
  end
220
240
  end
221
241
 
222
- def source_map
223
- @source_map.is_a?(String) || (@source_map == true && !@out_file.nil?)
224
- end
225
-
226
- attr_reader :global_functions
227
-
228
- # Order
229
- # 1. Loading a file relative to the file in which the @use or @import appeared.
230
- # 2. Each custom importer.
231
- # 3. Loading a file relative to the current working directory.
232
- # 4. Each load path in includePaths
233
- # 5. Each load path specified in the SASS_PATH environment variable, which should
234
- # be semicolon-separated on Windows and colon-separated elsewhere.
235
- def importers
236
- custom_importers = @importer.map.with_index do |_, id|
242
+ def to_proto_importer(importer, id)
243
+ if importer.respond_to?(:canonicalize) && importer.respond_to?(:load)
237
244
  EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
238
245
  importer_id: id
239
246
  )
247
+ elsif importer.respond_to?(:find_file_url)
248
+ EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
249
+ file_importer_id: id
250
+ )
251
+ else
252
+ raise ArgumentError, 'importer must be an Importer or a FileImporter'
240
253
  end
254
+ end
241
255
 
242
- include_path_importers = @include_paths
243
- .concat(Embedded.include_paths)
244
- .map do |include_path|
245
- EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
246
- path: File.absolute_path(include_path)
256
+ def to_proto_importers(importers, load_paths)
257
+ proto_importers = importers.map.with_index do |importer, id|
258
+ to_proto_importer(importer, id)
259
+ end
260
+
261
+ load_paths.each do |load_path|
262
+ proto_importers << EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
263
+ path: File.absolute_path(load_path)
247
264
  )
248
265
  end
249
266
 
250
- custom_importers.concat include_path_importers
267
+ proto_importers
268
+ end
269
+
270
+ def importer_with_id(id)
271
+ if id == @importers.length
272
+ @importer
273
+ else
274
+ @importers[id]
275
+ end
251
276
  end
252
277
  end
253
278
  end
@@ -3,7 +3,7 @@
3
3
  module Sass
4
4
  class Embedded
5
5
  class Compiler
6
- REQUIREMENTS = '~> 1.0.0-beta.11'
6
+ REQUIREMENTS = '~> 1.0.0-beta.16'
7
7
  end
8
8
  end
9
9
  end
@@ -4,7 +4,7 @@ require 'observer'
4
4
  require 'open3'
5
5
  require_relative '../embedded_protocol'
6
6
  require_relative 'compiler/path'
7
- require_relative 'error'
7
+ require_relative 'protocol_error'
8
8
 
9
9
  module Sass
10
10
  class Embedded
@@ -17,9 +17,9 @@ module Sass
17
17
  ONEOF_MESSAGE = EmbeddedProtocol::InboundMessage
18
18
  .descriptor
19
19
  .lookup_oneof('message')
20
- .collect do |field_descriptor|
20
+ .to_h do |field_descriptor|
21
21
  [field_descriptor.subtype, field_descriptor.name]
22
- end.to_h
22
+ end
23
23
 
24
24
  private_constant :ONEOF_MESSAGE
25
25
 
@@ -41,7 +41,7 @@ module Sass
41
41
 
42
42
  def add_observer(*args)
43
43
  @observerable_mutex.synchronize do
44
- raise IOError, 'half-closed compiler' if half_closed?
44
+ raise ProtocolError, 'half-closed compiler' if half_closed?
45
45
 
46
46
  super(*args)
47
47
 
@@ -25,6 +25,7 @@ module Sass
25
25
 
26
26
  def update(error, message)
27
27
  @subscription.unsubscribe
28
+
28
29
  @mutex.synchronize do
29
30
  @error = error
30
31
  @message = message
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ class Embedded
5
+ class ProtocolError < StandardError; end
6
+ end
7
+ end