asciimath2unitsml 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/rake.yml +2 -23
- data/.hound.yml +5 -0
- data/.rubocop.yml +4 -8
- data/Gemfile +1 -1
- data/README.adoc +19 -1
- data/Rakefile +1 -1
- data/asciimath2unitsml.gemspec +14 -17
- data/bin/rspec +1 -2
- data/lib/asciimath2unitsml.rb +0 -1
- data/lib/asciimath2unitsml/conv.rb +74 -119
- data/lib/asciimath2unitsml/dimensions.rb +117 -0
- data/lib/asciimath2unitsml/parse.rb +127 -137
- data/lib/asciimath2unitsml/read.rb +42 -0
- data/lib/asciimath2unitsml/render.rb +48 -31
- data/lib/asciimath2unitsml/unit.rb +29 -23
- data/lib/asciimath2unitsml/validate.rb +59 -0
- data/lib/asciimath2unitsml/version.rb +1 -1
- data/lib/unitsdb/dimensions.yaml +65 -8
- data/lib/unitsdb_ruby/unitsdb.rb +87 -55
- data/spec/conv_spec.rb +1447 -1227
- data/spec/spec_helper.rb +10 -10
- metadata +23 -19
@@ -0,0 +1,117 @@
|
|
1
|
+
module Asciimath2UnitsML
|
2
|
+
class Conv
|
3
|
+
def dimension_components(dims)
|
4
|
+
return if dims.nil? || dims.empty?
|
5
|
+
|
6
|
+
<<~XML
|
7
|
+
<Dimension xmlns='#{UNITSML_NS}' xml:id="#{dim_id(dims)}">
|
8
|
+
#{dims.map { |u| dimension1(u) }.join("\n")}
|
9
|
+
</Dimension>
|
10
|
+
XML
|
11
|
+
end
|
12
|
+
|
13
|
+
U2D = {
|
14
|
+
"m" => { dimension: "Length", order: 1, symbol: "L" },
|
15
|
+
"g" => { dimension: "Mass", order: 2, symbol: "M" },
|
16
|
+
"kg" => { dimension: "Mass", order: 2, symbol: "M" },
|
17
|
+
"s" => { dimension: "Time", order: 3, symbol: "T" },
|
18
|
+
"A" => { dimension: "ElectricCurrent", order: 4, symbol: "I" },
|
19
|
+
"K" => { dimension: "ThermodynamicTemperature", order: 5,
|
20
|
+
symbol: "Theta" },
|
21
|
+
"degK" => { dimension: "ThermodynamicTemperature", order: 5,
|
22
|
+
symbol: "Theta" },
|
23
|
+
"mol" => { dimension: "AmountOfSubstance", order: 6, symbol: "N" },
|
24
|
+
"cd" => { dimension: "LuminousIntensity", order: 7, symbol: "J" },
|
25
|
+
"deg" => { dimension: "PlaneAngle", order: 8, symbol: "phi" },
|
26
|
+
}.freeze
|
27
|
+
|
28
|
+
Dim2D = {
|
29
|
+
"dim_L" => U2D["m"],
|
30
|
+
"dim_M" => U2D["g"],
|
31
|
+
"dim_T" => U2D["s"],
|
32
|
+
"dim_I" => U2D["A"],
|
33
|
+
"dim_Theta" => U2D["K"],
|
34
|
+
"dim_N" => U2D["mol"],
|
35
|
+
"dim_J" => U2D["cd"],
|
36
|
+
"dim_phi" => U2D["deg"],
|
37
|
+
}.freeze
|
38
|
+
|
39
|
+
def units2dimensions(units)
|
40
|
+
norm = decompose_units(units)
|
41
|
+
return units2dimensions_dim_input(norm) if norm[0][:dim]
|
42
|
+
return if norm.any? do |u|
|
43
|
+
u[:unit] == "unknown" || u[:prefix] == "unknown" || u[:unit].nil?
|
44
|
+
end
|
45
|
+
|
46
|
+
norm.map do |u|
|
47
|
+
{ dimension: U2D[u[:unit]][:dimension],
|
48
|
+
unit: u[:unit],
|
49
|
+
exponent: u[:exponent] || 1,
|
50
|
+
symbol: U2D[u[:unit]][:symbol] }
|
51
|
+
end.sort { |a, b| U2D[a[:unit]][:order] <=> U2D[b[:unit]][:order] }
|
52
|
+
end
|
53
|
+
|
54
|
+
def units2dimensions_dim_input(norm)
|
55
|
+
norm.map do |u|
|
56
|
+
{ dimension: Dim2D[u[:dim]][:dimension],
|
57
|
+
exponent: u[:exponent] || 1,
|
58
|
+
id: u[:dim],
|
59
|
+
symbol: Dim2D[u[:dim]][:symbol] }
|
60
|
+
end.sort { |a, b| Dim2D[a[:id]][:order] <=> Dim2D[b[:id]][:order] }
|
61
|
+
end
|
62
|
+
|
63
|
+
def dimension1(dim)
|
64
|
+
%(<#{dim[:dimension]} symbol="#{dim[:symbol]}"
|
65
|
+
powerNumerator="#{float_to_display(dim[:exponent])}"/>)
|
66
|
+
end
|
67
|
+
|
68
|
+
def dim_id(dims)
|
69
|
+
return nil if dims.nil? || dims.empty?
|
70
|
+
|
71
|
+
dimhash = dims.each_with_object({}) { |h, m| m[h[:dimension]] = h }
|
72
|
+
dimsvector = %w(Length Mass Time ElectricCurrent ThermodynamicTemperature
|
73
|
+
AmountOfSubstance LuminousIntensity PlaneAngle)
|
74
|
+
.map { |h| dimhash.dig(h, :exponent) }.join(":")
|
75
|
+
id = @dimensions_id&.values&.select { |d| d.vector == dimsvector }
|
76
|
+
&.first&.id and return id.to_s
|
77
|
+
"D_" + dims.map do |d|
|
78
|
+
(U2D.dig(d[:unit], :symbol) || Dim2D.dig(d[:id], :symbol)) +
|
79
|
+
(d[:exponent] == 1 ? "" : float_to_display(d[:exponent]))
|
80
|
+
end.join("")
|
81
|
+
end
|
82
|
+
|
83
|
+
def decompose_units(units)
|
84
|
+
gather_units(units_only(units).map { |u| decompose_unit(u) }.flatten)
|
85
|
+
end
|
86
|
+
|
87
|
+
def dimid2dimensions(normtext)
|
88
|
+
@dimensions_id[normtext].keys.map do |k|
|
89
|
+
{ dimension: k,
|
90
|
+
symbol: U2D.values.select { |v| v[:dimension] == k }.first[:symbol],
|
91
|
+
exponent: @dimensions_id[normtext].exponent(k) }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def dimension(normtext)
|
96
|
+
return unless @units[normtext]&.dimension
|
97
|
+
|
98
|
+
dims = dimid2dimensions(@units[normtext]&.dimension)
|
99
|
+
<<~XML
|
100
|
+
<Dimension xmlns='#{UNITSML_NS}' xml:id="#{@units[normtext]&.dimension}">
|
101
|
+
#{dims.map { |u| dimension1(u) }.join("\n")}
|
102
|
+
</Dimension>
|
103
|
+
XML
|
104
|
+
end
|
105
|
+
|
106
|
+
def unitsml(units, origtext, normtext, quantity, name)
|
107
|
+
dims = units2dimensions(units)
|
108
|
+
<<~XML
|
109
|
+
#{unit(units, origtext, normtext, dims, name)}
|
110
|
+
#{prefix(units)}
|
111
|
+
#{dimension(normtext)}
|
112
|
+
#{dimension_components(dims)}
|
113
|
+
#{quantity(normtext, quantity)}
|
114
|
+
XML
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -1,143 +1,111 @@
|
|
1
1
|
module Asciimath2UnitsML
|
2
2
|
class Conv
|
3
3
|
include Rsec::Helpers
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
next if v.name.nil? || v.name.empty?
|
12
|
-
m[v.symbolid] = v
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def flip_name_and_symbols(hash)
|
17
|
-
hash.each_with_object({}) do |(k, v), m|
|
18
|
-
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
|
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]
|
42
11
|
end
|
43
12
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|
-
end
|
68
|
-
|
69
|
-
def symbolize_keys(hash)
|
70
|
-
return hash if hash.is_a? String
|
71
|
-
hash.inject({}) do |result, (key, value)|
|
72
|
-
new_key = case key
|
73
|
-
when String then key.to_sym
|
74
|
-
else key
|
75
|
-
end
|
76
|
-
new_value = case value
|
77
|
-
when Hash then symbolize_keys(value)
|
78
|
-
when Array then value.map { |m| symbolize_keys(m) }
|
79
|
-
else value
|
80
|
-
end
|
81
|
-
result[new_key] = new_value
|
82
|
-
result
|
83
|
-
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
|
84
22
|
end
|
85
23
|
|
86
|
-
def
|
24
|
+
def units_parse(exponent, multiplier)
|
87
25
|
prefix2 = /#{@prefixes.keys.select { |x| x.size == 2 }.join("|")}/.r
|
88
26
|
prefix1 = /#{@prefixes.keys.select { |x| x.size == 1 }.join("|")}/.r
|
89
27
|
unit_keys = @units.keys.reject do |k|
|
90
28
|
/\*|\^|\/|^1$/.match(k) || @units[k].prefixed
|
91
29
|
end.map { |k| Regexp.escape(k) }
|
92
30
|
unit1 = /#{unit_keys.sort_by(&:length).reverse.join("|")}/.r
|
93
|
-
|
94
|
-
|
95
|
-
multiplier = %r{\*|//|/}.r.map { |x| { multiplier: x[0] } }
|
96
|
-
unit =
|
31
|
+
|
32
|
+
unit =
|
97
33
|
seq("sqrt(", unit1, ")") { |x| { prefix: nil, unit: x[1], display_exponent: "0.5" } } |
|
98
34
|
seq("sqrt(", prefix1, unit1, ")") { |x| { prefix: x[1], unit: x[2], display_exponent: "0.5" } } |
|
99
35
|
seq("sqrt(", prefix2, unit1, ")") { |x| { prefix: x[1], unit: x[2], display_exponent: "0.5" } } |
|
100
|
-
seq(unit1, exponent._? & multiplier) { |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._?
|
103
|
-
seq(prefix2, unit1, exponent._?
|
104
|
-
"1".r.map { |_| { prefix: nil, unit: "1", display_exponent: nil } }
|
105
|
-
|
36
|
+
seq(unit1, exponent._? & (multiplier | ")".r)) { |x| { prefix: nil, unit: x[0], display_exponent: (x[1][0]) } } |
|
37
|
+
seq(unit1, exponent._?).eof { |x| { prefix: nil, unit: x[0], display_exponent: (x[1][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]) } } |
|
40
|
+
"1".r.map { |_| { prefix: nil, unit: "1", 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
|
106
43
|
seq(prefix1, "-") { |x| [{ prefix: x[0], unit: nil, display_exponent: nil }] } |
|
107
|
-
|
108
|
-
|
44
|
+
units1.join(multiplier)
|
45
|
+
units
|
109
46
|
end
|
110
47
|
|
111
|
-
def parse(
|
112
|
-
text = Array(
|
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)
|
113
56
|
units = @parser.parse!(text[0])
|
114
57
|
if !units || Rsec::INVALID[units]
|
115
58
|
raise Rsec::SyntaxError.new "error parsing UnitsML expression", x, 1, 0
|
116
59
|
end
|
60
|
+
|
61
|
+
Rsec::Fail.reset
|
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
|
+
|
117
71
|
Rsec::Fail.reset
|
118
|
-
postprocess(units, text)
|
119
|
-
end
|
120
|
-
|
121
|
-
def postprocess(units, text)
|
122
|
-
units = postprocess1(units)
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
72
|
+
postprocess(units, text, false)
|
73
|
+
end
|
74
|
+
|
75
|
+
def postprocess(units, text, is_units)
|
76
|
+
units = postprocess1(units.flatten)
|
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
|
130
88
|
end.join("*")
|
131
|
-
|
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]}" : ""
|
132
99
|
end
|
133
100
|
|
134
101
|
def postprocess1(units)
|
135
102
|
inverse = false
|
136
|
-
units.each_with_object([]) do |u, m|
|
103
|
+
units.each_with_object([]) do |u, m|
|
137
104
|
if u[:multiplier]
|
138
|
-
inverse =
|
105
|
+
inverse = !inverse if u[:multiplier] == "/"
|
139
106
|
else
|
140
|
-
u[:exponent] =
|
107
|
+
u[:exponent] =
|
108
|
+
inverse ? "-#{u[:display_exponent] || '1'}" : u[:display_exponent]
|
141
109
|
u[:exponent] = u[:exponent]&.sub(/^--+/, "")
|
142
110
|
end
|
143
111
|
m << u
|
@@ -149,36 +117,53 @@ module Asciimath2UnitsML
|
|
149
117
|
MathML2UnitsML(xml).to_xml
|
150
118
|
end
|
151
119
|
|
152
|
-
# https://www.w3.org/TR/mathml-units/ section 2:
|
120
|
+
# https://www.w3.org/TR/mathml-units/ section 2:
|
121
|
+
# delimit number Invisible-Times unit
|
153
122
|
def MathML2UnitsML(xml)
|
154
123
|
xml.is_a? String and xml = Nokogiri::XML(xml)
|
155
124
|
xml.xpath(".//m:mtext", "m" => MATHML_NS).each do |x|
|
156
|
-
next unless %r{^unitsml\(.+\)$}.match(x.text)
|
125
|
+
next unless %r{^unitsml\(.+\)$}.match?(x.text)
|
126
|
+
|
157
127
|
text = x.text.sub(%r{^unitsml\((.+)\)$}m, "\\1")
|
158
|
-
units, origtext, normtext, quantity, name, symbol, multiplier =
|
159
|
-
|
160
|
-
|
161
|
-
|
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
|
135
|
+
x.replace("#{delimspace(rendering, x)}"\
|
136
|
+
"<mrow xref='#{unit_id(origtext)}'>#{rendering}</mrow>\n"\
|
162
137
|
"#{unitsml(units, origtext, normtext, quantity, name)}")
|
163
138
|
end
|
164
139
|
dedup_ids(xml)
|
165
140
|
end
|
166
141
|
|
167
|
-
# if previous sibling's last descendent non-whitespace is MathML and
|
142
|
+
# if previous sibling's last descendent non-whitespace is MathML and
|
143
|
+
# mn or mi, no space
|
168
144
|
def delimspace(rendering, elem)
|
169
|
-
prec_text_elem =
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
145
|
+
prec_text_elem =
|
146
|
+
elem.xpath("./preceding-sibling::*[namespace-uri() = '#{MATHML_NS}']/"\
|
147
|
+
"descendant::text()[normalize-space()!='']"\
|
148
|
+
"[last()]/parent::*").last
|
149
|
+
return "" if prec_text_elem.nil? ||
|
150
|
+
!%w(mn mi).include?(prec_text_elem&.name)
|
151
|
+
|
152
|
+
text = HTMLEntities.new.encode(Nokogiri::XML("<mrow>#{rendering}</mrow>")
|
153
|
+
.text.strip)
|
154
|
+
if /\p{L}|\p{N}/.match?(text)
|
155
|
+
"<mo rspace='thickmathspace'>⁢</mo>"
|
156
|
+
else "<mo>⁢</mo>"
|
157
|
+
end
|
175
158
|
end
|
176
159
|
|
177
160
|
def dedup_ids(xml)
|
178
161
|
%w(Unit Dimension Prefix Quantity).each do |t|
|
179
|
-
xml.xpath(".//m:#{t}/@xml:id", "m" => UNITSML_NS).map
|
162
|
+
xml.xpath(".//m:#{t}/@xml:id", "m" => UNITSML_NS).map(&:text)
|
163
|
+
.uniq.each do |v|
|
180
164
|
xml.xpath(".//*[@xml:id = '#{v}']").each_with_index do |n, i|
|
181
|
-
next if i
|
165
|
+
next if i.zero?
|
166
|
+
|
182
167
|
n.remove
|
183
168
|
end
|
184
169
|
end
|
@@ -187,45 +172,50 @@ module Asciimath2UnitsML
|
|
187
172
|
end
|
188
173
|
|
189
174
|
def asciimath2mathml(expression)
|
190
|
-
AsciiMath::MathMLBuilder.new(:
|
191
|
-
AsciiMath.parse(HTMLEntities.new.decode(expression)).ast
|
192
|
-
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}'>")
|
193
178
|
end
|
194
179
|
|
195
180
|
def embeddedmathml(mathml)
|
196
181
|
x = Nokogiri::XML(mathml)
|
197
|
-
x.xpath(".//m:mi", "m" => MATHML_NS)
|
182
|
+
x.xpath(".//m:mi", "m" => MATHML_NS)
|
183
|
+
.each { |mi| mi["mathvariant"] = "normal" }
|
198
184
|
x.children.to_xml
|
199
185
|
end
|
200
186
|
|
201
187
|
def ambig_units
|
202
|
-
u = @units_id.each_with_object({}) do |(
|
188
|
+
u = @units_id.each_with_object({}) do |(_k, v), m|
|
203
189
|
v.symbolids.each do |x|
|
204
|
-
next if %r{[*/^]}.match(x)
|
190
|
+
next if %r{[*/^]}.match?(x)
|
205
191
|
next unless v.symbols_hash[x][:html] != x
|
192
|
+
|
206
193
|
m[v.symbols_hash[x][:html]] ||= []
|
207
194
|
m[v.symbols_hash[x][:html]] << x
|
208
195
|
end
|
209
196
|
end
|
210
|
-
u.
|
197
|
+
u.each_key { |k| u[k] = u[k].unshift(k) if @symbols.dig(k, :html) == k }
|
211
198
|
render_ambig_units(u)
|
212
199
|
end
|
213
200
|
|
214
201
|
def render_ambig_units(u)
|
215
202
|
maxcols = 0
|
216
203
|
u.each { |_, v| maxcols = v.size if maxcols < v.size }
|
217
|
-
puts %([cols="#{maxcols + 1}*"]\n|===\n|Symbol | Unit + ID #{
|
204
|
+
puts %([cols="#{maxcols + 1}*"]\n|===\n|Symbol | Unit + ID #{'| ' * (maxcols - 1)}\n)
|
218
205
|
puts "\n\n"
|
219
|
-
u.keys.sort_by
|
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|
|
220
210
|
print "| #{html2adoc(k)} "
|
221
|
-
u[k].sort_by
|
222
|
-
puts "#{
|
211
|
+
u[k].sort_by(&:size).each { |v1| print "| #{@units[v1].name}: `#{v1}` " }
|
212
|
+
puts "#{'| ' * (maxcols - u[k].size)}\n"
|
223
213
|
end
|
224
214
|
puts "|===\n"
|
225
215
|
end
|
226
216
|
|
227
|
-
def html2adoc(
|
228
|
-
|
217
|
+
def html2adoc(elem)
|
218
|
+
elem.gsub(%r{<i>}, "__").gsub(%r{</i>}, "__")
|
229
219
|
.gsub(%r{<sup>}, "^").gsub(%r{</sup>}, "^")
|
230
220
|
.gsub(%r{<sub>}, "~").gsub(%r{</sub>}, "~")
|
231
221
|
end
|