asciimath2unitsml 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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