sass-embedded 0.1.3 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c42f58b6f4f3200d3033fd59e65e7cd33132731ab4520bafb2a375cf55577ec
4
- data.tar.gz: 2da13b64dab78a0b3fccd9a90cfcc6bd5affcd09dfe0b978aed53b69b2afa51e
3
+ metadata.gz: e03d2c1775fdd10b7f9d2b21898ac0a6e31e0be96157139742384c7be9b4275a
4
+ data.tar.gz: dacdc9589a8da93246b791794f97be2c8818f8a492d77e473c9fa543fd49db9e
5
5
  SHA512:
6
- metadata.gz: d484872bd432f0092e67f699b18af1e242c982ff0e2019f9d23340593744ca58a015f5d63c76ae83d0a29e05ed362a2015f8f55bdbe472da67488e99c1cdaa8f
7
- data.tar.gz: bd452474519dabcd9d793205d8f0dcc64482a5313d48d9eda4464f0a5d6ed8b9d6a34ea1c57e4a8f178beafb008b080481fd6059ab2f3ad53494e2acd272527b
6
+ metadata.gz: 3be32cd37a7078fceabd16c661cf985fdfc1aa31fbf8b88e6c768cb8edd57749a30e28a77f367d6cc8c6c505710f402e1970ae6c12210b3f46fc10a42cf8d81d
7
+ data.tar.gz: 5a122cd7c2e883f28b9401ce70d8fb43fcfcf39e1ff64484f5bf036c6978ca1a01cf8d69b1ebbf22f0fde81f98272127cf5a96d381b0279028d316d90775ebfb
@@ -27,7 +27,7 @@ jobs:
27
27
  bundler-cache: true
28
28
 
29
29
  - name: Download dart-sass-embedded
30
- run: bundle exec rake download
30
+ run: bundle exec rake extconf
31
31
  env:
32
32
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33
33
 
@@ -41,4 +41,4 @@ jobs:
41
41
 
42
42
  - name: Test Gem
43
43
  run: |-
44
- ruby -r sass -e "puts Sass.render({ data: 'h1 { color: black; }' })[:css]"
44
+ ruby -r sass -e "puts Sass.render(data: 'h1 { color: black; }')[:css]"
data/.rubocop.yml ADDED
@@ -0,0 +1,14 @@
1
+ AllCops:
2
+ Exclude:
3
+ - '**/*_pb.rb'
4
+ - 'vendor/**/*'
5
+
6
+ TargetRubyVersion: 2.6
7
+
8
+ NewCops: enable
9
+
10
+ Layout/LineLength:
11
+ Enabled: false
12
+
13
+ Metrics:
14
+ Enabled: false
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Embedded Sass Host for Ruby
2
2
 
3
+ [![build](https://github.com/ntkme/embedded-host-ruby/actions/workflows/build.yml/badge.svg)](https://github.com/ntkme/embedded-host-ruby/actions/workflows/build.yml)
4
+
3
5
  This is a Ruby library that implements the host side of the [Embedded Sass protocol](https://github.com/sass/sass-embedded-protocol).
4
6
 
5
7
  It exposes a Ruby API for Sass that's backed by a native [Dart Sass](https://sass-lang.com/dart-sass) executable.
@@ -9,9 +11,7 @@ It exposes a Ruby API for Sass that's backed by a native [Dart Sass](https://sas
9
11
  ``` ruby
10
12
  require "sass"
11
13
 
12
- Sass.render({
13
- file: "style.scss"
14
- })
14
+ Sass.render(file: "style.scss")
15
15
  ```
16
16
 
17
17
  ---
data/Rakefile CHANGED
@@ -2,15 +2,22 @@
2
2
 
3
3
  require 'bundler/gem_tasks'
4
4
 
5
- task default: :test
5
+ task default: %i[rubocop test]
6
6
 
7
7
  desc 'Download dart-sass-embedded'
8
- task :download do
9
- require_relative 'ext/sass_embedded/extconf'
8
+ task :extconf do
9
+ system('make', '-C', 'ext')
10
10
  end
11
11
 
12
12
  desc 'Run all tests'
13
- task :test do
13
+ task test: :extconf do
14
14
  $LOAD_PATH.unshift('lib', 'test')
15
15
  Dir.glob('./test/**/*_test.rb').sort.each { |f| require f }
16
16
  end
17
+
18
+ begin
19
+ require 'rubocop/rake_task'
20
+ RuboCop::RakeTask.new
21
+ rescue LoadError
22
+ nil
23
+ end
File without changes
data/ext/Makefile ADDED
@@ -0,0 +1,51 @@
1
+ ifeq ($(OS),Windows_NT)
2
+ RM = cmd /c del /f /q /s
3
+ else
4
+ RM = rm -fr
5
+ endif
6
+ EXTCONF = ruby -- extconf.rb --without-sass-embedded --without-sass-embedded-protocol --without-protoc
7
+
8
+ .PHONY: all
9
+ all: sass_embedded embedded_sass_pb.rb
10
+
11
+ .PHONY: install
12
+ install:
13
+
14
+ .PHONY: clean
15
+ clean:
16
+ $(RM) embedded_sass_pb.rb protoc sass_embedded
17
+
18
+ .PHONY: distclean
19
+ distclean: clean
20
+ $(RM) embedded_sass.proto protoc-*.zip sass_embedded-*.tar.gz
21
+
22
+ ifeq ($(OS),Windows_NT)
23
+ sass_embedded-*.zip:
24
+ else
25
+ sass_embedded-*.tar.gz:
26
+ endif
27
+ $(EXTCONF) --with-sass-embedded
28
+
29
+ ifeq ($(OS),Windows_NT)
30
+ sass_embedded: sass_embedded-*.zip
31
+ powershell -c "Get-Item $< | Expand-Archive -DestinationPath . -Force"
32
+ else
33
+ sass_embedded: sass_embedded-*.tar.gz
34
+ tar -vxzf $<
35
+ endif
36
+
37
+ protoc-*.zip:
38
+ $(EXTCONF) --with-protoc
39
+
40
+ protoc: protoc-*.zip
41
+ ifeq ($(OS),Windows_NT)
42
+ powershell -c "Get-Item $< | Expand-Archive -DestinationPath $@ -Force"
43
+ else
44
+ unzip -od $@ $<
45
+ endif
46
+
47
+ embedded_sass.proto:
48
+ $(EXTCONF) --with-sass-embedded-protocol
49
+
50
+ %_pb.rb: %.proto protoc
51
+ ./protoc/bin/protoc --ruby_out=. $<
data/ext/extconf.rb ADDED
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'mkmf'
5
+ require 'json'
6
+ require 'open-uri'
7
+ require 'fileutils'
8
+ require_relative '../lib/sass/platform'
9
+
10
+ module Sass
11
+ # Install dependencies for sass-embedded during gem install
12
+ class Extconf
13
+ def initialize
14
+ get_with_config('sass-embedded', true) { latest_sass_embedded }
15
+ get_with_config('sass-embedded-protocol', true) { latest_sass_embedded_protocol }
16
+ get_with_config('protoc', true) { latest_protoc }
17
+ end
18
+
19
+ private
20
+
21
+ def get_with_config(config, default)
22
+ val = with_config(config, default)
23
+ case val
24
+ when true
25
+ if block_given?
26
+ get yield
27
+ else
28
+ get default
29
+ end
30
+ when false
31
+ nil
32
+ else
33
+ get val
34
+ end
35
+ end
36
+
37
+ def get(uri_s)
38
+ uri = URI.parse(uri_s)
39
+ path = File.absolute_path(File.basename(uri.path), __dir__)
40
+ if uri.is_a?(URI::File) || uri.instance_of?(URI::Generic)
41
+ FileUtils.copy_file uri.path, path
42
+ elsif uri.respond_to? :open
43
+ uri.open do |source|
44
+ File.open(path, 'wb') do |destination|
45
+ destination.write source.read
46
+ end
47
+ end
48
+ else
49
+ raise
50
+ end
51
+ rescue StandardError
52
+ raise "Failed to get: #{uri}"
53
+ end
54
+
55
+ def latest_release(repo, prerelease: false)
56
+ if prerelease
57
+ headers = {}
58
+ headers['Authorization'] = "token #{ENV['GITHUB_TOKEN']}" if ENV['GITHUB_TOKEN']
59
+ URI.parse("https://api.github.com/repos/#{repo}/releases").open(headers) do |file|
60
+ JSON.parse(file.read)[0]['tag_name']
61
+ end
62
+ else
63
+ URI.parse("https://github.com/#{repo}/releases/latest").open do |file|
64
+ File.basename file.base_uri.to_s
65
+ end
66
+ end
67
+ end
68
+
69
+ def latest_sass_embedded
70
+ repo = 'sass/dart-sass-embedded'
71
+
72
+ # TODO, don't use prerelease once a release is available
73
+ tag_name = latest_release repo, prerelease: true
74
+
75
+ os = case Sass::Platform::OS
76
+ when 'darwin'
77
+ 'macos'
78
+ when 'linux'
79
+ 'linux'
80
+ when 'windows'
81
+ 'windows'
82
+ else
83
+ raise "Unsupported OS: #{Sass::Platform::OS}"
84
+ end
85
+
86
+ arch = case Sass::Platform::ARCH
87
+ when 'x86_64'
88
+ 'x64'
89
+ when 'i386'
90
+ 'ia32'
91
+ else
92
+ raise "Unsupported Arch: #{Sass::Platform::ARCH}"
93
+ end
94
+
95
+ ext = case os
96
+ when 'windows'
97
+ 'zip'
98
+ else
99
+ 'tar.gz'
100
+ end
101
+
102
+ "https://github.com/#{repo}/releases/download/#{tag_name}/sass_embedded-#{tag_name}-#{os}-#{arch}.#{ext}"
103
+ end
104
+
105
+ def latest_protoc
106
+ repo = 'protocolbuffers/protobuf'
107
+
108
+ tag_name = latest_release repo
109
+
110
+ os = case Sass::Platform::OS
111
+ when 'darwin'
112
+ 'osx'
113
+ when 'linux'
114
+ 'linux'
115
+ when 'windows'
116
+ 'win'
117
+ else
118
+ raise "Unsupported OS: #{Sass::Platform::OS}"
119
+ end
120
+
121
+ arch = case Sass::Platform::ARCH
122
+ when 'aarch64'
123
+ 'aarch_64'
124
+ when 'sparcv9'
125
+ 's390'
126
+ when 'i386'
127
+ 'x86_32'
128
+ when 'x86_64'
129
+ 'x86_64'
130
+ when 'powerpc64'
131
+ 'ppcle_64'
132
+ else
133
+ raise "Unsupported Arch: #{Sass::Platform::ARCH}"
134
+ end
135
+
136
+ os_arch = case os
137
+ when 'win'
138
+ os + arch.split('_').last
139
+ else
140
+ "#{os}-#{arch}"
141
+ end
142
+
143
+ ext = 'zip'
144
+
145
+ "https://github.com/#{repo}/releases/download/#{tag_name}/protoc-#{tag_name[1..]}-#{os_arch}.#{ext}"
146
+ end
147
+
148
+ def latest_sass_embedded_protocol
149
+ repo = 'sass/embedded-protocol'
150
+
151
+ # TODO: use latest release once available
152
+ # tag_name = latest_release repo
153
+ tag_name = 'HEAD'
154
+
155
+ "https://raw.githubusercontent.com/#{repo}/#{tag_name}/embedded_sass.proto"
156
+ end
157
+ end
158
+ end
159
+
160
+ Sass::Extconf.new
data/lib/sass.rb CHANGED
@@ -1,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # The Sass module
3
4
  module Sass
4
5
  # The global include_paths for Sass files. This is meant for plugins and
5
6
  # libraries to register the paths to their Sass stylesheets to that they may
6
7
  # be `@imported`. This include path is used by every instance of
7
- # {Sass::Embedded::Compiler}. They are lower-precedence than any include
8
- # paths passed in via the `:include_paths` option.
8
+ # {Sass::Embedded}. They are lower-precedence than any include paths passed
9
+ # in via the `:include_paths` option.
9
10
  #
10
11
  # If the `SASS_PATH` environment variable is set,
11
12
  # the initial value of `include_paths` will be initialized based on that.
@@ -13,7 +14,7 @@ module Sass
13
14
  # (semicolon-separated on Windows).
14
15
  #
15
16
  # @example
16
- # Sass.include_paths << File.dirname(__FILE__ + '/sass')
17
+ # Sass.include_paths << File.dirname(__FILE__) + '/sass'
17
18
  # @return [Array<String, Pathname>]
18
19
  def self.include_paths
19
20
  @include_paths ||= if ENV['SASS_PATH']
@@ -23,14 +24,21 @@ module Sass
23
24
  end
24
25
  end
25
26
 
26
- def self.render(options)
27
- unless defined? @compiler
28
- @compiler = Sass::Embedded::Compiler.new
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
+ @embedded = Sass::Embedded.new
29
37
  at_exit do
30
- @compiler.close
38
+ @embedded.close
31
39
  end
32
40
  end
33
- @compiler.render options
41
+ @embedded.render(**kwargs)
34
42
  end
35
43
  end
36
44
 
@@ -38,5 +46,5 @@ require_relative 'sass/version'
38
46
  require_relative 'sass/error'
39
47
  require_relative 'sass/platform'
40
48
  require_relative 'sass/util'
41
- require_relative 'sass/embedded/transport'
42
- require_relative 'sass/embedded/compiler'
49
+ require_relative 'sass/transport'
50
+ require_relative 'sass/embedded'
@@ -0,0 +1,317 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ # The interface for using dart-sass-embedded
5
+ class Embedded
6
+ def initialize
7
+ @transport = Transport.new
8
+ @id_semaphore = Mutex.new
9
+ @id = 0
10
+ end
11
+
12
+ # rubocop:disable Lint/UnusedMethodArgument
13
+
14
+ def render(data: nil,
15
+ file: nil,
16
+ indented_syntax: false,
17
+ include_paths: [],
18
+ output_style: :expanded,
19
+ precision: 5,
20
+ indent_type: :space,
21
+ indent_width: 2,
22
+ linefeed: :lf,
23
+ source_comments: false,
24
+ source_map: false,
25
+ out_file: nil,
26
+ omit_source_map_url: false,
27
+ source_map_contents: false,
28
+ source_map_embed: false,
29
+ source_map_root: '',
30
+ functions: {},
31
+ importer: [])
32
+ # rubocop:enable Lint/UnusedMethodArgument
33
+
34
+ start = Util.now
35
+
36
+ compilation_id = next_id
37
+
38
+ renderer = Renderer.new(
39
+ data: data,
40
+ file: file,
41
+ indented_syntax: indented_syntax,
42
+ include_paths: include_paths,
43
+ output_style: output_style,
44
+ source_map: source_map,
45
+ out_file: out_file,
46
+ functions: functions,
47
+ importer: importer
48
+ )
49
+
50
+ response = @transport.send renderer.compile_request(compilation_id), compilation_id
51
+
52
+ loop do
53
+ case response
54
+ when EmbeddedProtocol::OutboundMessage::CompileResponse
55
+ break
56
+ when EmbeddedProtocol::OutboundMessage::CanonicalizeRequest
57
+ response = @transport.send renderer.canonicalize_response(response), compilation_id
58
+ when EmbeddedProtocol::OutboundMessage::ImportRequest
59
+ response = @transport.send renderer.import_response(response), compilation_id
60
+ when EmbeddedProtocol::OutboundMessage::FunctionCallRequest
61
+ response = @transport.send renderer.function_call_response(response), compilation_id
62
+ when EmbeddedProtocol::ProtocolError
63
+ raise ProtocolError, response.message
64
+ else
65
+ raise ProtocolError, "Unexpected packet received: #{response}"
66
+ end
67
+ end
68
+
69
+ if response.failure
70
+ raise RenderError.new(
71
+ response.failure.message,
72
+ response.failure.formatted,
73
+ if response.failure.span
74
+ response.failure.span.url == '' ? 'stdin' : URI.parse(response.failure.span.url).path
75
+ end,
76
+ response.failure.span ? response.failure.span.start.line + 1 : nil,
77
+ response.failure.span ? response.failure.span.start.column + 1 : nil,
78
+ 1
79
+ )
80
+ end
81
+
82
+ finish = Util.now
83
+
84
+ {
85
+ css: response.success.css,
86
+ map: response.success.source_map,
87
+ stats: {
88
+ entry: file.nil? ? 'data' : file,
89
+ start: start,
90
+ end: finish,
91
+ duration: finish - start
92
+ }
93
+ }
94
+ end
95
+
96
+ def close
97
+ @transport.close
98
+ nil
99
+ end
100
+
101
+ private
102
+
103
+ def info
104
+ version_response = @transport.send EmbeddedProtocol::InboundMessage::VersionRequest.new(
105
+ id: next_id
106
+ )
107
+ {
108
+ compiler_version: version_response.compiler_version,
109
+ protocol_version: version_response.protocol_version,
110
+ implementation_name: version_response.implementation_name,
111
+ implementation_version: version_response.implementation_version
112
+ }
113
+ end
114
+
115
+ def next_id
116
+ @id_semaphore.synchronize do
117
+ @id += 1
118
+ @id = 0 if @id == Transport::PROTOCOL_ERROR_ID
119
+ @id
120
+ end
121
+ end
122
+
123
+ # Helper class that maintains render state
124
+ class Renderer
125
+ def initialize(data:,
126
+ file:,
127
+ indented_syntax:,
128
+ include_paths:,
129
+ output_style:,
130
+ source_map:,
131
+ out_file:,
132
+ functions:,
133
+ importer:)
134
+ raise ArgumentError, 'Either :data or :file must be set.' if file.nil? && data.nil?
135
+
136
+ @data = data
137
+ @file = file
138
+ @indented_syntax = indented_syntax
139
+ @include_paths = include_paths
140
+ @output_style = output_style
141
+ @source_map = source_map
142
+ @out_file = out_file
143
+ @global_functions = functions.keys
144
+ @functions = functions.transform_keys do |key|
145
+ key.to_s.split('(')[0].chomp
146
+ end
147
+ @importer = importer
148
+ @import_responses = {}
149
+ end
150
+
151
+ def compile_request(id)
152
+ EmbeddedProtocol::InboundMessage::CompileRequest.new(
153
+ id: id,
154
+ string: string,
155
+ path: path,
156
+ style: style,
157
+ source_map: source_map,
158
+ importers: importers,
159
+ global_functions: global_functions,
160
+ alert_color: $stderr.tty?,
161
+ alert_ascii: Platform::OS == 'windows'
162
+ )
163
+ end
164
+
165
+ def canonicalize_response(canonicalize_request)
166
+ url = Util.file_uri(File.absolute_path(canonicalize_request.url, (@file.nil? ? 'stdin' : @file)))
167
+
168
+ begin
169
+ result = @importer[canonicalize_request.importer_id].call canonicalize_request.url, @file
170
+ raise result if result.is_a? StandardError
171
+ rescue StandardError => e
172
+ return EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
173
+ id: canonicalize_request.id,
174
+ error: e.message
175
+ )
176
+ end
177
+
178
+ if result&.key? :contents
179
+ @import_responses[url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
180
+ id: canonicalize_request.id,
181
+ success: EmbeddedProtocol::InboundMessage::ImportResponse::ImportSuccess.new(
182
+ contents: result[:contents],
183
+ syntax: EmbeddedProtocol::Syntax::SCSS,
184
+ source_map_url: nil
185
+ )
186
+ )
187
+ EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
188
+ id: canonicalize_request.id,
189
+ url: url
190
+ )
191
+ elsif result&.key? :file
192
+ canonicalized_url = Util.file_uri(result[:file])
193
+
194
+ # TODO: FileImportRequest is not supported yet.
195
+ # Workaround by reading contents and return it when server asks
196
+ @import_responses[canonicalized_url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
197
+ id: canonicalize_request.id,
198
+ success: EmbeddedProtocol::InboundMessage::ImportResponse::ImportSuccess.new(
199
+ contents: File.read(result[:file]),
200
+ syntax: EmbeddedProtocol::Syntax::SCSS,
201
+ source_map_url: nil
202
+ )
203
+ )
204
+
205
+ EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
206
+ id: canonicalize_request.id,
207
+ url: canonicalized_url
208
+ )
209
+ else
210
+ EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
211
+ id: canonicalize_request.id
212
+ )
213
+ end
214
+ end
215
+
216
+ def import_response(import_request)
217
+ url = import_request.url
218
+
219
+ if @import_responses.key? url
220
+ @import_responses[url].id = import_request.id
221
+ else
222
+ @import_responses[url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
223
+ id: import_request.id,
224
+ error: "Failed to import: #{url}"
225
+ )
226
+ end
227
+
228
+ @import_responses[url]
229
+ end
230
+
231
+ def function_call_response(function_call_request)
232
+ EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
233
+ id: function_call_request.id,
234
+ success: @functions[function_call_request.name].call(*function_call_request.arguments)
235
+ )
236
+ rescue StandardError => e
237
+ EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
238
+ id: function_call_request.id,
239
+ error: e.message
240
+ )
241
+ end
242
+
243
+ private
244
+
245
+ def syntax
246
+ if @indented_syntax == true
247
+ EmbeddedProtocol::Syntax::INDENTED
248
+ else
249
+ EmbeddedProtocol::Syntax::SCSS
250
+ end
251
+ end
252
+
253
+ def url
254
+ return if @file.nil?
255
+
256
+ Util.file_uri(@file)
257
+ end
258
+
259
+ def string
260
+ return if @data.nil?
261
+
262
+ EmbeddedProtocol::InboundMessage::CompileRequest::StringInput.new(
263
+ source: @data,
264
+ url: url,
265
+ syntax: syntax
266
+ )
267
+ end
268
+
269
+ def path
270
+ @file if @data.nil?
271
+ end
272
+
273
+ def style
274
+ case @output_style.to_sym
275
+ when :expanded
276
+ EmbeddedProtocol::OutputStyle::EXPANDED
277
+ when :compressed
278
+ EmbeddedProtocol::OutputStyle::COMPRESSED
279
+ when :nested, :compact
280
+ raise ArgumentError, "#{@output_style} is not a supported output_style"
281
+ else
282
+ raise ArgumentError, "#{@output_style} is not a valid utput_style"
283
+ end
284
+ end
285
+
286
+ def source_map
287
+ @source_map.is_a?(String) || (@source_map == true && !@out_file.nil?)
288
+ end
289
+
290
+ attr_reader :global_functions
291
+
292
+ # Order
293
+ # 1. Loading a file relative to the file in which the @use or @import appeared.
294
+ # 2. Each custom importer.
295
+ # 3. Loading a file relative to the current working directory.
296
+ # 4. Each load path in includePaths
297
+ # 5. Each load path specified in the SASS_PATH environment variable, which should be semicolon-separated on Windows and colon-separated elsewhere.
298
+ def importers
299
+ custom_importers = @importer.map.with_index do |_, id|
300
+ EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
301
+ importer_id: id
302
+ )
303
+ end
304
+
305
+ include_path_importers = @include_paths
306
+ .concat(Sass.include_paths)
307
+ .map do |include_path|
308
+ EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
309
+ path: File.absolute_path(include_path)
310
+ )
311
+ end
312
+
313
+ custom_importers.concat include_path_importers
314
+ end
315
+ end
316
+ end
317
+ end