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 +4 -4
- data/LICENSE +1 -1
- data/README.md +3 -23
- data/ext/sass/extconf.rb +1 -3
- data/lib/sass/compile_error.rb +24 -0
- data/lib/sass/compile_result.rb +18 -0
- data/lib/sass/embedded/channel.rb +1 -1
- data/lib/sass/embedded/compile_context.rb +162 -137
- data/lib/sass/embedded/compiler/requirements.rb +1 -1
- data/lib/sass/embedded/compiler.rb +4 -4
- data/lib/sass/embedded/observer.rb +1 -0
- data/lib/sass/embedded/protocol_error.rb +7 -0
- data/lib/sass/embedded/render.rb +344 -0
- data/lib/sass/embedded/{util.rb → url.rb} +5 -13
- data/lib/sass/embedded/version.rb +1 -1
- data/lib/sass/embedded.rb +87 -210
- data/lib/sass/file_importer.rb +10 -0
- data/lib/sass/importer.rb +14 -0
- data/lib/sass/importer_result.rb +14 -0
- data/lib/sass/logger/source_location.rb +24 -0
- data/lib/sass/logger/source_span.rb +30 -0
- data/lib/sass/logger.rb +20 -0
- data/lib/sass.rb +40 -4
- metadata +26 -19
- data/lib/sass/embedded/error.rb +0 -29
- data/lib/sass/embedded/result.rb +0 -34
- data/lib/sass/embedded/struct.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e3c01d861dce5149bb56f25e6cb89e54d21a26bc4e50486298f860b2386198b7
|
4
|
+
data.tar.gz: 36f04488a3118b833f6210766e590a617fe7204dabb31b0908023b32a008ed21
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c7c15d96579e3dc1843c3dfc66709c9a3ae48bcbb7458f0defcc91c313cffb53dc43b01d114c35b13b8a7b8cfae516440037730283d52e5ea506fffa70a9bcac
|
7
|
+
data.tar.gz: ae089947ade94c0550e9a066860e89e1c774572ddc1ab7c5b42327f4a9f3fe6db41c4422ce96a9454d63b44ae8675091239278ebd8d6f524438c0f680a3e5e26
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -16,32 +16,12 @@ gem install sass-embedded
|
|
16
16
|
## Usage
|
17
17
|
|
18
18
|
``` ruby
|
19
|
-
require
|
19
|
+
require 'sass'
|
20
20
|
|
21
|
-
Sass.
|
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
@@ -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
|
@@ -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#
|
9
|
+
# The {Observer} for {Embedded#compile}.
|
10
10
|
class CompileContext
|
11
11
|
include Observer
|
12
12
|
|
13
13
|
def initialize(channel,
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
path:,
|
15
|
+
source:,
|
16
|
+
|
17
|
+
importer:,
|
18
|
+
load_paths:,
|
19
|
+
syntax:,
|
20
|
+
url:,
|
21
|
+
|
19
22
|
source_map:,
|
20
|
-
|
23
|
+
style:,
|
24
|
+
|
21
25
|
functions:,
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
@
|
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
|
-
@
|
32
|
-
|
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
|
-
@
|
37
|
-
|
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
|
73
|
+
return unless message.compilation_id == id
|
56
74
|
|
57
|
-
|
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
|
-
|
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:
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
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 =
|
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
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
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
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
174
|
-
|
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
|
-
|
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
|
-
|
227
|
+
raise ArgumentError, 'syntax must be one of :scss, :indented, :css'
|
188
228
|
end
|
189
229
|
end
|
190
230
|
|
191
|
-
def
|
192
|
-
|
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
|
223
|
-
|
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
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
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
|
-
|
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
|
@@ -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 '
|
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
|
-
.
|
20
|
+
.to_h do |field_descriptor|
|
21
21
|
[field_descriptor.subtype, field_descriptor.name]
|
22
|
-
end
|
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
|
44
|
+
raise ProtocolError, 'half-closed compiler' if half_closed?
|
45
45
|
|
46
46
|
super(*args)
|
47
47
|
|