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