sass-embedded 0.4.1 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +0 -3
- data/README.md +26 -0
- data/ext/extconf.rb +14 -2
- data/lib/sass.rb +28 -15
- data/lib/sass/embedded.rb +45 -308
- data/lib/sass/error.rb +8 -6
- data/lib/sass/info.rb +30 -0
- data/lib/sass/{context.rb → observer.rb} +8 -8
- 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 +21 -14
- data/lib/sass/util.rb +3 -1
- data/lib/sass/version.rb +1 -1
- data/sass-embedded.gemspec +1 -1
- data/test/functions_test.rb +4 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d8fe5d208436fad17c2eb0b4542de995dff90b8fb69983b05db6d4519526ee5
|
4
|
+
data.tar.gz: d202c23bdca1b462fedda0284a9ea9a98103beacddcad969be5e0e9e0dbc24c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b512dcca31e35eec561f0a6b9dfab8c0d6232934d997e552ba4a1f3574ea9d3edb85ccb9b7ef6df4bfc85e486a05390d0301609515a05df9b05589c2e2348e41
|
7
|
+
data.tar.gz: 0a80a2df0b37ee916bb406b84d598c390d723a3d54500de9aed4b3fce7f129cdb047060442a0d47d4873b8954a88ca5c6b4d85d957a6e16806ada372adae2c5e
|
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,13 +1,14 @@
|
|
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
|
class << self
|
6
|
-
# The global include_paths for Sass files. This is meant for plugins and
|
7
|
+
# The global {.include_paths} for Sass files. This is meant for plugins and
|
7
8
|
# libraries to register the paths to their Sass stylesheets to that they may
|
8
|
-
# be `@
|
9
|
-
# {Sass::Embedded}. They are lower-precedence than any include
|
10
|
-
# in via the
|
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.
|
11
12
|
#
|
12
13
|
# If the `SASS_PATH` environment variable is set,
|
13
14
|
# the initial value of `include_paths` will be initialized based on that.
|
@@ -16,7 +17,7 @@ module Sass
|
|
16
17
|
#
|
17
18
|
# @example
|
18
19
|
# Sass.include_paths << File.dirname(__FILE__) + '/sass'
|
19
|
-
# @return [Array
|
20
|
+
# @return [Array]
|
20
21
|
def include_paths
|
21
22
|
@include_paths ||= if ENV['SASS_PATH']
|
22
23
|
ENV['SASS_PATH'].split(File::PATH_SEPARATOR)
|
@@ -25,17 +26,26 @@ module Sass
|
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
29
|
+
# The global {.info} method. This instantiates a global {Embedded} instance
|
30
|
+
# and calls {Embedded#info}.
|
31
|
+
#
|
32
|
+
# @raise [ProtocolError]
|
28
33
|
def info
|
29
34
|
embedded.info
|
30
35
|
end
|
31
36
|
|
32
|
-
# The global render
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
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; }')
|
36
44
|
# @example
|
37
|
-
# Sass.render(
|
38
|
-
# @return [
|
45
|
+
# Sass.render(file: 'style.css')
|
46
|
+
# @return [Result]
|
47
|
+
# @raise [ProtocolError]
|
48
|
+
# @raise [RenderError]
|
39
49
|
def render(**kwargs)
|
40
50
|
embedded.render(**kwargs)
|
41
51
|
end
|
@@ -50,10 +60,13 @@ module Sass
|
|
50
60
|
end
|
51
61
|
end
|
52
62
|
|
53
|
-
require_relative 'sass/version'
|
54
|
-
require_relative 'sass/error'
|
55
63
|
require_relative 'sass/platform'
|
56
64
|
require_relative 'sass/util'
|
65
|
+
require_relative 'sass/struct'
|
66
|
+
require_relative 'sass/result'
|
67
|
+
require_relative 'sass/error'
|
57
68
|
require_relative 'sass/transport'
|
58
|
-
require_relative 'sass/
|
69
|
+
require_relative 'sass/observer'
|
70
|
+
require_relative 'sass/version'
|
71
|
+
require_relative 'sass/render'
|
59
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,20 +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
|
-
@info ||=
|
26
|
+
@info ||= Version.new(@transport, next_id).message
|
17
27
|
end
|
18
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]
|
19
36
|
def render(data: nil,
|
20
37
|
file: nil,
|
21
38
|
indented_syntax: false,
|
22
39
|
include_paths: [],
|
23
40
|
output_style: :expanded,
|
24
|
-
# precision: 5,
|
25
41
|
indent_type: :space,
|
26
42
|
indent_width: 2,
|
27
43
|
linefeed: :lf,
|
28
|
-
# source_comments: false,
|
29
44
|
source_map: false,
|
30
45
|
out_file: nil,
|
31
46
|
omit_source_map_url: false,
|
@@ -40,41 +55,41 @@ module Sass
|
|
40
55
|
indent_width = parse_indent_width(indent_width)
|
41
56
|
linefeed = parse_linefeed(linefeed)
|
42
57
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
if
|
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).message
|
68
|
+
|
69
|
+
if message.failure
|
55
70
|
raise RenderError.new(
|
56
|
-
|
57
|
-
|
58
|
-
if
|
71
|
+
message.failure.message,
|
72
|
+
message.failure.formatted,
|
73
|
+
if message.failure.span.nil?
|
59
74
|
nil
|
60
|
-
elsif
|
75
|
+
elsif message.failure.span.url == ''
|
61
76
|
'stdin'
|
62
77
|
else
|
63
|
-
Util.path(
|
78
|
+
Util.path(message.failure.span.url)
|
64
79
|
end,
|
65
|
-
|
66
|
-
|
80
|
+
message.failure.span ? message.failure.span.start.line + 1 : nil,
|
81
|
+
message.failure.span ? message.failure.span.start.column + 1 : nil,
|
67
82
|
1
|
68
83
|
)
|
69
84
|
end
|
70
85
|
|
71
|
-
map, source_map = post_process_map(map:
|
86
|
+
map, source_map = post_process_map(map: message.success.source_map,
|
72
87
|
file: file,
|
73
88
|
out_file: out_file,
|
74
89
|
source_map: source_map,
|
75
90
|
source_map_root: source_map_root)
|
76
91
|
|
77
|
-
css = post_process_css(css:
|
92
|
+
css = post_process_css(css: message.success.css,
|
78
93
|
indent_type: indent_type,
|
79
94
|
indent_width: indent_width,
|
80
95
|
linefeed: linefeed,
|
@@ -86,16 +101,9 @@ module Sass
|
|
86
101
|
|
87
102
|
finish = Util.now
|
88
103
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
stats: {
|
93
|
-
entry: file.nil? ? 'data' : file,
|
94
|
-
start: start,
|
95
|
-
end: finish,
|
96
|
-
duration: finish - start
|
97
|
-
}
|
98
|
-
}
|
104
|
+
stats = Result::Stats.new(file.nil? ? 'data' : file, start, finish, finish - start)
|
105
|
+
|
106
|
+
Result.new(css, map, stats)
|
99
107
|
end
|
100
108
|
|
101
109
|
def close
|
@@ -186,7 +194,7 @@ module Sass
|
|
186
194
|
when :tab
|
187
195
|
"\t"
|
188
196
|
else
|
189
|
-
raise ArgumentError, 'indent_type must be :space
|
197
|
+
raise ArgumentError, 'indent_type must be one of :space, :tab'
|
190
198
|
end
|
191
199
|
end
|
192
200
|
|
@@ -219,276 +227,5 @@ module Sass
|
|
219
227
|
@id
|
220
228
|
end
|
221
229
|
end
|
222
|
-
|
223
|
-
# InfoContext
|
224
|
-
class InfoContext < Context
|
225
|
-
def initialize(transport, id)
|
226
|
-
super(transport, id)
|
227
|
-
@transport.send EmbeddedProtocol::InboundMessage::VersionRequest.new(id: @id)
|
228
|
-
end
|
229
|
-
|
230
|
-
def update(error, message)
|
231
|
-
raise error unless error.nil?
|
232
|
-
|
233
|
-
response = message[message.message.to_s]
|
234
|
-
|
235
|
-
case response
|
236
|
-
when EmbeddedProtocol::ProtocolError
|
237
|
-
raise ProtocolError, response.message
|
238
|
-
when EmbeddedProtocol::OutboundMessage::VersionResponse
|
239
|
-
return unless response.id == @id
|
240
|
-
|
241
|
-
Thread.new do
|
242
|
-
super(nil, response)
|
243
|
-
end
|
244
|
-
end
|
245
|
-
rescue StandardError => e
|
246
|
-
Thread.new do
|
247
|
-
super(e, nil)
|
248
|
-
end
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
# RenderContext
|
253
|
-
class RenderContext < Context
|
254
|
-
def initialize(transport, id,
|
255
|
-
data:,
|
256
|
-
file:,
|
257
|
-
indented_syntax:,
|
258
|
-
include_paths:,
|
259
|
-
output_style:,
|
260
|
-
source_map:,
|
261
|
-
out_file:,
|
262
|
-
functions:,
|
263
|
-
importer:)
|
264
|
-
raise ArgumentError, 'either data or file must be set' if file.nil? && data.nil?
|
265
|
-
|
266
|
-
super(transport, id)
|
267
|
-
|
268
|
-
@data = data
|
269
|
-
@file = file
|
270
|
-
@indented_syntax = indented_syntax
|
271
|
-
@include_paths = include_paths
|
272
|
-
@output_style = output_style
|
273
|
-
@source_map = source_map
|
274
|
-
@out_file = out_file
|
275
|
-
@global_functions = functions.keys
|
276
|
-
@functions = functions.transform_keys do |key|
|
277
|
-
key.to_s.split('(')[0].chomp
|
278
|
-
end
|
279
|
-
@importer = importer
|
280
|
-
@import_responses = {}
|
281
|
-
|
282
|
-
@transport.send compile_request
|
283
|
-
end
|
284
|
-
|
285
|
-
def update(error, message)
|
286
|
-
raise error unless error.nil?
|
287
|
-
|
288
|
-
response = message[message.message.to_s]
|
289
|
-
|
290
|
-
case response
|
291
|
-
when EmbeddedProtocol::ProtocolError
|
292
|
-
raise ProtocolError, response.message
|
293
|
-
when EmbeddedProtocol::OutboundMessage::CompileResponse
|
294
|
-
return unless response.id == @id
|
295
|
-
|
296
|
-
Thread.new do
|
297
|
-
super(nil, response)
|
298
|
-
end
|
299
|
-
when EmbeddedProtocol::OutboundMessage::LogEvent
|
300
|
-
# not implemented yet
|
301
|
-
when EmbeddedProtocol::OutboundMessage::CanonicalizeRequest
|
302
|
-
return unless response['compilation_id'] == @id
|
303
|
-
|
304
|
-
Thread.new do
|
305
|
-
@transport.send canonicalize_response(response)
|
306
|
-
end
|
307
|
-
when EmbeddedProtocol::OutboundMessage::ImportRequest
|
308
|
-
return unless response['compilation_id'] == @id
|
309
|
-
|
310
|
-
Thread.new do
|
311
|
-
@transport.send import_response(response)
|
312
|
-
end
|
313
|
-
when EmbeddedProtocol::OutboundMessage::FileImportRequest
|
314
|
-
raise NotImplementedError, 'FileImportRequest is not implemented'
|
315
|
-
when EmbeddedProtocol::OutboundMessage::FunctionCallRequest
|
316
|
-
return unless response['compilation_id'] == @id
|
317
|
-
|
318
|
-
Thread.new do
|
319
|
-
@transport.send function_call_response(response)
|
320
|
-
end
|
321
|
-
end
|
322
|
-
rescue StandardError => e
|
323
|
-
Thread.new do
|
324
|
-
super(e, nil)
|
325
|
-
end
|
326
|
-
end
|
327
|
-
|
328
|
-
private
|
329
|
-
|
330
|
-
def compile_request
|
331
|
-
EmbeddedProtocol::InboundMessage::CompileRequest.new(
|
332
|
-
id: @id,
|
333
|
-
string: string,
|
334
|
-
path: path,
|
335
|
-
style: style,
|
336
|
-
source_map: source_map,
|
337
|
-
importers: importers,
|
338
|
-
global_functions: global_functions,
|
339
|
-
alert_color: $stderr.tty?,
|
340
|
-
alert_ascii: Platform::OS == 'windows'
|
341
|
-
)
|
342
|
-
end
|
343
|
-
|
344
|
-
def canonicalize_response(canonicalize_request)
|
345
|
-
url = Util.file_uri(File.absolute_path(canonicalize_request.url, (@file.nil? ? 'stdin' : @file)))
|
346
|
-
|
347
|
-
begin
|
348
|
-
result = @importer[canonicalize_request.importer_id].call canonicalize_request.url, @file
|
349
|
-
raise result if result.is_a? StandardError
|
350
|
-
rescue StandardError => e
|
351
|
-
return EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
352
|
-
id: canonicalize_request.id,
|
353
|
-
error: e.message
|
354
|
-
)
|
355
|
-
end
|
356
|
-
|
357
|
-
if result&.key? :contents
|
358
|
-
@import_responses[url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
|
359
|
-
id: canonicalize_request.id,
|
360
|
-
success: EmbeddedProtocol::InboundMessage::ImportResponse::ImportSuccess.new(
|
361
|
-
contents: result[:contents],
|
362
|
-
syntax: EmbeddedProtocol::Syntax::SCSS,
|
363
|
-
source_map_url: nil
|
364
|
-
)
|
365
|
-
)
|
366
|
-
EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
367
|
-
id: canonicalize_request.id,
|
368
|
-
url: url
|
369
|
-
)
|
370
|
-
elsif result&.key? :file
|
371
|
-
canonicalized_url = Util.file_uri(result[:file])
|
372
|
-
|
373
|
-
# TODO: FileImportRequest is not supported yet.
|
374
|
-
# Workaround by reading contents and return it when server asks
|
375
|
-
@import_responses[canonicalized_url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
|
376
|
-
id: canonicalize_request.id,
|
377
|
-
success: EmbeddedProtocol::InboundMessage::ImportResponse::ImportSuccess.new(
|
378
|
-
contents: File.read(result[:file]),
|
379
|
-
syntax: EmbeddedProtocol::Syntax::SCSS,
|
380
|
-
source_map_url: nil
|
381
|
-
)
|
382
|
-
)
|
383
|
-
|
384
|
-
EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
385
|
-
id: canonicalize_request.id,
|
386
|
-
url: canonicalized_url
|
387
|
-
)
|
388
|
-
else
|
389
|
-
EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
390
|
-
id: canonicalize_request.id
|
391
|
-
)
|
392
|
-
end
|
393
|
-
end
|
394
|
-
|
395
|
-
def import_response(import_request)
|
396
|
-
url = import_request.url
|
397
|
-
|
398
|
-
if @import_responses.key? url
|
399
|
-
@import_responses[url].id = import_request.id
|
400
|
-
else
|
401
|
-
@import_responses[url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
|
402
|
-
id: import_request.id,
|
403
|
-
error: "Failed to import: #{url}"
|
404
|
-
)
|
405
|
-
end
|
406
|
-
|
407
|
-
@import_responses[url]
|
408
|
-
end
|
409
|
-
|
410
|
-
def function_call_response(function_call_request)
|
411
|
-
EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
|
412
|
-
id: function_call_request.id,
|
413
|
-
success: @functions[function_call_request.name].call(*function_call_request.arguments)
|
414
|
-
)
|
415
|
-
rescue StandardError => e
|
416
|
-
EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
|
417
|
-
id: function_call_request.id,
|
418
|
-
error: e.message
|
419
|
-
)
|
420
|
-
end
|
421
|
-
|
422
|
-
def syntax
|
423
|
-
if @indented_syntax == true
|
424
|
-
EmbeddedProtocol::Syntax::INDENTED
|
425
|
-
else
|
426
|
-
EmbeddedProtocol::Syntax::SCSS
|
427
|
-
end
|
428
|
-
end
|
429
|
-
|
430
|
-
def url
|
431
|
-
return if @file.nil?
|
432
|
-
|
433
|
-
Util.file_uri @file
|
434
|
-
end
|
435
|
-
|
436
|
-
def string
|
437
|
-
return if @data.nil?
|
438
|
-
|
439
|
-
EmbeddedProtocol::InboundMessage::CompileRequest::StringInput.new(
|
440
|
-
source: @data,
|
441
|
-
url: url,
|
442
|
-
syntax: syntax
|
443
|
-
)
|
444
|
-
end
|
445
|
-
|
446
|
-
def path
|
447
|
-
@file if @data.nil?
|
448
|
-
end
|
449
|
-
|
450
|
-
def style
|
451
|
-
case @output_style&.to_sym
|
452
|
-
when :expanded
|
453
|
-
EmbeddedProtocol::OutputStyle::EXPANDED
|
454
|
-
when :compressed
|
455
|
-
EmbeddedProtocol::OutputStyle::COMPRESSED
|
456
|
-
when :nested, :compact
|
457
|
-
raise ArgumentError, "#{@output_style} is not a supported output_style"
|
458
|
-
else
|
459
|
-
raise ArgumentError, "#{@output_style} is not a valid utput_style"
|
460
|
-
end
|
461
|
-
end
|
462
|
-
|
463
|
-
def source_map
|
464
|
-
@source_map.is_a?(String) || (@source_map == true && !@out_file.nil?)
|
465
|
-
end
|
466
|
-
|
467
|
-
attr_reader :global_functions
|
468
|
-
|
469
|
-
# Order
|
470
|
-
# 1. Loading a file relative to the file in which the @use or @import appeared.
|
471
|
-
# 2. Each custom importer.
|
472
|
-
# 3. Loading a file relative to the current working directory.
|
473
|
-
# 4. Each load path in includePaths
|
474
|
-
# 5. Each load path specified in the SASS_PATH environment variable, which should be semicolon-separated on Windows and colon-separated elsewhere.
|
475
|
-
def importers
|
476
|
-
custom_importers = @importer.map.with_index do |_, id|
|
477
|
-
EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
|
478
|
-
importer_id: id
|
479
|
-
)
|
480
|
-
end
|
481
|
-
|
482
|
-
include_path_importers = @include_paths
|
483
|
-
.concat(Sass.include_paths)
|
484
|
-
.map do |include_path|
|
485
|
-
EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
|
486
|
-
path: File.absolute_path(include_path)
|
487
|
-
)
|
488
|
-
end
|
489
|
-
|
490
|
-
custom_importers.concat include_path_importers
|
491
|
-
end
|
492
|
-
end
|
493
230
|
end
|
494
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
|
@@ -1,35 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Sass
|
4
|
-
#
|
5
|
-
class
|
4
|
+
# The {Observer} for receiving messages from {Transport}.
|
5
|
+
class Observer
|
6
6
|
def initialize(transport, id)
|
7
|
-
raise NotImplementedError if instance_of?
|
7
|
+
raise NotImplementedError if instance_of? Observer
|
8
8
|
|
9
9
|
@transport = transport
|
10
10
|
@id = id
|
11
11
|
@mutex = Mutex.new
|
12
12
|
@condition_variable = ConditionVariable.new
|
13
|
-
@response = nil
|
14
13
|
@error = nil
|
14
|
+
@message = nil
|
15
15
|
@transport.add_observer self
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def message
|
19
19
|
@mutex.synchronize do
|
20
|
-
@condition_variable.wait(@mutex) if @error.nil? && @
|
20
|
+
@condition_variable.wait(@mutex) if @error.nil? && @message.nil?
|
21
21
|
end
|
22
22
|
|
23
23
|
raise @error unless @error.nil?
|
24
24
|
|
25
|
-
@
|
25
|
+
@message
|
26
26
|
end
|
27
27
|
|
28
28
|
def update(error, message)
|
29
29
|
@transport.delete_observer self
|
30
30
|
@mutex.synchronize do
|
31
31
|
@error = error
|
32
|
-
@
|
32
|
+
@message = message
|
33
33
|
@condition_variable.broadcast
|
34
34
|
end
|
35
35
|
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,24 +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
35
|
def add_observer(*args)
|
29
|
-
@
|
36
|
+
@observerable_mutex.synchronize do
|
30
37
|
super(*args)
|
31
38
|
end
|
32
39
|
end
|
33
40
|
|
34
|
-
def send(
|
35
|
-
|
36
|
-
|
37
|
-
|
41
|
+
def send(message)
|
42
|
+
write EmbeddedProtocol::InboundMessage.new(
|
43
|
+
ONEOF_MESSAGE[message.class.descriptor] => message
|
44
|
+
).to_proto
|
38
45
|
end
|
39
46
|
|
40
47
|
def close
|
@@ -63,9 +70,9 @@ module Sass
|
|
63
70
|
end
|
64
71
|
payload = @stdout.read length
|
65
72
|
message = EmbeddedProtocol::OutboundMessage.decode payload
|
66
|
-
@
|
73
|
+
@observerable_mutex.synchronize do
|
67
74
|
changed
|
68
|
-
notify_observers nil, message
|
75
|
+
notify_observers nil, message[message.message.to_s]
|
69
76
|
end
|
70
77
|
rescue Interrupt
|
71
78
|
break
|
@@ -84,7 +91,7 @@ module Sass
|
|
84
91
|
rescue Interrupt
|
85
92
|
break
|
86
93
|
rescue IOError => e
|
87
|
-
@
|
94
|
+
@observerable_mutex.synchronize do
|
88
95
|
notify_observers e, nil
|
89
96
|
end
|
90
97
|
close
|
@@ -94,7 +101,7 @@ module Sass
|
|
94
101
|
end
|
95
102
|
|
96
103
|
def write(payload)
|
97
|
-
@
|
104
|
+
@stdin_mutex.synchronize do
|
98
105
|
length = payload.length
|
99
106
|
while length.positive?
|
100
107
|
@stdin.write ((length > 0x7f ? 0x80 : 0) | (length & 0x7f)).chr
|
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")
|
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,7 +1,7 @@
|
|
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.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- なつき
|
@@ -155,10 +155,14 @@ files:
|
|
155
155
|
- ext/Makefile
|
156
156
|
- ext/extconf.rb
|
157
157
|
- lib/sass.rb
|
158
|
-
- lib/sass/context.rb
|
159
158
|
- lib/sass/embedded.rb
|
160
159
|
- lib/sass/error.rb
|
160
|
+
- lib/sass/info.rb
|
161
|
+
- lib/sass/observer.rb
|
161
162
|
- lib/sass/platform.rb
|
163
|
+
- lib/sass/render.rb
|
164
|
+
- lib/sass/result.rb
|
165
|
+
- lib/sass/struct.rb
|
162
166
|
- lib/sass/transport.rb
|
163
167
|
- lib/sass/util.rb
|
164
168
|
- lib/sass/version.rb
|
@@ -174,7 +178,7 @@ files:
|
|
174
178
|
- test/render_test.rb
|
175
179
|
- test/source_maps_test.rb
|
176
180
|
- test/test_helper.rb
|
177
|
-
homepage: https://github.com/ntkme/embedded-host-ruby
|
181
|
+
homepage: https://github.com/ntkme/sass-embedded-host-ruby
|
178
182
|
licenses:
|
179
183
|
- MIT
|
180
184
|
metadata: {}
|