oreorenasass 3.4.4 → 3.4.5
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/MIT-LICENSE +1 -1
- data/README.md +50 -70
- data/Rakefile +5 -26
- data/VERSION +1 -1
- data/VERSION_NAME +1 -1
- data/bin/sass +1 -1
- data/bin/scss +1 -1
- data/lib/sass.rb +12 -19
- data/lib/sass/cache_stores/base.rb +2 -2
- data/lib/sass/cache_stores/chain.rb +1 -2
- data/lib/sass/cache_stores/filesystem.rb +5 -1
- data/lib/sass/cache_stores/memory.rb +1 -1
- data/lib/sass/cache_stores/null.rb +2 -2
- data/lib/sass/callbacks.rb +0 -1
- data/lib/sass/css.rb +13 -11
- data/lib/sass/engine.rb +173 -424
- data/lib/sass/environment.rb +58 -148
- data/lib/sass/error.rb +14 -11
- data/lib/sass/exec.rb +703 -5
- data/lib/sass/importers/base.rb +6 -49
- data/lib/sass/importers/filesystem.rb +19 -44
- data/lib/sass/logger.rb +4 -1
- data/lib/sass/logger/base.rb +4 -2
- data/lib/sass/logger/log_level.rb +7 -3
- data/lib/sass/media.rb +23 -20
- data/lib/sass/plugin.rb +7 -7
- data/lib/sass/plugin/compiler.rb +145 -304
- data/lib/sass/plugin/configuration.rb +23 -18
- data/lib/sass/plugin/merb.rb +1 -1
- data/lib/sass/plugin/staleness_checker.rb +3 -3
- data/lib/sass/repl.rb +3 -3
- data/lib/sass/script.rb +8 -35
- data/lib/sass/script/{value/arg_list.rb → arg_list.rb} +25 -9
- data/lib/sass/script/bool.rb +18 -0
- data/lib/sass/script/color.rb +606 -0
- data/lib/sass/script/css_lexer.rb +4 -8
- data/lib/sass/script/css_parser.rb +2 -5
- data/lib/sass/script/funcall.rb +245 -0
- data/lib/sass/script/functions.rb +408 -1491
- data/lib/sass/script/interpolation.rb +79 -0
- data/lib/sass/script/lexer.rb +68 -172
- data/lib/sass/script/list.rb +85 -0
- data/lib/sass/script/literal.rb +221 -0
- data/lib/sass/script/{tree/node.rb → node.rb} +12 -22
- data/lib/sass/script/{value/null.rb → null.rb} +7 -14
- data/lib/sass/script/{value/number.rb → number.rb} +75 -152
- data/lib/sass/script/{tree/operation.rb → operation.rb} +24 -17
- data/lib/sass/script/parser.rb +110 -245
- data/lib/sass/script/string.rb +51 -0
- data/lib/sass/script/{tree/string_interpolation.rb → string_interpolation.rb} +4 -5
- data/lib/sass/script/{tree/unary_operation.rb → unary_operation.rb} +6 -6
- data/lib/sass/script/variable.rb +58 -0
- data/lib/sass/scss/css_parser.rb +3 -9
- data/lib/sass/scss/parser.rb +421 -450
- data/lib/sass/scss/rx.rb +11 -19
- data/lib/sass/scss/static_parser.rb +7 -321
- data/lib/sass/selector.rb +194 -68
- data/lib/sass/selector/abstract_sequence.rb +14 -29
- data/lib/sass/selector/comma_sequence.rb +25 -108
- data/lib/sass/selector/sequence.rb +66 -159
- data/lib/sass/selector/simple.rb +25 -23
- data/lib/sass/selector/simple_sequence.rb +63 -173
- data/lib/sass/shared.rb +1 -1
- data/lib/sass/supports.rb +15 -13
- data/lib/sass/tree/charset_node.rb +1 -1
- data/lib/sass/tree/comment_node.rb +3 -3
- data/lib/sass/tree/css_import_node.rb +11 -11
- data/lib/sass/tree/debug_node.rb +2 -2
- data/lib/sass/tree/directive_node.rb +4 -21
- data/lib/sass/tree/each_node.rb +8 -8
- data/lib/sass/tree/extend_node.rb +7 -14
- data/lib/sass/tree/for_node.rb +4 -4
- data/lib/sass/tree/function_node.rb +4 -9
- data/lib/sass/tree/if_node.rb +1 -1
- data/lib/sass/tree/import_node.rb +5 -4
- data/lib/sass/tree/media_node.rb +14 -4
- data/lib/sass/tree/mixin_def_node.rb +4 -4
- data/lib/sass/tree/mixin_node.rb +8 -21
- data/lib/sass/tree/node.rb +12 -54
- data/lib/sass/tree/prop_node.rb +20 -39
- data/lib/sass/tree/return_node.rb +2 -3
- data/lib/sass/tree/root_node.rb +3 -19
- data/lib/sass/tree/rule_node.rb +22 -35
- data/lib/sass/tree/supports_node.rb +13 -0
- data/lib/sass/tree/trace_node.rb +1 -2
- data/lib/sass/tree/variable_node.rb +3 -9
- data/lib/sass/tree/visitors/base.rb +8 -5
- data/lib/sass/tree/visitors/check_nesting.rb +19 -49
- data/lib/sass/tree/visitors/convert.rb +56 -74
- data/lib/sass/tree/visitors/cssize.rb +74 -202
- data/lib/sass/tree/visitors/deep_copy.rb +5 -10
- data/lib/sass/tree/visitors/extend.rb +7 -7
- data/lib/sass/tree/visitors/perform.rb +185 -278
- data/lib/sass/tree/visitors/set_options.rb +6 -20
- data/lib/sass/tree/visitors/to_css.rb +81 -234
- data/lib/sass/tree/warn_node.rb +2 -2
- data/lib/sass/tree/while_node.rb +2 -2
- data/lib/sass/util.rb +152 -522
- data/lib/sass/util/multibyte_string_scanner.rb +0 -2
- data/lib/sass/util/subset_map.rb +3 -4
- data/lib/sass/util/test.rb +1 -0
- data/lib/sass/version.rb +22 -20
- data/test/Gemfile +3 -0
- data/test/Gemfile.lock +10 -0
- data/test/sass/cache_test.rb +20 -62
- data/test/sass/callbacks_test.rb +1 -1
- data/test/sass/conversion_test.rb +2 -296
- data/test/sass/css2sass_test.rb +4 -23
- data/test/sass/engine_test.rb +354 -411
- data/test/sass/exec_test.rb +2 -2
- data/test/sass/extend_test.rb +145 -324
- data/test/sass/functions_test.rb +86 -873
- data/test/sass/importer_test.rb +21 -241
- data/test/sass/logger_test.rb +1 -1
- data/test/sass/more_results/more_import.css +1 -1
- data/test/sass/plugin_test.rb +26 -16
- data/test/sass/results/compact.css +1 -1
- data/test/sass/results/complex.css +4 -4
- data/test/sass/results/expanded.css +1 -1
- data/test/sass/results/import.css +1 -1
- data/test/sass/results/import_charset_ibm866.css +2 -2
- data/test/sass/results/mixins.css +17 -17
- data/test/sass/results/nested.css +1 -1
- data/test/sass/results/parent_ref.css +2 -2
- data/test/sass/results/script.css +3 -3
- data/test/sass/results/scss_import.css +1 -1
- data/test/sass/script_conversion_test.rb +7 -36
- data/test/sass/script_test.rb +53 -485
- data/test/sass/scss/css_test.rb +28 -143
- data/test/sass/scss/rx_test.rb +4 -4
- data/test/sass/scss/scss_test.rb +325 -2119
- data/test/sass/templates/scss_import.scss +1 -2
- data/test/sass/test_helper.rb +1 -1
- data/test/sass/util/multibyte_string_scanner_test.rb +1 -1
- data/test/sass/util/subset_map_test.rb +2 -2
- data/test/sass/util_test.rb +1 -86
- data/test/test_helper.rb +8 -37
- metadata +19 -66
- data/lib/sass/exec/base.rb +0 -187
- data/lib/sass/exec/sass_convert.rb +0 -264
- data/lib/sass/exec/sass_scss.rb +0 -424
- data/lib/sass/features.rb +0 -47
- data/lib/sass/script/tree.rb +0 -16
- data/lib/sass/script/tree/funcall.rb +0 -306
- data/lib/sass/script/tree/interpolation.rb +0 -118
- data/lib/sass/script/tree/list_literal.rb +0 -77
- data/lib/sass/script/tree/literal.rb +0 -45
- data/lib/sass/script/tree/map_literal.rb +0 -64
- data/lib/sass/script/tree/selector.rb +0 -26
- data/lib/sass/script/tree/variable.rb +0 -57
- data/lib/sass/script/value.rb +0 -11
- data/lib/sass/script/value/base.rb +0 -240
- data/lib/sass/script/value/bool.rb +0 -35
- data/lib/sass/script/value/color.rb +0 -680
- data/lib/sass/script/value/helpers.rb +0 -262
- data/lib/sass/script/value/list.rb +0 -113
- data/lib/sass/script/value/map.rb +0 -70
- data/lib/sass/script/value/string.rb +0 -97
- data/lib/sass/selector/pseudo.rb +0 -256
- data/lib/sass/source/map.rb +0 -210
- data/lib/sass/source/position.rb +0 -39
- data/lib/sass/source/range.rb +0 -41
- data/lib/sass/stack.rb +0 -120
- data/lib/sass/tree/at_root_node.rb +0 -83
- data/lib/sass/tree/error_node.rb +0 -18
- data/lib/sass/tree/keyframe_rule_node.rb +0 -15
- data/lib/sass/util/cross_platform_random.rb +0 -19
- data/lib/sass/util/normalized_map.rb +0 -130
- data/lib/sass/util/ordered_hash.rb +0 -192
- data/test/sass/compiler_test.rb +0 -232
- data/test/sass/encoding_test.rb +0 -219
- data/test/sass/source_map_test.rb +0 -977
- data/test/sass/superselector_test.rb +0 -191
- data/test/sass/util/normalized_map_test.rb +0 -51
- data/test/sass/value_helpers_test.rb +0 -179
@@ -0,0 +1,221 @@
|
|
1
|
+
module Sass::Script
|
2
|
+
# The abstract superclass for SassScript objects.
|
3
|
+
#
|
4
|
+
# Many of these methods, especially the ones that correspond to SassScript operations,
|
5
|
+
# are designed to be overridden by subclasses which may change the semantics somewhat.
|
6
|
+
# The operations listed here are just the defaults.
|
7
|
+
class Literal < Node
|
8
|
+
require 'sass/script/string'
|
9
|
+
require 'sass/script/number'
|
10
|
+
require 'sass/script/color'
|
11
|
+
require 'sass/script/bool'
|
12
|
+
require 'sass/script/null'
|
13
|
+
require 'sass/script/list'
|
14
|
+
require 'sass/script/arg_list'
|
15
|
+
|
16
|
+
# Returns the Ruby value of the literal.
|
17
|
+
# The type of this value varies based on the subclass.
|
18
|
+
#
|
19
|
+
# @return [Object]
|
20
|
+
attr_reader :value
|
21
|
+
|
22
|
+
# Creates a new literal.
|
23
|
+
#
|
24
|
+
# @param value [Object] The object for \{#value}
|
25
|
+
def initialize(value = nil)
|
26
|
+
@value = value
|
27
|
+
super()
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns an empty array.
|
31
|
+
#
|
32
|
+
# @return [Array<Node>] empty
|
33
|
+
# @see Node#children
|
34
|
+
def children
|
35
|
+
[]
|
36
|
+
end
|
37
|
+
|
38
|
+
# @see Node#deep_copy
|
39
|
+
def deep_copy
|
40
|
+
dup
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns the options hash for this node.
|
44
|
+
#
|
45
|
+
# @return [{Symbol => Object}]
|
46
|
+
# @raise [Sass::SyntaxError] if the options hash hasn't been set.
|
47
|
+
# This should only happen when the literal was created
|
48
|
+
# outside of the parser and \{#to\_s} was called on it
|
49
|
+
def options
|
50
|
+
opts = super
|
51
|
+
return opts if opts
|
52
|
+
raise Sass::SyntaxError.new(<<MSG)
|
53
|
+
The #options attribute is not set on this #{self.class}.
|
54
|
+
This error is probably occurring because #to_s was called
|
55
|
+
on this literal within a custom Sass function without first
|
56
|
+
setting the #option attribute.
|
57
|
+
MSG
|
58
|
+
end
|
59
|
+
|
60
|
+
# The SassScript `==` operation.
|
61
|
+
# **Note that this returns a {Sass::Script::Bool} object,
|
62
|
+
# not a Ruby boolean**.
|
63
|
+
#
|
64
|
+
# @param other [Literal] The right-hand side of the operator
|
65
|
+
# @return [Bool] True if this literal is the same as the other,
|
66
|
+
# false otherwise
|
67
|
+
def eq(other)
|
68
|
+
Sass::Script::Bool.new(self.class == other.class && self.value == other.value)
|
69
|
+
end
|
70
|
+
|
71
|
+
# The SassScript `!=` operation.
|
72
|
+
# **Note that this returns a {Sass::Script::Bool} object,
|
73
|
+
# not a Ruby boolean**.
|
74
|
+
#
|
75
|
+
# @param other [Literal] The right-hand side of the operator
|
76
|
+
# @return [Bool] False if this literal is the same as the other,
|
77
|
+
# true otherwise
|
78
|
+
def neq(other)
|
79
|
+
Sass::Script::Bool.new(!eq(other).to_bool)
|
80
|
+
end
|
81
|
+
|
82
|
+
# The SassScript `==` operation.
|
83
|
+
# **Note that this returns a {Sass::Script::Bool} object,
|
84
|
+
# not a Ruby boolean**.
|
85
|
+
#
|
86
|
+
# @param other [Literal] The right-hand side of the operator
|
87
|
+
# @return [Bool] True if this literal is the same as the other,
|
88
|
+
# false otherwise
|
89
|
+
def unary_not
|
90
|
+
Sass::Script::Bool.new(!to_bool)
|
91
|
+
end
|
92
|
+
|
93
|
+
# The SassScript `=` operation
|
94
|
+
# (used for proprietary MS syntax like `alpha(opacity=20)`).
|
95
|
+
#
|
96
|
+
# @param other [Literal] The right-hand side of the operator
|
97
|
+
# @return [Script::String] A string containing both literals
|
98
|
+
# separated by `"="`
|
99
|
+
def single_eq(other)
|
100
|
+
Sass::Script::String.new("#{self.to_s}=#{other.to_s}")
|
101
|
+
end
|
102
|
+
|
103
|
+
# The SassScript `+` operation.
|
104
|
+
#
|
105
|
+
# @param other [Literal] The right-hand side of the operator
|
106
|
+
# @return [Script::String] A string containing both literals
|
107
|
+
# without any separation
|
108
|
+
def plus(other)
|
109
|
+
if other.is_a?(Sass::Script::String)
|
110
|
+
return Sass::Script::String.new(self.to_s + other.value, other.type)
|
111
|
+
end
|
112
|
+
Sass::Script::String.new(self.to_s + other.to_s)
|
113
|
+
end
|
114
|
+
|
115
|
+
# The SassScript `-` operation.
|
116
|
+
#
|
117
|
+
# @param other [Literal] The right-hand side of the operator
|
118
|
+
# @return [Script::String] A string containing both literals
|
119
|
+
# separated by `"-"`
|
120
|
+
def minus(other)
|
121
|
+
Sass::Script::String.new("#{self.to_s}-#{other.to_s}")
|
122
|
+
end
|
123
|
+
|
124
|
+
# The SassScript `/` operation.
|
125
|
+
#
|
126
|
+
# @param other [Literal] The right-hand side of the operator
|
127
|
+
# @return [Script::String] A string containing both literals
|
128
|
+
# separated by `"/"`
|
129
|
+
def div(other)
|
130
|
+
Sass::Script::String.new("#{self.to_s}/#{other.to_s}")
|
131
|
+
end
|
132
|
+
|
133
|
+
# The SassScript unary `+` operation (e.g. `+$a`).
|
134
|
+
#
|
135
|
+
# @param other [Literal] The right-hand side of the operator
|
136
|
+
# @return [Script::String] A string containing the literal
|
137
|
+
# preceded by `"+"`
|
138
|
+
def unary_plus
|
139
|
+
Sass::Script::String.new("+#{self.to_s}")
|
140
|
+
end
|
141
|
+
|
142
|
+
# The SassScript unary `-` operation (e.g. `-$a`).
|
143
|
+
#
|
144
|
+
# @param other [Literal] The right-hand side of the operator
|
145
|
+
# @return [Script::String] A string containing the literal
|
146
|
+
# preceded by `"-"`
|
147
|
+
def unary_minus
|
148
|
+
Sass::Script::String.new("-#{self.to_s}")
|
149
|
+
end
|
150
|
+
|
151
|
+
# The SassScript unary `/` operation (e.g. `/$a`).
|
152
|
+
#
|
153
|
+
# @param other [Literal] The right-hand side of the operator
|
154
|
+
# @return [Script::String] A string containing the literal
|
155
|
+
# preceded by `"/"`
|
156
|
+
def unary_div
|
157
|
+
Sass::Script::String.new("/#{self.to_s}")
|
158
|
+
end
|
159
|
+
|
160
|
+
# @return [String] A readable representation of the literal
|
161
|
+
def inspect
|
162
|
+
value.inspect
|
163
|
+
end
|
164
|
+
|
165
|
+
# @return [Boolean] `true` (the Ruby boolean value)
|
166
|
+
def to_bool
|
167
|
+
true
|
168
|
+
end
|
169
|
+
|
170
|
+
# Compares this object with another.
|
171
|
+
#
|
172
|
+
# @param other [Object] The object to compare with
|
173
|
+
# @return [Boolean] Whether or not this literal is equivalent to `other`
|
174
|
+
def ==(other)
|
175
|
+
eq(other).to_bool
|
176
|
+
end
|
177
|
+
|
178
|
+
# @return [Fixnum] The integer value of this literal
|
179
|
+
# @raise [Sass::SyntaxError] if this literal isn't an integer
|
180
|
+
def to_i
|
181
|
+
raise Sass::SyntaxError.new("#{self.inspect} is not an integer.")
|
182
|
+
end
|
183
|
+
|
184
|
+
# @raise [Sass::SyntaxError] if this literal isn't an integer
|
185
|
+
def assert_int!; to_i; end
|
186
|
+
|
187
|
+
# Returns the value of this literal as a list.
|
188
|
+
# Single literals are considered the same as single-element lists.
|
189
|
+
#
|
190
|
+
# @return [Array<Literal>] The of this literal as a list
|
191
|
+
def to_a
|
192
|
+
[self]
|
193
|
+
end
|
194
|
+
|
195
|
+
# Returns the string representation of this literal
|
196
|
+
# as it would be output to the CSS document.
|
197
|
+
#
|
198
|
+
# @return [String]
|
199
|
+
def to_s(opts = {})
|
200
|
+
raise Sass::SyntaxError.new("[BUG] All subclasses of Sass::Literal must implement #to_s.")
|
201
|
+
end
|
202
|
+
alias_method :to_sass, :to_s
|
203
|
+
|
204
|
+
# Returns whether or not this object is null.
|
205
|
+
#
|
206
|
+
# @return [Boolean] `false`
|
207
|
+
def null?
|
208
|
+
false
|
209
|
+
end
|
210
|
+
|
211
|
+
protected
|
212
|
+
|
213
|
+
# Evaluates the literal.
|
214
|
+
#
|
215
|
+
# @param environment [Sass::Environment] The environment in which to evaluate the SassScript
|
216
|
+
# @return [Literal] This literal
|
217
|
+
def _perform(environment)
|
218
|
+
self
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Sass::Script
|
1
|
+
module Sass::Script
|
2
2
|
# The abstract superclass for SassScript parse tree nodes.
|
3
3
|
#
|
4
4
|
# Use \{#perform} to evaluate a parse tree.
|
@@ -13,16 +13,6 @@ module Sass::Script::Tree
|
|
13
13
|
# @return [Fixnum]
|
14
14
|
attr_accessor :line
|
15
15
|
|
16
|
-
# The source range in the document on which this node appeared.
|
17
|
-
#
|
18
|
-
# @return [Sass::Source::Range]
|
19
|
-
attr_accessor :source_range
|
20
|
-
|
21
|
-
# The file name of the document on which this node appeared.
|
22
|
-
#
|
23
|
-
# @return [String]
|
24
|
-
attr_accessor :filename
|
25
|
-
|
26
16
|
# Sets the options hash for this node,
|
27
17
|
# as well as for all child nodes.
|
28
18
|
# See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
|
@@ -32,7 +22,7 @@ module Sass::Script::Tree
|
|
32
22
|
@options = options
|
33
23
|
children.each do |c|
|
34
24
|
if c.is_a? Hash
|
35
|
-
c.values.each {|v| v.options = options}
|
25
|
+
c.values.each {|v| v.options = options }
|
36
26
|
else
|
37
27
|
c.options = options
|
38
28
|
end
|
@@ -45,7 +35,7 @@ module Sass::Script::Tree
|
|
45
35
|
# instead, override \{#\_perform}.
|
46
36
|
#
|
47
37
|
# @param environment [Sass::Environment] The environment in which to evaluate the SassScript
|
48
|
-
# @return [
|
38
|
+
# @return [Literal] The SassScript object that is the value of the SassScript
|
49
39
|
def perform(environment)
|
50
40
|
_perform(environment)
|
51
41
|
rescue Sass::SyntaxError => e
|
@@ -80,30 +70,30 @@ module Sass::Script::Tree
|
|
80
70
|
# Converts underscores to dashes if the :dasherize option is set.
|
81
71
|
def dasherize(s, opts)
|
82
72
|
if opts[:dasherize]
|
83
|
-
s.gsub(/_/,
|
73
|
+
s.gsub(/_/,'-')
|
84
74
|
else
|
85
75
|
s
|
86
76
|
end
|
87
77
|
end
|
88
78
|
|
89
79
|
# Evaluates this node.
|
90
|
-
# Note that all {
|
80
|
+
# Note that all {Literal} objects created within this method
|
91
81
|
# should have their \{#options} attribute set, probably via \{#opts}.
|
92
82
|
#
|
93
83
|
# @param environment [Sass::Environment] The environment in which to evaluate the SassScript
|
94
|
-
# @return [
|
84
|
+
# @return [Literal] The SassScript object that is the value of the SassScript
|
95
85
|
# @see #perform
|
96
86
|
def _perform(environment)
|
97
87
|
Sass::Util.abstract(self)
|
98
88
|
end
|
99
89
|
|
100
|
-
# Sets the \{#options} field on the given
|
90
|
+
# Sets the \{#options} field on the given literal and returns it
|
101
91
|
#
|
102
|
-
# @param
|
103
|
-
# @return [
|
104
|
-
def opts(
|
105
|
-
|
106
|
-
|
92
|
+
# @param literal [Literal]
|
93
|
+
# @return [Literal]
|
94
|
+
def opts(literal)
|
95
|
+
literal.options = options
|
96
|
+
literal
|
107
97
|
end
|
108
98
|
end
|
109
99
|
end
|
@@ -1,18 +1,11 @@
|
|
1
|
-
|
2
|
-
# A SassScript object representing a null value.
|
3
|
-
class Null < Base
|
4
|
-
# The null value in SassScript.
|
5
|
-
#
|
6
|
-
# This is assigned before new is overridden below so that we use the default implementation.
|
7
|
-
NULL = new(nil)
|
1
|
+
require 'sass/script/literal'
|
8
2
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
#
|
13
|
-
|
14
|
-
|
15
|
-
NULL
|
3
|
+
module Sass::Script
|
4
|
+
# A SassScript object representing a null value.
|
5
|
+
class Null < Literal
|
6
|
+
# Creates a new null literal.
|
7
|
+
def initialize
|
8
|
+
super nil
|
16
9
|
end
|
17
10
|
|
18
11
|
# @return [Boolean] `false` (the Ruby boolean value)
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
require 'sass/script/literal'
|
2
|
+
|
3
|
+
module Sass::Script
|
2
4
|
# A SassScript object representing a number.
|
3
5
|
# SassScript numbers can have decimal values,
|
4
6
|
# and can also have units.
|
@@ -7,7 +9,7 @@ module Sass::Script::Value
|
|
7
9
|
#
|
8
10
|
# Numbers can also have more complex units, such as `1px*em/in`.
|
9
11
|
# These cannot be inputted directly in Sass code at the moment.
|
10
|
-
class Number <
|
12
|
+
class Number < Literal
|
11
13
|
# The Ruby value of the number.
|
12
14
|
#
|
13
15
|
# @return [Numeric]
|
@@ -15,7 +17,7 @@ module Sass::Script::Value
|
|
15
17
|
|
16
18
|
# A list of units in the numerator of the number.
|
17
19
|
# For example, `1px*em/in*cm` would return `["px", "em"]`
|
18
|
-
# @return [Array<String>]
|
20
|
+
# @return [Array<String>]
|
19
21
|
attr_reader :numerator_units
|
20
22
|
|
21
23
|
# A list of units in the denominator of the number.
|
@@ -51,15 +53,24 @@ module Sass::Script::Value
|
|
51
53
|
@precision_factor ||= 10.0**precision
|
52
54
|
end
|
53
55
|
|
56
|
+
# Handles the deprecation warning for the PRECISION constant
|
57
|
+
# This can be removed in 3.2.
|
58
|
+
def self.const_missing(const)
|
59
|
+
if const == :PRECISION
|
60
|
+
Sass::Util.sass_warn("Sass::Script::Number::PRECISION is deprecated and will be removed in a future release. Use Sass::Script::Number.precision_factor instead.")
|
61
|
+
const_set(:PRECISION, self.precision_factor)
|
62
|
+
else
|
63
|
+
super
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
54
67
|
# Used so we don't allocate two new arrays for each new number.
|
55
68
|
NO_UNITS = []
|
56
69
|
|
57
70
|
# @param value [Numeric] The value of the number
|
58
|
-
# @param numerator_units [
|
59
|
-
# @param denominator_units [
|
71
|
+
# @param numerator_units [Array<String>] See \{#numerator\_units}
|
72
|
+
# @param denominator_units [Array<String>] See \{#denominator\_units}
|
60
73
|
def initialize(value, numerator_units = NO_UNITS, denominator_units = NO_UNITS)
|
61
|
-
numerator_units = [numerator_units] if numerator_units.is_a?(::String)
|
62
|
-
denominator_units = [denominator_units] if denominator_units.is_a?(::String)
|
63
74
|
super(value)
|
64
75
|
@numerator_units = numerator_units
|
65
76
|
@denominator_units = denominator_units
|
@@ -75,11 +86,11 @@ module Sass::Script::Value
|
|
75
86
|
# {Color}
|
76
87
|
# : Adds this number to each of the RGB color channels.
|
77
88
|
#
|
78
|
-
# {
|
79
|
-
# : See {
|
89
|
+
# {Literal}
|
90
|
+
# : See {Literal#plus}.
|
80
91
|
#
|
81
|
-
# @param other [
|
82
|
-
# @return [
|
92
|
+
# @param other [Literal] The right-hand side of the operator
|
93
|
+
# @return [Literal] The result of the operation
|
83
94
|
# @raise [Sass::UnitConversionError] if `other` is a number with incompatible units
|
84
95
|
def plus(other)
|
85
96
|
if other.is_a? Number
|
@@ -97,11 +108,11 @@ module Sass::Script::Value
|
|
97
108
|
# {Number}
|
98
109
|
# : Subtracts this number from the other, converting units if possible.
|
99
110
|
#
|
100
|
-
# {
|
101
|
-
# : See {
|
111
|
+
# {Literal}
|
112
|
+
# : See {Literal#minus}.
|
102
113
|
#
|
103
|
-
# @param other [
|
104
|
-
# @return [
|
114
|
+
# @param other [Literal] The right-hand side of the operator
|
115
|
+
# @return [Literal] The result of the operation
|
105
116
|
# @raise [Sass::UnitConversionError] if `other` is a number with incompatible units
|
106
117
|
def minus(other)
|
107
118
|
if other.is_a? Number
|
@@ -153,16 +164,16 @@ module Sass::Script::Value
|
|
153
164
|
# {Number}
|
154
165
|
# : Divides this number by the other, converting units appropriately.
|
155
166
|
#
|
156
|
-
# {
|
157
|
-
# : See {
|
167
|
+
# {Literal}
|
168
|
+
# : See {Literal#div}.
|
158
169
|
#
|
159
|
-
# @param other [
|
160
|
-
# @return [
|
170
|
+
# @param other [Literal] The right-hand side of the operator
|
171
|
+
# @return [Literal] The result of the operation
|
161
172
|
def div(other)
|
162
173
|
if other.is_a? Number
|
163
174
|
res = operate(other, :/)
|
164
|
-
if original && other.original
|
165
|
-
res.original = "#{original}/#{other.original}"
|
175
|
+
if self.original && other.original
|
176
|
+
res.original = "#{self.original}/#{other.original}"
|
166
177
|
end
|
167
178
|
res
|
168
179
|
else
|
@@ -175,9 +186,12 @@ module Sass::Script::Value
|
|
175
186
|
# @param other [Number] The right-hand side of the operator
|
176
187
|
# @return [Number] This number modulo the other
|
177
188
|
# @raise [NoMethodError] if `other` is an invalid type
|
178
|
-
# @raise [Sass::UnitConversionError] if `other` has
|
189
|
+
# @raise [Sass::UnitConversionError] if `other` has any units
|
179
190
|
def mod(other)
|
180
191
|
if other.is_a?(Number)
|
192
|
+
unless other.unitless?
|
193
|
+
raise Sass::UnitConversionError.new("Cannot modulo by a number with units: #{other.inspect}.")
|
194
|
+
end
|
181
195
|
operate(other, :%)
|
182
196
|
else
|
183
197
|
raise NoMethodError.new(nil, :mod)
|
@@ -186,10 +200,10 @@ module Sass::Script::Value
|
|
186
200
|
|
187
201
|
# The SassScript `==` operation.
|
188
202
|
#
|
189
|
-
# @param other [
|
203
|
+
# @param other [Literal] The right-hand side of the operator
|
190
204
|
# @return [Boolean] Whether this number is equal to the other object
|
191
205
|
def eq(other)
|
192
|
-
return Bool
|
206
|
+
return Sass::Script::Bool.new(false) unless other.is_a?(Sass::Script::Number)
|
193
207
|
this = self
|
194
208
|
begin
|
195
209
|
if unitless?
|
@@ -198,21 +212,10 @@ module Sass::Script::Value
|
|
198
212
|
other = other.coerce(@numerator_units, @denominator_units)
|
199
213
|
end
|
200
214
|
rescue Sass::UnitConversionError
|
201
|
-
return Bool
|
215
|
+
return Sass::Script::Bool.new(false)
|
202
216
|
end
|
203
|
-
Bool.new(this.value == other.value)
|
204
|
-
end
|
205
|
-
|
206
|
-
def hash
|
207
|
-
[value, numerator_units, denominator_units].hash
|
208
|
-
end
|
209
217
|
|
210
|
-
|
211
|
-
# Hash-equality must be transitive, so it just compares the exact value,
|
212
|
-
# numerator units, and denominator units.
|
213
|
-
def eql?(other)
|
214
|
-
value == other.value && numerator_units == other.numerator_units &&
|
215
|
-
denominator_units == other.denominator_units
|
218
|
+
Sass::Script::Bool.new(this.value == other.value)
|
216
219
|
end
|
217
220
|
|
218
221
|
# The SassScript `>` operation.
|
@@ -271,17 +274,8 @@ module Sass::Script::Value
|
|
271
274
|
#
|
272
275
|
# @return [String] The representation
|
273
276
|
def inspect(opts = {})
|
274
|
-
return original if original
|
275
|
-
|
276
277
|
value = self.class.round(self.value)
|
277
|
-
|
278
|
-
|
279
|
-
# Ruby will occasionally print in scientific notation if the number is
|
280
|
-
# small enough. That's technically valid CSS, but it's not well-supported
|
281
|
-
# and confusing.
|
282
|
-
str = ("%0.#{self.class.precision}f" % value).gsub(/0*$/, '') if str.include?('e')
|
283
|
-
|
284
|
-
unitless? ? str : "#{str}#{unit_str}"
|
278
|
+
unitless? ? value.to_s : "#{value}#{unit_str}"
|
285
279
|
end
|
286
280
|
alias_method :to_sass, :inspect
|
287
281
|
|
@@ -289,7 +283,7 @@ module Sass::Script::Value
|
|
289
283
|
# @raise [Sass::SyntaxError] if the number isn't an integer
|
290
284
|
def to_i
|
291
285
|
super unless int?
|
292
|
-
value
|
286
|
+
return value
|
293
287
|
end
|
294
288
|
|
295
289
|
# @return [Boolean] Whether or not this number is an integer.
|
@@ -302,24 +296,6 @@ module Sass::Script::Value
|
|
302
296
|
@numerator_units.empty? && @denominator_units.empty?
|
303
297
|
end
|
304
298
|
|
305
|
-
# Checks whether the number has the numerator unit specified.
|
306
|
-
#
|
307
|
-
# @example
|
308
|
-
# number = Sass::Script::Value::Number.new(10, "px")
|
309
|
-
# number.is_unit?("px") => true
|
310
|
-
# number.is_unit?(nil) => false
|
311
|
-
#
|
312
|
-
# @param unit [::String, nil] The unit the number should have or nil if the number
|
313
|
-
# should be unitless.
|
314
|
-
# @see Number#unitless? The unitless? method may be more readable.
|
315
|
-
def is_unit?(unit)
|
316
|
-
if unit
|
317
|
-
denominator_units.size == 0 && numerator_units.size == 1 && numerator_units.first == unit
|
318
|
-
else
|
319
|
-
unitless?
|
320
|
-
end
|
321
|
-
end
|
322
|
-
|
323
299
|
# @return [Boolean] Whether or not this number has units that can be represented in CSS
|
324
300
|
# (that is, zero or one \{#numerator\_units}).
|
325
301
|
def legal_units?
|
@@ -344,9 +320,9 @@ module Sass::Script::Value
|
|
344
320
|
# current units
|
345
321
|
def coerce(num_units, den_units)
|
346
322
|
Number.new(if unitless?
|
347
|
-
value
|
323
|
+
self.value
|
348
324
|
else
|
349
|
-
value * coercion_factor(@numerator_units, num_units) /
|
325
|
+
self.value * coercion_factor(@numerator_units, num_units) /
|
350
326
|
coercion_factor(@denominator_units, den_units)
|
351
327
|
end, num_units, den_units)
|
352
328
|
end
|
@@ -354,10 +330,12 @@ module Sass::Script::Value
|
|
354
330
|
# @param other [Number] A number to decide if it can be compared with this number.
|
355
331
|
# @return [Boolean] Whether or not this number can be compared with the other.
|
356
332
|
def comparable_to?(other)
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
333
|
+
begin
|
334
|
+
operate(other, :+)
|
335
|
+
true
|
336
|
+
rescue Sass::UnitConversionError
|
337
|
+
false
|
338
|
+
end
|
361
339
|
end
|
362
340
|
|
363
341
|
# Returns a human readable representation of the units in this number.
|
@@ -382,11 +360,11 @@ module Sass::Script::Value
|
|
382
360
|
elsif num % 1 == 0.0
|
383
361
|
num.to_i
|
384
362
|
else
|
385
|
-
((num * precision_factor).round / precision_factor).to_f
|
363
|
+
((num * self.precision_factor).round / self.precision_factor).to_f
|
386
364
|
end
|
387
365
|
end
|
388
366
|
|
389
|
-
OPERATIONS = [:+, :-, :<=, :<, :>,
|
367
|
+
OPERATIONS = [:+, :-, :<=, :<, :>, :>=]
|
390
368
|
|
391
369
|
def operate(other, operation)
|
392
370
|
this = self
|
@@ -398,7 +376,7 @@ module Sass::Script::Value
|
|
398
376
|
end
|
399
377
|
end
|
400
378
|
# avoid integer division
|
401
|
-
value = :/ == operation ? this.value.to_f : this.value
|
379
|
+
value = (:/ == operation) ? this.value.to_f : this.value
|
402
380
|
result = value.send(operation, other.value)
|
403
381
|
|
404
382
|
if result.is_a?(Numeric)
|
@@ -413,33 +391,29 @@ module Sass::Script::Value
|
|
413
391
|
from_units, to_units = sans_common_units(from_units, to_units)
|
414
392
|
|
415
393
|
if from_units.size != to_units.size || !convertable?(from_units | to_units)
|
416
|
-
raise Sass::UnitConversionError.new(
|
417
|
-
"Incompatible units: '#{from_units.join('*')}' and '#{to_units.join('*')}'.")
|
394
|
+
raise Sass::UnitConversionError.new("Incompatible units: '#{from_units.join('*')}' and '#{to_units.join('*')}'.")
|
418
395
|
end
|
419
396
|
|
420
|
-
from_units.zip(to_units).inject(1) {|m,
|
397
|
+
from_units.zip(to_units).inject(1) {|m,p| m * conversion_factor(p[0], p[1]) }
|
421
398
|
end
|
422
399
|
|
423
400
|
def compute_units(this, other, operation)
|
424
401
|
case operation
|
425
402
|
when :*
|
426
|
-
[this.numerator_units + other.numerator_units,
|
427
|
-
this.denominator_units + other.denominator_units]
|
403
|
+
[this.numerator_units + other.numerator_units, this.denominator_units + other.denominator_units]
|
428
404
|
when :/
|
429
|
-
[this.numerator_units + other.denominator_units,
|
430
|
-
|
431
|
-
else
|
405
|
+
[this.numerator_units + other.denominator_units, this.denominator_units + other.numerator_units]
|
406
|
+
else
|
432
407
|
[this.numerator_units, this.denominator_units]
|
433
408
|
end
|
434
409
|
end
|
435
410
|
|
436
411
|
def normalize!
|
437
412
|
return if unitless?
|
438
|
-
@numerator_units, @denominator_units =
|
439
|
-
sans_common_units(@numerator_units, @denominator_units)
|
413
|
+
@numerator_units, @denominator_units = sans_common_units(@numerator_units, @denominator_units)
|
440
414
|
|
441
415
|
@denominator_units.each_with_index do |d, i|
|
442
|
-
if convertable?(d) && (u = @numerator_units.
|
416
|
+
if convertable?(d) && (u = @numerator_units.detect(&method(:convertable?)))
|
443
417
|
@value /= conversion_factor(d, u)
|
444
418
|
@denominator_units.delete_at(i)
|
445
419
|
@numerator_units.delete_at(@numerator_units.index(u))
|
@@ -447,84 +421,33 @@ module Sass::Script::Value
|
|
447
421
|
end
|
448
422
|
end
|
449
423
|
|
450
|
-
#
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
'cm' => Rational(1, 2.54),
|
459
|
-
'pc' => Rational(1, 6),
|
460
|
-
'mm' => Rational(1, 25.4),
|
461
|
-
'pt' => Rational(1, 72),
|
462
|
-
'px' => Rational(1, 96)
|
463
|
-
},
|
464
|
-
{
|
465
|
-
'deg' => Rational(1, 360),
|
466
|
-
'grad' => Rational(1, 400),
|
467
|
-
'rad' => Rational(1, 2 * Math::PI),
|
468
|
-
'turn' => Rational(1)
|
469
|
-
},
|
470
|
-
{
|
471
|
-
's' => Rational(1),
|
472
|
-
'ms' => Rational(1, 1000)
|
473
|
-
},
|
474
|
-
{
|
475
|
-
'Hz' => Rational(1),
|
476
|
-
'kHz' => Rational(1000)
|
477
|
-
},
|
478
|
-
{
|
479
|
-
'dpi' => Rational(1),
|
480
|
-
'dpcm' => Rational(1, 2.54),
|
481
|
-
'dppx' => Rational(1, 96)
|
482
|
-
}
|
483
|
-
]
|
484
|
-
|
485
|
-
# A hash from each known unit to the set of units that it's mutually
|
486
|
-
# convertible with.
|
487
|
-
MUTUALLY_CONVERTIBLE = {}
|
488
|
-
relative_sizes.map do |values|
|
489
|
-
set = values.keys.to_set
|
490
|
-
values.keys.each {|name| MUTUALLY_CONVERTIBLE[name] = set}
|
491
|
-
end
|
492
|
-
|
493
|
-
# A two-dimensional hash from two units to the conversion ratio between
|
494
|
-
# them. Multiply `X` by `CONVERSION_TABLE[X][Y]` to convert it to `Y`.
|
495
|
-
CONVERSION_TABLE = {}
|
496
|
-
relative_sizes.each do |values|
|
497
|
-
values.each do |(name1, value1)|
|
498
|
-
CONVERSION_TABLE[name1] ||= {}
|
499
|
-
values.each do |(name2, value2)|
|
500
|
-
value = value1 / value2
|
501
|
-
CONVERSION_TABLE[name1][name2] = value.denominator == 1 ? value.to_i : value.to_f
|
502
|
-
end
|
503
|
-
end
|
504
|
-
end
|
424
|
+
# A hash of unit names to their index in the conversion table
|
425
|
+
CONVERTABLE_UNITS = {"in" => 0, "cm" => 1, "pc" => 2, "mm" => 3, "pt" => 4, "px" => 5 }
|
426
|
+
CONVERSION_TABLE = [[ 1, 2.54, 6, 25.4, 72 , 96 ], # in
|
427
|
+
[ nil, 1, 2.36220473, 10, 28.3464567, 37.795275591], # cm
|
428
|
+
[ nil, nil, 1, 4.23333333, 12 , 16 ], # pc
|
429
|
+
[ nil, nil, nil, 1, 2.83464567, 3.7795275591], # mm
|
430
|
+
[ nil, nil, nil, nil, 1 , 1.3333333333], # pt
|
431
|
+
[ nil, nil, nil, nil, nil , 1 ]] # px
|
505
432
|
|
506
433
|
def conversion_factor(from_unit, to_unit)
|
507
|
-
CONVERSION_TABLE[from_unit][to_unit]
|
434
|
+
res = CONVERSION_TABLE[CONVERTABLE_UNITS[from_unit]][CONVERTABLE_UNITS[to_unit]]
|
435
|
+
return 1.0 / conversion_factor(to_unit, from_unit) if res.nil?
|
436
|
+
res
|
508
437
|
end
|
509
438
|
|
510
439
|
def convertable?(units)
|
511
|
-
units
|
512
|
-
return true if units.empty?
|
513
|
-
return false unless (mutually_convertible = MUTUALLY_CONVERTIBLE[units.first])
|
514
|
-
units.subset?(mutually_convertible)
|
440
|
+
Array(units).all? {|u| CONVERTABLE_UNITS.include?(u)}
|
515
441
|
end
|
516
442
|
|
517
443
|
def sans_common_units(units1, units2)
|
518
444
|
units2 = units2.dup
|
519
445
|
# Can't just use -, because we want px*px to coerce properly to px*mm
|
520
|
-
|
521
|
-
j = units2.index(u)
|
522
|
-
next u unless j
|
446
|
+
return units1.map do |u|
|
447
|
+
next u unless j = units2.index(u)
|
523
448
|
units2.delete_at(j)
|
524
449
|
nil
|
525
|
-
end
|
526
|
-
units1.compact!
|
527
|
-
return units1, units2
|
450
|
+
end.compact, units2
|
528
451
|
end
|
529
452
|
end
|
530
453
|
end
|