asciimath2unitsml 0.3.1 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2eabcf099e41ebc168ea5904e903893af61c95667e0f778fdf17e39e18fd867a
4
- data.tar.gz: 6316d4d968b656249cd69b255e8c68f9f0c7307055fe55d205902c9409d21a9b
3
+ metadata.gz: f51b82e234fddaf66252f77a276a3acf68dae4356502a3c900253f5d4d4dffcf
4
+ data.tar.gz: 59dd18f009952329c1c07af2132ec06123c06dd3caea4ee7f22f17c0f4ec1cbc
5
5
  SHA512:
6
- metadata.gz: 4450d314da42fa0941730c668090c7d3bef43ccd8da4a9ad7e5b29a008dcb8abbf9935732229f988a58cbe624ec10eba52e2400efddb7b09a71b6fe51d9ee579
7
- data.tar.gz: 66e66fee285dc9788006a58b98e0e3660b8e829aa29c601eb45a3d2ad263da31582df9267a2a93053f24d0ff89503092395b0ec1ff3ffe8d99ec6161b05a260c
6
+ metadata.gz: 9a925e3db85d3086d676c07c101609e87674d620394f5fa0a536ab3652f3aa9c0cc6a74507d79264e0154bf51ea4121d47b7275a94212bc934b822b0392a9970
7
+ data.tar.gz: 59d98ebd629a20e8f03dc32a1870474e5808b9d38f51a87feec5eae9f0746535bed9dcf38b1faf3939319bb3989b1d926088e8d834388e48f045070e3749312a
@@ -7,6 +7,7 @@ require_relative "string"
7
7
  require_relative "parse"
8
8
  require_relative "render"
9
9
  require_relative "unit"
10
+ require_relative "validate"
10
11
 
11
12
  module Asciimath2UnitsML
12
13
  MATHML_NS = "http://www.w3.org/1998/Math/MathML".freeze
@@ -14,56 +15,57 @@ module Asciimath2UnitsML
14
15
 
15
16
  class Conv
16
17
  def initialize(options = {})
17
- @dimensions_id = read_yaml("../unitsdb/dimensions.yaml").
18
- each_with_object({}) do |(k, v), m|
18
+ @dimensions_id = read_yaml("../unitsdb/dimensions.yaml")
19
+ .each_with_object({}) do |(k, v), m|
19
20
  m[k.to_s] = UnitsDB::Dimension.new(k, v)
20
21
  end
21
- @prefixes_id = read_yaml("../unitsdb/prefixes.yaml").
22
- each_with_object({}) do |(k, v), m|
22
+ @prefixes_id = read_yaml("../unitsdb/prefixes.yaml")
23
+ .each_with_object({}) do |(k, v), m|
23
24
  m[k] = UnitsDB::Prefix.new(k, v)
24
25
  end
25
26
  @prefixes = flip_name_and_symbol(@prefixes_id)
26
- @quantities = read_yaml("../unitsdb/quantities.yaml").
27
- each_with_object({}) do |(k, v), m|
27
+ @quantities = read_yaml("../unitsdb/quantities.yaml")
28
+ .each_with_object({}) do |(k, v), m|
28
29
  m[k.to_s] = UnitsDB::Quantity.new(k, v)
29
30
  end
30
- @units_id = read_yaml("../unitsdb/units.yaml").
31
- each_with_object({}) do |(k, v), m|
31
+ @units_id = read_yaml("../unitsdb/units.yaml")
32
+ .each_with_object({}) do |(k, v), m|
32
33
  m[k.to_s] = UnitsDB::Unit.new(k.to_s, v)
33
34
  end
34
35
  @units = flip_name_and_symbols(@units_id)
35
- @symbols = @units.each_with_object({}) do |(k, v), m|
36
+ @symbols = @units.each_with_object({}) do |(_k, v), m|
36
37
  v.symbolids.each { |x| m[x] = v.symbols_hash[x] }
37
38
  end
38
39
  @parser = parser
39
- @multiplier = multiplier(options[:multiplier] || "\u00b7")
40
+ @multiplier = multiplier(options[:multiplier] || "\u22c5")
40
41
  end
41
42
 
42
- def float_to_display(f)
43
- ret = f.to_f.round(1).to_s.sub(/\.0$/, "")
43
+ def float_to_display(float)
44
+ float.to_f.round(1).to_s.sub(/\.0$/, "")
44
45
  end
45
46
 
46
47
  def prefix(units)
47
- units.map { |u| u[:prefix] }.reject { |u| u.nil? }.uniq.map do |p|
48
+ units.map { |u| u[:prefix] }.reject(&:nil?).uniq.map do |p|
48
49
  <<~END
49
- <Prefix xmlns='#{UNITSML_NS}' prefixBase='#{@prefixes[p].base}'
50
- prefixPower='#{@prefixes[p].power}' xml:id='#{@prefixes[p].id}'>
51
- <PrefixName xml:lang="en">#{@prefixes[p].name}</PrefixName>
52
- <PrefixSymbol type="ASCII">#{@prefixes[p].ascii}</PrefixSymbol>
53
- <PrefixSymbol type="unicode">#{@prefixes[p].unicode}</PrefixSymbol>
54
- <PrefixSymbol type="LaTeX">#{@prefixes[p].latex}</PrefixSymbol>
55
- <PrefixSymbol type="HTML">#{htmlent @prefixes[p].html}</PrefixSymbol>
56
- </Prefix>
50
+ <Prefix xmlns='#{UNITSML_NS}' prefixBase='#{@prefixes[p].base}'
51
+ prefixPower='#{@prefixes[p].power}' xml:id='#{@prefixes[p].id}'>
52
+ <PrefixName xml:lang="en">#{@prefixes[p].name}</PrefixName>
53
+ <PrefixSymbol type="ASCII">#{@prefixes[p].ascii}</PrefixSymbol>
54
+ <PrefixSymbol type="unicode">#{@prefixes[p].unicode}</PrefixSymbol>
55
+ <PrefixSymbol type="LaTeX">#{@prefixes[p].latex}</PrefixSymbol>
56
+ <PrefixSymbol type="HTML">#{htmlent @prefixes[p].html}</PrefixSymbol>
57
+ </Prefix>
57
58
  END
58
59
  end.join("\n")
59
60
  end
60
61
 
61
62
  def dimension_components(dims)
62
63
  return if dims.nil? || dims.empty?
64
+
63
65
  <<~END
64
- <Dimension xmlns='#{UNITSML_NS}' xml:id="#{dim_id(dims)}">
65
- #{dims.map { |u| dimension1(u) }.join("\n") }
66
- </Dimension>
66
+ <Dimension xmlns='#{UNITSML_NS}' xml:id="#{dim_id(dims)}">
67
+ #{dims.map { |u| dimension1(u) }.join("\n")}
68
+ </Dimension>
67
69
  END
68
70
  end
69
71
 
@@ -87,27 +89,29 @@ module Asciimath2UnitsML
87
89
  return if norm.any? do |u|
88
90
  u[:unit] == "unknown" || u[:prefix] == "unknown" || u[:unit].nil?
89
91
  end
92
+
90
93
  norm.map do |u|
91
94
  { dimension: U2D[u[:unit]][:dimension],
92
95
  unit: u[:unit],
93
96
  exponent: u[:exponent] || 1,
94
- symbol: U2D[u[:unit]][:symbol] }
97
+ symbol: U2D[u[:unit]][:symbol] }
95
98
  end.sort { |a, b| U2D[a[:unit]][:order] <=> U2D[b[:unit]][:order] }
96
99
  end
97
100
 
98
101
  def dimension1(u)
99
- %(<#{u[:dimension]} symbol="#{u[:symbol]}"
102
+ %(<#{u[:dimension]} symbol="#{u[:symbol]}"
100
103
  powerNumerator="#{float_to_display(u[:exponent])}"/>)
101
104
  end
102
105
 
103
106
  def dim_id(dims)
104
107
  return nil if dims.nil? || dims.empty?
108
+
105
109
  dimhash = dims.each_with_object({}) { |h, m| m[h[:dimension]] = h }
106
- dimsvector = %w(Length Mass Time ElectricCurrent ThermodynamicTemperature
110
+ dimsvector = %w(Length Mass Time ElectricCurrent ThermodynamicTemperature
107
111
  AmountOfSubstance LuminousIntensity PlaneAngle)
108
112
  .map { |h| dimhash.dig(h, :exponent) }.join(":")
109
- id = @dimensions_id&.values&.select { |d| d.vector == dimsvector }&.
110
- first&.id and return id.to_s
113
+ id = @dimensions_id&.values&.select { |d| d.vector == dimsvector }
114
+ &.first&.id and return id.to_s
111
115
  "D_" + dims.map do |d|
112
116
  U2D[d[:unit]][:symbol] +
113
117
  (d[:exponent] == 1 ? "" : float_to_display(d[:exponent]))
@@ -119,15 +123,17 @@ module Asciimath2UnitsML
119
123
  end
120
124
 
121
125
  def gather_units(units)
122
- units.sort { |a, b| a[:unit] <=> b[:unit] }.each_with_object([]) do |k, m|
126
+ units.sort_by { |a| a[:unit] }.each_with_object([]) do |k, m|
123
127
  if m.empty? || m[-1][:unit] != k[:unit] then m << k
124
128
  else
125
129
  m[-1] = {
126
130
  prefix: combine_prefixes(
127
- @prefixes[m[-1][:prefix]], @prefixes[k[:prefix]]),
131
+ @prefixes[m[-1][:prefix]], @prefixes[k[:prefix]]
132
+ ),
128
133
  unit: m[-1][:unit],
129
134
  exponent: (k[:exponent]&.to_f || 1) +
130
- (m[-1][:exponent]&.to_f || 1) }
135
+ (m[-1][:exponent]&.to_f || 1),
136
+ }
131
137
  end
132
138
  end
133
139
  end
@@ -142,9 +148,12 @@ module Asciimath2UnitsML
142
148
  { prefix: u[:prefix], unit: "unknown", exponent: u[:exponent] }
143
149
  else
144
150
  @units[u[:unit]].si_derived_bases.each_with_object([]) do |k, m|
145
- prefix = !k[:prefix].nil? && !k[:prefix].empty? ?
146
- combine_prefixes(@prefixes_id[k[:prefix]], @prefixes[u[:prefix]]) :
147
- u[:prefix]
151
+ prefix = if !k[:prefix].nil? && !k[:prefix].empty?
152
+ combine_prefixes(@prefixes_id[k[:prefix]],
153
+ @prefixes[u[:prefix]])
154
+ else
155
+ u[:prefix]
156
+ end
148
157
  m << { prefix: prefix,
149
158
  unit: @units_id[k[:id]].symbolid,
150
159
  exponent: (k[:power]&.to_i || 1) * (u[:exponent]&.to_f || 1) }
@@ -157,6 +166,7 @@ module Asciimath2UnitsML
157
166
  return p1.symbolid if p2.nil?
158
167
  return p2.symbolid if p1.nil?
159
168
  return "unknown" if p1.base != p2.base
169
+
160
170
  @prefixes.each do |_, p|
161
171
  return p.symbolid if p.base == p1.base && p.power == p1.power + p2.power
162
172
  end
@@ -174,13 +184,14 @@ module Asciimath2UnitsML
174
184
  def quantity(normtext, quantity)
175
185
  return unless @units[normtext] && @units[normtext].quantities.size == 1 ||
176
186
  @quantities[quantity]
187
+
177
188
  id = quantity || @units[normtext].quantities.first
178
189
  @units[normtext]&.dimension and
179
190
  dim = %( dimensionURL="##{@units[normtext].dimension}")
180
191
  <<~END
181
- <Quantity xmlns='#{UNITSML_NS}' xml:id="#{id}"#{dim} quantityType="base">
182
- #{quantityname(id)}
183
- </Quantity>
192
+ <Quantity xmlns='#{UNITSML_NS}' xml:id="#{id}"#{dim} quantityType="base">
193
+ #{quantityname(id)}
194
+ </Quantity>
184
195
  END
185
196
  end
186
197
 
@@ -193,23 +204,24 @@ module Asciimath2UnitsML
193
204
  end
194
205
 
195
206
  def dimension(normtext)
196
- return unless @units[normtext]&.dimension
207
+ return unless @units[normtext]&.dimension
208
+
197
209
  dims = dimid2dimensions(@units[normtext]&.dimension)
198
210
  <<~END
199
- <Dimension xmlns='#{UNITSML_NS}' xml:id="#{@units[normtext]&.dimension}">
200
- #{dims.map { |u| dimension1(u) }.join("\n") }
201
- </Dimension>
211
+ <Dimension xmlns='#{UNITSML_NS}' xml:id="#{@units[normtext]&.dimension}">
212
+ #{dims.map { |u| dimension1(u) }.join("\n")}
213
+ </Dimension>
202
214
  END
203
215
  end
204
216
 
205
217
  def unitsml(units, origtext, normtext, quantity, name)
206
218
  dims = units2dimensions(units)
207
219
  <<~END
208
- #{unit(units, origtext, normtext, dims, name)}
209
- #{prefix(units)}
210
- #{dimension(normtext)}
211
- #{dimension_components(dims)}
212
- #{quantity(normtext, quantity)}
220
+ #{unit(units, origtext, normtext, dims, name)}
221
+ #{prefix(units)}
222
+ #{dimension(normtext)}
223
+ #{dimension_components(dims)}
224
+ #{quantity(normtext, quantity)}
213
225
  END
214
226
  end
215
227
  end
@@ -3,71 +3,29 @@ module Asciimath2UnitsML
3
3
  include Rsec::Helpers
4
4
 
5
5
  def read_yaml(path)
6
- validate_yaml(symbolize_keys(YAML.load_file(File.join(File.join(File.dirname(__FILE__), path)))), path)
6
+ validate_yaml(symbolize_keys(YAML
7
+ .load_file(File.join(File.join(File.dirname(__FILE__), path)))), path)
7
8
  end
8
9
 
9
10
  def flip_name_and_symbol(hash)
10
- hash.each_with_object({}) do |(k, v), m|
11
+ hash.each_with_object({}) do |(_k, v), m|
11
12
  next if v.name.nil? || v.name.empty?
13
+
12
14
  m[v.symbolid] = v
13
15
  end
14
16
  end
15
17
 
16
18
  def flip_name_and_symbols(hash)
17
- hash.each_with_object({}) do |(k, v), m|
19
+ hash.each_with_object({}) do |(_k, v), m|
18
20
  next if v.name.nil? || v.name.empty?
19
- v.symbolids.each { |s| m[s] = v }
20
- end
21
- end
22
-
23
- def validate_yaml(hash, path)
24
- return hash if path == "../unitsdb/quantities.yaml"
25
- return hash if path == "../unitsdb/dimensions.yaml"
26
- hash.each_with_object({}) do |(k, v), m|
27
- path == "../unitsdb/units.yaml" and validate_unit(v)
28
- m = validate_symbols(m, v)
29
- v[:unit_symbols]&.each { |s| validate_unit_symbol_cardinality(s, k) }
30
- end
31
- hash
32
- end
33
-
34
- def validate_unit(v)
35
- if v[:quantity_reference]
36
- v[:quantity_reference].is_a?(Array) or
37
- raise StandardError.new "No quantity_reference array provided for unit: #{v}"
38
- end
39
- if v[:unit_name]
40
- v[:unit_name].is_a?(Array) or raise StandardError.new "No unit_name array provided for unit: #{v}"
41
- end
42
- end
43
21
 
44
- def validate_symbols(m, v)
45
- symbol = symbol_key(v)
46
- !symbol.nil? or raise StandardError.new "No symbol provided for unit: #{v}"
47
- Array(symbol)&.each do |s|
48
- m[s] && s != "1" and
49
- raise StandardError.new "symbol #{s} is not unique in #{v}: already used for #{m[s]}"
50
- m[s] = v
22
+ v.symbolids.each { |s| m[s] = v }
51
23
  end
52
- m
53
- end
54
-
55
- def validate_unit_symbol_cardinality(us, k)
56
- return true if us.nil?
57
- !us[:id].nil? && !us[:ascii].nil? && !us[:html].nil? && !us[:mathml].nil? && !us[:latex].nil? &&
58
- !us[:unicode].nil? and return true
59
- raise StandardError.new "malformed unit_symbol for #{k}: #{us}"
60
- end
61
-
62
- def symbol_key(v)
63
- symbol = v[:unit_symbols]&.each_with_object([]) { |s, m| m << (s["id"] || s[:id]) } ||
64
- v.dig(:symbol, :ascii) || v[:symbol] #|| v[:short]
65
- symbol = [symbol] if !symbol.nil? && v[:unit_symbols] && !symbol.is_a?(Array)
66
- symbol
67
24
  end
68
25
 
69
26
  def symbolize_keys(hash)
70
27
  return hash if hash.is_a? String
28
+
71
29
  hash.inject({}) do |result, (key, value)|
72
30
  new_key = case key
73
31
  when String then key.to_sym
@@ -97,10 +55,10 @@ module Asciimath2UnitsML
97
55
  seq("sqrt(", unit1, ")") { |x| { prefix: nil, unit: x[1], display_exponent: "0.5" } } |
98
56
  seq("sqrt(", prefix1, unit1, ")") { |x| { prefix: x[1], unit: x[2], display_exponent: "0.5" } } |
99
57
  seq("sqrt(", prefix2, unit1, ")") { |x| { prefix: x[1], unit: x[2], display_exponent: "0.5" } } |
100
- seq(unit1, exponent._? & (multiplier | ")".r)) { |x| { prefix: nil, unit: x[0], display_exponent: (x[1][0] )} } |
101
- seq(unit1, exponent._?).eof { |x| { prefix: nil, unit: x[0], display_exponent: (x[1][0] )} } |
102
- seq(prefix1, unit1, exponent._? ) { |x| { prefix: x[0], unit: x[1], display_exponent: (x[2][0] ) } } |
103
- seq(prefix2, unit1, exponent._? ) { |x| { prefix: x[0], unit: x[1], display_exponent: (x[2][0] ) } } |
58
+ seq(unit1, exponent._? & (multiplier | ")".r)) { |x| { prefix: nil, unit: x[0], display_exponent: (x[1][0]) } } |
59
+ 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]) } } |
104
62
  "1".r.map { |_| { prefix: nil, unit: "1", display_exponent: nil } }
105
63
  units1 = "(".r >> lazy{units} << ")" | unit
106
64
  units = seq(prefix2, "-") { |x| [{ prefix: x[0], unit: nil, display_exponent: nil }] } |
@@ -115,6 +73,7 @@ module Asciimath2UnitsML
115
73
  if !units || Rsec::INVALID[units]
116
74
  raise Rsec::SyntaxError.new "error parsing UnitsML expression", x, 1, 0
117
75
  end
76
+
118
77
  Rsec::Fail.reset
119
78
  postprocess(units, text)
120
79
  end
@@ -134,11 +93,12 @@ module Asciimath2UnitsML
134
93
 
135
94
  def postprocess1(units)
136
95
  inverse = false
137
- units.each_with_object([]) do |u, m|
96
+ units.each_with_object([]) do |u, m|
138
97
  if u[:multiplier]
139
- inverse = !inverse if (u[:multiplier] == "/")
98
+ inverse = !inverse if u[:multiplier] == "/"
140
99
  else
141
- u[:exponent] = inverse ? "-#{u[:display_exponent] || '1'}" : u[:display_exponent]
100
+ u[:exponent] =
101
+ inverse ? "-#{u[:display_exponent] || '1'}" : u[:display_exponent]
142
102
  u[:exponent] = u[:exponent]&.sub(/^--+/, "")
143
103
  end
144
104
  m << u
@@ -155,11 +115,13 @@ module Asciimath2UnitsML
155
115
  xml.is_a? String and xml = Nokogiri::XML(xml)
156
116
  xml.xpath(".//m:mtext", "m" => MATHML_NS).each do |x|
157
117
  next unless %r{^unitsml\(.+\)$}.match(x.text)
118
+
158
119
  text = x.text.sub(%r{^unitsml\((.+)\)$}m, "\\1")
159
120
  units, origtext, normtext, quantity, name, symbol, multiplier = parse(text)
160
121
  rendering = symbol ? embeddedmathml(asciimath2mathml(symbol)) :
161
122
  mathmlsymbol(units, false, multiplier)
162
- x.replace("#{delimspace(rendering, x)}<mrow xref='#{unit_id(origtext)}'>#{rendering}</mrow>\n"\
123
+ x.replace("#{delimspace(rendering, x)}"\
124
+ "<mrow xref='#{unit_id(origtext)}'>#{rendering}</mrow>\n"\
163
125
  "#{unitsml(units, origtext, normtext, quantity, name)}")
164
126
  end
165
127
  dedup_ids(xml)
@@ -167,19 +129,25 @@ module Asciimath2UnitsML
167
129
 
168
130
  # if previous sibling's last descendent non-whitespace is MathML and mn or mi, no space
169
131
  def delimspace(rendering, elem)
170
- prec_text_elem = elem.xpath("./preceding-sibling::*[namespace-uri() = '#{MATHML_NS}']/"\
171
- "descendant::text()[normalize-space()!=''][last()]/parent::*").last
172
- return "" if prec_text_elem.nil? || !%w(mn mi).include?(prec_text_elem&.name)
173
- text = HTMLEntities.new.encode(Nokogiri::XML("<mrow>#{rendering}</mrow>").text.strip)
132
+ prec_text_elem =
133
+ elem.xpath("./preceding-sibling::*[namespace-uri() = '#{MATHML_NS}']/"\
134
+ "descendant::text()[normalize-space()!=''][last()]/parent::*").last
135
+ return "" if prec_text_elem.nil? ||
136
+ !%w(mn mi).include?(prec_text_elem&.name)
137
+
138
+ text = HTMLEntities.new.encode(Nokogiri::XML("<mrow>#{rendering}</mrow>")
139
+ .text.strip)
174
140
  /\p{L}|\p{N}/.match(text) ?
175
141
  "<mo rspace='thickmathspace'>&#x2062;</mo>" : "<mo>&#x2062;</mo>"
176
142
  end
177
143
 
178
144
  def dedup_ids(xml)
179
145
  %w(Unit Dimension Prefix Quantity).each do |t|
180
- xml.xpath(".//m:#{t}/@xml:id", "m" => UNITSML_NS).map { |a| a.text }.uniq.each do |v|
146
+ xml.xpath(".//m:#{t}/@xml:id", "m" => UNITSML_NS).map(&:text)
147
+ .uniq.each do |v|
181
148
  xml.xpath(".//*[@xml:id = '#{v}']").each_with_index do |n, i|
182
- next if i == 0
149
+ next if i.zero?
150
+
183
151
  n.remove
184
152
  end
185
153
  end
@@ -189,26 +157,28 @@ module Asciimath2UnitsML
189
157
 
190
158
  def asciimath2mathml(expression)
191
159
  AsciiMath::MathMLBuilder.new(:msword => true).append_expression(
192
- AsciiMath.parse(HTMLEntities.new.decode(expression)).ast).to_s.
193
- gsub(/<math>/, "<math xmlns='#{MATHML_NS}'>")
160
+ AsciiMath.parse(HTMLEntities.new.decode(expression)).ast).to_s
161
+ .gsub(/<math>/, "<math xmlns='#{MATHML_NS}'>")
194
162
  end
195
163
 
196
164
  def embeddedmathml(mathml)
197
165
  x = Nokogiri::XML(mathml)
198
- x.xpath(".//m:mi", "m" => MATHML_NS).each { |mi| mi["mathvariant"] = "normal" }
166
+ x.xpath(".//m:mi", "m" => MATHML_NS)
167
+ .each { |mi| mi["mathvariant"] = "normal" }
199
168
  x.children.to_xml
200
169
  end
201
170
 
202
171
  def ambig_units
203
- u = @units_id.each_with_object({}) do |(k, v), m|
172
+ u = @units_id.each_with_object({}) do |(_k, v), m|
204
173
  v.symbolids.each do |x|
205
174
  next if %r{[*/^]}.match(x)
206
175
  next unless v.symbols_hash[x][:html] != x
176
+
207
177
  m[v.symbols_hash[x][:html]] ||= []
208
178
  m[v.symbols_hash[x][:html]] << x
209
179
  end
210
180
  end
211
- u.keys.each { |k| u[k] = u[k].unshift(k) if @symbols.dig(k, :html) == k }
181
+ u.each_key { |k| u[k] = u[k].unshift(k) if @symbols.dig(k, :html) == k }
212
182
  render_ambig_units(u)
213
183
  end
214
184
 
@@ -217,16 +187,17 @@ module Asciimath2UnitsML
217
187
  u.each { |_, v| maxcols = v.size if maxcols < v.size }
218
188
  puts %([cols="#{maxcols + 1}*"]\n|===\n|Symbol | Unit + ID #{"| " * (maxcols - 1)}\n)
219
189
  puts "\n\n"
220
- u.keys.sort_by { |a| [-u[a].size, a.gsub(%r{\&[^;]+;}, "").gsub(/[^A-Za-z]/, "").downcase] }.each do |k|
190
+ u.keys.sort_by { |a| [-u[a].size, a.gsub(%r{\&[^;]+;}, "")
191
+ .gsub(/[^A-Za-z]/, "").downcase] }.each do |k|
221
192
  print "| #{html2adoc(k)} "
222
- u[k].sort_by { |v1| v1.size }.each { |v1| print "| #{@units[v1].name}: `#{v1}` " }
223
- puts "#{"| " * (maxcols - u[k].size) }\n"
193
+ u[k].sort_by(&:size).each { |v1| print "| #{@units[v1].name}: `#{v1}` " }
194
+ puts "#{'| ' * (maxcols - u[k].size) }\n"
224
195
  end
225
196
  puts "|===\n"
226
197
  end
227
198
 
228
- def html2adoc(k)
229
- k.gsub(%r{<i>}, "__").gsub(%r{</i>}, "__")
199
+ def html2adoc(elem)
200
+ elem.gsub(%r{<i>}, "__").gsub(%r{</i>}, "__")
230
201
  .gsub(%r{<sup>}, "^").gsub(%r{</sup>}, "^")
231
202
  .gsub(%r{<sub>}, "~").gsub(%r{</sub>}, "~")
232
203
  end
@@ -0,0 +1,57 @@
1
+ module Asciimath2UnitsML
2
+ class Conv
3
+ def validate_yaml(hash, path)
4
+ return hash if path == "../unitsdb/quantities.yaml"
5
+ return hash if path == "../unitsdb/dimensions.yaml"
6
+
7
+ hash.each_with_object({}) do |(k, v), m|
8
+ path == "../unitsdb/units.yaml" and validate_unit(v)
9
+ m = validate_symbols(m, v)
10
+ v[:unit_symbols]&.each { |s| validate_unit_symbol_cardinality(s, k) }
11
+ end
12
+ hash
13
+ end
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}"
19
+ 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}"
23
+ end
24
+ end
25
+
26
+ def validate_symbols(m, v)
27
+ symbol = symbol_key(v)
28
+ !symbol.nil? or
29
+ raise StandardError.new "No symbol provided for unit: #{v}"
30
+ 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
35
+ end
36
+ m
37
+ end
38
+
39
+ def validate_unit_symbol_cardinality(us, k)
40
+ return true if us.nil?
41
+
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}"
46
+ end
47
+
48
+ def symbol_key(v)
49
+ symbol = v[:unit_symbols]&.each_with_object([]) do |s, m|
50
+ 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
+ symbol = [symbol]
54
+ symbol
55
+ end
56
+ end
57
+ end
@@ -1,3 +1,3 @@
1
1
  module Asciimath2UnitsML
2
- VERSION = '0.3.1'.freeze
2
+ VERSION = '0.3.2'.freeze
3
3
  end
data/spec/conv_spec.rb CHANGED
@@ -11,7 +11,7 @@ RSpec.describe Asciimath2UnitsML do
11
11
  <mo rspace='thickmathspace'>&#x2062;</mo>
12
12
  <mrow xref='U_mm.s-2'>
13
13
  <mi mathvariant='normal'>mm</mi>
14
- <mo>&#xB7;</mo>
14
+ <mo>&#x22C5;</mo>
15
15
  <msup>
16
16
  <mrow>
17
17
  <mi mathvariant='normal'>s</mi>
@@ -26,14 +26,14 @@ RSpec.describe Asciimath2UnitsML do
26
26
  <UnitSystem name='SI' type='SI_derived' xml:lang='en-US'/>
27
27
  <UnitName xml:lang='en'>mm*s^-2</UnitName>
28
28
  <UnitSymbol type='HTML'>
29
- mm&#xB7;s
29
+ mm&#x22C5;s
30
30
  <sup>&#x2212;2</sup>
31
31
  </UnitSymbol>
32
32
  <UnitSymbol type='MathML'>
33
33
  <math xmlns='http://www.w3.org/1998/Math/MathML'>
34
34
  <mrow>
35
35
  <mi mathvariant='normal'>mm</mi>
36
- <mo>&#xB7;</mo>
36
+ <mo>&#x22C5;</mo>
37
37
  <msup>
38
38
  <mrow>
39
39
  <mi mathvariant='normal'>s</mi>
@@ -418,7 +418,7 @@ OUTPUT
418
418
  <mo rspace='thickmathspace'>&#x2062;</mo>
419
419
  <mrow xref='U_kg.s-2'>
420
420
  <mi mathvariant='normal'>kg</mi>
421
- <mo>&#xB7;</mo>
421
+ <mo>&#x22C5;</mo>
422
422
  <msup>
423
423
  <mrow>
424
424
  <mi mathvariant='normal'>s</mi>
@@ -433,14 +433,14 @@ OUTPUT
433
433
  <UnitSystem name='SI' type='SI_derived' xml:lang='en-US'/>
434
434
  <UnitName xml:lang='en'>kg*s^-2</UnitName>
435
435
  <UnitSymbol type='HTML'>
436
- kg&#xB7;s
436
+ kg&#x22C5;s
437
437
  <sup>&#x2212;2</sup>
438
438
  </UnitSymbol>
439
439
  <UnitSymbol type='MathML'>
440
440
  <math xmlns='http://www.w3.org/1998/Math/MathML'>
441
441
  <mrow>
442
442
  <mi mathvariant='normal'>kg</mi>
443
- <mo>&#xB7;</mo>
443
+ <mo>&#x22C5;</mo>
444
444
  <msup>
445
445
  <mrow>
446
446
  <mi mathvariant='normal'>s</mi>
@@ -474,7 +474,7 @@ OUTPUT
474
474
  <mo rspace='thickmathspace'>&#x2062;</mo>
475
475
  <mrow xref='U_kg.s-2'>
476
476
  <mi mathvariant='normal'>kg</mi>
477
- <mo>&#xB7;</mo>
477
+ <mo>&#x22C5;</mo>
478
478
  <msup>
479
479
  <mrow>
480
480
  <mi mathvariant='normal'>s</mi>
@@ -500,23 +500,23 @@ OUTPUT
500
500
  <mi mathvariant='normal'>K</mi>
501
501
  <mo>/</mo>
502
502
  <mi mathvariant='normal'>kg</mi>
503
- <mo>&#xB7;</mo>
503
+ <mo>&#x22C5;</mo>
504
504
  <mi mathvariant='normal'>m</mi>
505
505
  </mrow>
506
506
  <Unit xmlns='https://schema.unitsml.org/unitsml/1.0' xml:id='U_K.kg-1.m-1' dimensionURL='#D_L-1M-1Theta'>
507
507
  <UnitSystem name='SI' type='SI_derived' xml:lang='en-US'/>
508
508
  <UnitName xml:lang='en'>K*kg^-1*m^-1</UnitName>
509
509
  <UnitSymbol type='HTML'>
510
- K&#xB7;kg
510
+ K&#x22C5;kg
511
511
  <sup>&#x2212;1</sup>
512
- &#xB7;m
512
+ &#x22C5;m
513
513
  <sup>&#x2212;1</sup>
514
514
  </UnitSymbol>
515
515
  <UnitSymbol type='MathML'>
516
516
  <math xmlns='http://www.w3.org/1998/Math/MathML'>
517
517
  <mrow>
518
518
  <mi mathvariant='normal'>K</mi>
519
- <mo>&#xB7;</mo>
519
+ <mo>&#x22C5;</mo>
520
520
  <msup>
521
521
  <mrow>
522
522
  <mi mathvariant='normal'>kg</mi>
@@ -526,7 +526,7 @@ OUTPUT
526
526
  <mn>1</mn>
527
527
  </mrow>
528
528
  </msup>
529
- <mo>&#xB7;</mo>
529
+ <mo>&#x22C5;</mo>
530
530
  <msup>
531
531
  <mrow>
532
532
  <mi mathvariant='normal'>m</mi>
@@ -726,7 +726,7 @@ INPUT
726
726
  <mo rspace='thickmathspace'>&#x2062;</mo>
727
727
  <mrow xref='U_A.C3'>
728
728
  <mi mathvariant='normal'>A</mi>
729
- <mo>&#xB7;</mo>
729
+ <mo>&#x22C5;</mo>
730
730
  <msup>
731
731
  <mrow>
732
732
  <mi mathvariant='normal'>C</mi>
@@ -740,14 +740,14 @@ INPUT
740
740
  <UnitSystem name='SI' type='SI_derived' xml:lang='en-US'/>
741
741
  <UnitName xml:lang='en'>A*C^3</UnitName>
742
742
  <UnitSymbol type='HTML'>
743
- A&#xB7;C
743
+ A&#x22C5;C
744
744
  <sup>3</sup>
745
745
  </UnitSymbol>
746
746
  <UnitSymbol type='MathML'>
747
747
  <math xmlns='http://www.w3.org/1998/Math/MathML'>
748
748
  <mrow>
749
749
  <mi mathvariant='normal'>A</mi>
750
- <mo>&#xB7;</mo>
750
+ <mo>&#x22C5;</mo>
751
751
  <msup>
752
752
  <mrow>
753
753
  <mi mathvariant='normal'>C</mi>
@@ -791,23 +791,23 @@ INPUT
791
791
  <mi mathvariant='normal'>J</mi>
792
792
  <mo>/</mo>
793
793
  <mi mathvariant='normal'>kg</mi>
794
- <mo>&#xB7;</mo>
794
+ <mo>&#x22C5;</mo>
795
795
  <mi mathvariant='normal'>K</mi>
796
796
  </mrow>
797
797
  <Unit xmlns='https://schema.unitsml.org/unitsml/1.0' xml:id='U_NISTu13.u27p10_3e-1/1.u5e-1/1' dimensionURL='#D_L2M0T-2Theta-1'>
798
798
  <UnitSystem name='SI' type='SI_derived' xml:lang='en-US'/>
799
799
  <UnitName xml:lang='en'>joule per kilogram kelvin</UnitName>
800
800
  <UnitSymbol type='HTML'>
801
- J&#xB7;kg
801
+ J&#x22C5;kg
802
802
  <sup>&#x2212;1</sup>
803
- &#xB7;K
803
+ &#x22C5;K
804
804
  <sup>&#x2212;1</sup>
805
805
  </UnitSymbol>
806
806
  <UnitSymbol type='MathML'>
807
807
  <math xmlns='http://www.w3.org/1998/Math/MathML'>
808
808
  <mrow>
809
809
  <mi mathvariant='normal'>J</mi>
810
- <mo>&#xB7;</mo>
810
+ <mo>&#x22C5;</mo>
811
811
  <msup>
812
812
  <mrow>
813
813
  <mi mathvariant='normal'>kg</mi>
@@ -817,7 +817,7 @@ INPUT
817
817
  <mn>1</mn>
818
818
  </mrow>
819
819
  </msup>
820
- <mo>&#xB7;</mo>
820
+ <mo>&#x22C5;</mo>
821
821
  <msup>
822
822
  <mrow>
823
823
  <mi mathvariant='normal'>K</mi>
@@ -1131,7 +1131,7 @@ INPUT
1131
1131
  <mo rspace='thickmathspace'>&#x2062;</mo>
1132
1132
  <mrow xref='U_mW.cm-2'>
1133
1133
  <mi mathvariant='normal'>mW</mi>
1134
- <mo>&#xB7;</mo>
1134
+ <mo>&#x22C5;</mo>
1135
1135
  <msup>
1136
1136
  <mrow>
1137
1137
  <mi mathvariant='normal'>cm</mi>
@@ -1146,14 +1146,14 @@ INPUT
1146
1146
  <UnitSystem name='SI' type='SI_derived' xml:lang='en-US'/>
1147
1147
  <UnitName xml:lang='en'>mW*cm^-2</UnitName>
1148
1148
  <UnitSymbol type='HTML'>
1149
- mW&#xB7;cm
1149
+ mW&#x22C5;cm
1150
1150
  <sup>&#x2212;2</sup>
1151
1151
  </UnitSymbol>
1152
1152
  <UnitSymbol type='MathML'>
1153
1153
  <math xmlns='http://www.w3.org/1998/Math/MathML'>
1154
1154
  <mrow>
1155
1155
  <mi mathvariant='normal'>mW</mi>
1156
- <mo>&#xB7;</mo>
1156
+ <mo>&#x22C5;</mo>
1157
1157
  <msup>
1158
1158
  <mrow>
1159
1159
  <mi mathvariant='normal'>cm</mi>
@@ -1254,7 +1254,7 @@ INPUT
1254
1254
  <UnitSymbol type='HTML'>
1255
1255
  cal
1256
1256
  <sub>th</sub>
1257
- &#xB7;cm
1257
+ &#x22C5;cm
1258
1258
  <sup>&#x2212;2</sup>
1259
1259
  </UnitSymbol>
1260
1260
  <UnitSymbol type='MathML'>
@@ -1268,7 +1268,7 @@ INPUT
1268
1268
  <mi mathvariant='normal'>th</mi>
1269
1269
  </mrow>
1270
1270
  </msub>
1271
- <mo>&#xB7;</mo>
1271
+ <mo>&#x22C5;</mo>
1272
1272
  <msup>
1273
1273
  <mrow>
1274
1274
  <mi mathvariant='normal'>cm</mi>
@@ -1348,14 +1348,14 @@ INPUT
1348
1348
  <UnitSystem name='SI' type='SI_derived' xml:lang='en-US'/>
1349
1349
  <UnitName xml:lang='en'>cm*s^-2</UnitName>
1350
1350
  <UnitSymbol type='HTML'>
1351
- cm&#xB7;s
1351
+ cm&#x22C5;s
1352
1352
  <sup>&#x2212;2</sup>
1353
1353
  </UnitSymbol>
1354
1354
  <UnitSymbol type='MathML'>
1355
1355
  <math xmlns='http://www.w3.org/1998/Math/MathML'>
1356
1356
  <mrow>
1357
1357
  <mi mathvariant='normal'>cm</mi>
1358
- <mo>&#xB7;</mo>
1358
+ <mo>&#x22C5;</mo>
1359
1359
  <msup>
1360
1360
  <mrow>
1361
1361
  <mi mathvariant='normal'>s</mi>
@@ -1412,14 +1412,14 @@ INPUT
1412
1412
  <UnitSystem name='SI' type='SI_derived' xml:lang='en-US'/>
1413
1413
  <UnitName xml:lang='en'>cm*s^-2</UnitName>
1414
1414
  <UnitSymbol type='HTML'>
1415
- cm&#xB7;s
1415
+ cm&#x22C5;s
1416
1416
  <sup>&#x2212;2</sup>
1417
1417
  </UnitSymbol>
1418
1418
  <UnitSymbol type='MathML'>
1419
1419
  <math xmlns='http://www.w3.org/1998/Math/MathML'>
1420
1420
  <mrow>
1421
1421
  <mi mathvariant='normal'>cm</mi>
1422
- <mo>&#xB7;</mo>
1422
+ <mo>&#x22C5;</mo>
1423
1423
  <msup>
1424
1424
  <mrow>
1425
1425
  <mi mathvariant='normal'>s</mi>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciimath2unitsml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-29 00:00:00.000000000 Z
11
+ date: 2021-04-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciimath
@@ -245,6 +245,7 @@ files:
245
245
  - lib/asciimath2unitsml/render.rb
246
246
  - lib/asciimath2unitsml/string.rb
247
247
  - lib/asciimath2unitsml/unit.rb
248
+ - lib/asciimath2unitsml/validate.rb
248
249
  - lib/asciimath2unitsml/version.rb
249
250
  - lib/unitsdb/dimensions.yaml
250
251
  - lib/unitsdb/prefixes.yaml