sass-embedded 1.99.0 → 1.101.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/ext/sass/Rakefile +80 -382
- data/ext/sass/file_utils.rb +77 -0
- data/ext/sass/package.json +1 -1
- data/ext/sass/platform.rb +46 -0
- data/ext/sass/sass-1.101.0.tgz +0 -0
- data/ext/sass/sass_config.rb +190 -0
- data/ext/sass/utils.rb +41 -0
- data/lib/sass/compiler/channel.rb +6 -6
- data/lib/sass/compiler/dispatcher.rb +1 -1
- data/lib/sass/compiler/{host → session}/function_registry.rb +9 -4
- data/lib/sass/compiler/{host → session}/importer_registry.rb +21 -6
- data/lib/sass/compiler/{host → session}/logger_registry.rb +3 -3
- data/lib/sass/compiler/session/path.rb +34 -0
- data/lib/sass/compiler/{host → session}/protofier.rb +1 -1
- data/lib/sass/compiler/session/stack_trace.rb +46 -0
- data/lib/sass/compiler/{host → session}/struct.rb +1 -1
- data/lib/sass/compiler/{host.rb → session.rb} +19 -12
- data/lib/sass/compiler.rb +5 -4
- data/lib/sass/embedded/version.rb +1 -1
- data/lib/sass/embedded_protocol.rb +1 -1
- data/lib/sass/exception.rb +69 -17
- data/lib/sass/gem_package_importer.rb +14 -5
- data/lib/sass/uri.rb +56 -0
- data/lib/sass/value/color/space/utils.rb +2 -2
- metadata +18 -11
- data/ext/sass/sass-1.99.0.tgz +0 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# The {Platform} module.
|
|
4
|
+
#
|
|
5
|
+
# @!visibility private
|
|
6
|
+
module Platform
|
|
7
|
+
HOST_CPU = RbConfig::CONFIG['host_cpu'].downcase
|
|
8
|
+
|
|
9
|
+
CPU = case HOST_CPU
|
|
10
|
+
when /amd64|x86_64|x64/
|
|
11
|
+
'x86_64'
|
|
12
|
+
when /i\d86|x86|i86pc/
|
|
13
|
+
'i386'
|
|
14
|
+
when /arm64|aarch64/
|
|
15
|
+
'aarch64'
|
|
16
|
+
when /arm/
|
|
17
|
+
'arm'
|
|
18
|
+
when /ppc64le|powerpc64le/
|
|
19
|
+
'ppc64le'
|
|
20
|
+
else
|
|
21
|
+
HOST_CPU
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
HOST_OS = RbConfig::CONFIG['host_os'].downcase
|
|
25
|
+
|
|
26
|
+
OS = case HOST_OS
|
|
27
|
+
when /darwin/
|
|
28
|
+
'darwin'
|
|
29
|
+
when /linux-android/
|
|
30
|
+
'linux-android'
|
|
31
|
+
when /linux-musl/
|
|
32
|
+
'linux-musl'
|
|
33
|
+
when /linux-none/
|
|
34
|
+
'linux-none'
|
|
35
|
+
when /linux-uclibc/
|
|
36
|
+
'linux-uclibc'
|
|
37
|
+
when /linux/
|
|
38
|
+
'linux'
|
|
39
|
+
when *Gem::WIN_PATTERNS
|
|
40
|
+
'windows'
|
|
41
|
+
else
|
|
42
|
+
HOST_OS
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
ARCH = "#{CPU}-#{OS}".freeze
|
|
46
|
+
end
|
|
Binary file
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'platform'
|
|
4
|
+
|
|
5
|
+
# The {SassConfig} module.
|
|
6
|
+
#
|
|
7
|
+
# @!visibility private
|
|
8
|
+
module SassConfig
|
|
9
|
+
module_function
|
|
10
|
+
|
|
11
|
+
def package_json(path = '.')
|
|
12
|
+
require 'json'
|
|
13
|
+
|
|
14
|
+
JSON.parse(File.read(File.absolute_path('package.json', path)))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def dart_support?
|
|
18
|
+
%w[darwin linux linux-android linux-musl windows].include?(Platform::OS) &&
|
|
19
|
+
%w[x86_64 aarch64 arm riscv64].include?(Platform::CPU)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def dart_sass_version
|
|
23
|
+
package_json(__dir__)['dependencies']['sass']
|
|
24
|
+
# TODO: remove after https://github.com/sass/dart-sass/pull/2413
|
|
25
|
+
.delete_prefix('file:sass-').delete_suffix('.tgz')
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def dart_sass
|
|
29
|
+
repo = 'https://github.com/sass/dart-sass'
|
|
30
|
+
|
|
31
|
+
tag_name = dart_sass_version
|
|
32
|
+
|
|
33
|
+
message = "dart-sass for #{Platform::ARCH} not available at #{repo}/releases/tag/#{tag_name}"
|
|
34
|
+
|
|
35
|
+
env = ''
|
|
36
|
+
|
|
37
|
+
os = case Platform::OS
|
|
38
|
+
when 'darwin'
|
|
39
|
+
'macos'
|
|
40
|
+
when 'linux'
|
|
41
|
+
'linux'
|
|
42
|
+
when 'linux-android'
|
|
43
|
+
'android'
|
|
44
|
+
when 'linux-musl'
|
|
45
|
+
env = '-musl'
|
|
46
|
+
'linux'
|
|
47
|
+
when 'windows'
|
|
48
|
+
'windows'
|
|
49
|
+
else
|
|
50
|
+
raise NotImplementedError, message
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
cpu = case Platform::CPU
|
|
54
|
+
when 'x86_64'
|
|
55
|
+
'x64'
|
|
56
|
+
when 'aarch64'
|
|
57
|
+
'arm64'
|
|
58
|
+
when 'arm'
|
|
59
|
+
'arm'
|
|
60
|
+
when 'riscv64'
|
|
61
|
+
'riscv64'
|
|
62
|
+
else
|
|
63
|
+
raise NotImplementedError, message
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
ext = Platform::OS == 'windows' ? 'zip' : 'tar.gz'
|
|
67
|
+
|
|
68
|
+
"#{repo}/releases/download/#{tag_name}/dart-sass-#{tag_name}-#{os}-#{cpu}#{env}.#{ext}"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def protoc
|
|
72
|
+
repo = 'https://repo.maven.apache.org/maven2/com/google/protobuf/protoc'
|
|
73
|
+
|
|
74
|
+
dependency = Gem::Dependency.new('google-protobuf')
|
|
75
|
+
|
|
76
|
+
spec = dependency.to_spec
|
|
77
|
+
|
|
78
|
+
version = spec.version
|
|
79
|
+
|
|
80
|
+
message = "protoc for #{Platform::ARCH} not available at #{repo}/#{version}"
|
|
81
|
+
|
|
82
|
+
os = case Platform::OS
|
|
83
|
+
when 'darwin'
|
|
84
|
+
'osx'
|
|
85
|
+
when 'linux', 'linux-android', 'linux-musl', 'linux-none', 'linux-uclibc'
|
|
86
|
+
'linux'
|
|
87
|
+
when 'windows'
|
|
88
|
+
'windows'
|
|
89
|
+
else
|
|
90
|
+
raise NotImplementedError, message
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
cpu = case Platform::CPU
|
|
94
|
+
when 'i386'
|
|
95
|
+
'x86_32'
|
|
96
|
+
when 'x86_64'
|
|
97
|
+
'x86_64'
|
|
98
|
+
when 'aarch64'
|
|
99
|
+
Platform::OS == 'windows' ? 'x86_64' : 'aarch_64'
|
|
100
|
+
when 'ppc64le'
|
|
101
|
+
'ppcle_64'
|
|
102
|
+
when 's390x'
|
|
103
|
+
's390_64'
|
|
104
|
+
else
|
|
105
|
+
raise NotImplementedError, message
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
uri = "#{repo}/#{version}/protoc-#{version}-#{os}-#{cpu}.exe"
|
|
109
|
+
|
|
110
|
+
Utils.fetch_https("#{uri}.sha1")
|
|
111
|
+
|
|
112
|
+
uri
|
|
113
|
+
rescue Gem::RemoteFetcher::FetchError
|
|
114
|
+
dependency_request = Gem::Resolver::DependencyRequest.new(dependency, nil)
|
|
115
|
+
|
|
116
|
+
versions = Gem::Resolver::BestSet.new.find_all(dependency_request).filter_map do |s|
|
|
117
|
+
s.version if s.platform == Gem::Platform::RUBY
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
versions.sort.reverse_each do |v|
|
|
121
|
+
uri = "#{repo}/#{v}/protoc-#{v}-#{os}-#{cpu}.exe"
|
|
122
|
+
|
|
123
|
+
Utils.fetch_https("#{uri}.sha1")
|
|
124
|
+
|
|
125
|
+
return uri
|
|
126
|
+
rescue Gem::RemoteFetcher::FetchError
|
|
127
|
+
next
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
raise NotImplementedError, message
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def embedded_sass_protocol
|
|
134
|
+
require 'json'
|
|
135
|
+
|
|
136
|
+
rubyarchdir = ENV.fetch('RUBYARCHDIR', nil)
|
|
137
|
+
|
|
138
|
+
rubylibdir = ENV.fetch('RUBYLIBDIR', nil)
|
|
139
|
+
|
|
140
|
+
version = Utils.capture(RbConfig.ruby,
|
|
141
|
+
"-I#{File.absolute_path('../../lib', __dir__)}",
|
|
142
|
+
*("-I#{rubyarchdir}" if rubyarchdir),
|
|
143
|
+
*("-I#{rubylibdir}" if rubylibdir),
|
|
144
|
+
File.absolute_path('../../exe/sass', __dir__),
|
|
145
|
+
'--embedded',
|
|
146
|
+
'--version')
|
|
147
|
+
|
|
148
|
+
tag_name = JSON.parse(version)['protocolVersion']
|
|
149
|
+
|
|
150
|
+
"https://github.com/sass/sass/raw/embedded-protocol-#{tag_name}/spec/embedded_sass.proto"
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def development?
|
|
154
|
+
File.exist?('../../Gemfile')
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def gem_version
|
|
158
|
+
require_relative '../../lib/sass/embedded/version'
|
|
159
|
+
|
|
160
|
+
development? ? dart_sass_version : Sass::Embedded::VERSION
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def gem_platform
|
|
164
|
+
platform = Gem::Platform.new("#{Platform::CPU}-#{Platform::HOST_OS}")
|
|
165
|
+
case Platform::OS
|
|
166
|
+
when 'darwin'
|
|
167
|
+
case platform.cpu
|
|
168
|
+
when 'aarch64'
|
|
169
|
+
Gem::Platform.new(['arm64', platform.os])
|
|
170
|
+
else
|
|
171
|
+
platform
|
|
172
|
+
end
|
|
173
|
+
when 'linux'
|
|
174
|
+
if platform.version&.start_with?('gnu')
|
|
175
|
+
platform
|
|
176
|
+
else
|
|
177
|
+
Gem::Platform.new([platform.cpu, platform.os, "gnu#{platform.version}"])
|
|
178
|
+
end
|
|
179
|
+
when 'windows'
|
|
180
|
+
case platform.cpu
|
|
181
|
+
when 'x86_64'
|
|
182
|
+
Gem::Platform.new('x64-mingw-ucrt')
|
|
183
|
+
else
|
|
184
|
+
Gem::Platform.new([platform.cpu, 'mingw', 'ucrt'])
|
|
185
|
+
end
|
|
186
|
+
else
|
|
187
|
+
platform
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
data/ext/sass/utils.rb
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# The {Utils} module.
|
|
4
|
+
#
|
|
5
|
+
# @!visibility private
|
|
6
|
+
module Utils
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
def capture(...)
|
|
10
|
+
require 'open3'
|
|
11
|
+
|
|
12
|
+
stdout, stderr, status = Open3.capture3(...)
|
|
13
|
+
|
|
14
|
+
raise stderr unless status.success?
|
|
15
|
+
|
|
16
|
+
stdout
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def fetch_https(source_uri)
|
|
20
|
+
require 'rubygems/remote_fetcher'
|
|
21
|
+
|
|
22
|
+
source_uri = begin
|
|
23
|
+
Gem::Uri.parse!(source_uri)
|
|
24
|
+
rescue NoMethodError
|
|
25
|
+
URI.parse(source_uri)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
Gem::RemoteFetcher.fetcher.fetch_https(source_uri)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def windows_system_directory
|
|
32
|
+
path = capture('powershell.exe',
|
|
33
|
+
'-NoLogo',
|
|
34
|
+
'-NoProfile',
|
|
35
|
+
'-NonInteractive',
|
|
36
|
+
'-Command',
|
|
37
|
+
'[Environment]::GetFolderPath([Environment+SpecialFolder]::System) | Write-Host -NoNewline')
|
|
38
|
+
|
|
39
|
+
File.absolute_path(path)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -29,24 +29,24 @@ module Sass
|
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
def stream(
|
|
32
|
+
def stream(session)
|
|
33
33
|
@mutex.synchronize do
|
|
34
34
|
raise IOError, 'closed compiler' if @dispatcher.nil?
|
|
35
35
|
|
|
36
|
-
Stream.new(@dispatcher,
|
|
36
|
+
Stream.new(@dispatcher, session)
|
|
37
37
|
rescue Errno::EBUSY
|
|
38
38
|
@dispatcher = Dispatcher.new(*@args, **@kwargs, &@block)
|
|
39
|
-
Stream.new(@dispatcher,
|
|
39
|
+
Stream.new(@dispatcher, session)
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
# The {Stream} between {Dispatcher} and {
|
|
43
|
+
# The {Stream} between {Dispatcher} and {Session}.
|
|
44
44
|
class Stream
|
|
45
45
|
attr_reader :id
|
|
46
46
|
|
|
47
|
-
def initialize(dispatcher,
|
|
47
|
+
def initialize(dispatcher, session)
|
|
48
48
|
@dispatcher = dispatcher
|
|
49
|
-
@id = @dispatcher.subscribe(
|
|
49
|
+
@id = @dispatcher.subscribe(session)
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def close
|
|
@@ -4,7 +4,7 @@ module Sass
|
|
|
4
4
|
class Compiler
|
|
5
5
|
# The {Dispatcher} class.
|
|
6
6
|
#
|
|
7
|
-
# It dispatches messages between multiple instances of {
|
|
7
|
+
# It dispatches messages between multiple instances of {Session} and a single {Connection} to the compiler.
|
|
8
8
|
class Dispatcher
|
|
9
9
|
def initialize(idle_timeout: 0)
|
|
10
10
|
@id = 1
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
module Sass
|
|
4
4
|
class Compiler
|
|
5
|
-
class
|
|
5
|
+
class Session
|
|
6
6
|
# The {FunctionRegistry} class.
|
|
7
7
|
#
|
|
8
8
|
# It stores sass custom functions and handles function calls.
|
|
9
9
|
class FunctionRegistry
|
|
10
10
|
attr_reader :compile_context, :global_functions
|
|
11
11
|
|
|
12
|
-
def initialize(functions,
|
|
12
|
+
def initialize(functions, session:)
|
|
13
13
|
@compile_context = Object.new
|
|
14
14
|
@global_functions = functions.keys.map!(&:to_s)
|
|
15
15
|
@functions_by_name = functions.transform_keys do |signature|
|
|
@@ -26,7 +26,7 @@ module Sass
|
|
|
26
26
|
@functions_by_id = {}.compare_by_identity
|
|
27
27
|
@ids_by_function = {}.compare_by_identity
|
|
28
28
|
|
|
29
|
-
@
|
|
29
|
+
@session = session
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def register(function)
|
|
@@ -68,9 +68,14 @@ module Sass
|
|
|
68
68
|
accessed_argument_lists:
|
|
69
69
|
)
|
|
70
70
|
rescue StandardError => e
|
|
71
|
+
@session.backtrace = e.backtrace
|
|
71
72
|
EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
|
|
72
73
|
id: function_call_request.id,
|
|
73
|
-
error: e.
|
|
74
|
+
error: if e.respond_to?(:detailed_message)
|
|
75
|
+
e.detailed_message(highlight: false)
|
|
76
|
+
else # TODO: remove once ruby 3.1 support is dropped
|
|
77
|
+
"#{e.message} (#{e.class.name})"
|
|
78
|
+
end
|
|
74
79
|
)
|
|
75
80
|
end
|
|
76
81
|
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
module Sass
|
|
4
4
|
class Compiler
|
|
5
|
-
class
|
|
5
|
+
class Session
|
|
6
6
|
# The {ImporterRegistry} class.
|
|
7
7
|
#
|
|
8
8
|
# It stores importers and handles import requests.
|
|
9
9
|
class ImporterRegistry
|
|
10
10
|
attr_reader :importers
|
|
11
11
|
|
|
12
|
-
def initialize(importers, load_paths,
|
|
12
|
+
def initialize(importers, load_paths, session:)
|
|
13
13
|
@id = 0
|
|
14
14
|
@importers_by_id = {}.compare_by_identity
|
|
15
15
|
@importers = importers
|
|
@@ -22,7 +22,7 @@ module Sass
|
|
|
22
22
|
end
|
|
23
23
|
)
|
|
24
24
|
|
|
25
|
-
@
|
|
25
|
+
@session = session
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
IMPORTER_ATTRS = %i[non_canonical_scheme].freeze
|
|
@@ -79,9 +79,14 @@ module Sass
|
|
|
79
79
|
containing_url_unused: canonicalize_context.instance_variable_get(:@containing_url_unused)
|
|
80
80
|
)
|
|
81
81
|
rescue StandardError => e
|
|
82
|
+
@session.backtrace = e.backtrace
|
|
82
83
|
EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
|
|
83
84
|
id: canonicalize_request.id,
|
|
84
|
-
error: e.
|
|
85
|
+
error: if e.respond_to?(:detailed_message)
|
|
86
|
+
e.detailed_message(highlight: false)
|
|
87
|
+
else # TODO: remove once ruby 3.1 support is dropped
|
|
88
|
+
"#{e.message} (#{e.class.name})"
|
|
89
|
+
end
|
|
85
90
|
)
|
|
86
91
|
end
|
|
87
92
|
|
|
@@ -103,9 +108,14 @@ module Sass
|
|
|
103
108
|
)
|
|
104
109
|
)
|
|
105
110
|
rescue StandardError => e
|
|
111
|
+
@session.backtrace = e.backtrace
|
|
106
112
|
EmbeddedProtocol::InboundMessage::ImportResponse.new(
|
|
107
113
|
id: import_request.id,
|
|
108
|
-
error: e.
|
|
114
|
+
error: if e.respond_to?(:detailed_message)
|
|
115
|
+
e.detailed_message(highlight: false)
|
|
116
|
+
else # TODO: remove once ruby 3.1 support is dropped
|
|
117
|
+
"#{e.message} (#{e.class.name})"
|
|
118
|
+
end
|
|
109
119
|
)
|
|
110
120
|
end
|
|
111
121
|
|
|
@@ -121,9 +131,14 @@ module Sass
|
|
|
121
131
|
containing_url_unused: canonicalize_context.instance_variable_get(:@containing_url_unused)
|
|
122
132
|
)
|
|
123
133
|
rescue StandardError => e
|
|
134
|
+
@session.backtrace = e.backtrace
|
|
124
135
|
EmbeddedProtocol::InboundMessage::FileImportResponse.new(
|
|
125
136
|
id: file_import_request.id,
|
|
126
|
-
error: e.
|
|
137
|
+
error: if e.respond_to?(:detailed_message)
|
|
138
|
+
e.detailed_message(highlight: false)
|
|
139
|
+
else # TODO: remove once ruby 3.1 support is dropped
|
|
140
|
+
"#{e.message} (#{e.class.name})"
|
|
141
|
+
end
|
|
127
142
|
)
|
|
128
143
|
end
|
|
129
144
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Sass
|
|
4
4
|
class Compiler
|
|
5
|
-
class
|
|
5
|
+
class Session
|
|
6
6
|
# The {LoggerRegistry} class.
|
|
7
7
|
#
|
|
8
8
|
# It stores logger and handles log events.
|
|
@@ -24,13 +24,13 @@ module Sass
|
|
|
24
24
|
if @logger_respond_to_debug
|
|
25
25
|
@logger.debug(event.message, DebugContext.new(event))
|
|
26
26
|
else
|
|
27
|
-
Kernel.warn(event.formatted)
|
|
27
|
+
Kernel.warn(Path.pretty_formatted!(+event.formatted, event.span.url))
|
|
28
28
|
end
|
|
29
29
|
when :DEPRECATION_WARNING, :WARNING
|
|
30
30
|
if @logger_respond_to_warn
|
|
31
31
|
@logger.warn(event.message, WarnContext.new(event))
|
|
32
32
|
else
|
|
33
|
-
Kernel.warn(event.formatted)
|
|
33
|
+
Kernel.warn(StackTrace.pretty_formatted!(+event.formatted, event.stack_trace))
|
|
34
34
|
end
|
|
35
35
|
else
|
|
36
36
|
raise ArgumentError, "Unknown LogEvent.type #{event.type}"
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sass
|
|
4
|
+
class Compiler
|
|
5
|
+
class Session
|
|
6
|
+
# @see https://pub.dev/documentation/path/latest/path/
|
|
7
|
+
module Path
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
# @see https://pub.dev/documentation/path/latest/path/Context/prettyUri.html
|
|
11
|
+
def pretty_uri(uri)
|
|
12
|
+
return uri unless uri&.start_with?('file:')
|
|
13
|
+
|
|
14
|
+
absolute_path = Uri.file_uri_to_path(uri)
|
|
15
|
+
relative_path = Uri.decode_uri_component(Uri.relative(uri, Uri.pwd))
|
|
16
|
+
relative_path.count('/') > absolute_path.count('/') ? absolute_path : relative_path
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def pretty_formatted!(formatted, uri)
|
|
20
|
+
index = formatted.index(uri)
|
|
21
|
+
return formatted unless index
|
|
22
|
+
|
|
23
|
+
replacement = pretty_uri(uri)
|
|
24
|
+
return formatted if uri == replacement
|
|
25
|
+
|
|
26
|
+
formatted[index, uri.length] = replacement
|
|
27
|
+
formatted
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private_constant :Path
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sass
|
|
4
|
+
class Compiler
|
|
5
|
+
class Session
|
|
6
|
+
# @see https://pub.dev/documentation/stack_trace/latest/stack_trace/
|
|
7
|
+
module StackTrace
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
# @see https://pub.dev/documentation/stack_trace/latest/stack_trace/Trace/toString.html
|
|
11
|
+
def pretty_formatted!(formatted, stack_trace)
|
|
12
|
+
longest = 0
|
|
13
|
+
|
|
14
|
+
frames = stack_trace.lines("\n", chomp: true).map do |frame|
|
|
15
|
+
location, member = frame.split(/ +/, 2)
|
|
16
|
+
uri, line_column = location.split(' ', 2)
|
|
17
|
+
|
|
18
|
+
uri = Path.pretty_uri(uri)
|
|
19
|
+
location = line_column.nil? ? uri : "#{uri} #{line_column}"
|
|
20
|
+
|
|
21
|
+
longest = location.length if location.length > longest
|
|
22
|
+
[frame, location, member]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
offset = formatted.length
|
|
26
|
+
|
|
27
|
+
frames.reverse_each do |frame, location, member|
|
|
28
|
+
index = formatted.rindex(frame, offset)
|
|
29
|
+
next unless index
|
|
30
|
+
|
|
31
|
+
offset = index
|
|
32
|
+
|
|
33
|
+
replacement = "#{location.ljust(longest)} #{member}"
|
|
34
|
+
next if frame == replacement
|
|
35
|
+
|
|
36
|
+
formatted[index, frame.length] = replacement
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
formatted
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private_constant :StackTrace
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative '
|
|
4
|
-
require_relative '
|
|
5
|
-
require_relative '
|
|
6
|
-
require_relative '
|
|
7
|
-
require_relative '
|
|
3
|
+
require_relative 'session/function_registry'
|
|
4
|
+
require_relative 'session/importer_registry'
|
|
5
|
+
require_relative 'session/logger_registry'
|
|
6
|
+
require_relative 'session/path'
|
|
7
|
+
require_relative 'session/protofier'
|
|
8
|
+
require_relative 'session/stack_trace'
|
|
9
|
+
require_relative 'session/struct'
|
|
8
10
|
|
|
9
11
|
module Sass
|
|
10
12
|
class Compiler
|
|
11
|
-
# The {
|
|
13
|
+
# The {Session} class.
|
|
12
14
|
#
|
|
13
15
|
# It communicates with {Dispatcher} and handles the host logic.
|
|
14
|
-
class
|
|
16
|
+
class Session
|
|
17
|
+
attr_writer :backtrace
|
|
18
|
+
|
|
15
19
|
def initialize(channel)
|
|
16
20
|
@channel = channel
|
|
21
|
+
@backtrace = nil
|
|
17
22
|
end
|
|
18
23
|
|
|
19
24
|
def compile_request(path:,
|
|
@@ -38,8 +43,8 @@ module Sass
|
|
|
38
43
|
verbose:)
|
|
39
44
|
alert_color = Exception.to_tty? if alert_color.nil?
|
|
40
45
|
|
|
41
|
-
@function_registry = FunctionRegistry.new(functions,
|
|
42
|
-
@importer_registry = ImporterRegistry.new(importers, load_paths,
|
|
46
|
+
@function_registry = FunctionRegistry.new(functions, session: self)
|
|
47
|
+
@importer_registry = ImporterRegistry.new(importers, load_paths, session: self)
|
|
43
48
|
@logger_registry = LoggerRegistry.new(logger)
|
|
44
49
|
|
|
45
50
|
compile_request = EmbeddedProtocol::InboundMessage::CompileRequest.new(
|
|
@@ -83,13 +88,15 @@ module Sass
|
|
|
83
88
|
result = compile_response.public_send(oneof)
|
|
84
89
|
case oneof
|
|
85
90
|
when :failure
|
|
86
|
-
|
|
91
|
+
compile_error = CompileError.new(
|
|
87
92
|
result.message,
|
|
88
|
-
result.formatted == '' ? nil : result.formatted,
|
|
93
|
+
result.formatted == '' ? nil : StackTrace.pretty_formatted!(+result.formatted, result.stack_trace),
|
|
89
94
|
result.stack_trace == '' ? nil : result.stack_trace,
|
|
90
95
|
result.span.nil? ? nil : Logger::SourceSpan.new(result.span),
|
|
91
96
|
compile_response.loaded_urls.to_a
|
|
92
97
|
)
|
|
98
|
+
compile_error.set_backtrace(@backtrace) unless @backtrace.nil?
|
|
99
|
+
raise compile_error
|
|
93
100
|
when :success
|
|
94
101
|
CompileResult.new(
|
|
95
102
|
result.css,
|
|
@@ -221,6 +228,6 @@ module Sass
|
|
|
221
228
|
end
|
|
222
229
|
end
|
|
223
230
|
|
|
224
|
-
private_constant :
|
|
231
|
+
private_constant :Session
|
|
225
232
|
end
|
|
226
233
|
end
|
data/lib/sass/compiler.rb
CHANGED
|
@@ -5,7 +5,7 @@ require_relative 'compile_result'
|
|
|
5
5
|
require_relative 'compiler/channel'
|
|
6
6
|
require_relative 'compiler/connection'
|
|
7
7
|
require_relative 'compiler/dispatcher'
|
|
8
|
-
require_relative 'compiler/
|
|
8
|
+
require_relative 'compiler/session'
|
|
9
9
|
require_relative 'compiler/varint'
|
|
10
10
|
require_relative 'embedded/version'
|
|
11
11
|
require_relative 'embedded_protocol'
|
|
@@ -17,6 +17,7 @@ require_relative 'logger/source_location'
|
|
|
17
17
|
require_relative 'logger/source_span'
|
|
18
18
|
require_relative 'node_package_importer'
|
|
19
19
|
require_relative 'serializer'
|
|
20
|
+
require_relative 'uri'
|
|
20
21
|
require_relative 'value'
|
|
21
22
|
|
|
22
23
|
module Sass
|
|
@@ -86,7 +87,7 @@ module Sass
|
|
|
86
87
|
verbose: false)
|
|
87
88
|
raise ArgumentError, 'path must be set' if path.nil?
|
|
88
89
|
|
|
89
|
-
|
|
90
|
+
Session.new(@channel).compile_request(
|
|
90
91
|
path:,
|
|
91
92
|
source: nil,
|
|
92
93
|
importer: nil,
|
|
@@ -169,7 +170,7 @@ module Sass
|
|
|
169
170
|
verbose: false)
|
|
170
171
|
raise ArgumentError, 'source must be set' if source.nil?
|
|
171
172
|
|
|
172
|
-
|
|
173
|
+
Session.new(@channel).compile_request(
|
|
173
174
|
path: nil,
|
|
174
175
|
source:,
|
|
175
176
|
importer:,
|
|
@@ -198,7 +199,7 @@ module Sass
|
|
|
198
199
|
def info
|
|
199
200
|
@info ||= [
|
|
200
201
|
['sass-embedded', Embedded::VERSION, '(Embedded Host)', '[Ruby]'].join("\t"),
|
|
201
|
-
|
|
202
|
+
Session.new(@channel).version_request.join("\t")
|
|
202
203
|
].join("\n").freeze
|
|
203
204
|
end
|
|
204
205
|
|