mathml2asciimath 0.0.6 → 0.0.11

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: ed8645a43df0081966f9dfeb7adab874692f88744694c662b756b4422c49ce4d
4
- data.tar.gz: 2313a305a66a017c5dde637f3d2577530933b0619182a9edbe80328e604d5cf8
3
+ metadata.gz: aebdecff67a553ed83034b2f6fc90d1e1ec5b6be2225b2b74ae7bd951d1e313e
4
+ data.tar.gz: 8aea5d20406c5feab2d8a1713bd3928ecf6a4db264a2a1dbe6a3a87118db4f45
5
5
  SHA512:
6
- metadata.gz: df23f1866231c211cab0bd7fea974d792f15069b6286fcab8fca7a0121043807e21c41b52aa0fd23bbd6e906f7e67246533b7d66af47a5f4690ddfd93d3cb32d
7
- data.tar.gz: 074b6b0c7582313f40725e87d7ecb0a6a0866bd4a198eb9ba963b8d4a3d79712dfa9a7537c03bccae53321fc1a0cf083b9573c424329ea5a3208f41425e3bec8
6
+ metadata.gz: 27e09923df99f422a42ed234d4a9f0d2504f18f667bba3c45547d76d2852019399bfea08cae791e9bc27e1a946fe71b2ec6dd82492d436116f741f8c3e7b8ab2
7
+ data.tar.gz: 0b92d2dc4d0a5239a2487c80c27a812214c21de7164539ed4877fa140e9bb903dab8aec608e66bdb17e989c97f5d74385f4fa59de0016df878c3cff5d84d8679
@@ -0,0 +1,32 @@
1
+ # Auto-generated by Cimas: Do not edit it manually!
2
+ # See https://github.com/metanorma/cimas
3
+ name: rake
4
+
5
+ on:
6
+ push:
7
+ branches: [ master, main ]
8
+ tags: [ v* ]
9
+ pull_request:
10
+
11
+ jobs:
12
+ rake:
13
+ name: Test on Ruby ${{ matrix.ruby }} ${{ matrix.os }}
14
+ runs-on: ${{ matrix.os }}
15
+ continue-on-error: ${{ matrix.experimental }}
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ ruby: [ '3.0', '2.7', '2.6', '2.5', '2.4' ]
20
+ os: [ ubuntu-latest, windows-latest, macos-latest ]
21
+ experimental: [ false ]
22
+ steps:
23
+ - uses: actions/checkout@v2
24
+ with:
25
+ submodules: true
26
+
27
+ - uses: ruby/setup-ruby@v1
28
+ with:
29
+ ruby-version: ${{ matrix.ruby }}
30
+ bundler-cache: true
31
+
32
+ - run: bundle exec rake
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ .rubocop-https--*
data/.hound.yml CHANGED
@@ -1,3 +1,5 @@
1
+ # Auto-generated by Cimas: Do not edit it manually!
2
+ # See https://github.com/metanorma/cimas
1
3
  ruby:
2
- Enabled: true
4
+ enabled: true
3
5
  config_file: .rubocop.yml
data/.rubocop.yml CHANGED
@@ -1,10 +1,10 @@
1
- # This project follows the Ribose OSS style guide.
2
- # https://github.com/riboseinc/oss-guides
3
- # All project-specific additions and overrides should be specified in this file.
4
-
1
+ # Auto-generated by Cimas: Do not edit it manually!
2
+ # See https://github.com/metanorma/cimas
5
3
  inherit_from:
6
4
  - https://raw.githubusercontent.com/riboseinc/oss-guides/master/ci/rubocop.yml
5
+
6
+ # local repo-specific modifications
7
+ # ...
8
+
7
9
  AllCops:
8
- TargetRubyVersion: 2.3
9
- Rails:
10
- Enabled: true
10
+ TargetRubyVersion: 2.4
data/Gemfile CHANGED
@@ -1,5 +1,4 @@
1
1
  source "https://rubygems.org"
2
-
2
+
3
3
  # Specify your gem's dependencies in ruby-vobject.gemspec
4
4
  gemspec
5
-
data/README.adoc CHANGED
@@ -1,10 +1,12 @@
1
1
  = mathml2asciimath
2
2
 
3
3
  image:https://img.shields.io/gem/v/mathml2asciimath.svg["Gem Version", link="https://rubygems.org/gems/mathml2asciimath"]
4
- image:https://img.shields.io/travis/metanorma/mathml2asciimath/master.svg["Travis Build Status", link="https://travis-ci.org/metanorma/mathml2asciimath"]
5
- image:https://ci.appveyor.com/api/projects/status/qvd7fsh8m2aiua4c?svg=true["Appveyor Build Status", link="https://ci.appveyor.com/project/ribose/mathml2asciimath"]
6
- image:https://codeclimate.com/github/metanorma/mathml2asciimath/badges/gpa.svg["Code Climate", link="https://codeclimate.com/github/metanorma/mathml2asciimath"]
7
- image:https://ci.appveyor.com/api/projects/status/qvd7fsh8m2aiua4c?svg=true["Appveyor Build Status", link="https://ci.appveyor.com/project/ribose/mathml2asciimath"]
4
+ image:https://github.com/plurimath/mathml2asciimath/workflows/ubuntu/badge.svg["Ubuntu Build Status", link="https://github.com/plurimath/mathml2asciimath/actions?query=workflow%3Aubuntu"]
5
+ image:https://github.com/plurimath/mathml2asciimath/workflows/macos/badge.svg["OSX Build Status", link="https://github.com/plurimath/mathml2asciimath/actions?query=workflow%3Amacos"]
6
+ image:https://github.com/plurimath/mathml2asciimath/workflows/windows/badge.svg["Windows Build Status", link="https://github.com/plurimath/mathml2asciimath/actions?query=workflow%3Awindows"]
7
+ image:https://codeclimate.com/github/plurimath/mathml2asciimath/badges/gpa.svg["Code Climate", link="https://codeclimate.com/github/plurimath/mathml2asciimath"]
8
+ image:https://img.shields.io/github/issues-pr-raw/plurimath/mathml2asciimath.svg["Pull Requests", link="https://github.com/plurimath/mathml2asciimath/pulls"]
9
+ image:https://img.shields.io/github/commits-since/plurimath/mathml2asciimath/latest.svg["Commits since latest",link="https://github.com/plurimath/mathml2asciimath/releases"]
8
10
 
9
11
  Ruby gem to convert MathML into AsciiMath
10
12
 
data/Rakefile CHANGED
@@ -3,4 +3,4 @@ require "rspec/core/rake_task"
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
6
+ task default: :spec
data/bin/m2a.rb CHANGED
@@ -5,13 +5,11 @@ while a = gets
5
5
  matches = a.split(%r{(<math.*?</math>)})
6
6
  out = ""
7
7
  matches.each do |x|
8
- if /<math/.match x
9
- out += MathML2AsciiMath.m2a(x)
10
- else
11
- out += x
12
- end
8
+ out += if /<math/.match? x
9
+ MathML2AsciiMath.m2a(x)
10
+ else
11
+ x
12
+ end
13
13
  end
14
14
  print out
15
15
  end
16
-
17
-
data/bin/rspec CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
-
2
+
3
3
  # This file was generated by Bundler.
4
4
  #
5
5
  # The application 'rspec' is installed as part of a gem, and
@@ -3,267 +3,301 @@ require "htmlentities"
3
3
  require "pp"
4
4
 
5
5
  module MathML2AsciiMath
6
+ def self.m2a(xml)
7
+ normalized = xml
6
8
 
7
- def self.m2a(x)
8
- docxml = Nokogiri::XML(x)
9
- parse(docxml.root).gsub(/ /, " ").
10
- sub(/^\s+/, "").
11
- sub(/\s+$/, "")
9
+ # &:noblanks skips non-significant whitespaces in MathML
10
+ docxml = Nokogiri::XML.parse(normalized, &:noblanks)
11
+
12
+ # Get rid of things like
13
+ # <mtext>&#x2009;</mtext>
14
+ parse(docxml.root).gsub(/[[:blank:]]/, " ").unicode_normalize.squeeze(" ")
15
+ end
16
+
17
+ def self.encodechars(xml)
18
+ xml.gsub(/\u03b1/, "alpha")
19
+ .gsub(/\u03b2/, "beta")
20
+ .gsub(/\u03b3/, "gamma")
21
+ .gsub(/\u0393/, "Gamma")
22
+ .gsub(/\u03b4/, "delta")
23
+ .gsub(/\u0394/, "Delta")
24
+ .gsub(/\u2206/, "Delta")
25
+ .gsub(/\u03b5/, "epsilon")
26
+ .gsub(/\u025b/, "varepsilon")
27
+ .gsub(/\u03b6/, "zeta")
28
+ .gsub(/\u03b7/, "eta")
29
+ .gsub(/\u03b8/, "theta")
30
+ .gsub(/\u0398/, "Theta")
31
+ .gsub(/\u03d1/, "vartheta")
32
+ .gsub(/\u03b9/, "iota")
33
+ .gsub(/\u03ba/, "kappa")
34
+ .gsub(/\u03bb/, "lambda")
35
+ .gsub(/\u039b/, "Lambda")
36
+ .gsub(/\u03bc/, "mu")
37
+ .gsub(/\u03bd/, "nu")
38
+ .gsub(/\u03be/, "xi")
39
+ .gsub(/\u039e/, "Xi")
40
+ .gsub(/\u03c0/, "pi")
41
+ .gsub(/\u03a0/, "Pi")
42
+ .gsub(/\u03c1/, "rho")
43
+ .gsub(/\u03c2/, "beta")
44
+ .gsub(/\u03c3/, "sigma")
45
+ .gsub(/\u03a3/, "Sigma")
46
+ .gsub(/\u03c4/, "tau")
47
+ .gsub(/\u03c5/, "upsilon")
48
+ .gsub(/\u03c6/, "phi")
49
+ .gsub(/\u03a6/, "Phi")
50
+ .gsub(/\u03d5/, "varphi")
51
+ .gsub(/\u03c7/, "chi")
52
+ .gsub(/\u03c8/, "psi")
53
+ .gsub(/\u03a8/, "Psi")
54
+ .gsub(/\u03c9/, "omega")
55
+ .gsub(/\u03a9/, "omega")
56
+ .gsub(/\u22c5/, "*")
57
+ .gsub(/\u2219/, "*")
58
+ .gsub(/\u00b7/, "*")
59
+ .gsub(/\u2217/, "**")
60
+ .gsub(/\u22c6/, "***")
61
+ .gsub(/\//, "//")
62
+ .gsub(/\\/, "\\\\")
63
+ .gsub(/\u00d7/, "xx")
64
+ .gsub(/\u22c9/, "|><")
65
+ .gsub(/\u22ca/, "><|")
66
+ .gsub(/\u22c8/, "|><|")
67
+ .gsub(/\u00f7/, "-:")
68
+ .gsub(/\u2218/, "@")
69
+ .gsub(/\u2295/, "o+")
70
+ .gsub(/\u2a01/, "o+")
71
+ .gsub(/\u2297/, "ox")
72
+ .gsub(/\u2299/, "o.")
73
+ .gsub(/\u2211/, "sum")
74
+ .gsub(/\u220f/, "prod")
75
+ .gsub(/\u2227/, "^^")
76
+ .gsub(/\u22c0/, "^^^")
77
+ .gsub(/\u2228/, "vv")
78
+ .gsub(/\u22c1/, "vvv")
79
+ .gsub(/\u2229/, "nn")
80
+ .gsub(/\u22c2/, "nnn")
81
+ .gsub(/\u222a/, "uu")
82
+ .gsub(/\u22c3/, "uuu")
83
+ .gsub(/\u2260/, "!=")
84
+ .gsub(/\u2264/, "<=")
85
+ .gsub(/\u2265/, ">=")
86
+ .gsub(/\u227a/, "-<")
87
+ .gsub(/\u227b/, ">-")
88
+ .gsub(/\u2aaf/, "-<=")
89
+ .gsub(/\u2ab0/, ">-=")
90
+ .gsub(/\u2208/, "in")
91
+ .gsub(/\u2209/, "!in")
92
+ .gsub(/\u2282/, "sub")
93
+ .gsub(/\u2283/, "sup")
94
+ .gsub(/\u2286/, "sube")
95
+ .gsub(/\u2287/, "supe")
96
+ .gsub(/\u2261/, "-=")
97
+ .gsub(/\u2245/, "~=")
98
+ .gsub(/\u2248/, "~~")
99
+ .gsub(/\u221d/, "prop")
100
+ .gsub(/\u00ac/, "not")
101
+ .gsub(/\u21d2/, "=>")
102
+ .gsub(/\u21d4/, "<=>")
103
+ .gsub(/\u2200/, "AA")
104
+ .gsub(/\u2203/, "EE")
105
+ .gsub(/\u22a5/, "_|_")
106
+ .gsub(/\u22a4/, "TT")
107
+ .gsub(/\u22a2/, "|--")
108
+ .gsub(/\u22a8/, "|==")
109
+ .gsub(/\u22a8/, "|==")
110
+ .gsub(/\u2329/, "(:")
111
+ .gsub(/\u232a/, ":)")
112
+ .gsub(/\u2329/, "<<")
113
+ .gsub(/\u27e8/, "<<")
114
+ .gsub(/\u232a/, ">>")
115
+ .gsub(/\u27e9/, ">>")
116
+ .gsub(/\u222b/, "int")
117
+ .gsub(/\u222e/, "oint")
118
+ .gsub(/\u2202/, "del")
119
+ .gsub(/\u2207/, "grad")
120
+ .gsub(/\u00b1/, "+-")
121
+ .gsub(/\u2205/, "O/")
122
+ .gsub(/\u221e/, "oo")
123
+ .gsub(/\u2135/, "aleph")
124
+ .gsub(/\u2234/, ":.")
125
+ .gsub(/\u2235/, ":'")
126
+ .gsub(/\u2220/, "/_")
127
+ .gsub(/\u25b3/, "/_\\")
128
+ .gsub(/\u2032/, "'")
129
+ .gsub(/~/, "tilde")
130
+ .gsub(/\u00a0\u00a0\u00a0\u00a0/, "qquad")
131
+ .gsub(/\u00a0\u00a0/, "quad")
132
+ .gsub(/\u00a0/, "\\ ")
133
+ .gsub(/\u2322/, "frown")
134
+ .gsub(/\u00a0/, "quad")
135
+ .gsub(/\u22ef/, "cdots")
136
+ .gsub(/\u22ee/, "vdots")
137
+ .gsub(/\u22f1/, "ddots")
138
+ .gsub(/\u22c4/, "diamond")
139
+ .gsub(/\u25a1/, "square")
140
+ .gsub(/\u230a/, "|__")
141
+ .gsub(/\u230b/, "__|")
142
+ .gsub(/\u2308/, "|~")
143
+ .gsub(/\u2309/, "~|")
144
+ .gsub(/\u2102/, "CC")
145
+ .gsub(/\u2115/, "NN")
146
+ .gsub(/\u211a/, "QQ")
147
+ .gsub(/\u211d/, "RR")
148
+ .gsub(/\u2124/, "ZZ")
149
+ .gsub(/\u2191/, "uarr")
150
+ .gsub(/\u2193/, "darr")
151
+ .gsub(/\u2190/, "larr")
152
+ .gsub(/\u2194/, "harr")
153
+ .gsub(/\u21d2/, "rArr")
154
+ .gsub(/\u21d0/, "lArr")
155
+ .gsub(/\u21d4/, "hArr")
156
+ .gsub(/\u2192/, "->")
157
+ .gsub(/\u21a3/, ">->")
158
+ .gsub(/\u21a0/, "->>")
159
+ .gsub(/\u2916/, ">->>")
160
+ .gsub(/\u21a6/, "|->")
161
+ .gsub(/\u2026/, "...")
162
+ .gsub(/\u2212/, "-")
163
+ .gsub(/\u2061/, "") # function application
164
+ .gsub(/\u2751/, "square")
165
+ .gsub(/[\u2028\u2029]/, " ") # normalize thin spaces like \u2009, \u2008
12
166
  end
13
167
 
14
- def self.encodechars(x)
15
- x.gsub(/\u03b1/, "\\alpha").
16
- gsub(/\u03b2/, "\\beta").
17
- gsub(/\u03b3/, "\\gamma").
18
- gsub(/\u0393/, "\\Gamma").
19
- gsub(/\u03b4/, "\\delta").
20
- gsub(/\u0394/, "\\Delta").
21
- gsub(/\u2206/, "\\Delta").
22
- gsub(/\u03b5/, "\\epsilon").
23
- gsub(/\u025b/, "\\varepsilon").
24
- gsub(/\u03b6/, "\\zeta").
25
- gsub(/\u03b7/, "\\eta").
26
- gsub(/\u03b8/, "\\theta").
27
- gsub(/\u0398/, "\\Theta").
28
- gsub(/\u03d1/, "\\vartheta").
29
- gsub(/\u03b9/, "\\iota").
30
- gsub(/\u03ba/, "\\kappa").
31
- gsub(/\u03bb/, "\\lambda").
32
- gsub(/\u039b/, "\\Lambda").
33
- gsub(/\u03bc/, "\\mu").
34
- gsub(/\u03bd/, "\\nu").
35
- gsub(/\u03be/, "\\xi").
36
- gsub(/\u039e/, "\\Xi").
37
- gsub(/\u03c0/, "\\pi").
38
- gsub(/\u03a0/, "\\Pi").
39
- gsub(/\u03c1/, "\\rho").
40
- gsub(/\u03c2/, "\\beta").
41
- gsub(/\u03c3/, "\\sigma").
42
- gsub(/\u03a3/, "\\Sigma").
43
- gsub(/\u03c4/, "\\tau").
44
- gsub(/\u03c5/, "\\upsilon").
45
- gsub(/\u03c6/, "\\phi").
46
- gsub(/\u03a6/, "\\Phi").
47
- gsub(/\u03d5/, "\\varphi").
48
- gsub(/\u03c7/, "\\chi").
49
- gsub(/\u03c8/, "\\psi").
50
- gsub(/\u03a8/, "\\Psi").
51
- gsub(/\u03c9/, "\\omega").
52
- gsub(/\u22c5/, "*").
53
- gsub(/\u2219/, "*").
54
- gsub(/\u00b7/, "*").
55
- gsub(/\u2217/, "**").
56
- gsub(/\u22c6/, "***").
57
- gsub(/\//, "//").
58
- gsub(/\\/, "\\\\").
59
- gsub(/\u00d7/, "xx").
60
- gsub(/\u22c9/, "|><").
61
- gsub(/\u22ca/, "><|").
62
- gsub(/\u22c8/, "|><|").
63
- gsub(/\u00f7/, "-:").
64
- gsub(/\u2218/, "@").
65
- gsub(/\u2295/, "o+").
66
- gsub(/\u2a01/, "o+").
67
- gsub(/\u2297/, "ox").
68
- gsub(/\u2299/, "o.").
69
- gsub(/\u2211/, "sum").
70
- gsub(/\u220f/, "prod").
71
- gsub(/\u2227/, "^^").
72
- gsub(/\u22c0/, "^^^").
73
- gsub(/\u2228/, "vv").
74
- gsub(/\u22c1/, "vvv").
75
- gsub(/\u2229/, "nn").
76
- gsub(/\u22c2/, "nnn").
77
- gsub(/\u222a/, "uu").
78
- gsub(/\u22c3/, "uuu").
79
- gsub(/\u2260/, "!=").
80
- gsub(/\u2264/, "<=").
81
- gsub(/\u2265/, ">=").
82
- gsub(/\u227a/, "-<").
83
- gsub(/\u227b/, ">-").
84
- gsub(/\u2aaf/, "-<=").
85
- gsub(/\u2ab0/, ">-=").
86
- gsub(/\u2208/, "in").
87
- gsub(/\u2209/, "!in").
88
- gsub(/\u2282/, "sub").
89
- gsub(/\u2283/, "sup").
90
- gsub(/\u2286/, "sube").
91
- gsub(/\u2287/, "supe").
92
- gsub(/\u2261/, "-=").
93
- gsub(/\u2245/, "~=").
94
- gsub(/\u2248/, "~~").
95
- gsub(/\u221d/, "prop").
96
- gsub(/\u00ac/, "not").
97
- gsub(/\u21d2/, "=>").
98
- gsub(/\u21d4/, "<=>").
99
- gsub(/\u2200/, "AA").
100
- gsub(/\u2203/, "EE").
101
- gsub(/\u22a5/, "_|_").
102
- gsub(/\u22a4/, "TT").
103
- gsub(/\u22a2/, "|--").
104
- gsub(/\u22a8/, "|==").
105
- gsub(/\u22a8/, "|==").
106
- gsub(/\u2329/, "(:").
107
- gsub(/\u232a/, ":)").
108
- gsub(/\u2329/, "<<").
109
- gsub(/\u27e8/, "<<").
110
- gsub(/\u232a/, ">>").
111
- gsub(/\u27e9/, ">>").
112
- gsub(/\u222e/, "oint").
113
- gsub(/\u2202/, "del").
114
- gsub(/\u2207/, "grad").
115
- gsub(/\u00b1/, "+-").
116
- gsub(/\u2205/, "O/").
117
- gsub(/\u221e/, "oo").
118
- gsub(/\u2135/, "aleph").
119
- gsub(/\u2234/, ":.").
120
- gsub(/\u2235/, ":'").
121
- gsub(/\u2220/, "/_").
122
- gsub(/\u25b3/, "/_\\").
123
- gsub(/\u2032/, "'").
124
- gsub(/~/, "tilde").
125
- gsub(/\u00a0\u00a0\u00a0\u00a0/, "qquad").
126
- gsub(/\u00a0\u00a0/, "quad").
127
- gsub(/\u00a0/, "\\ ").
128
- gsub(/\u2322/, "frown").
129
- gsub(/\u00a0/, "quad").
130
- gsub(/\u22ef/, "cdots").
131
- gsub(/\u22ee/, "vdots").
132
- gsub(/\u22f1/, "ddots").
133
- gsub(/\u22c4/, "diamond").
134
- gsub(/\u25a1/, "square").
135
- gsub(/\u230a/, "|__").
136
- gsub(/\u230b/, "__|").
137
- gsub(/\u2308/, "|~").
138
- gsub(/\u2309/, "~|").
139
- gsub(/\u2102/, "CC").
140
- gsub(/\u2115/, "NN").
141
- gsub(/\u211a/, "QQ").
142
- gsub(/\u211d/, "RR").
143
- gsub(/\u2124/, "ZZ").
144
- gsub(/\u2191/, "uarr").
145
- gsub(/\u2193/, "darr").
146
- gsub(/\u2190/, "larr").
147
- gsub(/\u2194/, "harr").
148
- gsub(/\u21d2/, "rArr").
149
- gsub(/\u21d0/, "lArr").
150
- gsub(/\u21d4/, "hArr").
151
- gsub(/\u2192/, "->").
152
- gsub(/\u21a3/, ">->").
153
- gsub(/\u21a0/, "->>").
154
- gsub(/\u2916/, ">->>").
155
- gsub(/\u21a6/, "|->").
156
- gsub(/\u2026/, "...").
157
- gsub(/\u2212/, "-").
158
- gsub(/\u2061/, ""). # function application
159
- gsub(/\u2751/, "square")
168
+ def self.join_parsed_children(children, delimiter = " ")
169
+ children.map do |n|
170
+ parse(n).strip
171
+ end.join(delimiter)
160
172
  end
161
173
 
162
174
  def self.parse(node)
163
175
  out = ""
164
176
  if node.text?
165
177
  return encodechars(HTMLEntities.new.decode(node.text))
166
- else
167
- case node.name
168
- when "math"
169
- node.elements.each { |n| out << parse(n) }
170
- return out
171
- when "mrow"
172
- outarr = []
173
- node.children.each { |n| outarr << parse(n) }
174
- out = outarr.join("")
175
- if %w{mfrac msub munder munderover}.include? node.parent.name
176
- out = "(#{out})"
177
- end
178
- return out
179
- when "mfenced"
180
- outarr = []
181
- open = node["open"] || "("
182
- close = node["close"] || ")"
183
- separator = "," # TODO currently ignore the supplied separators
184
- node.elements.each { |n| outarr << parse(n) }
185
- out = outarr.join(separator)
186
- return "#{open}#{out}#{close}"
187
- when "msqrt"
188
- node.children.each { |n| out << parse(n) }
189
- return "sqrt(#{out})"
190
- when "mfrac"
191
- return "(#{parse(node.elements[0])})/(#{parse(node.elements[1])})"
192
- when "msup"
193
- sup = parse(node.elements[1])
194
- sup = "(#{sup})" unless sup.length == 1
195
- op = parse(node.elements[0]).gsub(/ $/, "")
196
- return "#{op}^#{sup}"
197
- when "msub"
198
- sub = parse(node.elements[1])
199
- sub = "(#{sub})" unless sub.length == 1
200
- op = parse(node.elements[0]).gsub(/ $/, "")
201
- return "#{op}_#{sub}"
202
- when "munderover", "msubsup"
203
- sub = parse(node.elements[1])
204
- sub = "(#{sub})" unless sub.length == 1
205
- sup = parse(node.elements[2])
206
- sup = "(#{sup})" unless sup.length == 1
207
- op = parse(node.elements[0]).gsub(/ $/, "")
208
- return "#{op}_#{sub}^#{sup}"
209
- when "munder"
210
- elem1 = parse(node.elements[1]).sub(/^\s+/, "").sub(/\s+$/, "")
211
- accent = case elem1
212
- when "\u0332" then "ul"
213
- when "\u23df" then "ubrace"
214
- else
215
- "underset"
216
- end
217
- if accent == "underset"
218
- return "underset(#{elem1})(#{parse(node.elements[0])})"
219
- else
220
- return "#{accent} #{parse(node.elements[0])}"
221
- end
222
- when "mover"
223
- elem1 = parse(node.elements[1]).sub(/^\s+/, "").sub(/\s+$/, "")
224
- accent = case elem1
225
- when "\u005e" then "hat"
226
- when "\u00af" then "bar"
227
- #when "\u2192" then "vec"
228
- when "->" then "vec"
229
- when "." then "dot"
230
- when ".." then "ddot"
231
- when "\u23de" then "obrace"
232
- else
233
- "overset"
234
- end
235
- if accent == "overset"
236
- return "overset(#{elem1})(#{parse(node.elements[0])})"
237
- else
238
- return "#{accent} #{parse(node.elements[0])}"
239
- end
240
- when "mtable"
241
- rows = []
242
- node.elements.each { |n| rows << parse(n) }
243
- return "[#{rows.join(",")}]"
244
- when "mtr"
245
- cols = []
246
- node.elements.each { |n| cols << parse(n) }
247
- return "[#{cols.join(",")}]"
248
- when "mtd"
249
- node.elements.each { |n| out << parse(n) }
250
- return "#{out}"
251
- when "mn", "mtext"
252
- node.children.each { |n| out << parse(n) }
253
- return "#{out}"
254
- when "mi"
255
- # mi is not meant to have space around it, but Word is conflating operators and operands
256
- node.children.each { |n| out << parse(n) }
257
- out = " #{out} " if /[^a-zA-Z0-9',]|[a-z][a-z]/.match out
258
- return out
259
- when "mo"
260
- node.children.each { |n| out << parse(n) }
261
- out = " #{out} " unless node["fence"]
262
- return out
178
+ end
179
+
180
+ case node.name.sub(/^[^:]*:/, "")
181
+ when "math"
182
+ join_parsed_children(node.elements)
183
+
184
+ when "annotation"
185
+ ""
186
+
187
+ when "semantics"
188
+ join_parsed_children(node.elements)
189
+
190
+ when "mrow"
191
+ out = join_parsed_children(node.elements)
192
+ if %w[mfrac msub munder munderover]
193
+ .include? node.parent.name.sub(/^[^:]*:/, "")
194
+ out = "(#{out})"
195
+ end
196
+ out
197
+
198
+ when "mfenced"
199
+ sym_open = node["open"] || "("
200
+ sym_close = node["close"] || ")"
201
+
202
+ separator = "," # TODO currently ignore the supplied separators
203
+ out = join_parsed_children(node.elements, separator)
204
+ "#{sym_open}#{out}#{sym_close}"
205
+
206
+ when "msqrt"
207
+ "sqrt(#{join_parsed_children(node.elements)})"
208
+
209
+ when "mfrac"
210
+ "(#{parse(node.elements[0])})/(#{parse(node.elements[1])})"
211
+
212
+ when "msup"
213
+ sup = parse(node.elements[1])
214
+ sup = "(#{sup})" unless sup.length == 1
215
+ op = parse(node.elements[0]).gsub(/ $/, "")
216
+ "#{op}^#{sup}"
217
+
218
+ when "msub"
219
+ sub = parse(node.elements[1])
220
+ sub = "(#{sub})" unless sub.length == 1
221
+ op = parse(node.elements[0]).gsub(/ $/, "")
222
+ "#{op}_#{sub}"
223
+
224
+ when "munderover", "msubsup"
225
+ sub = parse(node.elements[1])
226
+ sub = "(#{sub})" unless sub.length == 1
227
+ sup = parse(node.elements[2])
228
+ sup = "(#{sup})" unless sup.length == 1
229
+ op = parse(node.elements[0]).gsub(/ $/, "")
230
+ "#{op}_#{sub}^#{sup}"
231
+
232
+ when "munder"
233
+ elem1 = parse(node.elements[1]).strip
234
+ accent = case elem1
235
+ when "\u0332" then "ul"
236
+ when "\u23df" then "ubrace"
237
+ else
238
+ "underset"
239
+ end
240
+
241
+ if accent == "underset"
242
+ "underset(#{elem1})(#{parse(node.elements[0])})"
243
+ else
244
+ "#{accent} #{parse(node.elements[0])}"
245
+ end
246
+
247
+ when "mover"
248
+ elem1 = parse(node.elements[1]).strip
249
+ accent = case elem1
250
+ when "\u005e" then "hat"
251
+ when "\u00af" then "bar"
252
+ # when "\u2192" then "vec"
253
+ when "->" then "vec"
254
+ when "." then "dot"
255
+ when ".." then "ddot"
256
+ when "\u23de" then "obrace"
257
+ else
258
+ "overset"
259
+ end
260
+
261
+ if accent == "overset"
262
+ "overset(#{elem1})(#{parse(node.elements[0])})"
263
263
  else
264
- node.to_xml
264
+ "#{accent} #{parse(node.elements[0])}"
265
265
  end
266
+
267
+ when "mtable"
268
+ "[#{join_parsed_children(node.elements, ',')}]"
269
+
270
+ when "mtr"
271
+ "[#{join_parsed_children(node.elements, ',')}]"
272
+
273
+ when "mtd"
274
+ join_parsed_children(node.elements, ",")
275
+
276
+ when "mn", "mtext"
277
+ join_parsed_children(node.children, "")
278
+
279
+ when "mi"
280
+ # FIXME: What does this comment have to do with Word?
281
+ # mi is not meant to have space around it,
282
+ # but Word is conflating operators and operands
283
+ join_parsed_children(node.children)
284
+
285
+ # FIXME: Why do we need to add extra spaces?
286
+ # out = " #{out} " if /[^a-zA-Z0-9',]|[a-z][a-z]/.match out
287
+
288
+ when "mo"
289
+ out = join_parsed_children(node.children)
290
+ out = " #{out} " unless node["fence"]
291
+ out
292
+
293
+ when "mstyle"
294
+ join_parsed_children(node.children)
295
+
296
+ else
297
+ "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">" +
298
+ node.to_xml +
299
+ "</math>"
300
+
266
301
  end
267
302
  end
268
-
269
303
  end