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 +4 -4
- data/.github/workflows/ci.yml +20 -0
- data/AST.adoc +2 -2
- data/CHANGELOG.adoc +31 -0
- data/Gemfile +5 -0
- data/README.adoc +2 -1
- data/asciimath.gemspec +0 -5
- data/dump_symbol_table.rb +1 -1
- data/lib/asciimath/ast.rb +6 -4
- data/lib/asciimath/html.rb +3 -2
- data/lib/asciimath/latex.rb +10 -3
- data/lib/asciimath/markup.rb +56 -9
- data/lib/asciimath/mathml.rb +26 -9
- data/lib/asciimath/parser.rb +95 -45
- data/lib/asciimath/version.rb +1 -1
- data/spec/ast.rb +1 -1
- data/spec/customisation_spec.rb +2 -2
- data/spec/parser_spec.rb +93 -15
- metadata +8 -65
- data/.travis.yml +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c38e7e41750527b0992c27f6e636cb6b670eec3008563e1a5fe19fc86458991
|
4
|
+
data.tar.gz: 3313df7a9524d4a4e384be1ec54f38aafe2ff70553ae65aa695c530fff5f45e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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]) |++\
|
261
|
-
|++ldots++ |:ellipsis |++…++ (https://codepoints.net/U+2026[U+2026]) |++\
|
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
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:
|
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
|
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
|
data/lib/asciimath/html.rb
CHANGED
@@ -4,9 +4,10 @@ module AsciiMath
|
|
4
4
|
class HTMLBuilder < ::AsciiMath::MarkupBuilder
|
5
5
|
|
6
6
|
def initialize(opts = {})
|
7
|
-
super(opts[: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 << "<"
|
228
229
|
elsif cp == 62
|
229
230
|
@html << ">"
|
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
|
data/lib/asciimath/latex.rb
CHANGED
@@ -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(
|
393
|
+
e.all? { |s| is_very_small(s) }
|
387
394
|
when nil
|
388
395
|
true
|
389
396
|
else
|
data/lib/asciimath/markup.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 (
|
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
|
data/lib/asciimath/mathml.rb
CHANGED
@@ -5,7 +5,7 @@ module AsciiMath
|
|
5
5
|
class MathMLBuilder < ::AsciiMath::MarkupBuilder
|
6
6
|
|
7
7
|
def initialize(opts = {})
|
8
|
-
super(opts[: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 =>
|
156
|
-
append(sup, :row =>
|
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 =>
|
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 =>
|
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 << "<"
|
224
241
|
elsif cp == 62
|
225
242
|
@mathml << ">"
|
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
|
data/lib/asciimath/parser.rb
CHANGED
@@ -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),
|
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,
|
518
|
-
e =
|
522
|
+
def parse_expression(tok, close_paren_type)
|
523
|
+
e = nil
|
519
524
|
|
520
|
-
while (
|
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
|
-
|
525
|
-
if
|
526
|
-
e
|
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
|
533
|
+
e = concat_expressions(e, i1)
|
529
534
|
end
|
530
535
|
elsif t1[:type] == :eof
|
531
|
-
e
|
536
|
+
e = concat_expressions(e, i1)
|
532
537
|
break
|
533
538
|
else
|
534
|
-
e
|
539
|
+
e = concat_expressions(e, i1)
|
535
540
|
tok.push_back(t1)
|
536
|
-
if
|
541
|
+
if t1[:type] == close_paren_type
|
537
542
|
break
|
538
543
|
end
|
539
544
|
end
|
540
545
|
end
|
541
546
|
|
542
|
-
|
547
|
+
e
|
543
548
|
end
|
544
549
|
|
545
|
-
def parse_intermediate_expression(tok,
|
546
|
-
s = parse_simple_expression(tok,
|
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,
|
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,
|
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,
|
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,
|
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
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
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
|
-
|
606
|
+
e = parse_expression(tok, close_with)
|
597
607
|
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
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
|
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
|
-
|
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,
|
620
|
-
|
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)
|
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
|
-
|
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
|
data/lib/asciimath/version.rb
CHANGED
data/spec/ast.rb
CHANGED
data/spec/customisation_spec.rb
CHANGED
@@ -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
|
-
@
|
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
|
-
@
|
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
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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>ϑ</mi><mn>0</mn></msub></math>',
|
78
|
-
:mathml_word => '<math><munder><mrow><mover><mrow><mi>A</mi></mrow><
|
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>ϑ</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>ϑ</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>¯</mo></mover><munder><mi>A</mi><mo>_</mo></munder><mover><mi>v</mi><mo>→</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>¯</mo></mover><munder accentunder="true"><mi>A</mi><mo>_</mo></munder><mover accent="true"><mi>v</mi><mo>→</mo></mover></math>',
|
276
278
|
:html => '<span class="math-inline"><span class="math-blank">‍</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">‍</span></span></span><span class="math-blank">‍</span><span class="math-underover"><span class="math-smaller"><span class="math-operator">¯</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">‍</span></span></span><span class="math-blank">‍</span><span class="math-underover"><span class="math-smaller"><span class="math-blank">‍</span></span><span class="math-identifier">A</span><span class="math-smaller"><span class="math-operator">_</span></span></span><span class="math-blank">‍</span><span class="math-underover"><span class="math-smaller"><span class="math-operator">→</span></span><span class="math-identifier">v</span><span class="math-smaller"><span class="math-blank">‍</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>⏟</mo></munder><mover><mrow><mn>3</mn><mo>+</mo><mn>4</mn></mrow><mo>⏞</mo></mover></math>',
|
430
|
+
:mathml => '<math><munder accentunder="true"><mrow><mn>1</mn><mo>+</mo><mn>2</mn></mrow><mo>⏟</mo></munder><mover accent="true"><mrow><mn>3</mn><mo>+</mo><mn>4</mn></mrow><mo>⏞</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>⏜</mo></mover><mi>b</mi><mi>c</mi></msubsup></math>',
|
531
|
+
:mathml => '<math><msubsup><mover accent="true"><mi>a</mi><mo>⏜</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> </mo><
|
580
|
+
:mathml => '<math><mrow><mo>{</mo><mrow><mi>x</mi><mo> </mo><mo>:</mo><mo> </mo><mi>x</mi><mo>∈</mo><mi>A</mi><mo>∧</mo><mi>x</mi><mo>∈</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>⋅</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">⋅</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>α</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>∼</mo><mi>a</mi><mo>≪</mo><mi>b</mi><mo>≫</mo><mo>∓</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>…</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>⏟</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.
|
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:
|
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
|
-
|
160
|
-
|
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
|