class Sass::Script::Number
These cannot be inputted directly in Sass code at the moment.
Numbers can also have more complex units, such as ‘1px*em/in`.
are all valid values.
For example, `12`, `1px`, and `10.45em`
and can also have units.
SassScript numbers can have decimal values,
A SassScript object representing a number.
def self.round(num)
- Private: -
def self.round(num) if num.is_a?(Float) && (num.infinite? || num.nan?) num elsif num % 1 == 0.0 num.to_i else (num * PRECISION).round / PRECISION end end
def coerce(num_units, den_units)
-
(Sass::UnitConversionError)
- if the given units are incompatible with the number's
Returns:
-
(Number)
- The number with the new units
Parameters:
-
den_units
(Array
) -- The denominator units to coerce this number into. -
num_units
(Array
) -- The numerator units to coerce this number into.
def coerce(num_units, den_units) Number.new(if unitless? self.value else self.value * coercion_factor(self.numerator_units, num_units) / coercion_factor(self.denominator_units, den_units) end, num_units, den_units) end
def coercion_factor(from_units, to_units)
def coercion_factor(from_units, to_units) # get a list of unmatched units from_units, to_units = sans_common_units(from_units, to_units) if from_units.size != to_units.size || !convertable?(from_units | to_units) raise Sass::UnitConversionError.new("Incompatible units: '#{from_units.join('*')}' and '#{to_units.join('*')}'.") end from_units.zip(to_units).inject(1) {|m,p| m * conversion_factor(p[0], p[1]) } end
def comparable_to?(other)
-
(Boolean)
- Whether or not this number can be compared with the other.
Parameters:
-
other
(Number
) -- A number to decide if it can be compared with this number.
def comparable_to?(other) begin operate(other, :+) true rescue Sass::UnitConversionError false end end
def compute_units(this, other, operation)
def compute_units(this, other, operation) case operation when :* [this.numerator_units + other.numerator_units, this.denominator_units + other.denominator_units] when :/ [this.numerator_units + other.denominator_units, this.denominator_units + other.numerator_units] else [this.numerator_units, this.denominator_units] end end
def conversion_factor(from_unit, to_unit)
def conversion_factor(from_unit, to_unit) res = CONVERSION_TABLE[CONVERTABLE_UNITS[from_unit]][CONVERTABLE_UNITS[to_unit]] return 1.0 / conversion_factor(to_unit, from_unit) if res.nil? res end
def convertable?(units)
def convertable?(units) Array(units).all?(&CONVERTABLE_UNITS.method(:include?)) end
def div(other)
-
(Literal)
- The result of the operation
Parameters:
-
other
(Literal
) -- The right-hand side of the operator
def div(other) if other.is_a? Number res = operate(other, :/) if self.original && other.original && context != :equals res.original = "#{self.original}/#{other.original}" end res else super end end
def eq(other)
-
(Boolean)
- Whether this number is equal to the other object
Parameters:
-
other
(Literal
) -- The right-hand side of the operator
def eq(other) return Sass::Script::Bool.new(false) unless other.is_a?(Sass::Script::Number) this = self begin if unitless? this = this.coerce(other.numerator_units, other.denominator_units) else other = other.coerce(numerator_units, denominator_units) end rescue Sass::UnitConversionError return Sass::Script::Bool.new(false) end Sass::Script::Bool.new(this.value == other.value) end
def gt(other)
-
(NoMethodError)
- if `other` is an invalid type
Returns:
-
(Boolean)
- Whether this number is greater than the other
Parameters:
-
other
(Number
) -- The right-hand side of the operator
def gt(other) raise NoMethodError.new(nil, :gt) unless other.is_a?(Number) operate(other, :>) end
def gte(other)
-
(NoMethodError)
- if `other` is an invalid type
Returns:
-
(Boolean)
- Whether this number is greater than or equal to the other
Parameters:
-
other
(Number
) -- The right-hand side of the operator
def gte(other) raise NoMethodError.new(nil, :gte) unless other.is_a?(Number) operate(other, :>=) end
def initialize(value, numerator_units = [], denominator_units = [])
-
denominator_units
(Array
) -- See \{#denominator\_units} -
numerator_units
(Array
) -- See \{#numerator\_units} -
value
(Numeric
) -- The value of the number
def initialize(value, numerator_units = [], denominator_units = []) super(value) @numerator_units = numerator_units @denominator_units = denominator_units normalize! end
def inspect(opts = {})
-
(String)
- The representation
def inspect(opts = {}) "#{self.class.round(self.value)}#{unit_str}" end
def int?
-
(Boolean)
- Whether or not this number is an integer.
def int? value % 1 == 0.0 end
def legal_units?
-
(Boolean)
- Whether or not this number has units that can be represented in CSS
def legal_units? (numerator_units.empty? || numerator_units.size == 1) && denominator_units.empty? end
def lt(other)
-
(NoMethodError)
- if `other` is an invalid type
Returns:
-
(Boolean)
- Whether this number is less than the other
Parameters:
-
other
(Number
) -- The right-hand side of the operator
def lt(other) raise NoMethodError.new(nil, :lt) unless other.is_a?(Number) operate(other, :<) end
def lte(other)
-
(NoMethodError)
- if `other` is an invalid type
Returns:
-
(Boolean)
- Whether this number is less than or equal to the other
Parameters:
-
other
(Number
) -- The right-hand side of the operator
def lte(other) raise NoMethodError.new(nil, :lte) unless other.is_a?(Number) operate(other, :<=) end
def minus(other)
-
(Sass::UnitConversionError)
- if `other` is a number with incompatible units
Returns:
-
(Literal)
- The result of the operation
Parameters:
-
other
(Literal
) -- The right-hand side of the operator
def minus(other) if other.is_a? Number operate(other, :-) else super end end
def mod(other)
-
(Sass::UnitConversionError)
- if `other` has any units -
(NoMethodError)
- if `other` is an invalid type
Returns:
-
(Number)
- This number modulo the other
Parameters:
-
other
(Number
) -- The right-hand side of the operator
def mod(other) if other.is_a?(Number) unless other.unitless? raise Sass::UnitConversionError.new("Cannot modulo by a number with units: #{other.inspect}.") end operate(other, :%) else raise NoMethodError.new(nil, :mod) end end
def normalize!
def normalize! return if unitless? @numerator_units, @denominator_units = sans_common_units(numerator_units, denominator_units) @denominator_units.each_with_index do |d, i| if convertable?(d) && (u = @numerator_units.detect(&method(:convertable?))) @value /= conversion_factor(d, u) @denominator_units.delete_at(i) @numerator_units.delete_at(@numerator_units.index(u)) end end end
def operate(other, operation)
def operate(other, operation) this = self if [:+, :-, :<=, :<, :>, :>=].include?(operation) if unitless? this = this.coerce(other.numerator_units, other.denominator_units) else other = other.coerce(numerator_units, denominator_units) end end # avoid integer division value = (:/ == operation) ? this.value.to_f : this.value result = value.send(operation, other.value) if result.is_a?(Numeric) Number.new(result, *compute_units(this, other, operation)) else # Boolean op Bool.new(result) end end
def plus(other)
-
(Sass::UnitConversionError)
- if `other` is a number with incompatible units
Returns:
-
(Literal)
- The result of the operation
Parameters:
-
other
(Literal
) -- The right-hand side of the operator
def plus(other) if other.is_a? Number operate(other, :+) elsif other.is_a?(Color) other.plus(self) else super end end
def sans_common_units(units1, units2)
def sans_common_units(units1, units2) units2 = units2.dup # Can't just use -, because we want px*px to coerce properly to px*mm return units1.map do |u| next u unless j = units2.index(u) units2.delete_at(j) nil end.compact, units2 end
def times(other)
-
(NoMethodError)
- if `other` is an invalid type
Returns:
-
(Number, Color)
- The result of the operation
Parameters:
-
other
(Number, Color
) -- The right-hand side of the operator
def times(other) if other.is_a? Number operate(other, :*) elsif other.is_a? Color other.times(self) else raise NoMethodError.new(nil, :times) end end
def to_i
-
(Sass::SyntaxError)
- if the number isn't an integer
Returns:
-
(Fixnum)
- The integer value of the number
def to_i super unless int? return value end
def to_s
-
(Sass::SyntaxError)
- if this number has units that can't be used in CSS
Returns:
-
(String)
- The CSS representation of this number
def to_s return original if original raise Sass::SyntaxError.new("#{inspect} isn't a valid CSS value.") unless legal_units? inspect end
def unary_minus
-
(Number)
- The negative value of this number
def unary_minus Number.new(-value, numerator_units, denominator_units) end
def unary_plus
-
(Number)
- The value of this number
def unary_plus self end
def unit_str
-
(String)
- a string that represents the units in this number
def unit_str rv = numerator_units.sort.join("*") if denominator_units.any? rv << "/" rv << denominator_units.sort.join("*") end rv end
def unitless?
-
(Boolean)
- Whether or not this number has no units.
def unitless? numerator_units.empty? && denominator_units.empty? end