sass-embedded 0.9.1 → 0.11.0
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/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 +164 -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 +345 -0
- data/lib/sass/embedded/url.rb +33 -0
- 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 +31 -1
- metadata +27 -20
- data/lib/sass/embedded/error.rb +0 -29
- data/lib/sass/embedded/result.rb +0 -34
- data/lib/sass/embedded/struct.rb +0 -22
- data/lib/sass/embedded/util.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8d392419747bbe1cffb4c3843a60a8de343a07fc938c1ad061ce8cde4519fd4a
|
4
|
+
data.tar.gz: 358c8083d14d6d27d84d6091cad64dd39e35c1076295e030b668386b4856098a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3a50de89e870d5d4fe054eb0702da7774fba5e445e65fba3efb9364d6ed140bbb07cb1dec2d06bee96d08cf79017c383a921def2487c78468c2a3fe2c3e6a54e
|
7
|
+
data.tar.gz: e746cc7db807ab73557e03d342d7a5f88d81b7c581a5969d2a63dec1a63699828bc49fcfa1fa4d80ac5edb8452495b15bc8c2e5163127d4985276490c3259e98
|
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,11 @@ 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
|
+
Thread.new do
|
76
|
+
log message
|
77
|
+
end
|
58
78
|
when EmbeddedProtocol::OutboundMessage::CanonicalizeRequest
|
59
79
|
return unless message.compilation_id == id
|
60
80
|
|
@@ -68,7 +88,11 @@ module Sass
|
|
68
88
|
send_message import_response message
|
69
89
|
end
|
70
90
|
when EmbeddedProtocol::OutboundMessage::FileImportRequest
|
71
|
-
|
91
|
+
return unless message.compilation_id == id
|
92
|
+
|
93
|
+
Thread.new do
|
94
|
+
send_message file_import_response message
|
95
|
+
end
|
72
96
|
when EmbeddedProtocol::OutboundMessage::FunctionCallRequest
|
73
97
|
return unless message.compilation_id == id
|
74
98
|
|
@@ -84,94 +108,107 @@ module Sass
|
|
84
108
|
|
85
109
|
private
|
86
110
|
|
111
|
+
def log(event)
|
112
|
+
case event.type
|
113
|
+
when :DEBUG
|
114
|
+
if @logger.respond_to? :debug
|
115
|
+
@logger.debug(event.message, span: Logger::SourceSpan.from_proto(event.span))
|
116
|
+
else
|
117
|
+
Kernel.warn(event.formatted)
|
118
|
+
end
|
119
|
+
when :DEPRECATION_WARNING
|
120
|
+
if @logger.respond_to? :warn
|
121
|
+
@logger.warn(event.message, deprecation: true, span: Logger::SourceSpan.from_proto(event.span),
|
122
|
+
stack: event.stack_trace)
|
123
|
+
else
|
124
|
+
Kernel.warn(event.formatted)
|
125
|
+
end
|
126
|
+
when :WARNING
|
127
|
+
if @logger.respond_to? :warn
|
128
|
+
@logger.warn(event.message, deprecation: false, span: Logger::SourceSpan.from_proto(event.span),
|
129
|
+
stack: event.stack_trace)
|
130
|
+
else
|
131
|
+
Kernel.warn(event.formatted)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
87
136
|
def compile_request
|
88
137
|
EmbeddedProtocol::InboundMessage::CompileRequest.new(
|
89
138
|
id: id,
|
90
|
-
string:
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
139
|
+
string: unless @source.nil?
|
140
|
+
EmbeddedProtocol::InboundMessage::CompileRequest::StringInput.new(
|
141
|
+
source: @source,
|
142
|
+
url: @url,
|
143
|
+
syntax: to_proto_syntax(@syntax),
|
144
|
+
importer: @importer.nil? ? nil : to_proto_importer(@importer, @importers.length)
|
145
|
+
)
|
146
|
+
end,
|
147
|
+
path: @path,
|
148
|
+
style: to_proto_output_style(@style),
|
149
|
+
source_map: @source_map,
|
150
|
+
importers: to_proto_importers(@importers, @load_paths),
|
151
|
+
global_functions: @global_functions,
|
152
|
+
alert_ascii: @alert_ascii,
|
153
|
+
alert_color: @alert_color
|
98
154
|
)
|
99
155
|
end
|
100
156
|
|
101
157
|
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
|
158
|
+
url = importer_with_id(canonicalize_request.importer_id).canonicalize canonicalize_request.url
|
113
159
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
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
|
-
)
|
140
|
-
|
141
|
-
EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
142
|
-
id: canonicalize_request.id,
|
143
|
-
url: canonicalized_url
|
144
|
-
)
|
145
|
-
else
|
146
|
-
EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
147
|
-
id: canonicalize_request.id
|
148
|
-
)
|
149
|
-
end
|
160
|
+
EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
161
|
+
id: canonicalize_request.id,
|
162
|
+
url: url
|
163
|
+
)
|
164
|
+
rescue StandardError => e
|
165
|
+
EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
166
|
+
id: canonicalize_request.id,
|
167
|
+
error: e.message
|
168
|
+
)
|
150
169
|
end
|
151
170
|
|
152
171
|
def import_response(import_request)
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
172
|
+
importer_result = importer_with_id(import_request.importer_id).load import_request.url
|
173
|
+
|
174
|
+
EmbeddedProtocol::InboundMessage::ImportResponse.new(
|
175
|
+
id: import_request.id,
|
176
|
+
success: EmbeddedProtocol::InboundMessage::ImportResponse::ImportSuccess.new(
|
177
|
+
contents: importer_result.contents,
|
178
|
+
syntax: to_proto_syntax(importer_result.syntax),
|
179
|
+
source_map_url: importer_result.source_map_url
|
161
180
|
)
|
162
|
-
|
181
|
+
)
|
182
|
+
rescue StandardError => e
|
183
|
+
EmbeddedProtocol::InboundMessage::ImportResponse.new(
|
184
|
+
id: import_request.id,
|
185
|
+
error: e.message
|
186
|
+
)
|
187
|
+
end
|
163
188
|
|
164
|
-
|
189
|
+
def file_import_response(file_import_request)
|
190
|
+
file_importer = importer_with_id(file_import_request.importer_id)
|
191
|
+
file_url = file_importer.find_file_url file_import_request.url,
|
192
|
+
from_import: file_import_request.from_import
|
193
|
+
|
194
|
+
EmbeddedProtocol::InboundMessage::FileImportResponse.new(
|
195
|
+
id: file_import_request.id,
|
196
|
+
file_url: file_url
|
197
|
+
)
|
198
|
+
rescue StandardError => e
|
199
|
+
EmbeddedProtocol::InboundMessage::FileImportResponse.new(
|
200
|
+
id: file_import_request.id,
|
201
|
+
error: e.message
|
202
|
+
)
|
165
203
|
end
|
166
204
|
|
167
205
|
def function_call_response(function_call_request)
|
168
|
-
# TODO: convert argument_list to **kwargs
|
169
206
|
EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
|
170
207
|
id: function_call_request.id,
|
171
208
|
success: @functions[function_call_request.name].call(*function_call_request.arguments),
|
172
209
|
accessed_argument_lists: function_call_request.arguments
|
173
|
-
|
174
|
-
|
210
|
+
.filter { |argument| argument.value == :argument_list }
|
211
|
+
.map { |argument| argument.argument_list.id }
|
175
212
|
)
|
176
213
|
rescue StandardError => e
|
177
214
|
EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
|
@@ -180,36 +217,21 @@ module Sass
|
|
180
217
|
)
|
181
218
|
end
|
182
219
|
|
183
|
-
def syntax
|
184
|
-
|
220
|
+
def to_proto_syntax(syntax)
|
221
|
+
case syntax&.to_sym
|
222
|
+
when :scss
|
223
|
+
EmbeddedProtocol::Syntax::SCSS
|
224
|
+
when :indented
|
185
225
|
EmbeddedProtocol::Syntax::INDENTED
|
226
|
+
when :css
|
227
|
+
EmbeddedProtocol::Syntax::CSS
|
186
228
|
else
|
187
|
-
|
229
|
+
raise ArgumentError, 'syntax must be one of :scss, :indented, :css'
|
188
230
|
end
|
189
231
|
end
|
190
232
|
|
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
|
233
|
+
def to_proto_output_style(style)
|
234
|
+
case style&.to_sym
|
213
235
|
when :expanded
|
214
236
|
EmbeddedProtocol::OutputStyle::EXPANDED
|
215
237
|
when :compressed
|
@@ -219,35 +241,40 @@ module Sass
|
|
219
241
|
end
|
220
242
|
end
|
221
243
|
|
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|
|
244
|
+
def to_proto_importer(importer, id)
|
245
|
+
if importer.respond_to?(:canonicalize) && importer.respond_to?(:load)
|
237
246
|
EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
|
238
247
|
importer_id: id
|
239
248
|
)
|
249
|
+
elsif importer.respond_to?(:find_file_url)
|
250
|
+
EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
|
251
|
+
file_importer_id: id
|
252
|
+
)
|
253
|
+
else
|
254
|
+
raise ArgumentError, 'importer must be an Importer or a FileImporter'
|
240
255
|
end
|
256
|
+
end
|
241
257
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
258
|
+
def to_proto_importers(importers, load_paths)
|
259
|
+
proto_importers = importers.map.with_index do |importer, id|
|
260
|
+
to_proto_importer(importer, id)
|
261
|
+
end
|
262
|
+
|
263
|
+
load_paths.each do |load_path|
|
264
|
+
proto_importers << EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
|
265
|
+
path: File.absolute_path(load_path)
|
247
266
|
)
|
248
267
|
end
|
249
268
|
|
250
|
-
|
269
|
+
proto_importers
|
270
|
+
end
|
271
|
+
|
272
|
+
def importer_with_id(id)
|
273
|
+
if id == @importers.length
|
274
|
+
@importer
|
275
|
+
else
|
276
|
+
@importers[id]
|
277
|
+
end
|
251
278
|
end
|
252
279
|
end
|
253
280
|
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
|
|