asciimath 2.0.1 → 2.0.4

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: d4492ccf2978a02b79bf6d5a70a23871fd33db6893e4a90b1b159db3b4d7b8b3
4
- data.tar.gz: 43fbc1d2bba388ca359e0e908e0118b22189479cc05bf4a9882cb6459b4c6488
3
+ metadata.gz: 6c38e7e41750527b0992c27f6e636cb6b670eec3008563e1a5fe19fc86458991
4
+ data.tar.gz: 3313df7a9524d4a4e384be1ec54f38aafe2ff70553ae65aa695c530fff5f45e9
5
5
  SHA512:
6
- metadata.gz: 60c01de3ce18dd8eec2ff1a1fa559da2e0de840e08b59686ab3d1ff913a02f2656f2d8ceee1106657ae99bf9de2fdb2f80eeef1f71cc604845541d9d503f7bed
7
- data.tar.gz: 62e0c29f76f709c53b040260dee1e36dce9af4c8737822297ea9d1908b2c72ade763d236c36266c411ce8f7330fbf397d4f0877ac2d5fc80d9064c40920bcbee
6
+ metadata.gz: a7b29b1332ddb6965162a5b1e82d15c459e5a9ea4d514646b0663ea52adfe5b1999d1078e850dee228160e09b5ac052dde48b39aaa946d6587b97b2658109215
7
+ data.tar.gz: 6bfce3c229fea323dbfaff74ab1987802b9ae6c7b0ae32562b868bc5da2fd35bc76d0a8c9aa1e414c2765839e02065c5575d5366af89e4becadb882ee084ce08
@@ -0,0 +1,20 @@
1
+ name: CI
2
+ on: [push, pull_request]
3
+ jobs:
4
+ test:
5
+ strategy:
6
+ matrix:
7
+ ruby: [jruby, 2.3, 2.4, 2.5, 2.6, 2.7]
8
+ os: [ubuntu-latest, macos-latest, windows-latest]
9
+ runs-on: ${{ matrix.os }}
10
+ steps:
11
+ - name: Checkout
12
+ uses: actions/checkout@v2
13
+ - name: Set up Ruby
14
+ uses: ruby/setup-ruby@v1
15
+ with:
16
+ ruby-version: ${{ matrix.ruby }}
17
+ - name: Build
18
+ run: bundle install --jobs 4 --retry 3
19
+ - name: Test
20
+ run: bundle exec rake test
data/AST.adoc CHANGED
@@ -257,8 +257,8 @@ Empty matrix cells are represented as `AsciiMath::AST::Empty`.
257
257
  |++oo++ |:infty |++∞++ (https://codepoints.net/U+221E[U+221E]) |++\infty++
258
258
  |++infty++ |:infty |++∞++ (https://codepoints.net/U+221E[U+221E]) |++\infty++
259
259
  |++aleph++ |:aleph |++ℵ++ (https://codepoints.net/U+2135[U+2135]) |++\aleph++
260
- |++...++ |:ellipsis |++…++ (https://codepoints.net/U+2026[U+2026]) |++\ellipsis++
261
- |++ldots++ |:ellipsis |++…++ (https://codepoints.net/U+2026[U+2026]) |++\ellipsis++
260
+ |++...++ |:ellipsis |++…++ (https://codepoints.net/U+2026[U+2026]) |++\ldots++
261
+ |++ldots++ |:ellipsis |++…++ (https://codepoints.net/U+2026[U+2026]) |++\ldots++
262
262
  |++:.++ |:therefore |++∴++ (https://codepoints.net/U+2234[U+2234]) |++\therefore++
263
263
  |++therefore++ |:therefore |++∴++ (https://codepoints.net/U+2234[U+2234]) |++\therefore++
264
264
  |++:'++ |:because |++∵++ (https://codepoints.net/U+2235[U+2235]) |++\because++
data/CHANGELOG.adoc CHANGED
@@ -1,5 +1,36 @@
1
1
  = Asciimath Changelog
2
2
 
3
+ == 2.0.4
4
+
5
+ Bug fixes::
6
+
7
+ * Issue #69: correctly render sub and superscripts as following `obrace` and `ubrace`.
8
+ * Issue #70: fix MathML output for `frac`.
9
+ * Issue #71: correctly parse row vectors.
10
+
11
+ == 2.0.3
12
+
13
+ Enhancements::
14
+
15
+ * Issue #59: make escaping of non-ASCII characters in MathML and HTML output optional.
16
+
17
+ Bug fixes::
18
+
19
+ * Issue #58: produce `<mo>` tags instead of `<mi>` tags for non-alphanumeric strings.
20
+ * Issue #62: resolve infinite recursion in LaTeX generator.
21
+
22
+ == 2.0.2
23
+
24
+ Enhancements::
25
+
26
+ * Issue #51: generate `accent` and `accentunder` attributes on `munder`, `mover`, and `munderover` tags when appropriate
27
+ * Issue #52: map `phi` to U+03D5 and `varphi` to U+03C6 by default.
28
+ * Issue #53: Add support for Roman style font command `rm`.
29
+
30
+ Bug fixes::
31
+
32
+ * Issue #50: fix parsing error when unary and binary operators are missing an operand
33
+
3
34
  == 2.0.1
4
35
 
5
36
  Enhancements::
data/Gemfile CHANGED
@@ -2,3 +2,8 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in asciimath.gemspec
4
4
  gemspec
5
+
6
+ gem "bundler", "> 0"
7
+ gem "rake", "~> 13.0.0"
8
+ gem "rspec", "~> 3.9.0"
9
+ gem "nokogiri"
data/README.adoc CHANGED
@@ -1,4 +1,5 @@
1
1
  # AsciiMath
2
+ :uri-project: https://github.com/asciidoctor/asciimath
2
3
  ifndef::env-site[:status:]
3
4
 
4
5
  An http://asciimath.org[AsciiMath] parser and MathML/LaTeX generator written in pure Ruby.
@@ -7,7 +8,7 @@ ifdef::status[]
7
8
  [discrete]
8
9
  ## Status
9
10
 
10
- image:https://travis-ci.org/pepijnve/asciimath.svg?branch=master["Linux Build Status", link="https://travis-ci.org/asciidoctor/asciimath"]
11
+ image:{uri-project}/workflows/CI/badge.svg?branch=master["Build Status", link={uri-project}/actions?query=branch%3Amaster]
11
12
  image:https://img.shields.io/gem/v/asciimath.svg?label=gem%20version[Gem Version, link=https://rubygems.org/gems/asciimath]
12
13
  endif::status[]
13
14
 
data/asciimath.gemspec CHANGED
@@ -18,9 +18,4 @@ Gem::Specification.new do |spec|
18
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
20
  spec.require_paths = ["lib"]
21
-
22
- spec.add_development_dependency "bundler", "> 0"
23
- spec.add_development_dependency "rake", "~> 13.0.0"
24
- spec.add_development_dependency "rspec", "~> 3.9.0"
25
- spec.add_development_dependency "nokogiri", "~> 1.10.9"
26
21
  end
data/dump_symbol_table.rb CHANGED
@@ -21,7 +21,7 @@ AsciiMath::Parser::DEFAULT_PARSER_SYMBOL_TABLE.each_pair do |asciimath, value|
21
21
  next
22
22
  end
23
23
 
24
- mathml = AsciiMath::MathMLBuilder::DEFAULT_DISPLAY_SYMBOL_TABLE[sym]
24
+ mathml = AsciiMath::MathMLBuilder.default_display_symbol_table[sym]
25
25
 
26
26
  if mathml
27
27
  val = mathml[:value]
data/lib/asciimath/ast.rb CHANGED
@@ -51,8 +51,8 @@ module AsciiMath
51
51
  Number.new(value)
52
52
  end
53
53
 
54
- def symbol(symbol, text)
55
- Symbol.new(symbol, text)
54
+ def symbol(symbol, text, type)
55
+ Symbol.new(symbol, text, type)
56
56
  end
57
57
 
58
58
  def identifier(value)
@@ -340,14 +340,16 @@ module AsciiMath
340
340
 
341
341
  class Symbol < ValueNode
342
342
  attr_reader :text
343
+ attr_reader :type
343
344
 
344
- def initialize(value, text)
345
+ def initialize(value, text, type)
345
346
  super(value)
346
347
  @text = text.dup.freeze
348
+ @type = type
347
349
  end
348
350
 
349
351
  def ==(o)
350
- super && o.text == text
352
+ super && o.text == text && o.type == type
351
353
  end
352
354
 
353
355
  def to_s
@@ -4,9 +4,10 @@ module AsciiMath
4
4
  class HTMLBuilder < ::AsciiMath::MarkupBuilder
5
5
 
6
6
  def initialize(opts = {})
7
- super(opts[:symbol_table] || DEFAULT_DISPLAY_SYMBOL_TABLE)
7
+ super(opts[:symbol_table] || ::AsciiMath::MarkupBuilder.default_display_symbol_table(fix_phi: opts.fetch(:fix_phi, true)))
8
8
  @prefix = opts[:prefifx] || ''
9
9
  @inline = opts[:inline]
10
+ @escape_non_ascii = opts.fetch(:escape_non_ascii, true)
10
11
  @html = ''
11
12
  end
12
13
 
@@ -227,7 +228,7 @@ module AsciiMath
227
228
  @html << "&lt;"
228
229
  elsif cp == 62
229
230
  @html << "&gt;"
230
- elsif cp > 127
231
+ elsif cp > 127 && @escape_non_ascii
231
232
  @html << "&#x#{cp.to_s(16).upcase};"
232
233
  else
233
234
  @html << cp
@@ -27,7 +27,9 @@ module AsciiMath
27
27
  :ne => "\\neq",
28
28
  :assign => ":=",
29
29
  :lt => ?<,
30
+ :mlt => "\\ll",
30
31
  :gt => ?>,
32
+ :mgt => "\\gg",
31
33
  :sub => "\\text{–}",
32
34
  :sup => "\\text{^}",
33
35
  :implies => "\\Rightarrow",
@@ -83,6 +85,7 @@ module AsciiMath
83
85
  :f => "f",
84
86
  :g => "g",
85
87
  :to => "\\rightarrow",
88
+ :ellipsis => "\\ldots",
86
89
  :bold => "\\mathbf",
87
90
  :double_struck => "\\mathbb",
88
91
  :italic => "\\mathit",
@@ -96,6 +99,7 @@ module AsciiMath
96
99
  :bold_sans_serif => "\\mathsf",
97
100
  :sans_serif_italic => "\\mathsf",
98
101
  :sans_serif_bold_italic => "\\mathsf",
102
+ :roman => "\\mathrm",
99
103
  }.freeze
100
104
 
101
105
  private
@@ -165,7 +169,12 @@ module AsciiMath
165
169
  sup = expression.sup_expression
166
170
  e = expression.base_expression
167
171
 
172
+ if e.is_a?(AsciiMath::AST::UnaryOp) &&
173
+ %i[underbrace overbrace].include?(e.operator.value)
174
+ append(e)
175
+ else
168
176
  curly(e)
177
+ end
169
178
 
170
179
  if sub
171
180
  @latex << "_"
@@ -244,8 +253,6 @@ module AsciiMath
244
253
  end
245
254
 
246
255
  when AsciiMath::AST::Matrix
247
- len = expression.length - 1
248
-
249
256
  parens(expression.lparen, expression.rparen) do
250
257
  c = expression.length
251
258
  @latex << "\\begin{matrix} "
@@ -383,7 +390,7 @@ module AsciiMath
383
390
  when AsciiMath::AST::Group
384
391
  is_very_small(e.expression)
385
392
  when AsciiMath::AST::Sequence
386
- e.all? { |s| is_very_small(e) }
393
+ e.all? { |s| is_very_small(s) }
387
394
  when nil
388
395
  true
389
396
  else
@@ -4,7 +4,7 @@ require_relative 'symbol_table'
4
4
  module AsciiMath
5
5
  class MarkupBuilder
6
6
  # Operation symbols
7
- def self.add_default_display_symbols(b)
7
+ def self.add_default_display_symbols(b, fix_phi: true)
8
8
  b.add(:plus, '+', :operator)
9
9
  b.add(:minus, "\u2212", :operator)
10
10
  b.add(:cdot, "\u22C5", :operator)
@@ -38,7 +38,9 @@ module AsciiMath
38
38
  b.add(:ne, "\u2260", :operator)
39
39
  b.add(:assign, "\u2254", :operator)
40
40
  b.add(:lt, "\u003C", :operator)
41
+ b.add(:mlt, "\u226A", :operator)
41
42
  b.add(:gt, "\u003E", :operator)
43
+ b.add(:mgt, "\u226B", :operator)
42
44
  b.add(:le, "\u2264", :operator)
43
45
  b.add(:ge, "\u2265", :operator)
44
46
  b.add(:prec, "\u227A", :operator)
@@ -52,6 +54,7 @@ module AsciiMath
52
54
  b.add(:subseteq, "\u2286", :operator)
53
55
  b.add(:supseteq, "\u2287", :operator)
54
56
  b.add(:equiv, "\u2261", :operator)
57
+ b.add(:sim, "\u223C", :operator)
55
58
  b.add(:cong, "\u2245", :operator)
56
59
  b.add(:approx, "\u2248", :operator)
57
60
  b.add(:propto, "\u221D", :operator)
@@ -92,6 +95,7 @@ module AsciiMath
92
95
  b.add(:partial, "\u2202", :operator)
93
96
  b.add(:nabla, "\u2207", :operator)
94
97
  b.add(:pm, "\u00B1", :operator)
98
+ b.add(:mp, "\u2213", :operator)
95
99
  b.add(:emptyset, "\u2205", :operator)
96
100
  b.add(:infty, "\u221E", :operator)
97
101
  b.add(:aleph, "\u2135", :operator)
@@ -206,8 +210,8 @@ module AsciiMath
206
210
  b.add(:ddot, '..', :accent, :position => :over)
207
211
  b.add(:overarc, "\u23DC", :accent, :position => :over)
208
212
  b.add(:underline, '_', :accent, :position => :under)
209
- b.add(:underbrace, "\u23DF", :accent, :position => :under)
210
- b.add(:overbrace, "\u23DE", :accent, :position => :over)
213
+ b.add(:underbrace, "\u23DF", :accent, :position => :under, :underover => true)
214
+ b.add(:overbrace, "\u23DE", :accent, :position => :over, :underover => true)
211
215
  b.add(:bold, :bold, :font)
212
216
  b.add(:double_struck, :double_struck, :font)
213
217
  b.add(:italic, :italic, :font)
@@ -221,6 +225,7 @@ module AsciiMath
221
225
  b.add(:bold_sans_serif, :bold_sans_serif, :font)
222
226
  b.add(:sans_serif_italic, :sans_serif_italic, :font)
223
227
  b.add(:sans_serif_bold_italic, :sans_serif_bold_italic, :font)
228
+ b.add(:roman, :normal, :font)
224
229
 
225
230
  # Greek letters
226
231
  b.add(:alpha, "\u03b1", :identifier)
@@ -265,9 +270,14 @@ module AsciiMath
265
270
  b.add(:Tau, "\u03a4", :identifier)
266
271
  b.add(:upsilon, "\u03c5", :identifier)
267
272
  b.add(:Upsilon, "\u03a5", :identifier)
268
- b.add(:phi, "\u03c6", :identifier)
273
+ if fix_phi
274
+ b.add(:phi, "\u03d5", :identifier)
275
+ b.add(:varphi, "\u03c6", :identifier)
276
+ else
277
+ b.add(:phi, "\u03c6", :identifier)
278
+ b.add(:varphi, "\u03d5", :identifier)
279
+ end
269
280
  b.add(:Phi, "\u03a6", :identifier)
270
- b.add(:varphi, "\u03d5", :identifier)
271
281
  b.add(:chi, "\u03c7", :identifier)
272
282
  b.add(:Chi, "\u03a7", :identifier)
273
283
  b.add(:psi, "\u03c8", :identifier)
@@ -278,7 +288,18 @@ module AsciiMath
278
288
  b
279
289
  end
280
290
 
281
- DEFAULT_DISPLAY_SYMBOL_TABLE = ::AsciiMath::MarkupBuilder.add_default_display_symbols(AsciiMath::SymbolTableBuilder.new).build
291
+ private
292
+ DEFAULT_SYMBOL_TABLE = ::AsciiMath::MarkupBuilder.add_default_display_symbols(AsciiMath::SymbolTableBuilder.new, fix_phi: false).build
293
+ DEFAULT_SYMBOL_TABLE_FIX_PHI = ::AsciiMath::MarkupBuilder.add_default_display_symbols(AsciiMath::SymbolTableBuilder.new, fix_phi: true).build
294
+
295
+ public
296
+ def self.default_display_symbol_table(fix_phi: true)
297
+ if fix_phi
298
+ DEFAULT_SYMBOL_TABLE_FIX_PHI
299
+ else
300
+ DEFAULT_SYMBOL_TABLE
301
+ end
302
+ end
282
303
 
283
304
  def initialize(symbol_table)
284
305
  @symbol_table = symbol_table
@@ -312,7 +333,7 @@ module AsciiMath
312
333
  when ::AsciiMath::AST::Number
313
334
  append_number(node.value)
314
335
  when ::AsciiMath::AST::Identifier
315
- append_identifier(node.value)
336
+ append_identifier_or_operator(node.value)
316
337
  when ::AsciiMath::AST::Symbol
317
338
  if (symbol = resolve_symbol(node))
318
339
  case symbol[:type]
@@ -322,12 +343,12 @@ module AsciiMath
322
343
  append_identifier(symbol[:value])
323
344
  end
324
345
  else
325
- append_identifier(node[:value])
346
+ append_identifier_or_operator(node[:value])
326
347
  end
327
348
  when ::AsciiMath::AST::Paren
328
349
  append_paren(resolve_paren(node.lparen), node.expression, resolve_paren(node.rparen), opts)
329
350
  when ::AsciiMath::AST::SubSup
330
- if (resolve_symbol(node.base_expression) || {})[:underover]
351
+ if is_underover(node.base_expression)
331
352
  append_underover(node.base_expression, node.sub_expression, node.sup_expression)
332
353
  else
333
354
  append_subsup(node.base_expression, node.sub_expression, node.sup_expression)
@@ -366,6 +387,8 @@ module AsciiMath
366
387
  append_root(node.operand2, node.operand1)
367
388
  when :color
368
389
  append_color(node.operand1.to_hex_rgb, node.operand2)
390
+ when :frac
391
+ append_fraction(node.operand1, node.operand2)
369
392
  end
370
393
  end
371
394
  when ::AsciiMath::AST::InfixOp
@@ -388,6 +411,14 @@ module AsciiMath
388
411
  raise NotImplementedError.new __method__.to_s
389
412
  end
390
413
 
414
+ def append_identifier_or_operator(value)
415
+ if value.empty? || value =~ /[[:alnum:]].*/
416
+ append_identifier(value)
417
+ else
418
+ append_operator(value)
419
+ end
420
+ end
421
+
391
422
  def append_identifier(identifier)
392
423
  raise NotImplementedError.new __method__.to_s
393
424
  end
@@ -475,5 +506,21 @@ module AsciiMath
475
506
  nil
476
507
  end
477
508
  end
509
+
510
+ def is_accent(node)
511
+ resolved = resolve_symbol(node)
512
+ !resolved.nil? && resolved[:type] == :accent
513
+ end
514
+
515
+ def is_underover(node)
516
+ case node
517
+ when AsciiMath::AST::UnaryOp
518
+ symbol = node.operator
519
+ else
520
+ symbol = node
521
+ end
522
+
523
+ (resolve_symbol(symbol) || {})[:underover]
524
+ end
478
525
  end
479
526
  end
@@ -5,7 +5,7 @@ module AsciiMath
5
5
  class MathMLBuilder < ::AsciiMath::MarkupBuilder
6
6
 
7
7
  def initialize(opts = {})
8
- super(opts[:symbol_table] || DEFAULT_DISPLAY_SYMBOL_TABLE)
8
+ super(opts[:symbol_table] || ::AsciiMath::MarkupBuilder.default_display_symbol_table(fix_phi: opts.fetch(:fix_phi, true)))
9
9
  @prefix = opts[:prefix] || ''
10
10
  @mathml = ''
11
11
  if opts[:msword]
@@ -15,6 +15,7 @@ module AsciiMath
15
15
  @row_mode = :avoid
16
16
  @fence_mode = :row
17
17
  end
18
+ @escape_non_ascii = opts.fetch(:escape_non_ascii, true)
18
19
  end
19
20
 
20
21
  def to_s
@@ -149,21 +150,37 @@ module AsciiMath
149
150
  end
150
151
 
151
152
  def append_underover(base, sub, sup)
153
+ attrs = {}
154
+
155
+ sub_row_mode = @row_mode
156
+ if is_accent(sub)
157
+ attrs[:accentunder] = true
158
+ sub_row_mode = :avoid
159
+ end
160
+
161
+ sup_row_mode = @row_mode
162
+ if is_accent(sup)
163
+ attrs[:accent] = true
164
+ sup_row_mode = :avoid
165
+ end
166
+
167
+
168
+
152
169
  if sub && sup
153
- munderover do
170
+ munderover(attrs) do
154
171
  append(base, :row => @row_mode)
155
- append(sub, :row => @row_mode)
156
- append(sup, :row => @row_mode)
172
+ append(sub, :row => sub_row_mode)
173
+ append(sup, :row => sup_row_mode)
157
174
  end
158
175
  elsif sub
159
- munder do
176
+ munder(attrs) do
160
177
  append(base, :row => @row_mode)
161
- append(sub, :row => @row_mode)
178
+ append(sub, :row => sub_row_mode)
162
179
  end
163
180
  elsif sup
164
- mover do
181
+ mover(attrs) do
165
182
  append(base, :row => @row_mode)
166
- append(sup, :row => @row_mode)
183
+ append(sup, :row => sup_row_mode)
167
184
  end
168
185
  else
169
186
  append(base)
@@ -223,7 +240,7 @@ module AsciiMath
223
240
  @mathml << "&lt;"
224
241
  elsif cp == 62
225
242
  @mathml << "&gt;"
226
- elsif cp > 127
243
+ elsif cp > 127 && @escape_non_ascii
227
244
  @mathml << "&#x#{cp.to_s(16).upcase};"
228
245
  else
229
246
  @mathml << cp
@@ -253,7 +253,9 @@ module AsciiMath
253
253
  b.add('!=', 'ne', :ne, :symbol)
254
254
  b.add(':=', :assign, :symbol)
255
255
  b.add('<', 'lt', :lt, :symbol)
256
+ b.add('mlt', :mlt, :symbol)
256
257
  b.add('>', 'gt', :gt, :symbol)
258
+ b.add('mgt', :mgt, :symbol)
257
259
  b.add('<=', 'le', :le, :symbol)
258
260
  b.add('>=', 'ge', :ge, :symbol)
259
261
  b.add('-<', '-lt', 'prec', :prec, :symbol)
@@ -267,6 +269,7 @@ module AsciiMath
267
269
  b.add('sube', 'subseteq', :subseteq, :symbol)
268
270
  b.add('supe', 'supseteq', :supseteq, :symbol)
269
271
  b.add('-=', 'equiv', :equiv, :symbol)
272
+ b.add('~', 'sim', :sim, :symbol)
270
273
  b.add('~=', 'cong', :cong, :symbol)
271
274
  b.add('~~', 'approx', :approx, :symbol)
272
275
  b.add('prop', 'propto', :propto, :symbol)
@@ -312,6 +315,7 @@ module AsciiMath
312
315
  b.add('del', 'partial', :partial, :symbol)
313
316
  b.add('grad', 'nabla', :nabla, :symbol)
314
317
  b.add('+-', 'pm', :pm, :symbol)
318
+ b.add('-+', 'mp', :mp, :symbol)
315
319
  b.add('O/', 'emptyset', :emptyset, :symbol)
316
320
  b.add('oo', 'infty', :infty, :symbol)
317
321
  b.add('aleph', :aleph, :symbol)
@@ -441,6 +445,7 @@ module AsciiMath
441
445
  b.add('bsf', :bold_sans_serif, :unary)
442
446
  b.add('sfi', :sans_serif_italic, :unary)
443
447
  b.add('sfbi', :sans_serif_bold_italic, :unary)
448
+ b.add('rm', :roman, :unary)
444
449
 
445
450
  # Greek letters
446
451
  b.add('alpha', :alpha, :symbol)
@@ -506,7 +511,7 @@ module AsciiMath
506
511
  def parse(input)
507
512
  Expression.new(
508
513
  input,
509
- parse_expression(Tokenizer.new(input, @symbol_table), 0)
514
+ parse_expression(Tokenizer.new(input, @symbol_table), nil)
510
515
  )
511
516
  end
512
517
 
@@ -514,36 +519,36 @@ module AsciiMath
514
519
 
515
520
  include AsciiMath::AST
516
521
 
517
- def parse_expression(tok, depth)
518
- e = []
522
+ def parse_expression(tok, close_paren_type)
523
+ e = nil
519
524
 
520
- while (s1 = parse_intermediate_expression(tok, depth))
525
+ while (i1 = parse_intermediate_expression(tok, close_paren_type))
521
526
  t1 = tok.next_token
522
527
 
523
528
  if t1[:type] == :infix && t1[:value] == :frac
524
- s2 = parse_intermediate_expression(tok, depth)
525
- if s2
526
- e << infix(unwrap_paren(s1), symbol(:frac, t1[:text]), unwrap_paren(s2))
529
+ i2 = parse_intermediate_expression(tok, close_paren_type)
530
+ if i2
531
+ e = concat_expressions(e, infix(unwrap_paren(i1), token_to_symbol(t1), unwrap_paren(i2)))
527
532
  else
528
- e << s1
533
+ e = concat_expressions(e, i1)
529
534
  end
530
535
  elsif t1[:type] == :eof
531
- e << s1
536
+ e = concat_expressions(e, i1)
532
537
  break
533
538
  else
534
- e << s1
539
+ e = concat_expressions(e, i1)
535
540
  tok.push_back(t1)
536
- if (t1[:type] == :lrparen || t1[:type] == :rparen) && depth > 0
541
+ if t1[:type] == close_paren_type
537
542
  break
538
543
  end
539
544
  end
540
545
  end
541
546
 
542
- expression(*e)
547
+ e
543
548
  end
544
549
 
545
- def parse_intermediate_expression(tok, depth)
546
- s = parse_simple_expression(tok, depth)
550
+ def parse_intermediate_expression(tok, close_paren_type)
551
+ s = parse_simple_expression(tok, close_paren_type)
547
552
  sub = nil
548
553
  sup = nil
549
554
 
@@ -552,17 +557,17 @@ module AsciiMath
552
557
  when :infix
553
558
  case t1[:value]
554
559
  when :sub
555
- sub = parse_simple_expression(tok, depth)
560
+ sub = parse_simple_expression(tok, close_paren_type)
556
561
  if sub
557
562
  t2 = tok.next_token
558
563
  if t2[:type] == :infix && t2[:value] == :sup
559
- sup = parse_simple_expression(tok, depth)
564
+ sup = parse_simple_expression(tok, close_paren_type)
560
565
  else
561
566
  tok.push_back(t2)
562
567
  end
563
568
  end
564
569
  when :sup
565
- sup = parse_simple_expression(tok, depth)
570
+ sup = parse_simple_expression(tok, close_paren_type)
566
571
  else
567
572
  tok.push_back(t1)
568
573
  end
@@ -581,43 +586,55 @@ module AsciiMath
581
586
  end
582
587
  end
583
588
 
584
- def parse_simple_expression(tok, depth)
589
+ def parse_simple_expression(tok, close_paren_type)
585
590
  t1 = tok.next_token
586
591
 
587
592
  case t1[:type]
588
593
  when :lparen, :lrparen
594
+ if t1[:type] == :lparen
595
+ close_with = :rparen
596
+ else
597
+ close_with = :lrparen
598
+ end
599
+
589
600
  t2 = tok.next_token
590
- case t2[:type]
591
- when :rparen, :lrparen
592
- paren(token_to_symbol(t1), nil, token_to_symbol(t2))
593
- else
594
- tok.push_back(t2)
601
+ if t2[:type] == close_with
602
+ paren(token_to_symbol(t1), nil, token_to_symbol(t2))
603
+ else
604
+ tok.push_back(t2)
595
605
 
596
- e = parse_expression(tok, depth + 1)
606
+ e = parse_expression(tok, close_with)
597
607
 
598
- t2 = tok.next_token
599
- case t2[:type]
600
- when :rparen, :lrparen
601
- convert_to_matrix(paren(token_to_symbol(t1), e, token_to_symbol(t2)))
602
- else
603
- tok.push_back(t2)
604
- paren(token_to_symbol(t1), e, nil)
608
+ t2 = tok.next_token
609
+ if t2[:type] == close_with
610
+ convert_to_matrix(paren(token_to_symbol(t1), e, token_to_symbol(t2)))
611
+ else
612
+ tok.push_back(t2)
613
+ if t1[:type] == :lrparen
614
+ concat_expressions(token_to_symbol(t1), e)
615
+ else
616
+ paren(token_to_symbol(t1), e, nil)
605
617
  end
618
+ end
606
619
  end
607
620
  when :rparen
608
- if depth > 0
621
+ if close_paren_type.nil?
622
+ token_to_symbol(t1)
623
+ else
609
624
  tok.push_back(t1)
610
625
  nil
611
- else
612
- token_to_symbol(t1)
613
626
  end
614
627
  when :unary
615
- s = unwrap_paren(parse_simple_expression(tok, depth))
628
+ parse_simple_expression = parse_simple_expression(tok, close_paren_type)
629
+ s = unwrap_paren(parse_simple_expression)
630
+ s = identifier('') if s.nil?
616
631
  s = convert_node(s, t1[:convert_operand])
617
632
  unary(token_to_symbol(t1), s)
618
633
  when :binary
619
- s1 = unwrap_paren(parse_simple_expression(tok, depth))
620
- s2 = unwrap_paren(parse_simple_expression(tok, depth))
634
+ s1 = unwrap_paren(parse_simple_expression(tok, close_paren_type))
635
+ s1 = identifier('') if s1.nil?
636
+ s2 = unwrap_paren(parse_simple_expression(tok, close_paren_type))
637
+ s2 = identifier('') if s2.nil?
621
638
 
622
639
  s1 = convert_node(s1, t1[:convert_operand1])
623
640
  s2 = convert_node(s2, t1[:convert_operand2])
@@ -636,12 +653,37 @@ module AsciiMath
636
653
  end
637
654
  end
638
655
 
656
+ def concat_expressions(e1, e2)
657
+ case e1
658
+ when Sequence
659
+ case e2
660
+ when Sequence
661
+ expression(*(e1.to_a), *(e2.to_a))
662
+ when nil
663
+ e1
664
+ else
665
+ expression(*(e1.to_a), e2)
666
+ end
667
+ when nil
668
+ e2
669
+ else
670
+ case e2
671
+ when Sequence
672
+ expression(e1, *(e2.to_a))
673
+ when nil
674
+ e1
675
+ else
676
+ expression(e1, e2)
677
+ end
678
+ end
679
+ end
680
+
639
681
  def token_to_symbol(t1)
640
- symbol(t1[:value], t1[:text])
682
+ symbol(t1[:value], t1[:text], t1[:type])
641
683
  end
642
684
 
643
685
  def unwrap_paren(node)
644
- if node.is_a?(::AsciiMath::AST::Paren)
686
+ if node.is_a?(::AsciiMath::AST::Paren) && (node.lparen.nil? || node.lparen.type == :lparen) && (node.rparen.nil? || node.rparen.type == :rparen)
645
687
  group(node.lparen, node.expression, node.rparen)
646
688
  else
647
689
  node
@@ -649,14 +691,23 @@ module AsciiMath
649
691
  end
650
692
 
651
693
  def convert_to_matrix(node)
652
- return node unless node.is_a?(::AsciiMath::AST::Paren) && node.expression.is_a?(::AsciiMath::AST::Sequence)
694
+ return node unless node.is_a?(::AsciiMath::AST::Paren)
695
+
696
+ case node.expression
697
+ when ::AsciiMath::AST::Sequence
698
+ rows, separators = node.expression.partition.with_index { |obj, i| i.even? }
699
+ when ::AsciiMath::AST::Paren
700
+ rows = [node.expression]
701
+ separators = []
702
+ else
703
+ return node
704
+ end
653
705
 
654
- rows, separators = node.expression.partition.with_index { |obj, i| i.even? }
655
- return node unless rows.length > 1 &&
706
+ return node unless rows.length >= 1 &&
656
707
  rows.length > separators.length &&
657
708
  separators.all? { |item| is_matrix_separator(item) } &&
658
- (rows.all? { |item| item.is_a?(::AsciiMath::AST::Paren) && item.lparen == symbol(:lparen, '(') && item.rparen == symbol(:rparen, ')') } ||
659
- rows.all? { |item| item.is_a?(::AsciiMath::AST::Paren) && item.lparen == symbol(:lbracket, '[') && item.rparen == symbol(:rbracket, ']') })
709
+ (rows.all? { |item| item.is_a?(::AsciiMath::AST::Paren) && item.lparen == symbol(:lparen, '(', :lparen) && item.rparen == symbol(:rparen, ')', :rparen) } ||
710
+ rows.all? { |item| item.is_a?(::AsciiMath::AST::Paren) && item.lparen == symbol(:lbracket, '[', :lparen) && item.rparen == symbol(:rbracket, ']', :rparen) })
660
711
 
661
712
  rows = rows.map do |row|
662
713
  chunks = []
@@ -704,7 +755,6 @@ module AsciiMath
704
755
  def convert_to_color(color_expression)
705
756
  s = ""
706
757
  append_color_text(s, color_expression)
707
- s
708
758
 
709
759
  case s
710
760
  when /#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i
@@ -1,3 +1,3 @@
1
1
  module AsciiMath
2
- VERSION = "2.0.1"
2
+ VERSION = "2.0.4"
3
3
  end
data/spec/ast.rb CHANGED
@@ -90,7 +90,7 @@ module AsciiMath
90
90
  def symbol(text)
91
91
  symbol = ::AsciiMath::Parser::DEFAULT_PARSER_SYMBOL_TABLE[text]
92
92
  if symbol
93
- ACTUAL_AST.symbol(symbol[:value], text)
93
+ ACTUAL_AST.symbol(symbol[:value], text, symbol[:type])
94
94
  else
95
95
  nil
96
96
  end
@@ -14,7 +14,7 @@ describe 'AsciiMath::Parser', :variant => :ast do
14
14
  my_tokens_table.add('mysymbol', :mysymbol, :symbol)
15
15
 
16
16
  parsed = AsciiMath::parse("a + mysymbol + b", my_tokens_table.build)
17
- expect(parsed.ast).to eq(seq(identifier('a'), symbol('+'), ::AsciiMath::AST::Symbol.new(:mysymbol, 'mysymbol'), symbol('+'), identifier('b')))
17
+ expect(parsed.ast).to eq(seq(identifier('a'), symbol('+'), ::AsciiMath::AST::Symbol.new(:mysymbol, 'mysymbol', :symbol), symbol('+'), identifier('b')))
18
18
  end
19
19
 
20
20
  it "should support replacing standard symbols" do
@@ -23,6 +23,6 @@ describe 'AsciiMath::Parser', :variant => :ast do
23
23
  my_tokens_table.add('+', :foo, :symbol)
24
24
 
25
25
  parsed = AsciiMath::parse("a + b", my_tokens_table.build)
26
- expect(parsed.ast).to eq(seq(identifier('a'), ::AsciiMath::AST::Symbol.new(:foo, '+'), identifier('b')))
26
+ expect(parsed.ast).to eq(seq(identifier('a'), ::AsciiMath::AST::Symbol.new(:foo, '+', :symbol), identifier('b')))
27
27
  end
28
28
  end
data/spec/parser_spec.rb CHANGED
@@ -7,11 +7,11 @@ require 'nokogiri'
7
7
 
8
8
  module Xml
9
9
  def self.mathml2_xsd
10
- @schema ||= File.open(File.expand_path('../schema/mathml2/mathml2.xsd', __FILE__)) { |io| Nokogiri::XML::Schema(io) }
10
+ @mathml2_schema ||= File.open(File.expand_path('../schema/mathml2/mathml2.xsd', __FILE__)) { |io| Nokogiri::XML::Schema(io) }
11
11
  end
12
12
 
13
13
  def self.mathml3_xsd
14
- @schema ||= File.open(File.expand_path('../schema/mathml3/mathml3.xsd', __FILE__)) { |io| Nokogiri::XML::Schema(io) }
14
+ @mathml3_schema ||= File.open(File.expand_path('../schema/mathml3/mathml3.xsd', __FILE__)) { |io| Nokogiri::XML::Schema(io) }
15
15
  end
16
16
 
17
17
  def self.parse(content)
@@ -31,12 +31,14 @@ def should_generate(expected_output)
31
31
  expect(parsed.ast).to eq(expected)
32
32
  when :mathml
33
33
  expect(parsed.to_mathml).to eq(expected)
34
- xml_dom = Xml.parse(parsed.to_mathml(:xmlns => 'http://www.w3.org/1998/Math/MathML'))
35
- Xml.mathml2_xsd.validate(xml_dom).each do |error|
36
- fail(error.message)
37
- end
38
- Xml.mathml3_xsd.validate(xml_dom).each do |error|
39
- fail(error.message)
34
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE != 'jruby'
35
+ xml_dom = Xml.parse(parsed.to_mathml(:xmlns => 'http://www.w3.org/1998/Math/MathML'))
36
+ Xml.mathml2_xsd.validate(xml_dom).each do |error|
37
+ fail(error.message)
38
+ end
39
+ Xml.mathml3_xsd.validate(xml_dom).each do |error|
40
+ fail(error.message)
41
+ end
40
42
  end
41
43
  when :mathml_word
42
44
  expect(::AsciiMath::MathMLBuilder.new(:msword => true).append_expression(parsed.ast).to_s).to eq(expected)
@@ -74,8 +76,8 @@ RSpec.shared_examples 'AsciiMath Examples' do
74
76
  'j',
75
77
  sub(symbol('vartheta'), '0')
76
78
  ),
77
- :mathml => '<math><munder><mover><mi>A</mi><mo>^</mo></mover><mo>_</mo></munder><mo>=</mo><mover><mi>A</mi><mo>^</mo></mover><mi>exp</mi><mi>j</mi><msub><mi>&#x3D1;</mi><mn>0</mn></msub></math>',
78
- :mathml_word => '<math><munder><mrow><mover><mrow><mi>A</mi></mrow><mrow><mo>^</mo></mrow></mover></mrow><mrow><mo>_</mo></mrow></munder><mo>=</mo><mover><mrow><mi>A</mi></mrow><mrow><mo>^</mo></mrow></mover><mi>exp</mi><mi>j</mi><msub><mrow><mi>&#x3D1;</mi></mrow><mrow><mn>0</mn></mrow></msub></math>',
79
+ :mathml => '<math><munder><mover accent="true"><mi>A</mi><mo>^</mo></mover><mo>_</mo></munder><mo>=</mo><mover accent="true"><mi>A</mi><mo>^</mo></mover><mi>exp</mi><mi>j</mi><msub><mi>&#x3D1;</mi><mn>0</mn></msub></math>',
80
+ :mathml_word => '<math><munder><mrow><mover accent="true"><mrow><mi>A</mi></mrow><mo>^</mo></mover></mrow><mrow><mo>_</mo></mrow></munder><mo>=</mo><mover accent="true"><mrow><mi>A</mi></mrow><mo>^</mo></mover><mi>exp</mi><mi>j</mi><msub><mrow><mi>&#x3D1;</mi></mrow><mrow><mn>0</mn></mrow></msub></math>',
79
81
  :latex => '\\underset{\\text{–}}{\\hat{A}} = \\hat{A} \\exp j \\vartheta_0'
80
82
  ))
81
83
 
@@ -272,7 +274,7 @@ RSpec.shared_examples 'AsciiMath Examples' do
272
274
  unary(symbol('ul'), group('A')),
273
275
  unary(symbol('vec'), group('v')),
274
276
  ),
275
- :mathml => '<math><mover><mrow><mi>a</mi><mi>b</mi></mrow><mo>^</mo></mover><mover><mrow><mi>x</mi><mi>y</mi></mrow><mo>&#xAF;</mo></mover><munder><mi>A</mi><mo>_</mo></munder><mover><mi>v</mi><mo>&#x2192;</mo></mover></math>',
277
+ :mathml => '<math><mover accent="true"><mrow><mi>a</mi><mi>b</mi></mrow><mo>^</mo></mover><mover accent="true"><mrow><mi>x</mi><mi>y</mi></mrow><mo>&#xAF;</mo></mover><munder accentunder="true"><mi>A</mi><mo>_</mo></munder><mover accent="true"><mi>v</mi><mo>&#x2192;</mo></mover></math>',
276
278
  :html => '<span class="math-inline"><span class="math-blank">&#x200D;</span><span class="math-underover"><span class="math-smaller"><span class="math-operator">^</span></span><span class="math-row"><span class="math-identifier">a</span><span class="math-identifier">b</span></span><span class="math-smaller"><span class="math-blank">&#x200D;</span></span></span><span class="math-blank">&#x200D;</span><span class="math-underover"><span class="math-smaller"><span class="math-operator">&#xAF;</span></span><span class="math-row"><span class="math-identifier">x</span><span class="math-identifier">y</span></span><span class="math-smaller"><span class="math-blank">&#x200D;</span></span></span><span class="math-blank">&#x200D;</span><span class="math-underover"><span class="math-smaller"><span class="math-blank">&#x200D;</span></span><span class="math-identifier">A</span><span class="math-smaller"><span class="math-operator">_</span></span></span><span class="math-blank">&#x200D;</span><span class="math-underover"><span class="math-smaller"><span class="math-operator">&#x2192;</span></span><span class="math-identifier">v</span><span class="math-smaller"><span class="math-blank">&#x200D;</span></span></span></span>',
277
279
  :latex => '\\hat{a b} \\overline{x y} \\underline{A} \\vec{v}',
278
280
  ))
@@ -326,6 +328,13 @@ RSpec.shared_examples 'AsciiMath Examples' do
326
328
  :latex => '\\left ( \\begin{matrix} 1 \\\\ 42 \\end{matrix} \\right )',
327
329
  ))
328
330
 
331
+ example('((1,42))', &should_generate(
332
+ :ast => matrix([%w[1 42]]),
333
+ :mathml => '<math><mrow><mo>(</mo><mtable><mtr><mtd><mn>1</mn></mtd><mtd><mn>42</mn></mtd></mtr></mtable><mo>)</mo></mrow></math>',
334
+ :html => '<span class="math-inline"><span class="math-row"><span class="math-brace" style="font-size: 100%;">(</span><span class="math-matrix" style="grid-template-columns:repeat(2,1fr);grid-template-rows:repeat(1,1fr);"><span class="math-row"><span class="math-number">1</span></span><span class="math-row"><span class="math-number">42</span></span></span><span class="math-brace" style="font-size: 100%;">)</span></span></span>',
335
+ :latex => '\\left ( \\begin{matrix} 1 & 42 \\end{matrix} \\right )',
336
+ ))
337
+
329
338
  example('((1,2,3),(4,5,6),(7,8,9))', &should_generate(
330
339
  :ast => matrix([%w[1 2 3], %w[4 5 6], %w[7 8 9]]),
331
340
  :mathml => '<math><mrow><mo>(</mo><mtable><mtr><mtd><mn>1</mn></mtd><mtd><mn>2</mn></mtd><mtd><mn>3</mn></mtd></mtr><mtr><mtd><mn>4</mn></mtd><mtd><mn>5</mn></mtd><mtd><mn>6</mn></mtd></mtr><mtr><mtd><mn>7</mn></mtd><mtd><mn>8</mn></mtd><mtd><mn>9</mn></mtd></mtr></mtable><mo>)</mo></mrow></math>',
@@ -335,7 +344,7 @@ RSpec.shared_examples 'AsciiMath Examples' do
335
344
 
336
345
  example('|(a,b),(c,d)|=ad-bc', &should_generate(
337
346
  :ast => seq(
338
- matrix(symbol('|'), [%w(a b), %w(c d)], symbol('|'),),
347
+ matrix(symbol('|'), [%w(a b), %w(c d)], symbol('|')),
339
348
  symbol('='),
340
349
  'a', 'd',
341
350
  symbol('-'),
@@ -418,7 +427,7 @@ RSpec.shared_examples 'AsciiMath Examples' do
418
427
  unary(symbol('ubrace'), grseq('1', symbol('+'), '2')),
419
428
  unary(symbol('obrace'), group(symbol('('), seq('3', symbol('+'), '4'), nil))
420
429
  ),
421
- :mathml => '<math><munder><mrow><mn>1</mn><mo>+</mo><mn>2</mn></mrow><mo>&#x23DF;</mo></munder><mover><mrow><mn>3</mn><mo>+</mo><mn>4</mn></mrow><mo>&#x23DE;</mo></mover></math>',
430
+ :mathml => '<math><munder accentunder="true"><mrow><mn>1</mn><mo>+</mo><mn>2</mn></mrow><mo>&#x23DF;</mo></munder><mover accent="true"><mrow><mn>3</mn><mo>+</mo><mn>4</mn></mrow><mo>&#x23DE;</mo></mover></math>',
422
431
  :latex => '\\underbrace{1 + 2} \\overbrace{3 + 4}',
423
432
  ))
424
433
 
@@ -519,7 +528,7 @@ RSpec.shared_examples 'AsciiMath Examples' do
519
528
 
520
529
  example('overarc a_b^c', &should_generate(
521
530
  :ast => subsup(unary(symbol('overarc'), 'a'), 'b', 'c'),
522
- :mathml => '<math><msubsup><mover><mi>a</mi><mo>&#x23DC;</mo></mover><mi>b</mi><mi>c</mi></msubsup></math>',
531
+ :mathml => '<math><msubsup><mover accent="true"><mi>a</mi><mo>&#x23DC;</mo></mover><mi>b</mi><mi>c</mi></msubsup></math>',
523
532
  :latex => '{\\overset{\\frown}{a}}_b^c'
524
533
  ))
525
534
 
@@ -568,10 +577,79 @@ RSpec.shared_examples 'AsciiMath Examples' do
568
577
  seq('x', symbol('\ '), ':', symbol('\ '), 'x', symbol('in'), 'A', symbol('^^'), 'x', symbol('in'), 'B'),
569
578
  symbol('}')
570
579
  ),
571
- :mathml => '<math><mrow><mo>{</mo><mrow><mi>x</mi><mo>&#xA0;</mo><mi>:</mi><mo>&#xA0;</mo><mi>x</mi><mo>&#x2208;</mo><mi>A</mi><mo>&#x2227;</mo><mi>x</mi><mo>&#x2208;</mo><mi>B</mi></mrow><mo>}</mo></mrow></math>',
580
+ :mathml => '<math><mrow><mo>{</mo><mrow><mi>x</mi><mo>&#xA0;</mo><mo>:</mo><mo>&#xA0;</mo><mi>x</mi><mo>&#x2208;</mo><mi>A</mi><mo>&#x2227;</mo><mi>x</mi><mo>&#x2208;</mo><mi>B</mi></mrow><mo>}</mo></mrow></math>',
572
581
  :latex => '\\left \\{ x \\; : \\; x \\in A \\wedge x \\in B \\right \\}',
573
582
  ))
574
583
 
584
+ example('ii', &should_generate(
585
+ :ast => unary(symbol('ii'), identifier('')),
586
+ :mathml => '<math><mstyle mathvariant="italic"><mi></mi></mstyle></math>'
587
+ ))
588
+
589
+ example('rm(ms)', &should_generate(
590
+ :ast => unary(symbol('rm'), grseq(identifier('m'), identifier('s'))),
591
+ :mathml => '<math><mstyle mathvariant="normal"><mrow><mi>m</mi><mi>s</mi></mrow></mstyle></math>'
592
+ ))
593
+
594
+ example('hat', &should_generate(
595
+ :ast => unary(symbol('hat'), identifier('')),
596
+ :mathml => '<math><mover accent="true"><mi></mi><mo>^</mo></mover></math>'
597
+ ))
598
+
599
+ example('40% * 3!', &should_generate(
600
+ :ast => seq('40', '%', symbol('*'), '3', '!'),
601
+ :mathml => '<math><mn>40</mn><mo>%</mo><mo>&#x22C5;</mo><mn>3</mn><mo>!</mo></math>',
602
+ :html => '<span class="math-inline"><span class="math-number">40</span><span class="math-operator">%</span><span class="math-operator">&#x22C5;</span><span class="math-number">3</span><span class="math-operator">!</span></span>',
603
+ :latex => '40 \% \cdot 3 !'
604
+ ))
605
+
606
+ example('R(alpha_(K+1)|x)', &should_generate(
607
+ :ast => seq('R', paren(symbol('('), seq(sub('alpha', grseq('K', symbol('+'), '1')), symbol('|'), 'x'), symbol(')'))),
608
+ :mathml => '<math><mi>R</mi><mrow><mo>(</mo><mrow><msub><mi>&#x3B1;</mi><mrow><mi>K</mi><mo>+</mo><mn>1</mn></mrow></msub><mo>|</mo><mi>x</mi></mrow><mo>)</mo></mrow></math>',
609
+ :latex => 'R \\left ( \\alpha_{K + 1} | x \\right )'
610
+ ))
611
+
612
+ example('|(a),(b)|', &should_generate(
613
+ :ast => matrix(symbol('|'), [%w(a), %w(b)], symbol('|')),
614
+ ))
615
+
616
+ example('|a+b|', &should_generate(
617
+ :ast => paren(symbol('|'), seq('a', '+', 'b'), symbol('|')),
618
+ ))
619
+
620
+ example('|a+b|/c', &should_generate(
621
+ :ast => infix(paren(symbol('|'), seq('a', '+', 'b'), symbol('|')), '/', 'c'),
622
+ ))
623
+
624
+ example('[[a,b,|,c],[d,e,|,f]]', &should_generate(
625
+ :ast => matrix(symbol('['), [['a', 'b', symbol('|'), 'c'], ['d', 'e', symbol('|'), 'f']], symbol(']')),
626
+ ))
627
+
628
+ example('~a mlt b mgt -+c', &should_generate(
629
+ :ast => seq(symbol('~'), 'a', symbol('mlt'), 'b', symbol('mgt'), symbol('-+'), 'c'),
630
+ :latex => '\\sim a \\ll b \\gg \\mp c',
631
+ :mathml => '<math><mo>&#x223C;</mo><mi>a</mi><mo>&#x226A;</mo><mi>b</mi><mo>&#x226B;</mo><mo>&#x2213;</mo><mi>c</mi></math>'
632
+ ))
633
+
634
+ example('a+b+...+c', &should_generate(
635
+ :ast => seq('a', symbol('+'), 'b', symbol('+'), symbol('...'), symbol('+'), 'c'),
636
+ :latex => 'a + b + \ldots + c',
637
+ :mathml => '<math><mi>a</mi><mo>+</mo><mi>b</mi><mo>+</mo><mo>&#x2026;</mo><mo>+</mo><mi>c</mi></math>'
638
+ ))
639
+
640
+ example('frac{a}{b}', &should_generate(
641
+ :ast => binary('frac', group(symbol('{'), 'a', symbol('}')), group(symbol('{'), 'b', symbol('}'))),
642
+ :latex => '\frac{a}{b}',
643
+ :mathml => '<math><mfrac><mi>a</mi><mi>b</mi></mfrac></math>'
644
+ ))
645
+
646
+ example('ubrace(((1, 0),(0, 1)))_("Adjustment to texture space")', &should_generate(
647
+ :ast => subsup(unary(symbol('ubrace'), group(matrix([%w[1 0], %w[0 1]]))), group("Adjustment to texture space"), []),
648
+ :latex => '\underbrace{\left ( \begin{matrix} 1 & 0 \\\\ 0 & 1 \end{matrix} \right )}_{\text{Adjustment to texture space}}',
649
+ :mathml => '<math><munder><munder accentunder="true"><mrow><mo>(</mo><mtable><mtr><mtd><mn>1</mn></mtd><mtd><mn>0</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd><mtd><mn>1</mn></mtd></mtr></mtable><mo>)</mo></mrow><mo>&#x23DF;</mo></munder><mtext>Adjustment to texture space</mtext></munder></math>'
650
+ ))
651
+
652
+
575
653
  version = RUBY_VERSION.split('.').map { |s| s.to_i }
576
654
 
577
655
  if version[0] > 1 || version[1] > 8
metadata CHANGED
@@ -1,72 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciimath
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pepijn Van Eeckhoudt
8
8
  - Gark Garcia
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-06-29 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: bundler
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - ">"
19
- - !ruby/object:Gem::Version
20
- version: '0'
21
- type: :development
22
- prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">"
26
- - !ruby/object:Gem::Version
27
- version: '0'
28
- - !ruby/object:Gem::Dependency
29
- name: rake
30
- requirement: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - "~>"
33
- - !ruby/object:Gem::Version
34
- version: 13.0.0
35
- type: :development
36
- prerelease: false
37
- version_requirements: !ruby/object:Gem::Requirement
38
- requirements:
39
- - - "~>"
40
- - !ruby/object:Gem::Version
41
- version: 13.0.0
42
- - !ruby/object:Gem::Dependency
43
- name: rspec
44
- requirement: !ruby/object:Gem::Requirement
45
- requirements:
46
- - - "~>"
47
- - !ruby/object:Gem::Version
48
- version: 3.9.0
49
- type: :development
50
- prerelease: false
51
- version_requirements: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - "~>"
54
- - !ruby/object:Gem::Version
55
- version: 3.9.0
56
- - !ruby/object:Gem::Dependency
57
- name: nokogiri
58
- requirement: !ruby/object:Gem::Requirement
59
- requirements:
60
- - - "~>"
61
- - !ruby/object:Gem::Version
62
- version: 1.10.9
63
- type: :development
64
- prerelease: false
65
- version_requirements: !ruby/object:Gem::Requirement
66
- requirements:
67
- - - "~>"
68
- - !ruby/object:Gem::Version
69
- version: 1.10.9
12
+ date: 2022-04-21 00:00:00.000000000 Z
13
+ dependencies: []
70
14
  description: A pure Ruby AsciiMath parsing and conversion library.
71
15
  email:
72
16
  - pepijn@vaneeckhoudt.net
@@ -76,8 +20,8 @@ executables:
76
20
  extensions: []
77
21
  extra_rdoc_files: []
78
22
  files:
23
+ - ".github/workflows/ci.yml"
79
24
  - ".gitignore"
80
- - ".travis.yml"
81
25
  - AST.adoc
82
26
  - CHANGELOG.adoc
83
27
  - Gemfile
@@ -141,7 +85,7 @@ homepage: ''
141
85
  licenses:
142
86
  - MIT
143
87
  metadata: {}
144
- post_install_message:
88
+ post_install_message:
145
89
  rdoc_options: []
146
90
  require_paths:
147
91
  - lib
@@ -156,9 +100,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
156
100
  - !ruby/object:Gem::Version
157
101
  version: '0'
158
102
  requirements: []
159
- rubyforge_project:
160
- rubygems_version: 2.7.6
161
- signing_key:
103
+ rubygems_version: 3.2.22
104
+ signing_key:
162
105
  specification_version: 4
163
106
  summary: AsciiMath parser and converter
164
107
  test_files:
data/.travis.yml DELETED
@@ -1,16 +0,0 @@
1
- language: ruby
2
- cache:
3
- apt: true
4
- directories:
5
- - vendor/bundle
6
- - $HOME/.cache/pip
7
- rvm:
8
- - 2.3
9
- - 2.4
10
- - 2.5
11
- - jruby
12
- - truffleruby
13
- before_install:
14
- - type bundle || gem install bundler --version '~> 1.0'
15
- install:
16
- - bundle install --path vendor/bundle --jobs=3 --retry=3