sass-embedded 1.74.1-x86-mswin32
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 +7 -0
- data/LICENSE +20 -0
- data/README.md +48 -0
- data/exe/sass +21 -0
- data/ext/sass/cli.rb +12 -0
- data/ext/sass/dart-sass/sass.bat +7 -0
- data/ext/sass/dart-sass/src/LICENSE +1687 -0
- data/ext/sass/dart-sass/src/dart.exe +0 -0
- data/ext/sass/dart-sass/src/sass.snapshot +0 -0
- data/ext/sass/embedded_sass_pb.rb +63 -0
- data/lib/sass/calculation_value/calculation_operation.rb +49 -0
- data/lib/sass/calculation_value.rb +22 -0
- data/lib/sass/canonicalize_context.rb +21 -0
- data/lib/sass/compile_result.rb +24 -0
- data/lib/sass/compiler/channel.rb +68 -0
- data/lib/sass/compiler/connection.rb +92 -0
- data/lib/sass/compiler/dispatcher.rb +115 -0
- data/lib/sass/compiler/host/function_registry.rb +87 -0
- data/lib/sass/compiler/host/importer_registry.rb +137 -0
- data/lib/sass/compiler/host/logger_registry.rb +55 -0
- data/lib/sass/compiler/host/protofier.rb +390 -0
- data/lib/sass/compiler/host/structifier.rb +37 -0
- data/lib/sass/compiler/host.rb +226 -0
- data/lib/sass/compiler/varint.rb +39 -0
- data/lib/sass/compiler.rb +212 -0
- data/lib/sass/elf.rb +276 -0
- data/lib/sass/embedded/version.rb +7 -0
- data/lib/sass/embedded.rb +107 -0
- data/lib/sass/embedded_protocol.rb +10 -0
- data/lib/sass/exception.rb +69 -0
- data/lib/sass/fork_tracker.rb +51 -0
- data/lib/sass/logger/silent.rb +28 -0
- data/lib/sass/logger/source_location.rb +22 -0
- data/lib/sass/logger/source_span.rb +28 -0
- data/lib/sass/node_package_importer.rb +17 -0
- data/lib/sass/serializer.rb +36 -0
- data/lib/sass/value/argument_list.rb +37 -0
- data/lib/sass/value/boolean.rb +52 -0
- data/lib/sass/value/calculation.rb +90 -0
- data/lib/sass/value/color.rb +253 -0
- data/lib/sass/value/function.rb +51 -0
- data/lib/sass/value/fuzzy_math.rb +80 -0
- data/lib/sass/value/list.rb +79 -0
- data/lib/sass/value/map.rb +71 -0
- data/lib/sass/value/mixin.rb +36 -0
- data/lib/sass/value/null.rb +48 -0
- data/lib/sass/value/number/unit.rb +186 -0
- data/lib/sass/value/number.rb +366 -0
- data/lib/sass/value/string.rb +61 -0
- data/lib/sass/value.rb +136 -0
- data/lib/sass-embedded.rb +4 -0
- metadata +120 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sass
|
4
|
+
module Value
|
5
|
+
# Sass's null type.
|
6
|
+
#
|
7
|
+
# @see https://sass-lang.com/documentation/js-api/variables/sassnull/
|
8
|
+
class Null
|
9
|
+
include Value
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@value = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [nil]
|
16
|
+
attr_reader :value
|
17
|
+
|
18
|
+
# @return [Boolean]
|
19
|
+
def !
|
20
|
+
Boolean::TRUE
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [::Boolean]
|
24
|
+
def ==(other)
|
25
|
+
other.is_a?(Sass::Value::Null)
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [Integer]
|
29
|
+
def hash
|
30
|
+
@hash ||= value.hash
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [::Boolean]
|
34
|
+
def to_bool
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
alias to_nil value
|
39
|
+
|
40
|
+
# Sass's null value.
|
41
|
+
NULL = Null.new
|
42
|
+
|
43
|
+
def self.new
|
44
|
+
NULL
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sass
|
4
|
+
module Value
|
5
|
+
class Number
|
6
|
+
# The {Unit} module.
|
7
|
+
module Unit
|
8
|
+
CONVERSIONS = {
|
9
|
+
# Length
|
10
|
+
'in' => {
|
11
|
+
'in' => Rational(1),
|
12
|
+
'cm' => Rational(1, 2.54),
|
13
|
+
'pc' => Rational(1, 6),
|
14
|
+
'mm' => Rational(1, 25.4),
|
15
|
+
'q' => Rational(1, 101.6),
|
16
|
+
'pt' => Rational(1, 72),
|
17
|
+
'px' => Rational(1, 96)
|
18
|
+
},
|
19
|
+
'cm' => {
|
20
|
+
'in' => Rational(2.54),
|
21
|
+
'cm' => Rational(1),
|
22
|
+
'pc' => Rational(2.54, 6),
|
23
|
+
'mm' => Rational(1, 10),
|
24
|
+
'q' => Rational(1, 40),
|
25
|
+
'pt' => Rational(2.54, 72),
|
26
|
+
'px' => Rational(2.54, 96)
|
27
|
+
},
|
28
|
+
'pc' => {
|
29
|
+
'in' => Rational(6),
|
30
|
+
'cm' => Rational(6, 2.54),
|
31
|
+
'pc' => Rational(1),
|
32
|
+
'mm' => Rational(6, 25.4),
|
33
|
+
'q' => Rational(6, 101.6),
|
34
|
+
'pt' => Rational(1, 12),
|
35
|
+
'px' => Rational(1, 16)
|
36
|
+
},
|
37
|
+
'mm' => {
|
38
|
+
'in' => Rational(25.4),
|
39
|
+
'cm' => Rational(10),
|
40
|
+
'pc' => Rational(25.4, 6),
|
41
|
+
'mm' => Rational(1),
|
42
|
+
'q' => Rational(1, 4),
|
43
|
+
'pt' => Rational(25.4, 72),
|
44
|
+
'px' => Rational(25.4, 96)
|
45
|
+
},
|
46
|
+
'q' => {
|
47
|
+
'in' => Rational(101.6),
|
48
|
+
'cm' => Rational(40),
|
49
|
+
'pc' => Rational(101.6, 6),
|
50
|
+
'mm' => Rational(4),
|
51
|
+
'q' => Rational(1),
|
52
|
+
'pt' => Rational(101.6, 72),
|
53
|
+
'px' => Rational(101.6, 96)
|
54
|
+
},
|
55
|
+
'pt' => {
|
56
|
+
'in' => Rational(72),
|
57
|
+
'cm' => Rational(72, 2.54),
|
58
|
+
'pc' => Rational(12),
|
59
|
+
'mm' => Rational(72, 25.4),
|
60
|
+
'q' => Rational(72, 101.6),
|
61
|
+
'pt' => Rational(1),
|
62
|
+
'px' => Rational(3, 4)
|
63
|
+
},
|
64
|
+
'px' => {
|
65
|
+
'in' => Rational(96),
|
66
|
+
'cm' => Rational(96, 2.54),
|
67
|
+
'pc' => Rational(16),
|
68
|
+
'mm' => Rational(96, 25.4),
|
69
|
+
'q' => Rational(96, 101.6),
|
70
|
+
'pt' => Rational(4, 3),
|
71
|
+
'px' => Rational(1)
|
72
|
+
},
|
73
|
+
|
74
|
+
# Rotation
|
75
|
+
'deg' => {
|
76
|
+
'deg' => Rational(1),
|
77
|
+
'grad' => Rational(9, 10),
|
78
|
+
'rad' => Rational(180, Math::PI),
|
79
|
+
'turn' => Rational(360)
|
80
|
+
},
|
81
|
+
'grad' => {
|
82
|
+
'deg' => Rational(10, 9),
|
83
|
+
'grad' => Rational(1),
|
84
|
+
'rad' => Rational(200, Math::PI),
|
85
|
+
'turn' => Rational(400)
|
86
|
+
},
|
87
|
+
'rad' => {
|
88
|
+
'deg' => Rational(Math::PI, 180),
|
89
|
+
'grad' => Rational(Math::PI, 200),
|
90
|
+
'rad' => Rational(1),
|
91
|
+
'turn' => Rational(Math::PI * 2)
|
92
|
+
},
|
93
|
+
'turn' => {
|
94
|
+
'deg' => Rational(1, 360),
|
95
|
+
'grad' => Rational(1, 400),
|
96
|
+
'rad' => Rational(1, Math::PI * 2),
|
97
|
+
'turn' => Rational(1)
|
98
|
+
},
|
99
|
+
|
100
|
+
# Time
|
101
|
+
's' => {
|
102
|
+
's' => Rational(1),
|
103
|
+
'ms' => Rational(1, 1000)
|
104
|
+
},
|
105
|
+
'ms' => {
|
106
|
+
's' => Rational(1000),
|
107
|
+
'ms' => Rational(1)
|
108
|
+
},
|
109
|
+
|
110
|
+
# Frequency
|
111
|
+
'Hz' => {
|
112
|
+
'Hz' => Rational(1),
|
113
|
+
'kHz' => Rational(1000)
|
114
|
+
},
|
115
|
+
'kHz' => {
|
116
|
+
'Hz' => Rational(1, 1000),
|
117
|
+
'kHz' => Rational(1)
|
118
|
+
},
|
119
|
+
|
120
|
+
# Pixel density
|
121
|
+
'dpi' => {
|
122
|
+
'dpi' => Rational(1),
|
123
|
+
'dpcm' => Rational(2.54),
|
124
|
+
'dppx' => Rational(96)
|
125
|
+
},
|
126
|
+
'dpcm' => {
|
127
|
+
'dpi' => Rational(1, 2.54),
|
128
|
+
'dpcm' => Rational(1),
|
129
|
+
'dppx' => Rational(96, 2.54)
|
130
|
+
},
|
131
|
+
'dppx' => {
|
132
|
+
'dpi' => Rational(1, 96),
|
133
|
+
'dpcm' => Rational(2.54, 96),
|
134
|
+
'dppx' => Rational(1)
|
135
|
+
}
|
136
|
+
}.freeze
|
137
|
+
|
138
|
+
UNITS_BY_TYPE = {
|
139
|
+
time: %w[s ms],
|
140
|
+
frequency: %w[Hz kHz],
|
141
|
+
'pixel density': %w[dpi dpcm dppx]
|
142
|
+
}.freeze
|
143
|
+
|
144
|
+
TYPES_BY_UNIT = UNITS_BY_TYPE.invert
|
145
|
+
.to_a
|
146
|
+
.flat_map { |pair| pair[0].map { |key| [key, pair[1]] } }
|
147
|
+
.to_h
|
148
|
+
|
149
|
+
module_function
|
150
|
+
|
151
|
+
def conversion_factor(unit1, unit2)
|
152
|
+
return 1 if unit1 == unit2
|
153
|
+
|
154
|
+
CONVERSIONS.dig(unit1, unit2)
|
155
|
+
end
|
156
|
+
|
157
|
+
def canonicalize_units(units)
|
158
|
+
return units if units.empty?
|
159
|
+
|
160
|
+
if units.length == 1
|
161
|
+
type = TYPES_BY_UNIT[units.first]
|
162
|
+
return type.nil? ? units : [UNITS_BY_TYPE[type].first]
|
163
|
+
end
|
164
|
+
|
165
|
+
units.map do |unit|
|
166
|
+
type = TYPES_BY_UNIT[unit]
|
167
|
+
type.nil? ? units : [UNITS_BY_TYPE[type].first]
|
168
|
+
end.sort
|
169
|
+
end
|
170
|
+
|
171
|
+
def canonical_multiplier(units)
|
172
|
+
units.reduce(1) do |multiplier, unit|
|
173
|
+
multiplier * canonical_multiplier_for_unit(unit)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def canonical_multiplier_for_unit(unit)
|
178
|
+
inner_map = CONVERSIONS[unit]
|
179
|
+
inner_map.nil? ? 1 : 1 / inner_map.values.first
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
private_constant :Unit
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,366 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'number/unit'
|
4
|
+
|
5
|
+
module Sass
|
6
|
+
module Value
|
7
|
+
# Sass's number type.
|
8
|
+
#
|
9
|
+
# @see https://sass-lang.com/documentation/js-api/classes/sassnumber/
|
10
|
+
class Number
|
11
|
+
include Value
|
12
|
+
include CalculationValue
|
13
|
+
|
14
|
+
# @param value [Numeric]
|
15
|
+
# @param unit [::String, Hash]
|
16
|
+
# @option unit [Array<::String>] :numerator_units
|
17
|
+
# @option unit [Array<::String>] :denominator_units
|
18
|
+
def initialize(value, unit = nil)
|
19
|
+
case unit
|
20
|
+
when nil
|
21
|
+
numerator_units = []
|
22
|
+
denominator_units = []
|
23
|
+
when ::String
|
24
|
+
numerator_units = [unit]
|
25
|
+
denominator_units = []
|
26
|
+
when ::Hash
|
27
|
+
numerator_units = unit.fetch(:numerator_units, [])
|
28
|
+
unless numerator_units.is_a?(Array)
|
29
|
+
raise Sass::ScriptError, "invalid numerator_units #{numerator_units.inspect}"
|
30
|
+
end
|
31
|
+
|
32
|
+
denominator_units = unit.fetch(:denominator_units, [])
|
33
|
+
unless denominator_units.is_a?(Array)
|
34
|
+
raise Sass::ScriptError, "invalid denominator_units #{denominator_units.inspect}"
|
35
|
+
end
|
36
|
+
else
|
37
|
+
raise Sass::ScriptError, "invalid unit #{unit.inspect}"
|
38
|
+
end
|
39
|
+
|
40
|
+
unless denominator_units.empty? && numerator_units.empty?
|
41
|
+
value = value.dup
|
42
|
+
numerator_units = numerator_units.dup
|
43
|
+
new_denominator_units = []
|
44
|
+
|
45
|
+
denominator_units.each do |denominator_unit|
|
46
|
+
index = numerator_units.find_index do |numerator_unit|
|
47
|
+
factor = Unit.conversion_factor(denominator_unit, numerator_unit)
|
48
|
+
if factor.nil?
|
49
|
+
false
|
50
|
+
else
|
51
|
+
value *= factor
|
52
|
+
true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
if index.nil?
|
56
|
+
new_denominator_units.push(denominator_unit)
|
57
|
+
else
|
58
|
+
numerator_units.delete_at(index)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
denominator_units = new_denominator_units
|
63
|
+
end
|
64
|
+
|
65
|
+
@value = value.freeze
|
66
|
+
@numerator_units = numerator_units.each(&:freeze).freeze
|
67
|
+
@denominator_units = denominator_units.each(&:freeze).freeze
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [Numeric]
|
71
|
+
attr_reader :value
|
72
|
+
|
73
|
+
# @return [Array<::String>]
|
74
|
+
attr_reader :numerator_units, :denominator_units
|
75
|
+
|
76
|
+
# @return [::Boolean]
|
77
|
+
def ==(other)
|
78
|
+
return false unless other.is_a?(Sass::Value::Number)
|
79
|
+
|
80
|
+
return false if numerator_units.length != other.numerator_units.length ||
|
81
|
+
denominator_units.length != other.denominator_units.length
|
82
|
+
|
83
|
+
return FuzzyMath.equals(value, other.value) if unitless?
|
84
|
+
|
85
|
+
if Unit.canonicalize_units(numerator_units) != Unit.canonicalize_units(other.numerator_units) &&
|
86
|
+
Unit.canonicalize_units(denominator_units) != Unit.canonicalize_units(other.denominator_units)
|
87
|
+
return false
|
88
|
+
end
|
89
|
+
|
90
|
+
FuzzyMath.equals(
|
91
|
+
(value *
|
92
|
+
Unit.canonical_multiplier(numerator_units) /
|
93
|
+
Unit.canonical_multiplier(denominator_units)),
|
94
|
+
(other.value *
|
95
|
+
Unit.canonical_multiplier(other.numerator_units) /
|
96
|
+
Unit.canonical_multiplier(other.denominator_units))
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
# @return [Integer]
|
101
|
+
def hash
|
102
|
+
@hash ||= FuzzyMath.hash(canonical_units_value)
|
103
|
+
end
|
104
|
+
|
105
|
+
# @return [::Boolean]
|
106
|
+
def unitless?
|
107
|
+
numerator_units.empty? && denominator_units.empty?
|
108
|
+
end
|
109
|
+
|
110
|
+
# @return [Number]
|
111
|
+
# @raise [ScriptError]
|
112
|
+
def assert_unitless(name = nil)
|
113
|
+
raise Sass::ScriptError.new("Expected #{self} to have no units", name) unless unitless?
|
114
|
+
|
115
|
+
self
|
116
|
+
end
|
117
|
+
|
118
|
+
# @return [::Boolean]
|
119
|
+
def units?
|
120
|
+
!unitless?
|
121
|
+
end
|
122
|
+
|
123
|
+
# @param unit [::String]
|
124
|
+
# @return [::Boolean]
|
125
|
+
def unit?(unit)
|
126
|
+
single_unit? && numerator_units.first == unit
|
127
|
+
end
|
128
|
+
|
129
|
+
# @param unit [::String]
|
130
|
+
# @return [Number]
|
131
|
+
# @raise [ScriptError]
|
132
|
+
def assert_unit(unit, name = nil)
|
133
|
+
raise Sass::ScriptError.new("Expected #{self} to have unit #{unit.inspect}", name) unless unit?(unit)
|
134
|
+
|
135
|
+
self
|
136
|
+
end
|
137
|
+
|
138
|
+
# @return [::Boolean]
|
139
|
+
def integer?
|
140
|
+
FuzzyMath.integer?(value)
|
141
|
+
end
|
142
|
+
|
143
|
+
# @return [Integer]
|
144
|
+
# @raise [ScriptError]
|
145
|
+
def assert_integer(name = nil)
|
146
|
+
raise Sass::ScriptError.new("#{self} is not an integer", name) unless integer?
|
147
|
+
|
148
|
+
to_i
|
149
|
+
end
|
150
|
+
|
151
|
+
# @return [Integer]
|
152
|
+
def to_i
|
153
|
+
FuzzyMath.to_i(value)
|
154
|
+
end
|
155
|
+
|
156
|
+
# @param min [Numeric]
|
157
|
+
# @param max [Numeric]
|
158
|
+
# @return [Numeric]
|
159
|
+
# @raise [ScriptError]
|
160
|
+
def assert_between(min, max, name = nil)
|
161
|
+
FuzzyMath.assert_between(value, min, max, name)
|
162
|
+
end
|
163
|
+
|
164
|
+
# @param unit [::String]
|
165
|
+
# @return [::Boolean]
|
166
|
+
def compatible_with_unit?(unit)
|
167
|
+
single_unit? && !Unit.conversion_factor(numerator_units.first, unit).nil?
|
168
|
+
end
|
169
|
+
|
170
|
+
# @param new_numerator_units [Array<::String>]
|
171
|
+
# @param new_denominator_units [Array<::String>]
|
172
|
+
# @return [Number]
|
173
|
+
def convert(new_numerator_units, new_denominator_units, name = nil)
|
174
|
+
Number.new(convert_value(new_numerator_units, new_denominator_units, name), {
|
175
|
+
numerator_units: new_numerator_units,
|
176
|
+
denominator_units: new_denominator_units
|
177
|
+
})
|
178
|
+
end
|
179
|
+
|
180
|
+
# @param new_numerator_units [Array<::String>]
|
181
|
+
# @param new_denominator_units [Array<::String>]
|
182
|
+
# @return [Numeric]
|
183
|
+
def convert_value(new_numerator_units, new_denominator_units, name = nil)
|
184
|
+
coerce_or_convert_value(new_numerator_units, new_denominator_units,
|
185
|
+
coerce_unitless: false,
|
186
|
+
name:)
|
187
|
+
end
|
188
|
+
|
189
|
+
# @param other [Number]
|
190
|
+
# @return [Number]
|
191
|
+
def convert_to_match(other, name = nil, other_name = nil)
|
192
|
+
Number.new(convert_value_to_match(other, name, other_name), {
|
193
|
+
numerator_units: other.numerator_units,
|
194
|
+
denominator_units: other.denominator_units
|
195
|
+
})
|
196
|
+
end
|
197
|
+
|
198
|
+
# @param other [Number]
|
199
|
+
# @return [Numeric]
|
200
|
+
def convert_value_to_match(other, name = nil, other_name = nil)
|
201
|
+
coerce_or_convert_value(other.numerator_units, other.denominator_units,
|
202
|
+
coerce_unitless: false,
|
203
|
+
name:,
|
204
|
+
other:,
|
205
|
+
other_name:)
|
206
|
+
end
|
207
|
+
|
208
|
+
# @param new_numerator_units [Array<::String>]
|
209
|
+
# @param new_denominator_units [Array<::String>]
|
210
|
+
# @return [Number]
|
211
|
+
def coerce(new_numerator_units, new_denominator_units, name = nil)
|
212
|
+
Number.new(coerce_value(new_numerator_units, new_denominator_units, name), {
|
213
|
+
numerator_units: new_numerator_units,
|
214
|
+
denominator_units: new_denominator_units
|
215
|
+
})
|
216
|
+
end
|
217
|
+
|
218
|
+
# @param new_numerator_units [Array<::String>]
|
219
|
+
# @param new_denominator_units [Array<::String>]
|
220
|
+
# @return [Numeric]
|
221
|
+
def coerce_value(new_numerator_units, new_denominator_units, name = nil)
|
222
|
+
coerce_or_convert_value(new_numerator_units, new_denominator_units,
|
223
|
+
coerce_unitless: true,
|
224
|
+
name:)
|
225
|
+
end
|
226
|
+
|
227
|
+
# @param unit [::String]
|
228
|
+
# @return [Numeric]
|
229
|
+
def coerce_value_to_unit(unit, name = nil)
|
230
|
+
coerce_value([unit], [], name)
|
231
|
+
end
|
232
|
+
|
233
|
+
# @param other [Number]
|
234
|
+
# @return [Number]
|
235
|
+
def coerce_to_match(other, name = nil, other_name = nil)
|
236
|
+
Number.new(coerce_value_to_match(other, name, other_name), {
|
237
|
+
numerator_units: other.numerator_units,
|
238
|
+
denominator_units: other.denominator_units
|
239
|
+
})
|
240
|
+
end
|
241
|
+
|
242
|
+
# @param other [Number]
|
243
|
+
# @return [Numeric]
|
244
|
+
def coerce_value_to_match(other, name = nil, other_name = nil)
|
245
|
+
coerce_or_convert_value(other.numerator_units, other.denominator_units,
|
246
|
+
coerce_unitless: true,
|
247
|
+
name:,
|
248
|
+
other:,
|
249
|
+
other_name:)
|
250
|
+
end
|
251
|
+
|
252
|
+
# @return [Number]
|
253
|
+
def assert_number(_name = nil)
|
254
|
+
self
|
255
|
+
end
|
256
|
+
|
257
|
+
private
|
258
|
+
|
259
|
+
def single_unit?
|
260
|
+
numerator_units.length == 1 && denominator_units.empty?
|
261
|
+
end
|
262
|
+
|
263
|
+
def canonical_units_value
|
264
|
+
if unitless?
|
265
|
+
value
|
266
|
+
elsif single_unit?
|
267
|
+
value * Unit.canonical_multiplier_for_unit(numerator_units.first)
|
268
|
+
else
|
269
|
+
value * Unit.canonical_multiplier(numerator_units) / Unit.canonical_multiplier(denominator_units)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
def coerce_or_convert_value(new_numerator_units, new_denominator_units,
|
274
|
+
coerce_unitless:,
|
275
|
+
name: nil,
|
276
|
+
other: nil,
|
277
|
+
other_name: nil)
|
278
|
+
if other && (other.numerator_units != new_denominator_units && other.denominator_units != new_denominator_units)
|
279
|
+
raise Sass::ScriptError, "Expect #{other} to have units #{unit_string(new_numerator_units,
|
280
|
+
new_denominator_units).inspect}"
|
281
|
+
end
|
282
|
+
|
283
|
+
return value if numerator_units == new_numerator_units && denominator_units == new_denominator_units
|
284
|
+
|
285
|
+
return value if numerator_units == new_numerator_units && denominator_units == new_denominator_units
|
286
|
+
|
287
|
+
other_unitless = new_numerator_units.empty? && new_denominator_units.empty?
|
288
|
+
|
289
|
+
return value if coerce_unitless && (unitless? || other_unitless)
|
290
|
+
|
291
|
+
compatibility_error = lambda {
|
292
|
+
unless other.nil?
|
293
|
+
message = +"#{self} and"
|
294
|
+
message << " $#{other_name}:" unless other_name.nil?
|
295
|
+
message << " #{other} have incompatible units"
|
296
|
+
message << " (one has units and the other doesn't)" if unitless? || other_unitless
|
297
|
+
return Sass::ScriptError.new(message, name)
|
298
|
+
end
|
299
|
+
|
300
|
+
return Sass::ScriptError.new("Expected #{self} to have no units", name) unless other_unitless
|
301
|
+
|
302
|
+
if new_numerator_units.length == 1 && new_denominator_units.empty?
|
303
|
+
type = Unit::TYPES_BY_UNIT[new_numerator_units.first]
|
304
|
+
return Sass::ScriptError.new(
|
305
|
+
"Expected #{self} to have a #{type} unit (#{Unit::UNITS_BY_TYPE[type].join(', ')})", name
|
306
|
+
)
|
307
|
+
end
|
308
|
+
|
309
|
+
unit_length = new_numerator_units.length + new_denominator_units.length
|
310
|
+
units = unit_string(new_numerator_units, new_denominator_units)
|
311
|
+
Sass::ScriptError.new("Expected #{self} to have unit#{unit_length > 1 ? 's' : ''} #{units}", name)
|
312
|
+
}
|
313
|
+
|
314
|
+
result = value
|
315
|
+
|
316
|
+
old_numerator_units = numerator_units.dup
|
317
|
+
new_numerator_units.each do |new_numerator_unit|
|
318
|
+
index = old_numerator_units.find_index do |old_numerator_unit|
|
319
|
+
factor = Unit.conversion_factor(new_numerator_unit, old_numerator_unit)
|
320
|
+
if factor.nil?
|
321
|
+
false
|
322
|
+
else
|
323
|
+
result *= factor
|
324
|
+
true
|
325
|
+
end
|
326
|
+
end
|
327
|
+
raise compatibility_error.call if index.nil?
|
328
|
+
|
329
|
+
old_numerator_units.delete_at(index)
|
330
|
+
end
|
331
|
+
|
332
|
+
old_denominator_units = denominator_units.dup
|
333
|
+
new_denominator_units.each do |new_denominator_unit|
|
334
|
+
index = old_denominator_units.find_index do |old_denominator_unit|
|
335
|
+
factor = Unit.conversion_factor(new_denominator_unit, old_denominator_unit)
|
336
|
+
if factor.nil?
|
337
|
+
false
|
338
|
+
else
|
339
|
+
result /= factor
|
340
|
+
true
|
341
|
+
end
|
342
|
+
end
|
343
|
+
raise compatibility_error.call if index.nil?
|
344
|
+
|
345
|
+
old_denominator_units.delete_at(index)
|
346
|
+
end
|
347
|
+
|
348
|
+
raise compatibility_error.call unless old_numerator_units.empty? && old_denominator_units.empty?
|
349
|
+
|
350
|
+
result
|
351
|
+
end
|
352
|
+
|
353
|
+
def unit_string(numerator_units, denominator_units)
|
354
|
+
if numerator_units.empty?
|
355
|
+
return 'no units' if denominator_units.empty?
|
356
|
+
|
357
|
+
return denominator_units.length == 1 ? "#{denominator_units.first}^-1" : "(#{denominator_units.join('*')})^-1"
|
358
|
+
end
|
359
|
+
|
360
|
+
return numerator_units.join('*') if denominator_units.empty?
|
361
|
+
|
362
|
+
"#{numerator_units.join('*')}/#{denominator_units.join('*')}"
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sass
|
4
|
+
module Value
|
5
|
+
# Sass's string type.
|
6
|
+
#
|
7
|
+
# @see https://sass-lang.com/documentation/js-api/classes/sassstring/
|
8
|
+
class String
|
9
|
+
include Value
|
10
|
+
include CalculationValue
|
11
|
+
|
12
|
+
# @param text [::String]
|
13
|
+
# @param quoted [::Boolean]
|
14
|
+
def initialize(text = '', quoted: true)
|
15
|
+
@text = text.freeze
|
16
|
+
@quoted = quoted
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [::String]
|
20
|
+
attr_reader :text
|
21
|
+
|
22
|
+
# @return [::Boolean]
|
23
|
+
def quoted?
|
24
|
+
@quoted
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [::Boolean]
|
28
|
+
def ==(other)
|
29
|
+
other.is_a?(Sass::Value::String) && other.text == text
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Integer]
|
33
|
+
def hash
|
34
|
+
@hash ||= text.hash
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [String]
|
38
|
+
def assert_string(_name = nil)
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param sass_index [Number]
|
43
|
+
# @return [Integer]
|
44
|
+
def sass_index_to_string_index(sass_index, name = nil)
|
45
|
+
index = sass_index.assert_number(name).assert_integer(name)
|
46
|
+
raise Sass::ScriptError.new('String index may not be 0', name) if index.zero?
|
47
|
+
|
48
|
+
if index.abs > text.length
|
49
|
+
raise Sass::ScriptError.new("Invalid index #{sass_index} for a string with #{text.length} characters", name)
|
50
|
+
end
|
51
|
+
|
52
|
+
index.negative? ? text.length + index : index - 1
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [String]
|
56
|
+
def to_s
|
57
|
+
@quoted ? Serializer.serialize_quoted_string(@text) : Serializer.serialize_unquoted_string(@text)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|