sass-embedded 0.4.0 → 0.6.1
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/.rubocop.yml +0 -3
- data/README.md +26 -0
- data/ext/extconf.rb +14 -2
- data/lib/sass.rb +59 -37
- data/lib/sass/embedded.rb +50 -255
- data/lib/sass/error.rb +8 -6
- data/lib/sass/info.rb +30 -0
- data/lib/sass/observer.rb +37 -0
- data/lib/sass/render.rb +242 -0
- data/lib/sass/result.rb +30 -0
- data/lib/sass/struct.rb +20 -0
- data/lib/sass/transport.rb +30 -66
- data/lib/sass/util.rb +3 -1
- data/lib/sass/version.rb +1 -1
- data/sass-embedded.gemspec +2 -2
- data/test/functions_test.rb +4 -0
- metadata +9 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b23c7315185f78d02c9776c433a60a3ea62ce88b80a877ec17c66d4565416b5e
|
4
|
+
data.tar.gz: ce45e36c77e6aa2d04e211e5a50d265b1095c33d3a695793b68dc181b9fcf71f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 699daac722babfcca657ae536c65f31c7882273cec287d33c98bec4dbbef9c1ce38242fefaad89592de563495687ed151428bb1c9e331e7e85d4ee0eb023f1b3
|
7
|
+
data.tar.gz: b2cd65ecccfd4f07f8f280a493fe7484e819cce8210ae12fffd5ee954529a3fa3562d9a8f9a21ee2783ab98e36307f6421aedcdeea63ca832abf31ea7cd8d7b9
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -6,6 +6,12 @@ This is a Ruby library that implements the host side of the [Embedded Sass proto
|
|
6
6
|
|
7
7
|
It exposes a Ruby API for Sass that's backed by a native [Dart Sass](https://sass-lang.com/dart-sass) executable.
|
8
8
|
|
9
|
+
## Install
|
10
|
+
|
11
|
+
``` sh
|
12
|
+
gem install sass-embedded
|
13
|
+
```
|
14
|
+
|
9
15
|
## Usage
|
10
16
|
|
11
17
|
``` ruby
|
@@ -14,6 +20,26 @@ require "sass"
|
|
14
20
|
Sass.render(file: "style.scss")
|
15
21
|
```
|
16
22
|
|
23
|
+
## Options
|
24
|
+
|
25
|
+
`Sass.render()` support the following options:
|
26
|
+
|
27
|
+
- [`data`](https://sass-lang.com/documentation/js-api#data)
|
28
|
+
- [`file`](https://sass-lang.com/documentation/js-api#file)
|
29
|
+
- [`indented_syntax`](https://sass-lang.com/documentation/js-api#indentedsyntax)
|
30
|
+
- [`include_paths`](https://sass-lang.com/documentation/js-api#includepaths)
|
31
|
+
- [`output_style`](https://sass-lang.com/documentation/js-api#outputstyle)
|
32
|
+
- [`indent_type`](https://sass-lang.com/documentation/js-api#indenttype)
|
33
|
+
- [`indent_width`](https://sass-lang.com/documentation/js-api#indentwidth)
|
34
|
+
- [`linefeed`](https://sass-lang.com/documentation/js-api#linefeed)
|
35
|
+
- [`source_map`](https://sass-lang.com/documentation/js-api#sourcemap)
|
36
|
+
- [`out_file`](https://sass-lang.com/documentation/js-api#outfile)
|
37
|
+
- [`omit_source_map_url`](https://sass-lang.com/documentation/js-api#omitsourcemapurl)
|
38
|
+
- [`source_map_embed`](https://sass-lang.com/documentation/js-api#sourcemapembed)
|
39
|
+
- [`source_map_root`](https://sass-lang.com/documentation/js-api#sourcemaproot)
|
40
|
+
- [`functions`](https://sass-lang.com/documentation/js-api#functions)
|
41
|
+
- [`importer`](https://sass-lang.com/documentation/js-api#importer)
|
42
|
+
|
17
43
|
---
|
18
44
|
|
19
45
|
Disclaimer: this is not an official Google product.
|
data/ext/extconf.rb
CHANGED
@@ -8,12 +8,24 @@ require 'fileutils'
|
|
8
8
|
require_relative '../lib/sass/platform'
|
9
9
|
|
10
10
|
module Sass
|
11
|
-
#
|
11
|
+
# The dependency downloader. This downloads all the dependencies during gem
|
12
|
+
# installation. The companion Makefile then unpacks all downloaded
|
13
|
+
# dependencies. By default it downloads the latest release of each
|
14
|
+
# dependency from GitHub releases.
|
15
|
+
#
|
16
|
+
# It is possible to specify an alternative source or version of each
|
17
|
+
# dependency. Local sources can be used for offline installation.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
# gem install sass-embedded -- \
|
21
|
+
# --with-protoc=file:///path/to/protoc-*.zip \
|
22
|
+
# --with-sass-embedded=file:///path/to/sass_embedded-*.(tar.gz|zip) \
|
23
|
+
# --with-sass-embedded-protocol=file:///path/to/embedded_sass.proto
|
12
24
|
class Extconf
|
13
25
|
def initialize
|
26
|
+
get_with_config('protoc', true) { latest_protoc }
|
14
27
|
get_with_config('sass-embedded', true) { latest_sass_embedded }
|
15
28
|
get_with_config('sass-embedded-protocol', true) { latest_sass_embedded_protocol }
|
16
|
-
get_with_config('protoc', true) { latest_protoc }
|
17
29
|
end
|
18
30
|
|
19
31
|
private
|
data/lib/sass.rb
CHANGED
@@ -1,50 +1,72 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# The Sass module
|
3
|
+
# The Sass module. This communicates with Embedded Dart Sass using
|
4
|
+
# the Embedded Sass protocol.
|
4
5
|
module Sass
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
6
|
+
class << self
|
7
|
+
# The global {.include_paths} for Sass files. This is meant for plugins and
|
8
|
+
# libraries to register the paths to their Sass stylesheets to that they may
|
9
|
+
# be included via `@import` or `@use`. This include path is used by every
|
10
|
+
# instance of {Sass::Embedded}. They are lower-precedence than any include
|
11
|
+
# paths passed in via the `include_paths` option.
|
12
|
+
#
|
13
|
+
# If the `SASS_PATH` environment variable is set,
|
14
|
+
# the initial value of `include_paths` will be initialized based on that.
|
15
|
+
# The variable should be a colon-separated list of path names
|
16
|
+
# (semicolon-separated on Windows).
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
# Sass.include_paths << File.dirname(__FILE__) + '/sass'
|
20
|
+
# @return [Array]
|
21
|
+
def include_paths
|
22
|
+
@include_paths ||= if ENV['SASS_PATH']
|
23
|
+
ENV['SASS_PATH'].split(File::PATH_SEPARATOR)
|
24
|
+
else
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# The global {.info} method. This instantiates a global {Embedded} instance
|
30
|
+
# and calls {Embedded#info}.
|
31
|
+
#
|
32
|
+
# @raise [ProtocolError]
|
33
|
+
def info
|
34
|
+
embedded.info
|
35
|
+
end
|
36
|
+
|
37
|
+
# The global {.render} method. This instantiates a global {Embedded} instance
|
38
|
+
# and calls {Embedded#render}.
|
39
|
+
#
|
40
|
+
# See {file:README.md#options} for supported options.
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# Sass.render(data: 'h1 { font-size: 40px; }')
|
44
|
+
# @example
|
45
|
+
# Sass.render(file: 'style.css')
|
46
|
+
# @return [Result]
|
47
|
+
# @raise [ProtocolError]
|
48
|
+
# @raise [RenderError]
|
49
|
+
def render(**kwargs)
|
50
|
+
embedded.render(**kwargs)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def embedded
|
56
|
+
return @embedded if defined?(@embedded) && !@embedded.closed?
|
26
57
|
|
27
|
-
# The global render methods. This method automatically instantiates a
|
28
|
-
# global {Sass::Embedded} instance when invoked the first time and call
|
29
|
-
# `:render` method on the instance thereafter. The global {Sass::Embedded}
|
30
|
-
# is automatically closed via {Kernel.at_exit}.
|
31
|
-
# @example
|
32
|
-
# Sass.render(options)
|
33
|
-
# @return [Hash]
|
34
|
-
def self.render(**kwargs)
|
35
|
-
unless defined? @embedded
|
36
58
|
@embedded = Sass::Embedded.new
|
37
|
-
at_exit do
|
38
|
-
@embedded.close
|
39
|
-
end
|
40
59
|
end
|
41
|
-
@embedded.render(**kwargs)
|
42
60
|
end
|
43
61
|
end
|
44
62
|
|
45
|
-
require_relative 'sass/version'
|
46
|
-
require_relative 'sass/error'
|
47
63
|
require_relative 'sass/platform'
|
48
64
|
require_relative 'sass/util'
|
65
|
+
require_relative 'sass/struct'
|
66
|
+
require_relative 'sass/result'
|
67
|
+
require_relative 'sass/error'
|
49
68
|
require_relative 'sass/transport'
|
69
|
+
require_relative 'sass/observer'
|
70
|
+
require_relative 'sass/version'
|
71
|
+
require_relative 'sass/render'
|
50
72
|
require_relative 'sass/embedded'
|
data/lib/sass/embedded.rb
CHANGED
@@ -1,10 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'json'
|
4
3
|
require 'base64'
|
4
|
+
require 'json'
|
5
5
|
|
6
6
|
module Sass
|
7
|
-
# The
|
7
|
+
# The {Embedded} host for using dart-sass-embedded. Each instance creates
|
8
|
+
# its own {Transport}.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# embedded = Sass::Embedded.new
|
12
|
+
# result = embedded.render(data: 'h1 { font-size: 40px; }')
|
13
|
+
# result = embedded.render(file: 'style.css')
|
14
|
+
# embedded.close
|
8
15
|
class Embedded
|
9
16
|
def initialize
|
10
17
|
@transport = Transport.new
|
@@ -12,22 +19,28 @@ module Sass
|
|
12
19
|
@id = 0
|
13
20
|
end
|
14
21
|
|
22
|
+
# The {Embedded#info} method.
|
23
|
+
#
|
24
|
+
# @raise [ProtocolError]
|
15
25
|
def info
|
16
|
-
@
|
17
|
-
id: next_id
|
18
|
-
)
|
26
|
+
@info ||= Version.new(@transport, next_id).fetch
|
19
27
|
end
|
20
28
|
|
29
|
+
# The {Embedded#render} method.
|
30
|
+
#
|
31
|
+
# See {file:README.md#options} for supported options.
|
32
|
+
#
|
33
|
+
# @return [Result]
|
34
|
+
# @raise [ProtocolError]
|
35
|
+
# @raise [RenderError]
|
21
36
|
def render(data: nil,
|
22
37
|
file: nil,
|
23
38
|
indented_syntax: false,
|
24
39
|
include_paths: [],
|
25
40
|
output_style: :expanded,
|
26
|
-
# precision: 5,
|
27
41
|
indent_type: :space,
|
28
42
|
indent_width: 2,
|
29
43
|
linefeed: :lf,
|
30
|
-
# source_comments: false,
|
31
44
|
source_map: false,
|
32
45
|
out_file: nil,
|
33
46
|
omit_source_map_url: false,
|
@@ -42,61 +55,41 @@ module Sass
|
|
42
55
|
indent_width = parse_indent_width(indent_width)
|
43
56
|
linefeed = parse_linefeed(linefeed)
|
44
57
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
)
|
58
|
-
|
59
|
-
response = @transport.send renderer.compile_request(compilation_id), compilation_id
|
60
|
-
|
61
|
-
loop do
|
62
|
-
case response
|
63
|
-
when EmbeddedProtocol::OutboundMessage::CompileResponse
|
64
|
-
break
|
65
|
-
when EmbeddedProtocol::OutboundMessage::CanonicalizeRequest
|
66
|
-
response = @transport.send renderer.canonicalize_response(response), compilation_id
|
67
|
-
when EmbeddedProtocol::OutboundMessage::ImportRequest
|
68
|
-
response = @transport.send renderer.import_response(response), compilation_id
|
69
|
-
when EmbeddedProtocol::OutboundMessage::FunctionCallRequest
|
70
|
-
response = @transport.send renderer.function_call_response(response), compilation_id
|
71
|
-
when EmbeddedProtocol::ProtocolError
|
72
|
-
raise ProtocolError, response.message
|
73
|
-
else
|
74
|
-
raise ProtocolError, "Unexpected packet received: #{response}"
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
if response.failure
|
58
|
+
message = Render.new(@transport, next_id,
|
59
|
+
data: data,
|
60
|
+
file: file,
|
61
|
+
indented_syntax: indented_syntax,
|
62
|
+
include_paths: include_paths,
|
63
|
+
output_style: output_style,
|
64
|
+
source_map: source_map,
|
65
|
+
out_file: out_file,
|
66
|
+
functions: functions,
|
67
|
+
importer: importer).fetch
|
68
|
+
|
69
|
+
if message.failure
|
79
70
|
raise RenderError.new(
|
80
|
-
|
81
|
-
|
82
|
-
if
|
71
|
+
message.failure.message,
|
72
|
+
message.failure.formatted,
|
73
|
+
if message.failure.span.nil?
|
74
|
+
nil
|
75
|
+
elsif message.failure.span.url == ''
|
83
76
|
'stdin'
|
84
77
|
else
|
85
|
-
Util.path(
|
78
|
+
Util.path(message.failure.span.url)
|
86
79
|
end,
|
87
|
-
|
88
|
-
|
80
|
+
message.failure.span ? message.failure.span.start.line + 1 : nil,
|
81
|
+
message.failure.span ? message.failure.span.start.column + 1 : nil,
|
89
82
|
1
|
90
83
|
)
|
91
84
|
end
|
92
85
|
|
93
|
-
map, source_map = post_process_map(map:
|
86
|
+
map, source_map = post_process_map(map: message.success.source_map,
|
94
87
|
file: file,
|
95
88
|
out_file: out_file,
|
96
89
|
source_map: source_map,
|
97
90
|
source_map_root: source_map_root)
|
98
91
|
|
99
|
-
css = post_process_css(css:
|
92
|
+
css = post_process_css(css: message.success.css,
|
100
93
|
indent_type: indent_type,
|
101
94
|
indent_width: indent_width,
|
102
95
|
linefeed: linefeed,
|
@@ -108,21 +101,17 @@ module Sass
|
|
108
101
|
|
109
102
|
finish = Util.now
|
110
103
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
stats: {
|
115
|
-
entry: file.nil? ? 'data' : file,
|
116
|
-
start: start,
|
117
|
-
end: finish,
|
118
|
-
duration: finish - start
|
119
|
-
}
|
120
|
-
}
|
104
|
+
stats = Result::Stats.new(file.nil? ? 'data' : file, start, finish, finish - start)
|
105
|
+
|
106
|
+
Result.new(css, map, stats)
|
121
107
|
end
|
122
108
|
|
123
109
|
def close
|
124
110
|
@transport.close
|
125
|
-
|
111
|
+
end
|
112
|
+
|
113
|
+
def closed?
|
114
|
+
@transport.closed?
|
126
115
|
end
|
127
116
|
|
128
117
|
private
|
@@ -205,7 +194,7 @@ module Sass
|
|
205
194
|
when :tab
|
206
195
|
"\t"
|
207
196
|
else
|
208
|
-
raise ArgumentError, 'indent_type must be :space
|
197
|
+
raise ArgumentError, 'indent_type must be one of :space, :tab'
|
209
198
|
end
|
210
199
|
end
|
211
200
|
|
@@ -238,199 +227,5 @@ module Sass
|
|
238
227
|
@id
|
239
228
|
end
|
240
229
|
end
|
241
|
-
|
242
|
-
# Helper class that maintains render state
|
243
|
-
class Renderer
|
244
|
-
def initialize(data:,
|
245
|
-
file:,
|
246
|
-
indented_syntax:,
|
247
|
-
include_paths:,
|
248
|
-
output_style:,
|
249
|
-
source_map:,
|
250
|
-
out_file:,
|
251
|
-
functions:,
|
252
|
-
importer:)
|
253
|
-
raise ArgumentError, 'either data or file must be set' if file.nil? && data.nil?
|
254
|
-
|
255
|
-
@data = data
|
256
|
-
@file = file
|
257
|
-
@indented_syntax = indented_syntax
|
258
|
-
@include_paths = include_paths
|
259
|
-
@output_style = output_style
|
260
|
-
@source_map = source_map
|
261
|
-
@out_file = out_file
|
262
|
-
@global_functions = functions.keys
|
263
|
-
@functions = functions.transform_keys do |key|
|
264
|
-
key.to_s.split('(')[0].chomp
|
265
|
-
end
|
266
|
-
@importer = importer
|
267
|
-
@import_responses = {}
|
268
|
-
end
|
269
|
-
|
270
|
-
def compile_request(id)
|
271
|
-
EmbeddedProtocol::InboundMessage::CompileRequest.new(
|
272
|
-
id: id,
|
273
|
-
string: string,
|
274
|
-
path: path,
|
275
|
-
style: style,
|
276
|
-
source_map: source_map,
|
277
|
-
importers: importers,
|
278
|
-
global_functions: global_functions,
|
279
|
-
alert_color: $stderr.tty?,
|
280
|
-
alert_ascii: Platform::OS == 'windows'
|
281
|
-
)
|
282
|
-
end
|
283
|
-
|
284
|
-
def canonicalize_response(canonicalize_request)
|
285
|
-
url = Util.file_uri(File.absolute_path(canonicalize_request.url, (@file.nil? ? 'stdin' : @file)))
|
286
|
-
|
287
|
-
begin
|
288
|
-
result = @importer[canonicalize_request.importer_id].call canonicalize_request.url, @file
|
289
|
-
raise result if result.is_a? StandardError
|
290
|
-
rescue StandardError => e
|
291
|
-
return EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
292
|
-
id: canonicalize_request.id,
|
293
|
-
error: e.message
|
294
|
-
)
|
295
|
-
end
|
296
|
-
|
297
|
-
if result&.key? :contents
|
298
|
-
@import_responses[url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
|
299
|
-
id: canonicalize_request.id,
|
300
|
-
success: EmbeddedProtocol::InboundMessage::ImportResponse::ImportSuccess.new(
|
301
|
-
contents: result[:contents],
|
302
|
-
syntax: EmbeddedProtocol::Syntax::SCSS,
|
303
|
-
source_map_url: nil
|
304
|
-
)
|
305
|
-
)
|
306
|
-
EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
307
|
-
id: canonicalize_request.id,
|
308
|
-
url: url
|
309
|
-
)
|
310
|
-
elsif result&.key? :file
|
311
|
-
canonicalized_url = Util.file_uri(result[:file])
|
312
|
-
|
313
|
-
# TODO: FileImportRequest is not supported yet.
|
314
|
-
# Workaround by reading contents and return it when server asks
|
315
|
-
@import_responses[canonicalized_url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
|
316
|
-
id: canonicalize_request.id,
|
317
|
-
success: EmbeddedProtocol::InboundMessage::ImportResponse::ImportSuccess.new(
|
318
|
-
contents: File.read(result[:file]),
|
319
|
-
syntax: EmbeddedProtocol::Syntax::SCSS,
|
320
|
-
source_map_url: nil
|
321
|
-
)
|
322
|
-
)
|
323
|
-
|
324
|
-
EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
325
|
-
id: canonicalize_request.id,
|
326
|
-
url: canonicalized_url
|
327
|
-
)
|
328
|
-
else
|
329
|
-
EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
330
|
-
id: canonicalize_request.id
|
331
|
-
)
|
332
|
-
end
|
333
|
-
end
|
334
|
-
|
335
|
-
def import_response(import_request)
|
336
|
-
url = import_request.url
|
337
|
-
|
338
|
-
if @import_responses.key? url
|
339
|
-
@import_responses[url].id = import_request.id
|
340
|
-
else
|
341
|
-
@import_responses[url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
|
342
|
-
id: import_request.id,
|
343
|
-
error: "Failed to import: #{url}"
|
344
|
-
)
|
345
|
-
end
|
346
|
-
|
347
|
-
@import_responses[url]
|
348
|
-
end
|
349
|
-
|
350
|
-
def function_call_response(function_call_request)
|
351
|
-
EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
|
352
|
-
id: function_call_request.id,
|
353
|
-
success: @functions[function_call_request.name].call(*function_call_request.arguments)
|
354
|
-
)
|
355
|
-
rescue StandardError => e
|
356
|
-
EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
|
357
|
-
id: function_call_request.id,
|
358
|
-
error: e.message
|
359
|
-
)
|
360
|
-
end
|
361
|
-
|
362
|
-
private
|
363
|
-
|
364
|
-
def syntax
|
365
|
-
if @indented_syntax == true
|
366
|
-
EmbeddedProtocol::Syntax::INDENTED
|
367
|
-
else
|
368
|
-
EmbeddedProtocol::Syntax::SCSS
|
369
|
-
end
|
370
|
-
end
|
371
|
-
|
372
|
-
def url
|
373
|
-
return if @file.nil?
|
374
|
-
|
375
|
-
Util.file_uri @file
|
376
|
-
end
|
377
|
-
|
378
|
-
def string
|
379
|
-
return if @data.nil?
|
380
|
-
|
381
|
-
EmbeddedProtocol::InboundMessage::CompileRequest::StringInput.new(
|
382
|
-
source: @data,
|
383
|
-
url: url,
|
384
|
-
syntax: syntax
|
385
|
-
)
|
386
|
-
end
|
387
|
-
|
388
|
-
def path
|
389
|
-
@file if @data.nil?
|
390
|
-
end
|
391
|
-
|
392
|
-
def style
|
393
|
-
case @output_style&.to_sym
|
394
|
-
when :expanded
|
395
|
-
EmbeddedProtocol::OutputStyle::EXPANDED
|
396
|
-
when :compressed
|
397
|
-
EmbeddedProtocol::OutputStyle::COMPRESSED
|
398
|
-
when :nested, :compact
|
399
|
-
raise ArgumentError, "#{@output_style} is not a supported output_style"
|
400
|
-
else
|
401
|
-
raise ArgumentError, "#{@output_style} is not a valid utput_style"
|
402
|
-
end
|
403
|
-
end
|
404
|
-
|
405
|
-
def source_map
|
406
|
-
@source_map.is_a?(String) || (@source_map == true && !@out_file.nil?)
|
407
|
-
end
|
408
|
-
|
409
|
-
attr_reader :global_functions
|
410
|
-
|
411
|
-
# Order
|
412
|
-
# 1. Loading a file relative to the file in which the @use or @import appeared.
|
413
|
-
# 2. Each custom importer.
|
414
|
-
# 3. Loading a file relative to the current working directory.
|
415
|
-
# 4. Each load path in includePaths
|
416
|
-
# 5. Each load path specified in the SASS_PATH environment variable, which should be semicolon-separated on Windows and colon-separated elsewhere.
|
417
|
-
def importers
|
418
|
-
custom_importers = @importer.map.with_index do |_, id|
|
419
|
-
EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
|
420
|
-
importer_id: id
|
421
|
-
)
|
422
|
-
end
|
423
|
-
|
424
|
-
include_path_importers = @include_paths
|
425
|
-
.concat(Sass.include_paths)
|
426
|
-
.map do |include_path|
|
427
|
-
EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
|
428
|
-
path: File.absolute_path(include_path)
|
429
|
-
)
|
430
|
-
end
|
431
|
-
|
432
|
-
custom_importers.concat include_path_importers
|
433
|
-
end
|
434
|
-
end
|
435
230
|
end
|
436
231
|
end
|
data/lib/sass/error.rb
CHANGED
@@ -1,21 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Sass
|
4
|
-
class
|
4
|
+
class Error < StandardError; end
|
5
5
|
|
6
|
-
class ProtocolError <
|
6
|
+
class ProtocolError < Error; end
|
7
7
|
|
8
|
-
# The
|
9
|
-
class RenderError <
|
10
|
-
|
8
|
+
# The {Error} raised by {Embedded#render}.
|
9
|
+
class RenderError < Error
|
10
|
+
include Struct
|
11
|
+
|
12
|
+
attr_reader :formatted, :file, :line, :column, :status
|
11
13
|
|
12
14
|
def initialize(message, formatted, file, line, column, status)
|
15
|
+
super(message)
|
13
16
|
@formatted = formatted
|
14
17
|
@file = file
|
15
18
|
@line = line
|
16
19
|
@column = column
|
17
20
|
@status = status
|
18
|
-
super(message)
|
19
21
|
end
|
20
22
|
|
21
23
|
def backtrace
|
data/lib/sass/info.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sass
|
4
|
+
# The {Observer} for {Embedded#info}.
|
5
|
+
class Version < Observer
|
6
|
+
def initialize(transport, id)
|
7
|
+
super(transport, id)
|
8
|
+
@transport.send EmbeddedProtocol::InboundMessage::VersionRequest.new(id: @id)
|
9
|
+
end
|
10
|
+
|
11
|
+
def update(error, message)
|
12
|
+
raise error unless error.nil?
|
13
|
+
|
14
|
+
case message
|
15
|
+
when EmbeddedProtocol::ProtocolError
|
16
|
+
raise ProtocolError, message.message
|
17
|
+
when EmbeddedProtocol::OutboundMessage::VersionResponse
|
18
|
+
return unless message.id == @id
|
19
|
+
|
20
|
+
Thread.new do
|
21
|
+
super(nil, message)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
rescue StandardError => e
|
25
|
+
Thread.new do
|
26
|
+
super(e, nil)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sass
|
4
|
+
# The {Observer} for receiving messages from {Transport}.
|
5
|
+
class Observer
|
6
|
+
def initialize(transport, id)
|
7
|
+
raise NotImplementedError if instance_of? Observer
|
8
|
+
|
9
|
+
@transport = transport
|
10
|
+
@id = id
|
11
|
+
@mutex = Mutex.new
|
12
|
+
@condition_variable = ConditionVariable.new
|
13
|
+
@error = nil
|
14
|
+
@message = nil
|
15
|
+
@transport.add_observer self
|
16
|
+
end
|
17
|
+
|
18
|
+
def fetch
|
19
|
+
@mutex.synchronize do
|
20
|
+
@condition_variable.wait(@mutex) if @error.nil? && @message.nil?
|
21
|
+
end
|
22
|
+
|
23
|
+
raise @error unless @error.nil?
|
24
|
+
|
25
|
+
@message
|
26
|
+
end
|
27
|
+
|
28
|
+
def update(error, message)
|
29
|
+
@transport.delete_observer self
|
30
|
+
@mutex.synchronize do
|
31
|
+
@error = error
|
32
|
+
@message = message
|
33
|
+
@condition_variable.broadcast
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/sass/render.rb
ADDED
@@ -0,0 +1,242 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sass
|
4
|
+
# The {Observer} for {Embedded#render}.
|
5
|
+
class Render < Observer
|
6
|
+
def initialize(transport, id,
|
7
|
+
data:,
|
8
|
+
file:,
|
9
|
+
indented_syntax:,
|
10
|
+
include_paths:,
|
11
|
+
output_style:,
|
12
|
+
source_map:,
|
13
|
+
out_file:,
|
14
|
+
functions:,
|
15
|
+
importer:)
|
16
|
+
raise ArgumentError, 'either data or file must be set' if file.nil? && data.nil?
|
17
|
+
|
18
|
+
super(transport, id)
|
19
|
+
|
20
|
+
@data = data
|
21
|
+
@file = file
|
22
|
+
@indented_syntax = indented_syntax
|
23
|
+
@include_paths = include_paths
|
24
|
+
@output_style = output_style
|
25
|
+
@source_map = source_map
|
26
|
+
@out_file = out_file
|
27
|
+
@global_functions = functions.keys
|
28
|
+
@functions = functions.transform_keys do |key|
|
29
|
+
key.to_s.split('(')[0].chomp
|
30
|
+
end
|
31
|
+
@importer = importer
|
32
|
+
@import_responses = {}
|
33
|
+
|
34
|
+
@transport.send compile_request
|
35
|
+
end
|
36
|
+
|
37
|
+
def update(error, message)
|
38
|
+
raise error unless error.nil?
|
39
|
+
|
40
|
+
case message
|
41
|
+
when EmbeddedProtocol::ProtocolError
|
42
|
+
raise ProtocolError, message.message
|
43
|
+
when EmbeddedProtocol::OutboundMessage::CompileResponse
|
44
|
+
return unless message.id == @id
|
45
|
+
|
46
|
+
Thread.new do
|
47
|
+
super(nil, message)
|
48
|
+
end
|
49
|
+
when EmbeddedProtocol::OutboundMessage::LogEvent
|
50
|
+
# not implemented yet
|
51
|
+
when EmbeddedProtocol::OutboundMessage::CanonicalizeRequest
|
52
|
+
return unless message['compilation_id'] == @id
|
53
|
+
|
54
|
+
Thread.new do
|
55
|
+
@transport.send canonicalize_response message
|
56
|
+
end
|
57
|
+
when EmbeddedProtocol::OutboundMessage::ImportRequest
|
58
|
+
return unless message['compilation_id'] == @id
|
59
|
+
|
60
|
+
Thread.new do
|
61
|
+
@transport.send import_response message
|
62
|
+
end
|
63
|
+
when EmbeddedProtocol::OutboundMessage::FileImportRequest
|
64
|
+
raise NotImplementedError, 'FileImportRequest is not implemented'
|
65
|
+
when EmbeddedProtocol::OutboundMessage::FunctionCallRequest
|
66
|
+
return unless message['compilation_id'] == @id
|
67
|
+
|
68
|
+
Thread.new do
|
69
|
+
@transport.send function_call_response message
|
70
|
+
end
|
71
|
+
end
|
72
|
+
rescue StandardError => e
|
73
|
+
Thread.new do
|
74
|
+
super(e, nil)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def compile_request
|
81
|
+
EmbeddedProtocol::InboundMessage::CompileRequest.new(
|
82
|
+
id: @id,
|
83
|
+
string: string,
|
84
|
+
path: path,
|
85
|
+
style: style,
|
86
|
+
source_map: source_map,
|
87
|
+
importers: importers,
|
88
|
+
global_functions: global_functions,
|
89
|
+
alert_color: $stderr.tty?,
|
90
|
+
alert_ascii: Platform::OS == 'windows'
|
91
|
+
)
|
92
|
+
end
|
93
|
+
|
94
|
+
def canonicalize_response(canonicalize_request)
|
95
|
+
url = Util.file_uri(File.absolute_path(canonicalize_request.url, (@file.nil? ? 'stdin' : @file)))
|
96
|
+
|
97
|
+
begin
|
98
|
+
result = @importer[canonicalize_request.importer_id].call canonicalize_request.url, @file
|
99
|
+
raise result if result.is_a? StandardError
|
100
|
+
rescue StandardError => e
|
101
|
+
return EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
102
|
+
id: canonicalize_request.id,
|
103
|
+
error: e.message
|
104
|
+
)
|
105
|
+
end
|
106
|
+
|
107
|
+
if result&.key? :contents
|
108
|
+
@import_responses[url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
|
109
|
+
id: canonicalize_request.id,
|
110
|
+
success: EmbeddedProtocol::InboundMessage::ImportResponse::ImportSuccess.new(
|
111
|
+
contents: result[:contents],
|
112
|
+
syntax: EmbeddedProtocol::Syntax::SCSS,
|
113
|
+
source_map_url: nil
|
114
|
+
)
|
115
|
+
)
|
116
|
+
EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
117
|
+
id: canonicalize_request.id,
|
118
|
+
url: url
|
119
|
+
)
|
120
|
+
elsif result&.key? :file
|
121
|
+
canonicalized_url = Util.file_uri(result[:file])
|
122
|
+
|
123
|
+
# TODO: FileImportRequest is not supported yet.
|
124
|
+
# Workaround by reading contents and return it when server asks
|
125
|
+
@import_responses[canonicalized_url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
|
126
|
+
id: canonicalize_request.id,
|
127
|
+
success: EmbeddedProtocol::InboundMessage::ImportResponse::ImportSuccess.new(
|
128
|
+
contents: File.read(result[:file]),
|
129
|
+
syntax: EmbeddedProtocol::Syntax::SCSS,
|
130
|
+
source_map_url: nil
|
131
|
+
)
|
132
|
+
)
|
133
|
+
|
134
|
+
EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
135
|
+
id: canonicalize_request.id,
|
136
|
+
url: canonicalized_url
|
137
|
+
)
|
138
|
+
else
|
139
|
+
EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
140
|
+
id: canonicalize_request.id
|
141
|
+
)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def import_response(import_request)
|
146
|
+
url = import_request.url
|
147
|
+
|
148
|
+
if @import_responses.key? url
|
149
|
+
@import_responses[url].id = import_request.id
|
150
|
+
else
|
151
|
+
@import_responses[url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
|
152
|
+
id: import_request.id,
|
153
|
+
error: "Failed to import: #{url}"
|
154
|
+
)
|
155
|
+
end
|
156
|
+
|
157
|
+
@import_responses[url]
|
158
|
+
end
|
159
|
+
|
160
|
+
def function_call_response(function_call_request)
|
161
|
+
EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
|
162
|
+
id: function_call_request.id,
|
163
|
+
success: @functions[function_call_request.name].call(*function_call_request.arguments)
|
164
|
+
)
|
165
|
+
rescue StandardError => e
|
166
|
+
EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
|
167
|
+
id: function_call_request.id,
|
168
|
+
error: e.message
|
169
|
+
)
|
170
|
+
end
|
171
|
+
|
172
|
+
def syntax
|
173
|
+
if @indented_syntax == true
|
174
|
+
EmbeddedProtocol::Syntax::INDENTED
|
175
|
+
else
|
176
|
+
EmbeddedProtocol::Syntax::SCSS
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def url
|
181
|
+
return if @file.nil?
|
182
|
+
|
183
|
+
Util.file_uri @file
|
184
|
+
end
|
185
|
+
|
186
|
+
def string
|
187
|
+
return if @data.nil?
|
188
|
+
|
189
|
+
EmbeddedProtocol::InboundMessage::CompileRequest::StringInput.new(
|
190
|
+
source: @data,
|
191
|
+
url: url,
|
192
|
+
syntax: syntax
|
193
|
+
)
|
194
|
+
end
|
195
|
+
|
196
|
+
def path
|
197
|
+
@file if @data.nil?
|
198
|
+
end
|
199
|
+
|
200
|
+
def style
|
201
|
+
case @output_style&.to_sym
|
202
|
+
when :expanded
|
203
|
+
EmbeddedProtocol::OutputStyle::EXPANDED
|
204
|
+
when :compressed
|
205
|
+
EmbeddedProtocol::OutputStyle::COMPRESSED
|
206
|
+
else
|
207
|
+
raise ArgumentError, 'output_style must be one of :expanded, :compressed'
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def source_map
|
212
|
+
@source_map.is_a?(String) || (@source_map == true && !@out_file.nil?)
|
213
|
+
end
|
214
|
+
|
215
|
+
attr_reader :global_functions
|
216
|
+
|
217
|
+
# Order
|
218
|
+
# 1. Loading a file relative to the file in which the @use or @import appeared.
|
219
|
+
# 2. Each custom importer.
|
220
|
+
# 3. Loading a file relative to the current working directory.
|
221
|
+
# 4. Each load path in includePaths
|
222
|
+
# 5. Each load path specified in the SASS_PATH environment variable, which should
|
223
|
+
# be semicolon-separated on Windows and colon-separated elsewhere.
|
224
|
+
def importers
|
225
|
+
custom_importers = @importer.map.with_index do |_, id|
|
226
|
+
EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
|
227
|
+
importer_id: id
|
228
|
+
)
|
229
|
+
end
|
230
|
+
|
231
|
+
include_path_importers = @include_paths
|
232
|
+
.concat(Sass.include_paths)
|
233
|
+
.map do |include_path|
|
234
|
+
EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
|
235
|
+
path: File.absolute_path(include_path)
|
236
|
+
)
|
237
|
+
end
|
238
|
+
|
239
|
+
custom_importers.concat include_path_importers
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
data/lib/sass/result.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sass
|
4
|
+
# The {Result} of {Embedded#render}.
|
5
|
+
class Result
|
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
|
+
|
16
|
+
# The {Stats} of {Embedded#render}.
|
17
|
+
class Stats
|
18
|
+
include Struct
|
19
|
+
|
20
|
+
attr_reader :entry, :start, :end, :duration
|
21
|
+
|
22
|
+
def initialize(entry, start, finish, duration)
|
23
|
+
@entry = entry
|
24
|
+
@start = start
|
25
|
+
@end = finish
|
26
|
+
@duration = duration
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/sass/struct.rb
ADDED
@@ -0,0 +1,20 @@
|
|
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
|
data/lib/sass/transport.rb
CHANGED
@@ -5,9 +5,9 @@ require 'observer'
|
|
5
5
|
require_relative '../../ext/embedded_sass_pb'
|
6
6
|
|
7
7
|
module Sass
|
8
|
-
# The
|
9
|
-
#
|
10
|
-
#
|
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
11
|
class Transport
|
12
12
|
include Observable
|
13
13
|
|
@@ -17,45 +17,31 @@ module Sass
|
|
17
17
|
|
18
18
|
PROTOCOL_ERROR_ID = 4_294_967_295
|
19
19
|
|
20
|
+
ONEOF_MESSAGE = EmbeddedProtocol::InboundMessage
|
21
|
+
.descriptor
|
22
|
+
.lookup_oneof('message')
|
23
|
+
.collect do |field_descriptor|
|
24
|
+
[field_descriptor.subtype, field_descriptor.name]
|
25
|
+
end.to_h
|
26
|
+
|
20
27
|
def initialize
|
21
|
-
@
|
22
|
-
@
|
28
|
+
@observerable_mutex = Mutex.new
|
29
|
+
@stdin_mutex = Mutex.new
|
23
30
|
@stdin, @stdout, @stderr, @wait_thread = Open3.popen3(DART_SASS_EMBEDDED)
|
24
31
|
pipe @stderr, $stderr
|
25
32
|
receive
|
26
33
|
end
|
27
34
|
|
28
|
-
def
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
req_kind = req.class.name.split('::').last.gsub(/\B(?=[A-Z])/, '_').downcase
|
33
|
-
|
34
|
-
message = EmbeddedProtocol::InboundMessage.new(req_kind => req)
|
35
|
-
|
36
|
-
error = nil
|
37
|
-
res = nil
|
38
|
-
|
39
|
-
@observerable_semaphore.synchronize do
|
40
|
-
MessageObserver.new self, id do |e, r|
|
41
|
-
mutex.synchronize do
|
42
|
-
error = e
|
43
|
-
res = r
|
44
|
-
|
45
|
-
resource.signal
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
mutex.synchronize do
|
51
|
-
write message.to_proto
|
52
|
-
|
53
|
-
resource.wait(mutex)
|
35
|
+
def add_observer(*args)
|
36
|
+
@observerable_mutex.synchronize do
|
37
|
+
super(*args)
|
54
38
|
end
|
39
|
+
end
|
55
40
|
|
56
|
-
|
57
|
-
|
58
|
-
|
41
|
+
def send(message)
|
42
|
+
write EmbeddedProtocol::InboundMessage.new(
|
43
|
+
ONEOF_MESSAGE[message.class.descriptor] => message
|
44
|
+
).to_proto
|
59
45
|
end
|
60
46
|
|
61
47
|
def close
|
@@ -66,6 +52,10 @@ module Sass
|
|
66
52
|
nil
|
67
53
|
end
|
68
54
|
|
55
|
+
def closed?
|
56
|
+
@stdin.closed?
|
57
|
+
end
|
58
|
+
|
69
59
|
private
|
70
60
|
|
71
61
|
def receive
|
@@ -78,10 +68,11 @@ module Sass
|
|
78
68
|
bits += 7
|
79
69
|
break if byte <= 0x7f
|
80
70
|
end
|
81
|
-
changed
|
82
71
|
payload = @stdout.read length
|
83
|
-
|
84
|
-
|
72
|
+
message = EmbeddedProtocol::OutboundMessage.decode payload
|
73
|
+
@observerable_mutex.synchronize do
|
74
|
+
changed
|
75
|
+
notify_observers nil, message[message.message.to_s]
|
85
76
|
end
|
86
77
|
rescue Interrupt
|
87
78
|
break
|
@@ -100,7 +91,7 @@ module Sass
|
|
100
91
|
rescue Interrupt
|
101
92
|
break
|
102
93
|
rescue IOError => e
|
103
|
-
@
|
94
|
+
@observerable_mutex.synchronize do
|
104
95
|
notify_observers e, nil
|
105
96
|
end
|
106
97
|
close
|
@@ -110,7 +101,7 @@ module Sass
|
|
110
101
|
end
|
111
102
|
|
112
103
|
def write(payload)
|
113
|
-
@
|
104
|
+
@stdin_mutex.synchronize do
|
114
105
|
length = payload.length
|
115
106
|
while length.positive?
|
116
107
|
@stdin.write ((length > 0x7f ? 0x80 : 0) | (length & 0x7f)).chr
|
@@ -119,32 +110,5 @@ module Sass
|
|
119
110
|
@stdin.write payload
|
120
111
|
end
|
121
112
|
end
|
122
|
-
|
123
|
-
# The observer used to listen on messages from stdout, check if id
|
124
|
-
# matches the given request id, and yield back to the given block.
|
125
|
-
class MessageObserver
|
126
|
-
def initialize(obs, id, &block)
|
127
|
-
@obs = obs
|
128
|
-
@id = id
|
129
|
-
@block = block
|
130
|
-
@obs.add_observer self
|
131
|
-
end
|
132
|
-
|
133
|
-
def update(error, message)
|
134
|
-
if error
|
135
|
-
@obs.delete_observer self
|
136
|
-
@block.call error, nil
|
137
|
-
elsif message.error&.id == Transport::PROTOCOL_ERROR_ID
|
138
|
-
@obs.delete_observer self
|
139
|
-
@block.call ProtocolError.new(message.error.message), nil
|
140
|
-
else
|
141
|
-
res = message[message.message.to_s]
|
142
|
-
if (res['compilation_id'] || res['id']) == @id
|
143
|
-
@obs.delete_observer self
|
144
|
-
@block.call error, res
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
113
|
end
|
150
114
|
end
|
data/lib/sass/util.rb
CHANGED
data/lib/sass/version.rb
CHANGED
data/sass-embedded.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.email = ['i@ntk.me']
|
12
12
|
spec.summary = 'Use dart-sass with Ruby!'
|
13
13
|
spec.description = 'Use dart-sass with Ruby!'
|
14
|
-
spec.homepage = 'https://github.com/ntkme/embedded-host-ruby'
|
14
|
+
spec.homepage = 'https://github.com/ntkme/sass-embedded-host-ruby'
|
15
15
|
spec.license = 'MIT'
|
16
16
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0")
|
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
21
|
|
22
|
-
spec.required_ruby_version = '>= 2.6'
|
22
|
+
spec.required_ruby_version = '>= 2.6.0'
|
23
23
|
|
24
24
|
spec.require_paths = ['lib']
|
25
25
|
|
data/test/functions_test.rb
CHANGED
@@ -12,6 +12,8 @@ module Sass
|
|
12
12
|
@embedded.close
|
13
13
|
end
|
14
14
|
|
15
|
+
# rubocop:disable Layout/LineLength
|
16
|
+
|
15
17
|
def render(sass)
|
16
18
|
@embedded.render(data: sass,
|
17
19
|
functions: {
|
@@ -163,6 +165,8 @@ module Sass
|
|
163
165
|
})[:css]
|
164
166
|
end
|
165
167
|
|
168
|
+
# rubocop:enable Layout/LineLength
|
169
|
+
|
166
170
|
def test_functions_may_return_sass_string_type
|
167
171
|
assert_sass <<-SCSS, <<-CSS
|
168
172
|
div { url: url(sass_return_path("foo.svg")); }
|
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.
|
4
|
+
version: 0.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- なつき
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-05-
|
11
|
+
date: 2021-05-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: google-protobuf
|
@@ -157,7 +157,12 @@ files:
|
|
157
157
|
- lib/sass.rb
|
158
158
|
- lib/sass/embedded.rb
|
159
159
|
- lib/sass/error.rb
|
160
|
+
- lib/sass/info.rb
|
161
|
+
- lib/sass/observer.rb
|
160
162
|
- lib/sass/platform.rb
|
163
|
+
- lib/sass/render.rb
|
164
|
+
- lib/sass/result.rb
|
165
|
+
- lib/sass/struct.rb
|
161
166
|
- lib/sass/transport.rb
|
162
167
|
- lib/sass/util.rb
|
163
168
|
- lib/sass/version.rb
|
@@ -173,7 +178,7 @@ files:
|
|
173
178
|
- test/render_test.rb
|
174
179
|
- test/source_maps_test.rb
|
175
180
|
- test/test_helper.rb
|
176
|
-
homepage: https://github.com/ntkme/embedded-host-ruby
|
181
|
+
homepage: https://github.com/ntkme/sass-embedded-host-ruby
|
177
182
|
licenses:
|
178
183
|
- MIT
|
179
184
|
metadata: {}
|
@@ -185,7 +190,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
185
190
|
requirements:
|
186
191
|
- - ">="
|
187
192
|
- !ruby/object:Gem::Version
|
188
|
-
version:
|
193
|
+
version: 2.6.0
|
189
194
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
190
195
|
requirements:
|
191
196
|
- - ">="
|