class Sass::Value::Number
def coerce_or_convert_value(new_numerator_units, new_denominator_units,
def coerce_or_convert_value(new_numerator_units, new_denominator_units, coerce_unitless:, name: nil, other: nil, other_name: nil) if other && (other.numerator_units != new_denominator_units && other.denominator_units != new_denominator_units) raise Sass::ScriptError, "Expect #{other} to have units #{unit_string(new_numerator_units, new_denominator_units).inspect}" end return value if numerator_units == new_numerator_units && denominator_units == new_denominator_units return value if numerator_units == new_numerator_units && denominator_units == new_denominator_units other_unitless = new_numerator_units.empty? && new_denominator_units.empty? return value if coerce_unitless && (unitless? || other_unitless) compatibility_error = lambda { unless other.nil? message = "#{self} and" message << " $#{other_name}:" unless other_name.nil? message << " #{other} have incompatible units" message << " (one has units and the other doesn't)" if unitless? || other_unitless return Sass::ScriptError.new(message, name) end return Sass::ScriptError.new("Expected #{self} to have no units", name) unless other_unitless if new_numerator_units.length == 1 && new_denominator_units.empty? type = Unit::TYPES_BY_UNIT[new_numerator_units.first] return Sass::ScriptError.new( "Expected #{self} to have a #{type} unit (#{Unit::UNITS_BY_TYPE[type].join(', ')})", name ) end unit_length = new_numerator_units.length + new_denominator_units.length units = unit_string(new_numerator_units, new_denominator_units) Sass::ScriptError.new("Expected #{self} to have unit#{unit_length > 1 ? 's' : ''} #{units}", name) } result = value old_numerator_units = numerator_units.dup new_numerator_units.each do |new_numerator_unit| index = old_numerator_units.find_index do |old_numerator_unit| factor = Unit.conversion_factor(new_numerator_unit, old_numerator_unit) if factor.nil? false else result *= factor true end end raise compatibility_error.call if index.nil? old_numerator_units.delete_at(index) end old_denominator_units = denominator_units.dup new_denominator_units.each do |new_denominator_unit| index = old_denominator_units.find_index do |old_denominator_unit| factor = Unit.conversion_factor(new_denominator_unit, old_denominator_unit) if factor.nil? false else result /= factor true end end raise compatibility_error.call if index.nil? old_denominator_units.delete_at(index) end raise compatibility_error.call unless old_numerator_units.empty? && old_denominator_units.empty? result end