asciimath2unitsml 0.1.1 → 0.1.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 +4 -4
- data/README.adoc +1 -0
- data/lib/asciimath2unitsml/conv.rb +28 -17
- data/lib/asciimath2unitsml/parse.rb +31 -7
- data/lib/asciimath2unitsml/version.rb +1 -1
- data/spec/conv_spec.rb +67 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d06ecf91cb804e1a5827a46ef0e458a0fe1b444a476bc6e9d99ff2dd6c06d37
|
4
|
+
data.tar.gz: 615d0c46c6beb12bea4fb427379ba49835679fb3f1efd56692909d049e9e9be7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 270b64a21c8a566907c1d0a3e81e20f126bd48d277631678b65d662eb8d80da92799e127c0d75f0555226762157eefd1cf27135f3daa1b79693199c00758fa22
|
7
|
+
data.tar.gz: b78b7cc95c55fde702b677e8e0a70126066341afeed726d4e3d00958b4cd4ad4d11850ef694329eca640019b5354bb34fb7efd246d023c065e7c37388c9de87e
|
data/README.adoc
CHANGED
@@ -89,6 +89,7 @@ The converter is run as:
|
|
89
89
|
----
|
90
90
|
c = Asciimath2UnitsML::Conv.new()
|
91
91
|
c.Asciimath2UnitsML({Asciimath string containing "unitsml()"})
|
92
|
+
c.MathML2UnitsML({MathML document containing <mtext>unitsml()</mtext>})
|
92
93
|
c.MathML2UnitsML({Nokogiri parse of MathML document containing <mtext>unitsml()</mtext>})
|
93
94
|
----
|
94
95
|
|
@@ -32,17 +32,21 @@ module Asciimath2UnitsML
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
def units_only(units)
|
36
|
+
units.reject { |u| u[:multiplier] }
|
37
|
+
end
|
38
|
+
|
35
39
|
def unit_id(text)
|
36
40
|
"U_" +
|
37
41
|
(@units[text.to_sym] ? @units[text.to_sym][:id] : text.gsub(/\*/, ".").gsub(/\^/, ""))
|
38
42
|
end
|
39
43
|
|
40
|
-
def unit(units,
|
44
|
+
def unit(units, origtext, normtext, dims)
|
41
45
|
dimid = dim_id(dims)
|
42
46
|
<<~END
|
43
|
-
<Unit xmlns='#{UNITSML_NS}' xml:id='#{unit_id(
|
47
|
+
<Unit xmlns='#{UNITSML_NS}' xml:id='#{unit_id(origtext)}'#{dimid ? " dimensionURL='##{dimid}'" : ""}>
|
44
48
|
#{unitsystem(units)}
|
45
|
-
#{unitname(units,
|
49
|
+
#{unitname(units, normtext)}
|
46
50
|
#{unitsymbol(units)}
|
47
51
|
#{rootunits(units)}
|
48
52
|
</Unit>
|
@@ -51,6 +55,7 @@ module Asciimath2UnitsML
|
|
51
55
|
|
52
56
|
def unitsystem(units)
|
53
57
|
ret = []
|
58
|
+
units = units_only(units)
|
54
59
|
units.any? { |x| @units[x[:unit].to_sym][:si] != true } and
|
55
60
|
ret << "<UnitSystem name='not_SI' type='not_SI' xml:lang='en-US'/>"
|
56
61
|
if units.any? { |x| @units[x[:unit].to_sym][:si] == true }
|
@@ -79,21 +84,27 @@ module Asciimath2UnitsML
|
|
79
84
|
|
80
85
|
def htmlsymbol(units)
|
81
86
|
units.map do |u|
|
82
|
-
u[:
|
83
|
-
|
84
|
-
|
87
|
+
if u[:multiplier] then u[:multiplier] == "*" ? @multiplier[:html] : u[:multiplier]
|
88
|
+
else
|
89
|
+
u[:display_exponent] and exp = "<sup>#{u[:display_exponent].sub(/-/, "−")}</sup>"
|
90
|
+
"#{u[:prefix]}#{u[:unit]}#{exp}"
|
91
|
+
end
|
92
|
+
end.join("")
|
85
93
|
end
|
86
94
|
|
87
95
|
def mathmlsymbol(units)
|
88
96
|
exp = units.map do |u|
|
89
|
-
|
90
|
-
if u[:exponent]
|
91
|
-
exp = "<mn>#{u[:exponent]}</mn>".sub(/<mn>-/, "<mo>−</mo><mn>")
|
92
|
-
"<msup><mrow>#{base}</mrow><mrow>#{exp}</mrow></msup>"
|
97
|
+
if u[:multiplier] then u[:multiplier] == "*" ? @multiplier[:mathml] : "<mo>#{u[:multiplier]}</mo>"
|
93
98
|
else
|
94
|
-
base
|
99
|
+
base = "<mi mathvariant='normal'>#{u[:prefix]}#{u[:unit]}</mi>"
|
100
|
+
if u[:display_exponent]
|
101
|
+
exp = "<mn>#{u[:display_exponent]}</mn>".sub(/<mn>-/, "<mo>−</mo><mn>")
|
102
|
+
"<msup><mrow>#{base}</mrow><mrow>#{exp}</mrow></msup>"
|
103
|
+
else
|
104
|
+
base
|
105
|
+
end
|
95
106
|
end
|
96
|
-
end.join(
|
107
|
+
end.join("")
|
97
108
|
end
|
98
109
|
|
99
110
|
def mathmlsymbolwrap(units)
|
@@ -106,9 +117,9 @@ module Asciimath2UnitsML
|
|
106
117
|
|
107
118
|
def rootunits(units)
|
108
119
|
return if units.size == 1
|
109
|
-
exp = units.map do |u|
|
120
|
+
exp = units_only(units).map do |u|
|
110
121
|
prefix = " prefix='#{u[:prefix]}'" if u[:prefix]
|
111
|
-
exponent = " powerNumerator='#{u[:exponent]}'" if u[:exponent]
|
122
|
+
exponent = " powerNumerator='#{u[:exponent]}'" if u[:exponent] && u[:exponent] != "1"
|
112
123
|
"<EnumeratedRootUnit unit='#{@units[u[:unit].to_sym][:name]}'#{prefix}#{exponent}/>"
|
113
124
|
end.join("\n")
|
114
125
|
<<~END
|
@@ -159,7 +170,7 @@ module Asciimath2UnitsML
|
|
159
170
|
end
|
160
171
|
|
161
172
|
def normalise_units(units)
|
162
|
-
gather_units(units.map { |u| normalise_unit(u) }.flatten)
|
173
|
+
gather_units(units_only(units).map { |u| normalise_unit(u) }.flatten)
|
163
174
|
end
|
164
175
|
|
165
176
|
def gather_units(units)
|
@@ -197,10 +208,10 @@ module Asciimath2UnitsML
|
|
197
208
|
"unknown"
|
198
209
|
end
|
199
210
|
|
200
|
-
def unitsml(units,
|
211
|
+
def unitsml(units, origtext, normtext)
|
201
212
|
dims = units2dimensions(units)
|
202
213
|
<<~END
|
203
|
-
#{unit(units,
|
214
|
+
#{unit(units, origtext, normtext, dims)}
|
204
215
|
#{prefix(units)}
|
205
216
|
#{dimension(dims)}
|
206
217
|
END
|
@@ -38,10 +38,10 @@ module Asciimath2UnitsML
|
|
38
38
|
end.map { |k| Regexp.escape(k) }
|
39
39
|
unit1 = /#{unit_keys.sort_by(&:length).reverse.join("|")}/.r
|
40
40
|
exponent = /\^-?\d+/.r.map { |m| m.sub(/\^/, "") }
|
41
|
-
multiplier =
|
42
|
-
unit = seq(unit1, exponent._?) { |x| { prefix: nil, unit: x[0],
|
43
|
-
seq(prefix, unit1, exponent._?) { |x| { prefix: x[0][0], unit: x[1],
|
44
|
-
units_tail = seq(multiplier, unit) { |
|
41
|
+
multiplier = %r{[*/]}.r.map { |x| { multiplier: x } }
|
42
|
+
unit = seq(unit1, exponent._?) { |x| { prefix: nil, unit: x[0], display_exponent: (x[1][0] )} } |
|
43
|
+
seq(prefix, unit1, exponent._?) { |x| { prefix: x[0][0], unit: x[1], display_exponent: (x[2][0] ) } }
|
44
|
+
units_tail = seq(multiplier, unit) { |x| [x[0], x[1]] }
|
45
45
|
units = seq(unit, units_tail.star) { |x| [x[0], x[1]].flatten }
|
46
46
|
parser = units.eof
|
47
47
|
end
|
@@ -52,7 +52,29 @@ module Asciimath2UnitsML
|
|
52
52
|
raise Rsec::SyntaxError.new "error parsing UnitsML expression", x, 1, 0
|
53
53
|
end
|
54
54
|
Rsec::Fail.reset
|
55
|
-
units
|
55
|
+
postprocess(units, x)
|
56
|
+
end
|
57
|
+
|
58
|
+
def postprocess(units, text)
|
59
|
+
units = postprocess1(units)
|
60
|
+
normtext = units_only(units).each.map do |u|
|
61
|
+
exp = u[:exponent] && u[:exponent] != "1" ? "^#{u[:exponent]}" : ""
|
62
|
+
"#{u[:prefix]}#{u[:unit]}#{exp}"
|
63
|
+
end.join("*")
|
64
|
+
[units, text, normtext]
|
65
|
+
end
|
66
|
+
|
67
|
+
def postprocess1(units)
|
68
|
+
inverse = false
|
69
|
+
units.each_with_object([]) do |u, m|
|
70
|
+
if u[:multiplier]
|
71
|
+
inverse = (u[:multiplier] == "/")
|
72
|
+
else
|
73
|
+
u[:exponent] = inverse ? "-#{u[:display_exponent] || '1'}" : u[:display_exponent]
|
74
|
+
u[:exponent] = u[:exponent]&.sub(/^--+/, "")
|
75
|
+
end
|
76
|
+
m << u
|
77
|
+
end
|
56
78
|
end
|
57
79
|
|
58
80
|
U2D = {
|
@@ -73,12 +95,14 @@ module Asciimath2UnitsML
|
|
73
95
|
|
74
96
|
# https://www.w3.org/TR/mathml-units/ section 2: delimit number Invisible-Times unit
|
75
97
|
def MathML2UnitsML(xml)
|
98
|
+
xml.is_a? String and xml = Nokogiri::XML(xml)
|
76
99
|
xml.xpath(".//m:mtext", "m" => MATHML_NS).each do |x|
|
77
100
|
next unless %r{^unitsml\(.+\)$}.match(x.text)
|
78
101
|
text = x.text.sub(%r{^unitsml\((.+)\)$}m, "\\1")
|
79
|
-
units = parse(text)
|
102
|
+
units, origtext, normtext = parse(text)
|
80
103
|
delim = x&.previous_element&.name == "mn" ? "<mo rspace='thickmathspace'>⁢</mo>" : ""
|
81
|
-
x.replace("#{delim}<mrow xref='#{unit_id(text)}'>#{mathmlsymbol(units)}</mrow>\n
|
104
|
+
x.replace("#{delim}<mrow xref='#{unit_id(text)}'>#{mathmlsymbol(units)}</mrow>\n"\
|
105
|
+
"#{unitsml(units, origtext, normtext)}")
|
82
106
|
end
|
83
107
|
xml
|
84
108
|
end
|
data/spec/conv_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require "spec_helper"
|
|
3
3
|
RSpec.describe Asciimath2UnitsML do
|
4
4
|
it "converts an AsciiMath string to MathML + UnitsML" do
|
5
5
|
expect(xmlpp(Asciimath2UnitsML::Conv.new().Asciimath2UnitsML(<<~INPUT))).to be_equivalent_to xmlpp(<<~OUTPUT)
|
6
|
-
32 + 5 xx 7 "unitsml(kg^-2)" xx 9 "unitsml(g)" xx 1 "unitsml(kg*s^-2)" xx 812 "unitsml(m*s^-2)" - 9 "unitsml(C^3*A)" + 7 "unitsml(hp)"
|
6
|
+
32 + 5 xx 7 "unitsml(kg^-2)" xx 9 "unitsml(g)" xx 1 "unitsml(kg*s^-2)" xx 812 "unitsml(m*s^-2)" - 9 "unitsml(C^3*A)" + 7 "unitsml(hp)" + 13 "unitsml(A/C^-3)"
|
7
7
|
INPUT
|
8
8
|
<math xmlns='http://www.w3.org/1998/Math/MathML'>
|
9
9
|
<mn>32</mn>
|
@@ -246,6 +246,72 @@ RSpec.describe Asciimath2UnitsML do
|
|
246
246
|
OUTPUT
|
247
247
|
end
|
248
248
|
|
249
|
+
it "converts MathML to MatML + UnitsML" do
|
250
|
+
input = <<~INPUT
|
251
|
+
<math xmlns='http://www.w3.org/1998/Math/MathML'>
|
252
|
+
<mn>32</mn>
|
253
|
+
<mo>+</mo>
|
254
|
+
<mn>5</mn>
|
255
|
+
<mo>×</mo>
|
256
|
+
<mn>7</mn>
|
257
|
+
<mtext>unitsml(kg^-2)</mtext>
|
258
|
+
</math>
|
259
|
+
INPUT
|
260
|
+
output = <<~OUTPUT
|
261
|
+
<math xmlns='http://www.w3.org/1998/Math/MathML'>
|
262
|
+
<mn>32</mn>
|
263
|
+
<mo>+</mo>
|
264
|
+
<mn>5</mn>
|
265
|
+
<mo>×</mo>
|
266
|
+
<mn>7</mn>
|
267
|
+
<mo rspace='thickmathspace'>⁢</mo>
|
268
|
+
<mrow xref='U_kg-2'>
|
269
|
+
<msup>
|
270
|
+
<mrow>
|
271
|
+
<mi mathvariant='normal'>kg</mi>
|
272
|
+
</mrow>
|
273
|
+
<mrow>
|
274
|
+
<mo>−</mo>
|
275
|
+
<mn>2</mn>
|
276
|
+
</mrow>
|
277
|
+
</msup>
|
278
|
+
</mrow>
|
279
|
+
<Unit xmlns='http://unitsml.nist.gov/2005' xml:id='U_kg-2' dimensionURL='#D_M-2'>
|
280
|
+
<UnitSystem name='SI' type='SI_base' xml:lang='en-US'/>
|
281
|
+
<UnitName xml:lang='en'>kg^-2</UnitName>
|
282
|
+
<UnitSymbol type='HTML'>
|
283
|
+
kg
|
284
|
+
<sup>−2</sup>
|
285
|
+
</UnitSymbol>
|
286
|
+
<UnitSymbol type='MathML'>
|
287
|
+
<math xmlns='http://www.w3.org/1998/Math/MathML'>
|
288
|
+
<mrow>
|
289
|
+
<msup>
|
290
|
+
<mrow>
|
291
|
+
<mi mathvariant='normal'>kg</mi>
|
292
|
+
</mrow>
|
293
|
+
<mrow>
|
294
|
+
<mo>−</mo>
|
295
|
+
<mn>2</mn>
|
296
|
+
</mrow>
|
297
|
+
</msup>
|
298
|
+
</mrow>
|
299
|
+
</math>
|
300
|
+
</UnitSymbol>
|
301
|
+
</Unit>
|
302
|
+
<Prefix xmlns='http://unitsml.nist.gov/2005' prefixBase='10' prefixPower='3' xml:id='NISTp10_3'>
|
303
|
+
<PrefixName xml:lang='en'>kilo</PrefixName>
|
304
|
+
<PrefixSymbol type='ASCII'>k</PrefixSymbol>
|
305
|
+
</Prefix>
|
306
|
+
<Dimension xmlns='http://unitsml.nist.gov/2005' xml:id='D_M-2'>
|
307
|
+
<Mass symbol='M' powerNumerator='-2'/>
|
308
|
+
</Dimension>
|
309
|
+
</math>
|
310
|
+
OUTPUT
|
311
|
+
expect(xmlpp(Asciimath2UnitsML::Conv.new().MathML2UnitsML(input).to_xml)).to be_equivalent_to xmlpp(output)
|
312
|
+
expect(xmlpp(Asciimath2UnitsML::Conv.new().MathML2UnitsML(Nokogiri::XML(input)).to_xml)).to be_equivalent_to xmlpp(output)
|
313
|
+
end
|
314
|
+
|
249
315
|
it "raises error for illegal unit" do
|
250
316
|
expect{xmlpp(Asciimath2UnitsML::Conv.new().Asciimath2UnitsML(<<~INPUT))}.to raise_error(Rsec::SyntaxError)
|
251
317
|
12 "unitsml(que?)"
|
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.1.
|
4
|
+
version: 0.1.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-02-
|
11
|
+
date: 2021-02-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: asciimath
|