haml 2.0.10 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of haml might be problematic. Click here for more details.
- data/.yardopts +5 -0
- data/MIT-LICENSE +1 -1
- data/README.md +347 -0
- data/Rakefile +124 -19
- data/VERSION +1 -1
- data/VERSION_NAME +1 -0
- data/extra/haml-mode.el +397 -78
- data/extra/sass-mode.el +148 -36
- data/extra/update_watch.rb +13 -0
- data/lib/haml.rb +15 -993
- data/lib/haml/buffer.rb +131 -84
- data/lib/haml/engine.rb +129 -97
- data/lib/haml/error.rb +7 -7
- data/lib/haml/exec.rb +127 -42
- data/lib/haml/filters.rb +107 -42
- data/lib/haml/helpers.rb +210 -156
- data/lib/haml/helpers/action_view_extensions.rb +34 -39
- data/lib/haml/helpers/action_view_mods.rb +132 -139
- data/lib/haml/html.rb +77 -65
- data/lib/haml/precompiler.rb +404 -213
- data/lib/haml/shared.rb +78 -0
- data/lib/haml/template.rb +14 -14
- data/lib/haml/template/patch.rb +2 -2
- data/lib/haml/template/plugin.rb +2 -3
- data/lib/haml/util.rb +211 -6
- data/lib/haml/version.rb +30 -13
- data/lib/sass.rb +7 -856
- data/lib/sass/css.rb +169 -161
- data/lib/sass/engine.rb +344 -328
- data/lib/sass/environment.rb +79 -0
- data/lib/sass/error.rb +33 -11
- data/lib/sass/files.rb +139 -0
- data/lib/sass/plugin.rb +160 -117
- data/lib/sass/plugin/merb.rb +7 -6
- data/lib/sass/plugin/rails.rb +5 -6
- data/lib/sass/repl.rb +58 -0
- data/lib/sass/script.rb +59 -0
- data/lib/sass/script/bool.rb +17 -0
- data/lib/sass/script/color.rb +183 -0
- data/lib/sass/script/funcall.rb +50 -0
- data/lib/sass/script/functions.rb +198 -0
- data/lib/sass/script/lexer.rb +178 -0
- data/lib/sass/script/literal.rb +177 -0
- data/lib/sass/script/node.rb +14 -0
- data/lib/sass/script/number.rb +381 -0
- data/lib/sass/script/operation.rb +45 -0
- data/lib/sass/script/parser.rb +172 -0
- data/lib/sass/script/string.rb +12 -0
- data/lib/sass/script/unary_operation.rb +34 -0
- data/lib/sass/script/variable.rb +31 -0
- data/lib/sass/tree/comment_node.rb +73 -10
- data/lib/sass/tree/debug_node.rb +30 -0
- data/lib/sass/tree/directive_node.rb +42 -17
- data/lib/sass/tree/file_node.rb +41 -0
- data/lib/sass/tree/for_node.rb +48 -0
- data/lib/sass/tree/if_node.rb +54 -0
- data/lib/sass/tree/mixin_def_node.rb +29 -0
- data/lib/sass/tree/mixin_node.rb +48 -0
- data/lib/sass/tree/node.rb +214 -11
- data/lib/sass/tree/prop_node.rb +109 -0
- data/lib/sass/tree/rule_node.rb +178 -51
- data/lib/sass/tree/variable_node.rb +34 -0
- data/lib/sass/tree/while_node.rb +31 -0
- data/test/haml/engine_test.rb +331 -36
- data/test/haml/helper_test.rb +12 -1
- data/test/haml/results/content_for_layout.xhtml +0 -3
- data/test/haml/results/filters.xhtml +2 -0
- data/test/haml/results/list.xhtml +1 -1
- data/test/haml/template_test.rb +7 -2
- data/test/haml/templates/content_for_layout.haml +0 -2
- data/test/haml/templates/list.haml +1 -1
- data/test/haml/util_test.rb +92 -0
- data/test/sass/css2sass_test.rb +69 -24
- data/test/sass/engine_test.rb +586 -64
- data/test/sass/functions_test.rb +125 -0
- data/test/sass/more_results/more1.css +9 -0
- data/test/sass/more_results/more1_with_line_comments.css +26 -0
- data/test/sass/more_results/more_import.css +29 -0
- data/test/sass/more_templates/_more_partial.sass +2 -0
- data/test/sass/more_templates/more1.sass +23 -0
- data/test/sass/more_templates/more_import.sass +11 -0
- data/test/sass/plugin_test.rb +81 -28
- data/test/sass/results/line_numbers.css +49 -0
- data/test/sass/results/{constants.css → script.css} +4 -4
- data/test/sass/results/subdir/subdir.css +2 -0
- data/test/sass/results/units.css +11 -0
- data/test/sass/script_test.rb +258 -0
- data/test/sass/templates/import.sass +1 -1
- data/test/sass/templates/importee.sass +7 -2
- data/test/sass/templates/line_numbers.sass +13 -0
- data/test/sass/templates/{constants.sass → script.sass} +11 -10
- data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
- data/test/sass/templates/subdir/subdir.sass +2 -2
- data/test/sass/templates/units.sass +11 -0
- data/test/test_helper.rb +14 -0
- metadata +77 -19
- data/FAQ +0 -138
- data/README.rdoc +0 -319
- data/lib/sass/constant.rb +0 -216
- data/lib/sass/constant/color.rb +0 -101
- data/lib/sass/constant/literal.rb +0 -54
- data/lib/sass/constant/nil.rb +0 -9
- data/lib/sass/constant/number.rb +0 -87
- data/lib/sass/constant/operation.rb +0 -30
- data/lib/sass/constant/string.rb +0 -22
- data/lib/sass/tree/attr_node.rb +0 -57
- data/lib/sass/tree/value_node.rb +0 -20
data/lib/sass/constant.rb
DELETED
@@ -1,216 +0,0 @@
|
|
1
|
-
require 'sass/constant/operation'
|
2
|
-
require 'sass/constant/literal'
|
3
|
-
|
4
|
-
module Sass
|
5
|
-
module Constant # :nodoc:
|
6
|
-
# The character that begins a constant.
|
7
|
-
CONSTANT_CHAR = ?!
|
8
|
-
|
9
|
-
# Whitespace characters
|
10
|
-
WHITESPACE = [?\ , ?\t, ?\n, ?\r]
|
11
|
-
|
12
|
-
# The character used to escape values
|
13
|
-
ESCAPE_CHAR = ?\\
|
14
|
-
|
15
|
-
# The character used to open and close strings
|
16
|
-
STRING_CHAR = ?"
|
17
|
-
|
18
|
-
# A mapping of syntactically-significant characters
|
19
|
-
# to parsed symbols
|
20
|
-
SYMBOLS = {
|
21
|
-
?( => :open,
|
22
|
-
?) => :close,
|
23
|
-
?+ => :plus,
|
24
|
-
?- => :minus,
|
25
|
-
?* => :times,
|
26
|
-
?/ => :div,
|
27
|
-
?% => :mod,
|
28
|
-
CONSTANT_CHAR => :const,
|
29
|
-
STRING_CHAR => :str,
|
30
|
-
ESCAPE_CHAR => :esc
|
31
|
-
}
|
32
|
-
|
33
|
-
# The regular expression used to parse constants
|
34
|
-
MATCH = /^#{Regexp.escape(CONSTANT_CHAR.chr)}([^\s#{(SYMBOLS.keys + [ ?= ]).map {|c| Regexp.escape("#{c.chr}") }.join}]+)\s*((?:\|\|)?=)\s*(.+)/
|
35
|
-
|
36
|
-
# First-order operations
|
37
|
-
FIRST_ORDER = [:times, :div, :mod]
|
38
|
-
|
39
|
-
# Second-order operations
|
40
|
-
SECOND_ORDER = [:plus, :minus]
|
41
|
-
|
42
|
-
class << self
|
43
|
-
include Haml::Util
|
44
|
-
|
45
|
-
def parse(value, constants, line)
|
46
|
-
begin
|
47
|
-
operationalize(parenthesize(tokenize(value)), constants).to_s
|
48
|
-
rescue Sass::SyntaxError => e
|
49
|
-
if e.message == "Constant arithmetic error"
|
50
|
-
e.instance_eval do
|
51
|
-
@message += ": #{value.dump}."
|
52
|
-
end
|
53
|
-
end
|
54
|
-
e.sass_line = line
|
55
|
-
raise e
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
def tokenize(value)
|
62
|
-
escaped = false
|
63
|
-
is_string = false
|
64
|
-
beginning_of_token = true
|
65
|
-
str = ''
|
66
|
-
to_return = []
|
67
|
-
|
68
|
-
reset_str = Proc.new do
|
69
|
-
to_return << str unless str.empty?
|
70
|
-
''
|
71
|
-
end
|
72
|
-
|
73
|
-
each_char(value) do |byte|
|
74
|
-
unless escaped
|
75
|
-
if byte == ESCAPE_CHAR
|
76
|
-
escaped = true
|
77
|
-
next
|
78
|
-
end
|
79
|
-
|
80
|
-
last = to_return[-1]
|
81
|
-
|
82
|
-
# Do we need to open or close a string literal?
|
83
|
-
if byte == STRING_CHAR
|
84
|
-
is_string = !is_string
|
85
|
-
|
86
|
-
# Adjacent strings should be concatenated
|
87
|
-
if is_string && last && (!last.is_a?(Symbol) || last == :close)
|
88
|
-
to_return << :concat
|
89
|
-
end
|
90
|
-
|
91
|
-
str = reset_str.call
|
92
|
-
next
|
93
|
-
end
|
94
|
-
|
95
|
-
unless is_string
|
96
|
-
|
97
|
-
# Are we looking at whitespace?
|
98
|
-
if WHITESPACE.include?(byte)
|
99
|
-
str = reset_str.call
|
100
|
-
next
|
101
|
-
end
|
102
|
-
|
103
|
-
symbol = SYMBOLS[byte]
|
104
|
-
|
105
|
-
# Adjacent values without an operator should be concatenated
|
106
|
-
if (symbol.nil? || symbol == :open || symbol == :const) &&
|
107
|
-
last && (!last.is_a?(Symbol) || last == :close)
|
108
|
-
to_return << :concat
|
109
|
-
end
|
110
|
-
|
111
|
-
# String then open with no whitespace means funcall
|
112
|
-
if symbol == :open && !str.empty?
|
113
|
-
str = reset_str.call
|
114
|
-
to_return << :funcall
|
115
|
-
end
|
116
|
-
|
117
|
-
# Time for a unary minus!
|
118
|
-
if beginning_of_token && symbol == :minus
|
119
|
-
beginning_of_token = true
|
120
|
-
to_return << :neg
|
121
|
-
next
|
122
|
-
end
|
123
|
-
|
124
|
-
# Are we looking at an operator?
|
125
|
-
if symbol && (symbol != :mod || str.empty?)
|
126
|
-
str = reset_str.call
|
127
|
-
beginning_of_token = symbol != :close
|
128
|
-
to_return << symbol
|
129
|
-
next
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
escaped = false
|
135
|
-
beginning_of_token = false
|
136
|
-
str << byte.chr
|
137
|
-
end
|
138
|
-
|
139
|
-
if is_string
|
140
|
-
raise Sass::SyntaxError.new("Unterminated string: #{value.dump}.")
|
141
|
-
end
|
142
|
-
str = reset_str.call
|
143
|
-
to_return
|
144
|
-
end
|
145
|
-
|
146
|
-
def parenthesize(value, return_after_expr = false)
|
147
|
-
to_return = []
|
148
|
-
|
149
|
-
while (token = value.shift) && token != :close
|
150
|
-
case token
|
151
|
-
when :open
|
152
|
-
to_return << parenthesize(value)
|
153
|
-
when :neg
|
154
|
-
# This is never actually reached, but we'll leave it in just in case.
|
155
|
-
raise Sass::SyntaxError.new("Unterminated unary minus.") if value.first.nil?
|
156
|
-
to_return << [:neg, parenthesize(value, true)]
|
157
|
-
when :const
|
158
|
-
raise Sass::SyntaxError.new("Unterminated constant.") if value.first.nil?
|
159
|
-
raise Sass::SyntaxError.new("Invalid constant.") unless value.first.is_a?(::String)
|
160
|
-
|
161
|
-
to_return << [:const, value.first]
|
162
|
-
value.shift
|
163
|
-
else
|
164
|
-
to_return << token
|
165
|
-
end
|
166
|
-
|
167
|
-
return to_return.first if return_after_expr
|
168
|
-
end
|
169
|
-
return to_return
|
170
|
-
end
|
171
|
-
|
172
|
-
#--
|
173
|
-
# TODO: Don't pass around original value;
|
174
|
-
# have Constant.parse automatically add it to exception.
|
175
|
-
#++
|
176
|
-
def operationalize(value, constants)
|
177
|
-
value = [value] unless value.is_a?(Array)
|
178
|
-
case value.length
|
179
|
-
when 0
|
180
|
-
Sass::Constant::Nil.new
|
181
|
-
when 1
|
182
|
-
value = value[0]
|
183
|
-
if value.is_a? Array
|
184
|
-
operationalize(value, constants)
|
185
|
-
elsif value.is_a? Operation
|
186
|
-
value
|
187
|
-
else
|
188
|
-
Literal.parse(value)
|
189
|
-
end
|
190
|
-
when 2
|
191
|
-
if value[0] == :neg
|
192
|
-
Operation.new(Sass::Constant::Number.new('0'), operationalize(value[1], constants), :minus)
|
193
|
-
elsif value[0] == :const
|
194
|
-
Literal.parse(get_constant(value[1], constants))
|
195
|
-
else
|
196
|
-
raise SyntaxError.new("Constant arithmetic error")
|
197
|
-
end
|
198
|
-
when 3
|
199
|
-
Operation.new(operationalize(value[0], constants), operationalize(value[2], constants), value[1])
|
200
|
-
else
|
201
|
-
if SECOND_ORDER.include?(value[1]) && FIRST_ORDER.include?(value[3])
|
202
|
-
operationalize([value[0], value[1], operationalize(value[2..4], constants), *value[5..-1]], constants)
|
203
|
-
else
|
204
|
-
operationalize([operationalize(value[0..2], constants), *value[3..-1]], constants)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
def get_constant(value, constants)
|
210
|
-
to_return = constants[value]
|
211
|
-
raise SyntaxError.new("Undefined constant: \"!#{value}\".") unless to_return
|
212
|
-
to_return
|
213
|
-
end
|
214
|
-
end
|
215
|
-
end
|
216
|
-
end
|
data/lib/sass/constant/color.rb
DELETED
@@ -1,101 +0,0 @@
|
|
1
|
-
require 'sass/constant/literal'
|
2
|
-
|
3
|
-
module Sass::Constant # :nodoc:
|
4
|
-
class Color < Literal # :nodoc:
|
5
|
-
|
6
|
-
HTML4_COLORS = {
|
7
|
-
'black' => 0x000000,
|
8
|
-
'silver' => 0xc0c0c0,
|
9
|
-
'gray' => 0x808080,
|
10
|
-
'white' => 0xffffff,
|
11
|
-
'maroon' => 0x800000,
|
12
|
-
'red' => 0xff0000,
|
13
|
-
'purple' => 0x800080,
|
14
|
-
'fuchsia' => 0xff00ff,
|
15
|
-
'green' => 0x008000,
|
16
|
-
'lime' => 0x00ff00,
|
17
|
-
'olive' => 0x808000,
|
18
|
-
'yellow' => 0xffff00,
|
19
|
-
'navy' => 0x000080,
|
20
|
-
'blue' => 0x0000ff,
|
21
|
-
'teal' => 0x008080,
|
22
|
-
'aqua' => 0x00ffff
|
23
|
-
}
|
24
|
-
|
25
|
-
REGEXP = /\##{"([0-9a-fA-F]{1,2})" * 3}/
|
26
|
-
|
27
|
-
def parse(value)
|
28
|
-
if (value =~ REGEXP)
|
29
|
-
@value = value.scan(REGEXP)[0].map { |num| num.ljust(2, num).to_i(16) }
|
30
|
-
else
|
31
|
-
color = HTML4_COLORS[value.downcase]
|
32
|
-
@value = (0..2).map{ |n| color >> (n << 3) & 0xff }.reverse
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def plus(other)
|
37
|
-
if other.is_a? Sass::Constant::String
|
38
|
-
Sass::Constant::String.from_value(self.to_s + other.to_s)
|
39
|
-
else
|
40
|
-
piecewise(other, :+)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def minus(other)
|
45
|
-
if other.is_a? Sass::Constant::String
|
46
|
-
raise NoMethodError.new(nil, :minus)
|
47
|
-
else
|
48
|
-
piecewise(other, :-)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def times(other)
|
53
|
-
if other.is_a? Sass::Constant::String
|
54
|
-
raise NoMethodError.new(nil, :times)
|
55
|
-
else
|
56
|
-
piecewise(other, :*)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def div(other)
|
61
|
-
if other.is_a? Sass::Constant::String
|
62
|
-
raise NoMethodError.new(nil, :div)
|
63
|
-
else
|
64
|
-
piecewise(other, :/)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def mod(other)
|
69
|
-
if other.is_a? Sass::Constant::String
|
70
|
-
raise NoMethodError.new(nil, :mod)
|
71
|
-
else
|
72
|
-
piecewise(other, :%)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def to_s
|
77
|
-
red, green, blue = @value.map { |num| num.to_s(16).rjust(2, '0') }
|
78
|
-
"##{red}#{green}#{blue}"
|
79
|
-
end
|
80
|
-
|
81
|
-
protected
|
82
|
-
|
83
|
-
def self.filter_value(value)
|
84
|
-
value.map { |num| num.to_i }
|
85
|
-
end
|
86
|
-
|
87
|
-
private
|
88
|
-
|
89
|
-
def piecewise(other, operation)
|
90
|
-
other_num = other.is_a? Number
|
91
|
-
other_val = other.value
|
92
|
-
|
93
|
-
rgb = []
|
94
|
-
for i in (0...3)
|
95
|
-
res = @value[i].send(operation, other_num ? other_val : other_val[i])
|
96
|
-
rgb[i] = [ [res, 255].min, 0 ].max
|
97
|
-
end
|
98
|
-
Color.from_value(rgb)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
# Let the subclasses see the superclass
|
2
|
-
module Sass::Constant; class Literal; end; end; # :nodoc:
|
3
|
-
|
4
|
-
require 'sass/constant/string'
|
5
|
-
require 'sass/constant/number'
|
6
|
-
require 'sass/constant/color'
|
7
|
-
require 'sass/constant/nil'
|
8
|
-
|
9
|
-
class Sass::Constant::Literal # :nodoc:
|
10
|
-
# The regular expression matching numbers.
|
11
|
-
NUMBER = /^(-?\d*?\.?)(\d+)([^\d\s]*)$/
|
12
|
-
|
13
|
-
html_color_matcher = Sass::Constant::Color::HTML4_COLORS.keys.map { |c| "^#{c}$" }.join '|'
|
14
|
-
|
15
|
-
# The regular expression matching colors.
|
16
|
-
COLOR = /^\# (?: [\da-f]{3} | [\da-f]{6} ) | #{html_color_matcher}/ix
|
17
|
-
|
18
|
-
def self.parse(value)
|
19
|
-
case value
|
20
|
-
when NUMBER
|
21
|
-
Sass::Constant::Number.new(value)
|
22
|
-
when COLOR
|
23
|
-
Sass::Constant::Color.new(value)
|
24
|
-
else
|
25
|
-
Sass::Constant::String.new(value)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def initialize(value = nil)
|
30
|
-
self.parse(value) if value
|
31
|
-
end
|
32
|
-
|
33
|
-
def perform
|
34
|
-
self
|
35
|
-
end
|
36
|
-
|
37
|
-
def concat(other)
|
38
|
-
Sass::Constant::String.from_value("#{self.to_s} #{other.to_s}")
|
39
|
-
end
|
40
|
-
|
41
|
-
attr_reader :value
|
42
|
-
|
43
|
-
protected
|
44
|
-
|
45
|
-
def self.filter_value(value)
|
46
|
-
value
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.from_value(value)
|
50
|
-
instance = self.new
|
51
|
-
instance.instance_variable_set('@value', self.filter_value(value))
|
52
|
-
instance
|
53
|
-
end
|
54
|
-
end
|
data/lib/sass/constant/nil.rb
DELETED
data/lib/sass/constant/number.rb
DELETED
@@ -1,87 +0,0 @@
|
|
1
|
-
require 'sass/constant/literal'
|
2
|
-
|
3
|
-
module Sass::Constant # :nodoc:
|
4
|
-
class Number < Literal # :nodoc:
|
5
|
-
|
6
|
-
attr_reader :unit
|
7
|
-
|
8
|
-
def parse(value)
|
9
|
-
first, second, unit = value.scan(Literal::NUMBER)[0]
|
10
|
-
@value = first.empty? ? second.to_i : "#{first}#{second}".to_f
|
11
|
-
@unit = unit.empty? ? nil : unit
|
12
|
-
end
|
13
|
-
|
14
|
-
def plus(other)
|
15
|
-
if other.is_a? Number
|
16
|
-
operate(other, :+)
|
17
|
-
elsif other.is_a? Color
|
18
|
-
other.plus(self)
|
19
|
-
else
|
20
|
-
Sass::Constant::String.from_value(self.to_s + other.to_s)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def minus(other)
|
25
|
-
if other.is_a? Number
|
26
|
-
operate(other, :-)
|
27
|
-
else
|
28
|
-
raise NoMethodError.new(nil, :minus)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def times(other)
|
33
|
-
if other.is_a? Number
|
34
|
-
operate(other, :*)
|
35
|
-
elsif other.is_a? Color
|
36
|
-
other.times(self)
|
37
|
-
else
|
38
|
-
raise NoMethodError.new(nil, :times)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def div(other)
|
43
|
-
if other.is_a? Number
|
44
|
-
operate(other, :/)
|
45
|
-
else
|
46
|
-
raise NoMethodError.new(nil, :div)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def mod(other)
|
51
|
-
if other.is_a? Number
|
52
|
-
operate(other, :%)
|
53
|
-
else
|
54
|
-
raise NoMethodError.new(nil, :mod)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def to_s
|
59
|
-
value = @value
|
60
|
-
value = value.to_i if value % 1 == 0.0
|
61
|
-
"#{value}#{@unit}"
|
62
|
-
end
|
63
|
-
|
64
|
-
protected
|
65
|
-
|
66
|
-
def self.from_value(value, unit=nil)
|
67
|
-
instance = super(value)
|
68
|
-
instance.instance_variable_set('@unit', unit)
|
69
|
-
instance
|
70
|
-
end
|
71
|
-
|
72
|
-
def operate(other, operation)
|
73
|
-
unit = nil
|
74
|
-
if other.unit.nil?
|
75
|
-
unit = self.unit
|
76
|
-
elsif self.unit.nil?
|
77
|
-
unit = other.unit
|
78
|
-
elsif other.unit == self.unit
|
79
|
-
unit = self.unit
|
80
|
-
else
|
81
|
-
raise Sass::SyntaxError.new("Incompatible units: #{self.unit} and #{other.unit}.")
|
82
|
-
end
|
83
|
-
|
84
|
-
Number.from_value(self.value.send(operation, other.value), unit)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|