asciimath2unitsml 0.3.2 → 0.4.2

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.
@@ -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
-