asciimath2unitsml 0.3.2 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,94 +1,101 @@
1
1
  module Asciimath2UnitsML
2
2
  class Conv
3
3
  include Rsec::Helpers
4
-
5
- def read_yaml(path)
6
- validate_yaml(symbolize_keys(YAML
7
- .load_file(File.join(File.join(File.dirname(__FILE__), path)))), path)
8
- end
9
-
10
- def flip_name_and_symbol(hash)
11
- hash.each_with_object({}) do |(_k, v), m|
12
- next if v.name.nil? || v.name.empty?
13
-
14
- m[v.symbolid] = v
15
- end
16
- end
17
-
18
- def flip_name_and_symbols(hash)
19
- hash.each_with_object({}) do |(_k, v), m|
20
- next if v.name.nil? || v.name.empty?
21
-
22
- v.symbolids.each { |s| m[s] = v }
23
- end
4
+ def parsers
5
+ exponent = /\^\(-?\d+\)/.r.map { |m| m.sub(/\^/, "").gsub(/[()]/, "") } |
6
+ /\^-?\d+/.r.map { |m| m.sub(/\^/, "") }
7
+ multiplier = %r{\*|//|/}.r.map { |x| { multiplier: x[0] } }
8
+ units = units_parse(exponent, multiplier)
9
+ dimensions = dimensions_parser(exponent, multiplier)
10
+ [units.eof, dimensions.eof]
24
11
  end
25
12
 
26
- def symbolize_keys(hash)
27
- return hash if hash.is_a? String
28
-
29
- hash.inject({}) do |result, (key, value)|
30
- new_key = case key
31
- when String then key.to_sym
32
- else key
33
- end
34
- new_value = case value
35
- when Hash then symbolize_keys(value)
36
- when Array then value.map { |m| symbolize_keys(m) }
37
- else value
38
- end
39
- result[new_key] = new_value
40
- result
41
- end
13
+ def dimensions_parser(exponent, multiplier)
14
+ dim1 = /#{@dimensions.keys.sort_by(&:length).reverse.join("|")}/.r
15
+ dimension =
16
+ seq("sqrt(", dim1, ")") { |x| { dim: x[1], display_exponent: "0.5" } } |
17
+ seq(dim1, exponent._? & (multiplier | ")".r)) { |x| { dim: x[0], display_exponent: (x[1][0]) } } |
18
+ seq(dim1, exponent._?).eof { |x| { dim: x[0], display_exponent: (x[1][0]) } }
19
+ dimensions1 = "(".r >> lazy { dimensions } << ")" | dimension
20
+ dimensions = dimensions1.join(multiplier) # rubocop:disable Style/RedundantAssignment
21
+ dimensions
42
22
  end
43
23
 
44
- def parser
24
+ def units_parse(exponent, multiplier)
45
25
  prefix2 = /#{@prefixes.keys.select { |x| x.size == 2 }.join("|")}/.r
46
26
  prefix1 = /#{@prefixes.keys.select { |x| x.size == 1 }.join("|")}/.r
47
27
  unit_keys = @units.keys.reject do |k|
48
28
  /\*|\^|\/|^1$/.match(k) || @units[k].prefixed
49
29
  end.map { |k| Regexp.escape(k) }
50
30
  unit1 = /#{unit_keys.sort_by(&:length).reverse.join("|")}/.r
51
- exponent = /\^\(-?\d+\)/.r.map { |m| m.sub(/\^/, "").gsub(/[()]/, "") } |
52
- /\^-?\d+/.r.map { |m| m.sub(/\^/, "") }
53
- multiplier = %r{\*|//|/}.r.map { |x| { multiplier: x[0] } }
54
- unit =
31
+
32
+ unit =
55
33
  seq("sqrt(", unit1, ")") { |x| { prefix: nil, unit: x[1], display_exponent: "0.5" } } |
56
34
  seq("sqrt(", prefix1, unit1, ")") { |x| { prefix: x[1], unit: x[2], display_exponent: "0.5" } } |
57
35
  seq("sqrt(", prefix2, unit1, ")") { |x| { prefix: x[1], unit: x[2], display_exponent: "0.5" } } |
58
36
  seq(unit1, exponent._? & (multiplier | ")".r)) { |x| { prefix: nil, unit: x[0], display_exponent: (x[1][0]) } } |
59
37
  seq(unit1, exponent._?).eof { |x| { prefix: nil, unit: x[0], display_exponent: (x[1][0]) } } |
60
- seq(prefix1, unit1, exponent._? ) { |x| { prefix: x[0], unit: x[1], display_exponent: (x[2][0]) } } |
61
- seq(prefix2, unit1, exponent._? ) { |x| { prefix: x[0], unit: x[1], display_exponent: (x[2][0]) } } |
38
+ seq(prefix1, unit1, exponent._?) { |x| { prefix: x[0], unit: x[1], display_exponent: (x[2][0]) } } |
39
+ seq(prefix2, unit1, exponent._?) { |x| { prefix: x[0], unit: x[1], display_exponent: (x[2][0]) } } |
62
40
  "1".r.map { |_| { prefix: nil, unit: "1", display_exponent: nil } }
63
- units1 = "(".r >> lazy{units} << ")" | unit
64
- units = seq(prefix2, "-") { |x| [{ prefix: x[0], unit: nil, display_exponent: nil }] } |
41
+ units1 = "(".r >> lazy { units } << ")" | unit
42
+ units = seq(prefix2, "-") { |x| [{ prefix: x[0], unit: nil, display_exponent: nil }] } | # rubocop:disable Style/RedundantAssignment
65
43
  seq(prefix1, "-") { |x| [{ prefix: x[0], unit: nil, display_exponent: nil }] } |
66
44
  units1.join(multiplier)
67
- parser = units.eof
45
+ units
68
46
  end
69
47
 
70
- def parse(x)
71
- text = Array(x.split(/,\s*/))
48
+ def parse(expr)
49
+ text = Array(expr.split(/,\s*/))
50
+ if /dim_/.match?(text[0]) then parse_dimensions(text)
51
+ else parse_units(text)
52
+ end
53
+ end
54
+
55
+ def parse_units(text)
72
56
  units = @parser.parse!(text[0])
73
57
  if !units || Rsec::INVALID[units]
74
58
  raise Rsec::SyntaxError.new "error parsing UnitsML expression", x, 1, 0
75
59
  end
76
60
 
77
61
  Rsec::Fail.reset
78
- postprocess(units, text)
62
+ postprocess(units, text, true)
63
+ end
64
+
65
+ def parse_dimensions(text)
66
+ units = @dim_parser.parse!(text[0])
67
+ if !units || Rsec::INVALID[units]
68
+ raise Rsec::SyntaxError.new "error parsing UnitsML expression", x, 1, 0
69
+ end
70
+
71
+ Rsec::Fail.reset
72
+ postprocess(units, text, false)
79
73
  end
80
74
 
81
- def postprocess(units, text)
75
+ def postprocess(units, text, is_units)
82
76
  units = postprocess1(units.flatten)
83
- quantity = text[1..-1]&.select { |x| /^quantity:/.match(x) }&.first&.sub(/^quantity:\s*/, "")
84
- name = text[1..-1]&.select { |x| /^name:/.match(x) }&.first&.sub(/^name:\s*/, "")
85
- symbol = text[1..-1]&.select { |x| /^symbol:/.match(x) }&.first&.sub(/^symbol:\s*/, "")
86
- multiplier = text[1..-1]&.select { |x| /^multiplier:/.match(x) }&.first&.sub(/^multiplier:\s*/, "")
87
- normtext = units_only(units).each.map do |u|
88
- exp = u[:exponent] && u[:exponent] != "1" ? "^#{u[:exponent]}" : ""
89
- "#{u[:prefix]}#{u[:unit]}#{exp}"
77
+ normtext = postprocess_normtext(units, is_units)
78
+ [units, text[0], normtext, postprocess_extr(text, "quantity"),
79
+ postprocess_extr(text, "name"), postprocess_extr(text, "symbol"),
80
+ postprocess_extr(text, "multiplier")]
81
+ end
82
+
83
+ def postprocess_normtext(units, is_units)
84
+ units_only(units).each.map do |u|
85
+ if is_units then "#{u[:prefix]}#{u[:unit]}#{display_exp(u)}"
86
+ else "#{u[:dim]}#{display_exp(u)}"
87
+ end
90
88
  end.join("*")
91
- [units, text[0], normtext, quantity, name, symbol, multiplier]
89
+ end
90
+
91
+ def postprocess_extr(text, name)
92
+ text[1..-1]&.select do |x|
93
+ /^#{name}:/.match(x)
94
+ end&.first&.sub(/^#{name}:\s*/, "")
95
+ end
96
+
97
+ def display_exp(unit)
98
+ unit[:exponent] && unit[:exponent] != "1" ? "^#{unit[:exponent]}" : ""
92
99
  end
93
100
 
94
101
  def postprocess1(units)
@@ -110,16 +117,21 @@ module Asciimath2UnitsML
110
117
  MathML2UnitsML(xml).to_xml
111
118
  end
112
119
 
113
- # https://www.w3.org/TR/mathml-units/ section 2: delimit number Invisible-Times unit
120
+ # https://www.w3.org/TR/mathml-units/ section 2:
121
+ # delimit number Invisible-Times unit
114
122
  def MathML2UnitsML(xml)
115
123
  xml.is_a? String and xml = Nokogiri::XML(xml)
116
124
  xml.xpath(".//m:mtext", "m" => MATHML_NS).each do |x|
117
- next unless %r{^unitsml\(.+\)$}.match(x.text)
125
+ next unless %r{^unitsml\(.+\)$}.match?(x.text)
118
126
 
119
127
  text = x.text.sub(%r{^unitsml\((.+)\)$}m, "\\1")
120
- units, origtext, normtext, quantity, name, symbol, multiplier = parse(text)
121
- rendering = symbol ? embeddedmathml(asciimath2mathml(symbol)) :
122
- mathmlsymbol(units, false, multiplier)
128
+ units, origtext, normtext, quantity, name, symbol, multiplier =
129
+ parse(text)
130
+ rendering = if symbol
131
+ embeddedmathml(asciimath2mathml(symbol))
132
+ else
133
+ mathmlsymbol(units, false, multiplier)
134
+ end
123
135
  x.replace("#{delimspace(rendering, x)}"\
124
136
  "<mrow xref='#{unit_id(origtext)}'>#{rendering}</mrow>\n"\
125
137
  "#{unitsml(units, origtext, normtext, quantity, name)}")
@@ -127,18 +139,22 @@ module Asciimath2UnitsML
127
139
  dedup_ids(xml)
128
140
  end
129
141
 
130
- # if previous sibling's last descendent non-whitespace is MathML and mn or mi, no space
142
+ # if previous sibling's last descendent non-whitespace is MathML and
143
+ # mn or mi, no space
131
144
  def delimspace(rendering, elem)
132
145
  prec_text_elem =
133
146
  elem.xpath("./preceding-sibling::*[namespace-uri() = '#{MATHML_NS}']/"\
134
- "descendant::text()[normalize-space()!=''][last()]/parent::*").last
147
+ "descendant::text()[normalize-space()!='']"\
148
+ "[last()]/parent::*").last
135
149
  return "" if prec_text_elem.nil? ||
136
150
  !%w(mn mi).include?(prec_text_elem&.name)
137
151
 
138
152
  text = HTMLEntities.new.encode(Nokogiri::XML("<mrow>#{rendering}</mrow>")
139
153
  .text.strip)
140
- /\p{L}|\p{N}/.match(text) ?
141
- "<mo rspace='thickmathspace'>&#x2062;</mo>" : "<mo>&#x2062;</mo>"
154
+ if /\p{L}|\p{N}/.match?(text)
155
+ "<mo rspace='thickmathspace'>&#x2062;</mo>"
156
+ else "<mo>&#x2062;</mo>"
157
+ end
142
158
  end
143
159
 
144
160
  def dedup_ids(xml)
@@ -156,9 +172,9 @@ module Asciimath2UnitsML
156
172
  end
157
173
 
158
174
  def asciimath2mathml(expression)
159
- AsciiMath::MathMLBuilder.new(:msword => true).append_expression(
160
- AsciiMath.parse(HTMLEntities.new.decode(expression)).ast).to_s
161
- .gsub(/<math>/, "<math xmlns='#{MATHML_NS}'>")
175
+ AsciiMath::MathMLBuilder.new(msword: true).append_expression(
176
+ AsciiMath.parse(HTMLEntities.new.decode(expression)).ast,
177
+ ).to_s.gsub(/<math>/, "<math xmlns='#{MATHML_NS}'>")
162
178
  end
163
179
 
164
180
  def embeddedmathml(mathml)
@@ -171,7 +187,7 @@ module Asciimath2UnitsML
171
187
  def ambig_units
172
188
  u = @units_id.each_with_object({}) do |(_k, v), m|
173
189
  v.symbolids.each do |x|
174
- next if %r{[*/^]}.match(x)
190
+ next if %r{[*/^]}.match?(x)
175
191
  next unless v.symbols_hash[x][:html] != x
176
192
 
177
193
  m[v.symbols_hash[x][:html]] ||= []
@@ -185,13 +201,15 @@ module Asciimath2UnitsML
185
201
  def render_ambig_units(u)
186
202
  maxcols = 0
187
203
  u.each { |_, v| maxcols = v.size if maxcols < v.size }
188
- puts %([cols="#{maxcols + 1}*"]\n|===\n|Symbol | Unit + ID #{"| " * (maxcols - 1)}\n)
204
+ puts %([cols="#{maxcols + 1}*"]\n|===\n|Symbol | Unit + ID #{'| ' * (maxcols - 1)}\n)
189
205
  puts "\n\n"
190
- u.keys.sort_by { |a| [-u[a].size, a.gsub(%r{\&[^;]+;}, "")
191
- .gsub(/[^A-Za-z]/, "").downcase] }.each do |k|
206
+ u.keys.sort_by do |a|
207
+ [-u[a].size, a.gsub(%r{&[^;]+;}, "")
208
+ .gsub(/[^A-Za-z]/, "").downcase]
209
+ end.each do |k|
192
210
  print "| #{html2adoc(k)} "
193
211
  u[k].sort_by(&:size).each { |v1| print "| #{@units[v1].name}: `#{v1}` " }
194
- puts "#{'| ' * (maxcols - u[k].size) }\n"
212
+ puts "#{'| ' * (maxcols - u[k].size)}\n"
195
213
  end
196
214
  puts "|===\n"
197
215
  end
@@ -0,0 +1,42 @@
1
+ module Asciimath2UnitsML
2
+ class Conv
3
+ def read_yaml(path)
4
+ validate_yaml(symbolize_keys(YAML
5
+ .load_file(File.join(File.join(File.dirname(__FILE__), path)))), path)
6
+ end
7
+
8
+ def symbolize_keys(hash)
9
+ return hash if hash.is_a? String
10
+
11
+ hash.inject({}) do |result, (key, value)|
12
+ new_key = case key
13
+ when String then key.to_sym
14
+ else key
15
+ end
16
+ new_value = case value
17
+ when Hash then symbolize_keys(value)
18
+ when Array then value.map { |m| symbolize_keys(m) }
19
+ else value
20
+ end
21
+ result[new_key] = new_value
22
+ result
23
+ end
24
+ end
25
+
26
+ def flip_name_and_symbol(hash)
27
+ hash.each_with_object({}) do |(_k, v), m|
28
+ next if v.name.nil? || v.name.empty?
29
+
30
+ m[v.symbolid] = v
31
+ end
32
+ end
33
+
34
+ def flip_name_and_symbols(hash)
35
+ hash.each_with_object({}) do |(_k, v), m|
36
+ next if v.name.nil? || v.name.empty?
37
+
38
+ v.symbolids.each { |s| m[s] = v }
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,13 +1,14 @@
1
1
  module Asciimath2UnitsML
2
2
  class Conv
3
- def multiplier(x)
4
- case x
3
+ def multiplier(val)
4
+ case val
5
5
  when :space
6
6
  { html: "&#xA0;", mathml: "<mo rspace='thickmathspace'>&#x2062;</mo>" }
7
7
  when :nospace
8
8
  { html: "", mathml: "<mo>&#x2062;</mo>" }
9
9
  else
10
- { html: HTMLEntities.new.encode(x), mathml: "<mo>#{HTMLEntities.new.encode(x)}</mo>" }
10
+ { html: HTMLEntities.new.encode(val),
11
+ mathml: "<mo>#{HTMLEntities.new.encode(val)}</mo>" }
11
12
  end
12
13
  end
13
14
 
@@ -15,28 +16,31 @@ module Asciimath2UnitsML
15
16
  @symbols[unit][style] || unit
16
17
  end
17
18
 
18
- def htmlent(x)
19
- HTMLEntities.new.decode(x).split(/([<>&])/)
20
- .map { |c| /[<>'"]/.match(c) ? c : HTMLEntities.new.encode(c, :hexadecimal) }.join
19
+ def htmlent(xml)
20
+ HTMLEntities.new.decode(xml).split(/([<>&])/).map do |c|
21
+ /[<>'"]/.match?(c) ? c : HTMLEntities.new.encode(c, :hexadecimal)
22
+ end.join
21
23
  end
22
24
 
23
25
  def htmlsymbol(units, normalise)
24
26
  units.map do |u|
25
- if u[:multiplier] then u[:multiplier] == "*" ? @multiplier[:html] : u[:multiplier]
27
+ if u[:multiplier]
28
+ u[:multiplier] == "*" ? @multiplier[:html] : u[:multiplier]
26
29
  elsif u[:unit].nil? && u[:prefix]
27
30
  @prefixes[u[:prefix]].html
28
31
  else
29
- base = (u[:prefix] || "") + render(normalise ? @units[u[:unit]].symbolid : u[:unit], :html)
32
+ base = (u[:prefix] || "") +
33
+ render(normalise ? @units[u[:unit]].symbolid : u[:unit], :html)
30
34
  htmlsymbol_exponent(u, base)
31
35
  end
32
- end.join("")
36
+ end.join
33
37
  end
34
38
 
35
- def htmlsymbol_exponent(u, base)
36
- if u[:display_exponent] == "0.5"
39
+ def htmlsymbol_exponent(unit, base)
40
+ if unit[:display_exponent] == "0.5"
37
41
  base = "&#x221a;#{base}"
38
- elsif u[:display_exponent]
39
- exp = "<sup>#{u[:display_exponent].sub(/-/, "&#x2212;")}</sup>"
42
+ elsif unit[:display_exponent]
43
+ exp = "<sup>#{unit[:display_exponent].sub(/-/, '&#x2212;')}</sup>"
40
44
  base += exp
41
45
  end
42
46
  base
@@ -44,41 +48,54 @@ module Asciimath2UnitsML
44
48
 
45
49
  def mathmlsymbol(units, normalise, multiplier = nil)
46
50
  multiplier = multiplier ? "<mo>#{multiplier}</mo>" : @multiplier[:mathml]
47
- exp = units.map do |u|
48
- if u[:multiplier] then u[:multiplier] == "*" ? multiplier : "<mo>#{u[:multiplier]}</mo>"
51
+ units.map do |u|
52
+ if u[:multiplier]
53
+ u[:multiplier] == "*" ? multiplier : "<mo>#{u[:multiplier]}</mo>"
49
54
  elsif u[:unit].nil? && u[:prefix]
50
55
  %(<mi mathvariant='normal'>#{htmlent(@prefixes[u[:prefix]].html)}</mi>)
51
56
  else
52
57
  mathmlsymbol1(u, normalise)
53
58
  end
54
- end.join("")
59
+ end.join
60
+ end
61
+
62
+ def mathmlsymbol1(unit, normalise)
63
+ base = if unit[:dim]
64
+ render(normalise ? @dimensions[unit[:dim]].symbolid : unit[:dim],
65
+ :mathml)
66
+ else
67
+ render(normalise ? @units[unit[:unit]].symbolid : unit[:unit],
68
+ :mathml)
69
+ end
70
+ unit[:prefix] and base = mathmlsymbol1_prefixed(unit, base)
71
+ mathmlsymbol_exponent(unit, base)
55
72
  end
56
73
 
57
- def mathmlsymbol1(u, normalise)
58
- base = render(normalise ? @units[u[:unit]].symbolid : u[:unit], :mathml)
59
- if u[:prefix]
60
- prefix = htmlent(@prefixes[u[:prefix]].html)
61
- base = base.match(/<mi mathvariant='normal'>/) ?
62
- base.sub(/<mi mathvariant='normal'>/, "<mi mathvariant='normal'>#{prefix}") :
63
- "<mrow><mi mathvariant='normal'>#{prefix}#{base}</mrow>"
74
+ def mathmlsymbol1_prefixed(unit, base)
75
+ prefix = htmlent(@prefixes[unit[:prefix]].html)
76
+ if /<mi mathvariant='normal'>/.match?(base)
77
+ base.sub(/<mi mathvariant='normal'>/,
78
+ "<mi mathvariant='normal'>#{prefix}")
79
+ else
80
+ "<mrow><mi mathvariant='normal'>#{prefix}#{base}</mrow>"
64
81
  end
65
- mathmlsymbol_exponent(u, base)
66
82
  end
67
83
 
68
- def mathmlsymbol_exponent(u, base)
69
- if u[:display_exponent] == "0.5"
84
+ def mathmlsymbol_exponent(unit, base)
85
+ if unit[:display_exponent] == "0.5"
70
86
  base = "<msqrt>#{base}</msqrt>"
71
- elsif u[:display_exponent]
72
- exp = "<mn>#{u[:display_exponent]}</mn>".sub(/<mn>-/, "<mo>&#x2212;</mo><mn>")
87
+ elsif unit[:display_exponent]
88
+ exp = "<mn>#{unit[:display_exponent]}</mn>"
89
+ .sub(/<mn>-/, "<mo>&#x2212;</mo><mn>")
73
90
  base = "<msup><mrow>#{base}</mrow><mrow>#{exp}</mrow></msup>"
74
91
  end
75
92
  base
76
93
  end
77
94
 
78
95
  def mathmlsymbolwrap(units, normalise)
79
- <<~END
80
- <math xmlns='#{MATHML_NS}'><mrow>#{mathmlsymbol(units, normalise)}</mrow></math>
81
- END
96
+ <<~XML
97
+ <math xmlns='#{MATHML_NS}'><mrow>#{mathmlsymbol(units, normalise)}</mrow></math>
98
+ XML
82
99
  end
83
100
  end
84
101
  end
@@ -7,21 +7,22 @@ module Asciimath2UnitsML
7
7
  def unit_id(text)
8
8
  text = text.gsub(/[()]/, "")
9
9
  /-$/.match(text) and return @prefixes[text.sub(/-$/, "")].id
10
- "U_" + (@units[text] ? @units[text].id.gsub(/'/, "_") : text.gsub(/\*/, ".").gsub(/\^/, ""))
10
+ "U_#{@units[text] ? @units[text].id.gsub(/'/, '_') : text.gsub(/\*/, '.').gsub(/\^/, '')}"
11
11
  end
12
12
 
13
- def unit(units, origtext, normtext, dims, name)
13
+ def unit(units, _origtext, normtext, dims, name)
14
14
  return if units_only(units).any? { |x| x[:unit].nil? }
15
+
15
16
  dimid = dim_id(dims)
16
17
  norm_units = normalise_units(units)
17
- <<~END
18
- <Unit xmlns='#{UNITSML_NS}' xml:id='#{unit_id(normtext)}'#{dimid ? " dimensionURL='##{dimid}'" : ""}>
19
- #{unitsystem(units)}
20
- #{unitname(norm_units, normtext, name)}
21
- #{unitsymbol(norm_units)}
22
- #{rootunits(units)}
23
- </Unit>
24
- END
18
+ <<~XML
19
+ <Unit xmlns='#{UNITSML_NS}' xml:id='#{unit_id(normtext)}'#{dimid ? " dimensionURL='##{dimid}'" : ''}>
20
+ #{unitsystem(units)}
21
+ #{unitname(norm_units, normtext, name)}
22
+ #{unitsymbol(norm_units)}
23
+ #{rootunits(units)}
24
+ </Unit>
25
+ XML
25
26
  end
26
27
 
27
28
  def normalise_units(units)
@@ -36,14 +37,17 @@ module Asciimath2UnitsML
36
37
  # kg exception
37
38
  def unitsystem(units)
38
39
  return if units_only(units).any? { |x| x[:unit].nil? }
40
+
39
41
  ret = []
40
42
  units = units_only(units)
41
43
  units.any? { |x| @units[x[:unit]].system_name != "SI" } and
42
44
  ret << "<UnitSystem name='not_SI' type='not_SI' xml:lang='en-US'/>"
43
45
  if units.any? { |x| @units[x[:unit]].system_name == "SI" }
44
- base = units.size == 1 && @units[units[0][:unit]].system_type == "SI-base"
45
- base = true if units.size == 1 && units[0][:unit] == "g" && units[0][:prefix] == "k"
46
- ret << "<UnitSystem name='SI' type='#{base ? "SI_base" : "SI_derived"}' xml:lang='en-US'/>"
46
+ base = units.size == 1 &&
47
+ @units[units[0][:unit]].system_type == "SI-base"
48
+ base = true if units.size == 1 && units[0][:unit] == "g" &&
49
+ units[0][:prefix] == "k"
50
+ ret << "<UnitSystem name='SI' type='#{base ? 'SI_base' : 'SI_derived'}' xml:lang='en-US'/>"
47
51
  end
48
52
  ret.join("\n")
49
53
  end
@@ -54,28 +58,30 @@ module Asciimath2UnitsML
54
58
  end
55
59
 
56
60
  # TODO: compose name from the component units
57
- def compose_name(units, text)
61
+ def compose_name(_units, text)
58
62
  text
59
63
  end
60
64
 
61
65
  def unitsymbol(units)
62
- <<~END
63
- <UnitSymbol type="HTML">#{htmlsymbol(units, true)}</UnitSymbol>
64
- <UnitSymbol type="MathML">#{mathmlsymbolwrap(units, true)}</UnitSymbol>
65
- END
66
+ <<~XML
67
+ <UnitSymbol type="HTML">#{htmlsymbol(units, true)}</UnitSymbol>
68
+ <UnitSymbol type="MathML">#{mathmlsymbolwrap(units, true)}</UnitSymbol>
69
+ XML
66
70
  end
67
71
 
68
72
  def rootunits(units)
69
73
  return if units_only(units).any? { |x| x[:unit].nil? }
70
74
  return if units.size == 1 && !units[0][:prefix]
75
+
71
76
  exp = units_only(units).map do |u|
72
77
  prefix = " prefix='#{u[:prefix]}'" if u[:prefix]
73
- exponent = " powerNumerator='#{u[:exponent]}'" if u[:exponent] && u[:exponent] != "1"
74
- "<EnumeratedRootUnit unit='#{@units[u[:unit]].name}'#{prefix}#{exponent}/>"
78
+ u[:exponent] && u[:exponent] != "1" and
79
+ arg = " powerNumerator='#{u[:exponent]}'"
80
+ "<EnumeratedRootUnit unit='#{@units[u[:unit]].name}'#{prefix}#{arg}/>"
75
81
  end.join("\n")
76
- <<~END
77
- <RootUnits>#{exp}</RootUnits>
78
- END
82
+ <<~XML
83
+ <RootUnits>#{exp}</RootUnits>
84
+ XML
79
85
  end
80
86
  end
81
87
  end
@@ -12,44 +12,46 @@ module Asciimath2UnitsML
12
12
  hash
13
13
  end
14
14
 
15
- def validate_unit(v)
16
- if v[:quantity_reference]
17
- v[:quantity_reference].is_a?(Array) or
18
- raise StandardError.new "No quantity_reference array provided for unit: #{v}"
15
+ def validate_unit(unit)
16
+ if unit[:quantity_reference]
17
+ unit[:quantity_reference].is_a?(Array) or
18
+ raise StandardError
19
+ .new "No quantity_reference array provided for unit: #{unit}"
19
20
  end
20
- if v[:unit_name]
21
- v[:unit_name].is_a?(Array) or
22
- raise StandardError.new "No unit_name array provided for unit: #{v}"
21
+ if unit[:unit_name]
22
+ unit[:unit_name].is_a?(Array) or
23
+ raise StandardError
24
+ .new "No unit_name array provided for unit: #{unit}"
23
25
  end
24
26
  end
25
27
 
26
- def validate_symbols(m, v)
27
- symbol = symbol_key(v)
28
+ def validate_symbols(acc, val)
29
+ symbol = symbol_key(val)
28
30
  !symbol.nil? or
29
- raise StandardError.new "No symbol provided for unit: #{v}"
31
+ raise StandardError.new "No symbol provided for unit: #{val}"
30
32
  Array(symbol)&.each do |s|
31
- m[s] && s != "1" and
32
- raise StandardError.new "symbol #{s} is not unique in #{v}: "\
33
- "already used for #{m[s]}"
34
- m[s] = v
33
+ acc[s] && s != "1" and
34
+ raise StandardError.new "symbol #{s} is not unique in #{val}: "\
35
+ "already used for #{acc[s]}"
36
+ acc[s] = val
35
37
  end
36
- m
38
+ acc
37
39
  end
38
40
 
39
- def validate_unit_symbol_cardinality(us, k)
40
- return true if us.nil?
41
+ def validate_unit_symbol_cardinality(sym, key)
42
+ return true if sym.nil?
41
43
 
42
- !us[:id].nil? && !us[:ascii].nil? && !us[:html].nil? &&
43
- !us[:mathml].nil? && !us[:latex].nil? &&
44
- !us[:unicode].nil? and return true
45
- raise StandardError.new "malformed unit_symbol for #{k}: #{us}"
44
+ !sym[:id].nil? && !sym[:ascii].nil? && !sym[:html].nil? &&
45
+ !sym[:mathml].nil? && !sym[:latex].nil? &&
46
+ !sym[:unicode].nil? and return true
47
+ raise StandardError.new "malformed unit_symbol for #{key}: #{sym}"
46
48
  end
47
49
 
48
- def symbol_key(v)
49
- symbol = v[:unit_symbols]&.each_with_object([]) do |s, m|
50
+ def symbol_key(val)
51
+ symbol = val[:unit_symbols]&.each_with_object([]) do |s, m|
50
52
  m << (s["id"] || s[:id])
51
- end || v.dig(:symbol, :ascii) || v[:symbol] #|| v[:short]
52
- !symbol.nil? && v[:unit_symbols] && !symbol.is_a?(Array) and
53
+ end || val.dig(:symbol, :ascii) || val[:symbol] # || val[:short]
54
+ !symbol.nil? && val[:unit_symbols] && !symbol.is_a?(Array) and
53
55
  symbol = [symbol]
54
56
  symbol
55
57
  end
@@ -1,3 +1,3 @@
1
1
  module Asciimath2UnitsML
2
- VERSION = '0.3.2'.freeze
2
+ VERSION = "0.4.2".freeze
3
3
  end
@@ -1,4 +1,3 @@
1
1
  require_relative "asciimath2unitsml/version"
2
2
  require_relative "asciimath2unitsml/conv"
3
3
  require_relative "unitsdb_ruby/unitsdb"
4
-