Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ gem "byebug"
gem "equivalent-xml"
gem "oga"
gem "ox"
gem "plurimath"
gem "plurimath", github: "plurimath/plurimath", branch: "update/mathml_symbol_transformation"
gem "pry"
gem "rake"
gem "rspec"
Expand Down
25 changes: 19 additions & 6 deletions lib/unitsml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,34 @@ def parse(string)
def register
@register ||= Lutaml::Model::GlobalRegister.lookup(REGISTER_ID)
end

def register_model(klass, id:)
register.register_model(klass, id: id)
end

def get_class_from_register(class_name)
register.get_class(class_name)
end

def register_type_substitution(from:, to:)
register.register_global_type_substitution(
from_type: from,
to_type: to,
)
end
end

Lutaml::Model::GlobalRegister.register(
Lutaml::Model::Register.new(Unitsml::REGISTER_ID)
Lutaml::Model::Register.new(Unitsml::REGISTER_ID),
)

require "unitsdb"
require "unitsml/error"
require "unitsml/sqrt"
require "unitsml/unit"
require "unitsml/parse"
require "unitsml/fenced_numeric"
require "unitsml/number"
require "unitsml/parser"
require "unitsml/prefix"
require "unitsml/fenced"
Expand All @@ -51,11 +68,7 @@ def register
::Unitsdb::PrefixReference => Unitsml::Unitsdb::PrefixReference,
::Unitsdb::DimensionDetails => Unitsml::Unitsdb::DimensionQuantity,
}.each do |key, value|
Unitsml.register
.register_global_type_substitution(
from_type: key,
to_type: value,
)
Unitsml.register_type_substitution(from: key, to: value)
end

Lutaml::Model::Config.xml_adapter_type = RUBY_ENGINE == "opal" ? :oga : :ox
68 changes: 41 additions & 27 deletions lib/unitsml/dimension.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,56 +16,52 @@ def ==(object)
end

def dim_instance
@dim ||= Unitsdb.dimensions.find_parsables_by_id(dimension_name)
@dim_instance ||= Unitsdb.dimensions.find_parsables_by_id(dimension_name)
end

def dim_symbols
dim_instance.send(@dim.processed_keys.last).symbols.first
dim_instance.send(dim_instance.processed_keys.last).symbols.first
end

def to_mathml(_)
# MathML key's value in unitsdb/dimensions.yaml file includes mi tags only.
def to_mathml(options)
# MathML key's value in unitsdb/dimensions.yaml
# file includes mi tags only.
value = ::Mml::Mi.from_xml(dim_symbols.mathml)
method_name = power_numerator ? :msup : :mi
if power_numerator
value = ::Mml::Msup.new(
mrow_value: [
::Mml::Mrow.new(mi_value: [value]),
::Mml::Mrow.new(
mn_value: [::Mml::Mn.new(value: power_numerator)],
),
]
)
end
method_name = if power_numerator
value = msup_tag(value, options)
:msup
else
:mi
end
{ method_name: method_name, value: value }
end

def to_latex(_)
power_numerator_generic_code(:latex)
def to_latex(options)
power_numerator_generic_code(:latex, options)
end

def to_asciimath(_)
power_numerator_generic_code(:ascii)
def to_asciimath(options)
power_numerator_generic_code(:ascii, options)
end

def to_unicode(_)
power_numerator_generic_code(:unicode)
def to_unicode(options)
power_numerator_generic_code(:unicode, options)
end

def to_html(_)
def to_html(options)
value = dim_symbols.html
value = "#{value}<sup>#{power_numerator}</sup>" if power_numerator
value = "#{value}#{html_numerator_conversion(options)}" if power_numerator
value
end

def generate_id
"#{dimension_name.split('_').last}#{power_numerator}"
"#{dimension_name.split('_').last}#{power_numerator&.raw_value}"
end

def to_xml(_)
attributes = {
symbol: dim_instance.processed_symbol,
power_numerator: power_numerator || 1,
power_numerator: power_numerator&.raw_value || 1,
}
Model::DimensionQuantities.const_get(modelize(element_name)).new(attributes)
end
Expand All @@ -80,15 +76,33 @@ def modelize(value)

private

def power_numerator_generic_code(method_name)
def html_numerator_conversion(options)
"<sup>#{power_numerator.to_html(options)}</sup>"
end

def power_numerator_generic_code(method_name, options)
value = dim_symbols.public_send(method_name)
return value unless power_numerator

"#{value}^#{power_numerator}"
method_name = :asciimath if method_name == :ascii
"#{value}^#{power_numerator&.public_send(:"to_#{method_name}", options)}"
end

def element_name
dim_instance.processed_keys.first
end

def msup_tag(value, options)
mathml = power_numerator.to_mathml(options)
msup = ::Mml::Msup.new(
mrow_value: [::Mml::Mrow.new(mi_value: [value])],
)
[mathml].flatten.each do |record|
record_values = msup.public_send("#{record[:method_name]}_value") || []
record_values += [record[:value]]
msup.public_send("#{record[:method_name]}_value=", record_values)
end
msup
end
end
end
19 changes: 12 additions & 7 deletions lib/unitsml/extender.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ def to_html(options)
end

def to_unicode(options)
extender = options[:multiplier] ||
symbol == "*" ? "·" : symbol
extender = options[:multiplier] || unicode_extender
multiplier(extender)
end

Expand All @@ -45,16 +44,22 @@ def to_unicode(options)
def multiplier(extender, unicode: false, html: false)
case extender
when :space
if html
"&#xa0;"
else
unicode ? "&#x2062;" : " "
end
space_extender(html, unicode)
when :nospace
unicode ? "&#x2062;" : ""
else
unicode ? Utility.string_to_html_entity(extender) : extender
end
end

def space_extender(html, unicode)
return "&#xa0;" if html

unicode ? "&#x2062;" : " "
end

def unicode_extender
symbol == "*" ? "·" : symbol
end
end
end
18 changes: 18 additions & 0 deletions lib/unitsml/fenced.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module Unitsml
class Fenced
include FencedNumeric

attr_reader :open_paren, :value, :close_paren

def initialize(open_paren, value, close_paren)
Expand Down Expand Up @@ -36,6 +38,22 @@ def to_mathml(options = {})
{ method_name: :mrow, value: fenced }
end

def negative?
value.negative?
end

def update_negative_sign
value.update_negative_sign
end

def float_to_display
value.float_to_display
end

def raw_value
value.raw_value
end

def to_html(options = {})
fenced_conversion_for(lang: :html, options: options)
end
Expand Down
11 changes: 11 additions & 0 deletions lib/unitsml/fenced_numeric.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Unitsml
module FencedNumeric
def to_i
value.to_i
end

def to_f
value.to_f
end
end
end
4 changes: 2 additions & 2 deletions lib/unitsml/formula.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def extract_dimensions(formula)
elsif term.is_a?(Sqrt)
if term.value.is_a?(Dimension)
sqrt_term = term.value.dup
sqrt_term.power_numerator = "0.5"
sqrt_term.power_numerator = Number.new("0.5")
dimensions << sqrt_term
elsif term.value.is_a?(Fenced)
dimensions.concat(Array(term.value.dimensions_extraction))
Expand Down Expand Up @@ -149,7 +149,7 @@ def dimensions(dims, options)
end

def sort_dims(values)
dims_hash = Utility::Dim2D
dims_hash = Utility::DIM2D
values.sort do |first, second|
dims_hash.dig(first.dimension_name, :order) <=> dims_hash.dig(second.dimension_name, :order)
end
Expand Down
6 changes: 5 additions & 1 deletion lib/unitsml/intermediate_exp_rules.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ module IntermediateExpRules
include Parslet

# Rules for slashed number
rule(:slashed_number_int_exp) { slashed_number | (opening_paren >> slashed_number >> closing_paren) }
rule(:slashed_number_int_exp) { slashed_number | (opening_paren >> slashed_number_named_int_exp.as(:int_exp) >> closing_paren) }
rule(:slashed_number_named_int_exp) do
(opening_paren.as(:open_paren) >> slashed_number_int_exp >> closing_paren.as(:close_paren)) |
slashed_number_int_exp
end

# Rules for prefixes_units
rule(:wrapper_prefixes_units_value) { int_exp_prefixes_units | prefixes_units_int_exp }
Expand Down
79 changes: 79 additions & 0 deletions lib/unitsml/number.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# frozen_string_literal: true

module Unitsml
class Number
include FencedNumeric

attr_accessor :value
alias raw_value value

def initialize(value)
@value = value
end

def ==(object)
self.class == object.class &&
value == object&.value
end

def to_mathml(_options)
matched_value = value&.match(/-?(.+)/)
mn_value = matched_value ? matched_value[1] : value
mn_tag = ::Mml::Mn.new(value: mn_value)
value.start_with?("-") ? mrow_hash(mn_tag) : mn_hash(mn_tag)
end

def to_html(_options)
value.sub("-", "&#x2212;")
end

def to_latex(_options)
value
end

def to_asciimath(_options)
value
end

def to_unicode(_options)
value
end

def negative?
value.start_with?("-")
end

def update_negative_sign
if negative?
self.value = value.delete_prefix("-")
else
self.value = ["-", value].join
end
end

def float_to_display
return "" if value.nil?

value.to_f.round(1).to_s.sub(/\.0$/, "")
end

private

def mrow_hash(mn_tag)
{
method_name: :mrow,
value: ::Mml::Mrow.new(
mo_value: [::Mml::Mo.new(value: "&#x2212;")],
mn_value: [mn_tag],
),
}
end

def mn_hash(mn_tag)
{
method_name: :mn,
value: mn_tag,
}
end
end
end
2 changes: 1 addition & 1 deletion lib/unitsml/parse.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class Parse < Parslet::Parser
include IntermediateExpRules

rule(:sqrt) { str("sqrt") }
rule(:power) { str("^") >> slashed_number_int_exp }
rule(:power) { str("^") >> slashed_number_int_exp.as(:power_numerator) }
rule(:hyphen) { str("-") }
rule(:number) { hyphen.maybe >> match(/[0-9]/).repeat(1) }
rule(:spaces) { match(/\s/).repeat(1) }
Expand Down
9 changes: 4 additions & 5 deletions lib/unitsml/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,19 @@ def update_units_exponents(array, inverse, sqrt = false)
if object.is_a?(Sqrt)
object = object.value
if object.respond_to?(:power_numerator)
object.power_numerator = "0.5"
object.power_numerator = Number.new("0.5")
else
update_units_exponents([object], inverse, true)
end
end

case object
when Unit
next object.power_numerator = "0.5" if sqrt
next object.power_numerator = Number.new("0.5") if sqrt
next unless inverse

exponent = inverse ? "-#{object&.power_numerator || '1'}" : object.power_numerator
object.power_numerator = exponent&.sub(/^--+/, "")
when Dimension then object.power_numerator = "0.5" if sqrt
inverse ? object.inverse_power_numerator : object.power_numerator
when Dimension then object.power_numerator = Number.new("0.5") if sqrt
when Extender then inverse = !inverse if ["/", "//"].any?(object.symbol)
when Formula then update_units_exponents(object.value, inverse)
when Fenced then update_units_exponents([object.value], inverse, sqrt)
Expand Down
Loading
Loading