sass-embedded 1.74.1-aarch64-mingw-ucrt

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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +20 -0
  3. data/README.md +48 -0
  4. data/exe/sass +21 -0
  5. data/ext/sass/cli.rb +12 -0
  6. data/ext/sass/dart-sass/sass.bat +7 -0
  7. data/ext/sass/dart-sass/src/LICENSE +1687 -0
  8. data/ext/sass/dart-sass/src/dart.exe +0 -0
  9. data/ext/sass/dart-sass/src/sass.snapshot +0 -0
  10. data/ext/sass/embedded_sass_pb.rb +63 -0
  11. data/lib/sass/calculation_value/calculation_operation.rb +49 -0
  12. data/lib/sass/calculation_value.rb +22 -0
  13. data/lib/sass/canonicalize_context.rb +21 -0
  14. data/lib/sass/compile_result.rb +24 -0
  15. data/lib/sass/compiler/channel.rb +68 -0
  16. data/lib/sass/compiler/connection.rb +92 -0
  17. data/lib/sass/compiler/dispatcher.rb +115 -0
  18. data/lib/sass/compiler/host/function_registry.rb +87 -0
  19. data/lib/sass/compiler/host/importer_registry.rb +137 -0
  20. data/lib/sass/compiler/host/logger_registry.rb +55 -0
  21. data/lib/sass/compiler/host/protofier.rb +390 -0
  22. data/lib/sass/compiler/host/structifier.rb +37 -0
  23. data/lib/sass/compiler/host.rb +226 -0
  24. data/lib/sass/compiler/varint.rb +39 -0
  25. data/lib/sass/compiler.rb +212 -0
  26. data/lib/sass/elf.rb +276 -0
  27. data/lib/sass/embedded/version.rb +7 -0
  28. data/lib/sass/embedded.rb +107 -0
  29. data/lib/sass/embedded_protocol.rb +10 -0
  30. data/lib/sass/exception.rb +69 -0
  31. data/lib/sass/fork_tracker.rb +51 -0
  32. data/lib/sass/logger/silent.rb +28 -0
  33. data/lib/sass/logger/source_location.rb +22 -0
  34. data/lib/sass/logger/source_span.rb +28 -0
  35. data/lib/sass/node_package_importer.rb +17 -0
  36. data/lib/sass/serializer.rb +36 -0
  37. data/lib/sass/value/argument_list.rb +37 -0
  38. data/lib/sass/value/boolean.rb +52 -0
  39. data/lib/sass/value/calculation.rb +90 -0
  40. data/lib/sass/value/color.rb +253 -0
  41. data/lib/sass/value/function.rb +51 -0
  42. data/lib/sass/value/fuzzy_math.rb +80 -0
  43. data/lib/sass/value/list.rb +79 -0
  44. data/lib/sass/value/map.rb +71 -0
  45. data/lib/sass/value/mixin.rb +36 -0
  46. data/lib/sass/value/null.rb +48 -0
  47. data/lib/sass/value/number/unit.rb +186 -0
  48. data/lib/sass/value/number.rb +366 -0
  49. data/lib/sass/value/string.rb +61 -0
  50. data/lib/sass/value.rb +136 -0
  51. data/lib/sass-embedded.rb +4 -0
  52. metadata +120 -0
data/lib/sass/elf.rb ADDED
@@ -0,0 +1,276 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ # The {ELF} class.
5
+ #
6
+ # It parses ELF header to extract interpreter.
7
+ # @see https://github.com/torvalds/linux/blob/HEAD/include/uapi/linux/elf.h
8
+ # @see https://github.com/torvalds/linux/blob/HEAD/kernel/kexec_elf.c
9
+ class ELF
10
+ # rubocop:disable Naming/ConstantName
11
+
12
+ # 32-bit ELF base types.
13
+ Elf32_Addr = :__u32
14
+ Elf32_Half = :__u16
15
+ Elf32_Off = :__u32
16
+ Elf32_Sword = :__s32
17
+ Elf32_Word = :__u32
18
+
19
+ # 64-bit ELF base types.
20
+ Elf64_Addr = :__u64
21
+ Elf64_Half = :__u16
22
+ Elf64_SHalf = :__s16
23
+ Elf64_Off = :__u64
24
+ Elf64_Sword = :__s32
25
+ Elf64_Word = :__u32
26
+ Elf64_Xword = :__u64
27
+ Elf64_Sxword = :__s64
28
+
29
+ # rubocop:enable Naming/ConstantName
30
+
31
+ # These constants are for the segment types stored in the image headers
32
+ PT_NULL = 0
33
+ PT_LOAD = 1
34
+ PT_DYNAMIC = 2
35
+ PT_INTERP = 3
36
+ PT_NOTE = 4
37
+ PT_SHLIB = 5
38
+ PT_PHDR = 6
39
+ PT_TLS = 7
40
+ PT_LOOS = 0x60000000
41
+ PT_HIOS = 0x6fffffff
42
+ PT_LOPROC = 0x70000000
43
+ PT_HIPROC = 0x7fffffff
44
+ PT_GNU_EH_FRAME = (PT_LOOS + 0x474e550)
45
+ PT_GNU_STACK = (PT_LOOS + 0x474e551)
46
+ PT_GNU_RELRO = (PT_LOOS + 0x474e552)
47
+ PT_GNU_PROPERTY = (PT_LOOS + 0x474e553)
48
+
49
+ # These constants define the different elf file types
50
+ ET_NONE = 0
51
+ ET_REL = 1
52
+ ET_EXEC = 2
53
+ ET_DYN = 3
54
+ ET_CORE = 4
55
+ ET_LOPROC = 0xff00
56
+ ET_HIPROC = 0xffff
57
+
58
+ EI_NIDENT = 16
59
+
60
+ # rubocop:disable Naming/ConstantName
61
+
62
+ Elf32_Ehdr = [
63
+ [:unsigned_char, :e_ident, EI_NIDENT],
64
+ [Elf32_Half, :e_type],
65
+ [Elf32_Half, :e_machine],
66
+ [Elf32_Word, :e_version],
67
+ [Elf32_Addr, :e_entry],
68
+ [Elf32_Off, :e_phoff],
69
+ [Elf32_Off, :e_shoff],
70
+ [Elf32_Word, :e_flags],
71
+ [Elf32_Half, :e_ehsize],
72
+ [Elf32_Half, :e_phentsize],
73
+ [Elf32_Half, :e_phnum],
74
+ [Elf32_Half, :e_shentsize],
75
+ [Elf32_Half, :e_shnum],
76
+ [Elf32_Half, :e_shstrndx]
77
+ ].freeze
78
+
79
+ Elf64_Ehdr = [
80
+ [:unsigned_char, :e_ident, EI_NIDENT],
81
+ [Elf64_Half, :e_type],
82
+ [Elf64_Half, :e_machine],
83
+ [Elf64_Word, :e_version],
84
+ [Elf64_Addr, :e_entry],
85
+ [Elf64_Off, :e_phoff],
86
+ [Elf64_Off, :e_shoff],
87
+ [Elf64_Word, :e_flags],
88
+ [Elf64_Half, :e_ehsize],
89
+ [Elf64_Half, :e_phentsize],
90
+ [Elf64_Half, :e_phnum],
91
+ [Elf64_Half, :e_shentsize],
92
+ [Elf64_Half, :e_shnum],
93
+ [Elf64_Half, :e_shstrndx]
94
+ ].freeze
95
+
96
+ Elf32_Phdr = [
97
+ [Elf32_Word, :p_type],
98
+ [Elf32_Off, :p_offset],
99
+ [Elf32_Addr, :p_vaddr],
100
+ [Elf32_Addr, :p_paddr],
101
+ [Elf32_Word, :p_filesz],
102
+ [Elf32_Word, :p_memsz],
103
+ [Elf32_Word, :p_flags],
104
+ [Elf32_Word, :p_align]
105
+ ].freeze
106
+
107
+ Elf64_Phdr = [
108
+ [Elf64_Word, :p_type],
109
+ [Elf64_Word, :p_flags],
110
+ [Elf64_Off, :p_offset],
111
+ [Elf64_Addr, :p_vaddr],
112
+ [Elf64_Addr, :p_paddr],
113
+ [Elf64_Xword, :p_filesz],
114
+ [Elf64_Xword, :p_memsz],
115
+ [Elf64_Xword, :p_align]
116
+ ].freeze
117
+
118
+ # rubocop:enable Naming/ConstantName
119
+
120
+ # e_ident[] indexes
121
+ EI_MAG0 = 0
122
+ EI_MAG1 = 1
123
+ EI_MAG2 = 2
124
+ EI_MAG3 = 3
125
+ EI_CLASS = 4
126
+ EI_DATA = 5
127
+ EI_VERSION = 6
128
+ EI_OSABI = 7
129
+ EI_PAD = 8
130
+
131
+ # EI_MAG
132
+ ELFMAG0 = 0x7f
133
+ ELFMAG1 = 'E'.ord
134
+ ELFMAG2 = 'L'.ord
135
+ ELFMAG3 = 'F'.ord
136
+ ELFMAG = [ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3].pack('C*')
137
+ SELFMAG = 4
138
+
139
+ # e_ident[EI_CLASS]
140
+ ELFCLASSNONE = 0
141
+ ELFCLASS32 = 1
142
+ ELFCLASS64 = 2
143
+ ELFCLASSNUM = 3
144
+
145
+ # e_ident[EI_DATA]
146
+ ELFDATANONE = 0
147
+ ELFDATA2LSB = 1
148
+ ELFDATA2MSB = 2
149
+
150
+ def initialize(buffer)
151
+ @buffer = buffer
152
+ @ehdr = read_ehdr
153
+ @buffer.seek(@ehdr[:e_phoff], IO::SEEK_SET)
154
+ @proghdrs = Array.new(@ehdr[:e_phnum]) do
155
+ read_phdr
156
+ end
157
+ end
158
+
159
+ def relocatable?
160
+ @ehdr[:e_type] == ET_REL
161
+ end
162
+
163
+ def executable?
164
+ @ehdr[:e_type] == ET_EXEC
165
+ end
166
+
167
+ def shared_object?
168
+ @ehdr[:e_type] == ET_DYN
169
+ end
170
+
171
+ def core?
172
+ @ehdr[:e_type] == ET_CORE
173
+ end
174
+
175
+ def interpreter
176
+ phdr = @proghdrs.find { |p| p[:p_type] == PT_INTERP }
177
+ return if phdr.nil?
178
+
179
+ @buffer.seek(phdr[:p_offset], IO::SEEK_SET)
180
+ interpreter = @buffer.read(phdr[:p_filesz])
181
+ raise ArgumentError unless interpreter.end_with?("\0")
182
+
183
+ interpreter.chomp!("\0")
184
+ end
185
+
186
+ private
187
+
188
+ def file_class
189
+ @ehdr[:e_ident][EI_CLASS]
190
+ end
191
+
192
+ def data_encoding
193
+ @ehdr[:e_ident][EI_DATA]
194
+ end
195
+
196
+ def read_ehdr
197
+ @ehdr = { e_ident: @buffer.read(EI_NIDENT).unpack('C*') }
198
+ raise ArgumentError unless @ehdr[:e_ident].slice(EI_MAG0, SELFMAG).pack('C*') == ELFMAG
199
+
200
+ case file_class
201
+ when ELFCLASS32
202
+ Elf32_Ehdr
203
+ when ELFCLASS64
204
+ Elf64_Ehdr
205
+ else
206
+ raise ArgumentError
207
+ end.drop(1).to_h do |field|
208
+ [field[1], read1(field[0])]
209
+ end.merge!(@ehdr)
210
+ end
211
+
212
+ def read_phdr
213
+ case file_class
214
+ when ELFCLASS32
215
+ Elf32_Phdr
216
+ when ELFCLASS64
217
+ Elf64_Phdr
218
+ else
219
+ raise ArgumentError
220
+ end.to_h do |field|
221
+ [field[1], read1(field[0])]
222
+ end
223
+ end
224
+
225
+ def explicit_endian
226
+ case data_encoding
227
+ when ELFDATA2LSB
228
+ '<'
229
+ when ELFDATA2MSB
230
+ '>'
231
+ else
232
+ raise ArgumentError
233
+ end
234
+ end
235
+
236
+ def read1(type)
237
+ case type
238
+ when :__u8
239
+ @buffer.read(1).unpack1('C')
240
+ when :__u16
241
+ @buffer.read(2).unpack1("S#{explicit_endian}")
242
+ when :__u32
243
+ @buffer.read(4).unpack1("L#{explicit_endian}")
244
+ when :__u64
245
+ @buffer.read(8).unpack1("Q#{explicit_endian}")
246
+ when :__s8
247
+ @buffer.read(1).unpack1('c')
248
+ when :__s16
249
+ @buffer.read(2).unpack1("s#{explicit_endian}")
250
+ when :__s32
251
+ @buffer.read(4).unpack1("l#{explicit_endian}")
252
+ when :__s64
253
+ @buffer.read(8).unpack1("q#{explicit_endian}")
254
+ else
255
+ raise ArgumentError
256
+ end
257
+ end
258
+
259
+ INTERPRETER = begin
260
+ proc_self_exe = '/proc/self/exe'
261
+ if File.exist?(proc_self_exe)
262
+ File.open(proc_self_exe, 'rb') do |file|
263
+ elf = ELF.new(file)
264
+ interpreter = elf.interpreter
265
+ if interpreter.nil? && elf.shared_object?
266
+ File.readlink(proc_self_exe)
267
+ else
268
+ interpreter
269
+ end
270
+ end
271
+ end
272
+ end
273
+ end
274
+
275
+ private_constant :ELF
276
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ module Embedded
5
+ VERSION = '1.74.1'
6
+ end
7
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'compiler'
4
+
5
+ # The Sass module.
6
+ #
7
+ # This communicates with Embedded Dart Sass using the Embedded Sass protocol.
8
+ #
9
+ # @example
10
+ # Sass.compile('style.scss')
11
+ #
12
+ # @example
13
+ # Sass.compile_string('h1 { font-size: 40px; }')
14
+ module Sass
15
+ @compiler = nil
16
+ @mutex = Mutex.new
17
+
18
+ # rubocop:disable Layout/LineLength
19
+ class << self
20
+ # Compiles the Sass file at +path+ to CSS.
21
+ # @overload compile(path, load_paths: [], charset: true, source_map: false, source_map_include_sources: false, style: :expanded, functions: {}, importers: [], alert_ascii: false, alert_color: nil, fatal_deprecations: [], future_deprecations: [], logger: nil, quiet_deps: false, silence_deprecations: [], verbose: false)
22
+ # @param (see Compiler#compile)
23
+ # @return (see Compiler#compile)
24
+ # @raise (see Compiler#compile)
25
+ # @see Compiler#compile
26
+ def compile(...)
27
+ compiler.compile(...)
28
+ end
29
+
30
+ # Compiles a stylesheet whose contents is +source+ to CSS.
31
+ # @overload compile_string(source, importer: nil, load_paths: [], syntax: :scss, url: nil, charset: true, source_map: false, source_map_include_sources: false, style: :expanded, functions: {}, importers: [], alert_ascii: false, alert_color: nil, fatal_deprecations: [], future_deprecations: [], logger: nil, quiet_deps: false, silence_deprecations: [], verbose: false)
32
+ # @param (see Compiler#compile_string)
33
+ # @return (see Compiler#compile_string)
34
+ # @raise (see Compiler#compile_string)
35
+ # @see Compiler#compile_string
36
+ def compile_string(...)
37
+ compiler.compile_string(...)
38
+ end
39
+
40
+ # @param (see Compiler#info)
41
+ # @return (see Compiler#info)
42
+ # @raise (see Compiler#info)
43
+ # @see Compiler#info
44
+ def info
45
+ compiler.info
46
+ end
47
+
48
+ private
49
+
50
+ def compiler
51
+ return @compiler if @compiler
52
+
53
+ @mutex.synchronize do
54
+ return @compiler if @compiler
55
+
56
+ compiler = Class.new(Compiler) do
57
+ def initialize
58
+ @channel = Compiler.const_get(:Channel).new(Class.new(Compiler.const_get(:Dispatcher)) do
59
+ def initialize
60
+ super
61
+
62
+ idle_timeout = 10
63
+ @last_accessed_time = current_time
64
+
65
+ Thread.new do
66
+ Thread.current.name = 'sass-embedded-process-reaper'
67
+ duration = idle_timeout
68
+ loop do
69
+ sleep(duration.negative? ? idle_timeout : duration)
70
+ break if @mutex.synchronize do
71
+ raise Errno::EBUSY if _closed?
72
+
73
+ duration = idle_timeout - (current_time - @last_accessed_time)
74
+ duration.negative? && _idle? && _close
75
+ end
76
+ end
77
+ close
78
+ rescue Errno::EBUSY
79
+ # do nothing
80
+ end
81
+ end
82
+
83
+ private
84
+
85
+ def _idle
86
+ super
87
+
88
+ @last_accessed_time = current_time
89
+ end
90
+
91
+ def current_time
92
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
93
+ end
94
+ end)
95
+ end
96
+ end.new
97
+
98
+ at_exit do
99
+ compiler.close
100
+ end
101
+
102
+ @compiler = compiler
103
+ end
104
+ end
105
+ end
106
+ # rubocop:enable Layout/LineLength
107
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ # @see https://github.com/sass/sass/blob/HEAD/spec/embedded-protocol.md
5
+ module EmbeddedProtocol
6
+ require_relative '../../ext/sass/embedded_sass_pb'
7
+ end
8
+
9
+ private_constant :EmbeddedProtocol
10
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ # An exception thrown because a Sass compilation failed.
5
+ class CompileError < StandardError
6
+ # @return [String, nil]
7
+ attr_reader :sass_stack
8
+
9
+ # @return [Logger::SourceSpan, nil]
10
+ attr_reader :span
11
+
12
+ # @return [Array<String>]
13
+ attr_reader :loaded_urls
14
+
15
+ # @!visibility private
16
+ def initialize(message, full_message, sass_stack, span, loaded_urls)
17
+ super(message)
18
+
19
+ @full_message = full_message
20
+ @sass_stack = sass_stack
21
+ @span = span
22
+ @loaded_urls = loaded_urls
23
+ end
24
+
25
+ # @return [String]
26
+ def full_message(highlight: nil, order: nil, **)
27
+ return super if @full_message.nil?
28
+
29
+ highlight = Exception.respond_to?(:to_tty?) && Exception.to_tty? if highlight.nil?
30
+ if highlight
31
+ @full_message.dup
32
+ else
33
+ @full_message.gsub(/\e\[[0-9;]*m/, '')
34
+ end
35
+ end
36
+
37
+ # @return [String]
38
+ def to_css
39
+ content = full_message(highlight: false, order: :top)
40
+
41
+ <<~CSS.freeze
42
+ /* #{content.gsub('*/', "*\u2060/").gsub("\r\n", "\n").split("\n").join("\n * ")} */
43
+
44
+ body::before {
45
+ position: static;
46
+ display: block;
47
+ padding: 1em;
48
+ margin: 0 0 1em;
49
+ border-width: 0 0 2px;
50
+ border-bottom-style: solid;
51
+ font-family: monospace, monospace;
52
+ white-space: pre;
53
+ content: #{Serializer.serialize_quoted_string(content).gsub(/[^[:ascii:]][\h\t ]?/) do |match|
54
+ replacement = "\\#{match.ord.to_s(16)}"
55
+ replacement << " #{match[1]}" if match.length > 1
56
+ replacement
57
+ end};
58
+ }
59
+ CSS
60
+ end
61
+ end
62
+
63
+ # An exception thrown by Sass Script.
64
+ class ScriptError < StandardError
65
+ def initialize(message, name = nil)
66
+ super(name.nil? ? message : "$#{name}: #{message}")
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ # The {ForkTracker} module.
5
+ #
6
+ # It tracks objects that need to be closed after `Process.fork`.
7
+ module ForkTracker
8
+ HASH = {}.compare_by_identity
9
+
10
+ MUTEX = Mutex.new
11
+
12
+ private_constant :HASH, :MUTEX
13
+
14
+ module_function
15
+
16
+ def add(obj)
17
+ MUTEX.synchronize do
18
+ HASH[obj] = true
19
+ end
20
+ end
21
+
22
+ def delete(obj)
23
+ MUTEX.synchronize do
24
+ HASH.delete(obj)
25
+ end
26
+ end
27
+
28
+ def each(...)
29
+ MUTEX.synchronize do
30
+ HASH.keys
31
+ end.each(...)
32
+ end
33
+
34
+ # The {CoreExt} module.
35
+ #
36
+ # It closes objects after `Process.fork`.
37
+ module CoreExt
38
+ def _fork
39
+ pid = super
40
+ ForkTracker.each(&:close) if pid.zero?
41
+ pid
42
+ end
43
+ end
44
+
45
+ private_constant :CoreExt
46
+
47
+ Process.singleton_class.prepend(CoreExt) if Process.respond_to?(:_fork)
48
+ end
49
+
50
+ private_constant :ForkTracker
51
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ # A namespace for built-in Loggers.
5
+ #
6
+ # @see https://sass-lang.com/documentation/js-api/modules/logger/
7
+ module Logger
8
+ module_function
9
+
10
+ # A Logger that silently ignores all warnings and debug messages.
11
+ #
12
+ # @see https://sass-lang.com/documentation/js-api/variables/logger.silent/
13
+ def silent
14
+ Silent
15
+ end
16
+
17
+ # A Logger that silently ignores all warnings and debug messages.
18
+ module Silent
19
+ module_function
20
+
21
+ def warn(message, deprecation: false, span: nil, stack: nil); end
22
+
23
+ def debug(message, span: nil); end
24
+ end
25
+
26
+ private_constant :Silent
27
+ end
28
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ module Logger
5
+ # A specific location within a source file.
6
+ #
7
+ # This is always associated with a {SourceSpan} which indicates which file it refers to.
8
+ #
9
+ # @see https://sass-lang.com/documentation/js-api/interfaces/sourcelocation/
10
+ class SourceLocation
11
+ # @return [Integer]
12
+ attr_reader :offset, :line, :column
13
+
14
+ # @!visibility private
15
+ def initialize(source_location)
16
+ @offset = source_location.offset
17
+ @line = source_location.line
18
+ @column = source_location.column
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ module Logger
5
+ # A span of text within a source file.
6
+ #
7
+ # @see https://sass-lang.com/documentation/js-api/interfaces/sourcespan/
8
+ class SourceSpan
9
+ # @return [SourceLocation]
10
+ attr_reader :start, :end
11
+
12
+ # @return [String]
13
+ attr_reader :text
14
+
15
+ # @return [String, nil]
16
+ attr_reader :url, :context
17
+
18
+ # @!visibility private
19
+ def initialize(source_span)
20
+ @start = source_span.start.nil? ? nil : Logger::SourceLocation.new(source_span.start)
21
+ @end = source_span.end.nil? ? nil : Logger::SourceLocation.new(source_span.end)
22
+ @text = source_span.text
23
+ @url = source_span.url == '' ? nil : source_span.url
24
+ @context = source_span.context == '' ? nil : source_span.context
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ # The built-in Node.js package importer. This loads pkg: URLs from node_modules
5
+ # according to the standard Node.js resolution algorithm.
6
+ #
7
+ # @see https://sass-lang.com/documentation/js-api/classes/nodepackageimporter/
8
+ class NodePackageImporter
9
+ # @param entry_point_directory [String] The directory where the {NodePackageImporter} should start when resolving
10
+ # `pkg:` URLs in sources other than files on disk.
11
+ def initialize(entry_point_directory)
12
+ raise ArgumentError, 'entry_point_directory must be set' if entry_point_directory.nil?
13
+
14
+ @entry_point_directory = File.absolute_path(entry_point_directory)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ # The {Serializer} module.
5
+ module Serializer
6
+ module_function
7
+
8
+ CSS_ESCAPE = {
9
+ "\0" => "\uFFFD",
10
+ '\\' => '\\\\',
11
+ '"' => '\\"',
12
+ "'" => "\\'",
13
+ **[*"\x01".."\x08", *"\x0A".."\x1F", "\x7F"].product(
14
+ [*'0'..'9', *'a'..'f', *'A'..'F', "\t", ' ', nil]
15
+ ).to_h do |c, x|
16
+ ["#{c}#{x}".freeze, "\\#{c.ord.to_s(16)}#{" #{x}" if x}".freeze]
17
+ end
18
+ }.freeze
19
+
20
+ private_constant :CSS_ESCAPE
21
+
22
+ def serialize_quoted_string(string)
23
+ if !string.include?('"') || string.include?("'")
24
+ %("#{string.gsub(/[\0\\"]|[\x01-\x08\x0A-\x1F\x7F][\h\t ]?/, CSS_ESCAPE)}")
25
+ else
26
+ %('#{string.gsub(/[\0\\']|[\x01-\x08\x0A-\x1F\x7F][\h\t ]?/, CSS_ESCAPE)}')
27
+ end
28
+ end
29
+
30
+ def serialize_unquoted_string(string)
31
+ string.tr("\0", "\uFFFD").gsub(/\n */, ' ')
32
+ end
33
+ end
34
+
35
+ private_constant :Serializer
36
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sass
4
+ module Value
5
+ # Sass's argument list type.
6
+ #
7
+ # An argument list comes from a rest argument. It's distinct from a normal {List} in that it may contain a keyword
8
+ # map as well as the positional arguments.
9
+ #
10
+ # @see https://sass-lang.com/documentation/js-api/classes/sassargumentlist/
11
+ class ArgumentList < List
12
+ # @param contents [Array<Value>]
13
+ # @param keywords [Hash<Symbol, Value>]
14
+ # @param separator [::String]
15
+ def initialize(contents = [], keywords = {}, separator = ',')
16
+ super(contents, separator:)
17
+
18
+ @id = 0
19
+ @keywords_accessed = false
20
+ @keywords = keywords.freeze
21
+ end
22
+
23
+ # @return [Hash<Symbol, Value>]
24
+ def keywords
25
+ @keywords_accessed = true
26
+ @keywords
27
+ end
28
+
29
+ private
30
+
31
+ def initialize_dup(orig)
32
+ @id = 0
33
+ super
34
+ end
35
+ end
36
+ end
37
+ end