mathematical 0.6.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +48 -12
- data/Rakefile +3 -2
- data/ext/mathematical/cairo_callbacks.c +25 -0
- data/ext/mathematical/cairo_callbacks.h +7 -0
- data/ext/mathematical/extconf.rb +11 -11
- data/ext/mathematical/lasem/src/lsmmathmldocument.c +3 -0
- data/ext/mathematical/lasem/src/lsmmathmlencloseelement.c +142 -0
- data/ext/mathematical/lasem/src/lsmmathmlencloseelement.h +64 -0
- data/ext/mathematical/lasem/src/lsmmathmlenums.c +35 -0
- data/ext/mathematical/lasem/src/lsmmathmlenums.h +25 -1
- data/ext/mathematical/lasem/src/lsmmathmlpaddedelement.c +79 -0
- data/ext/mathematical/lasem/src/lsmmathmlpaddedelement.h +5 -0
- data/ext/mathematical/lasem/src/lsmmathmlstyleelement.c +6 -0
- data/ext/mathematical/lasem/src/lsmmathmltableelement.c +5 -5
- data/ext/mathematical/lasem/src/lsmmathmltraits.c +24 -0
- data/ext/mathematical/lasem/src/lsmmathmltraits.h +1 -0
- data/ext/mathematical/lasem/src/lsmmathmltypes.h +1 -0
- data/ext/mathematical/lasem/src/lsmmathmlutils.h +9 -2
- data/ext/mathematical/lasem/src/lsmmathmlview.c +283 -11
- data/ext/mathematical/lasem/src/lsmmathmlview.h +13 -0
- data/ext/mathematical/lasem_overrides.c +40 -0
- data/ext/mathematical/lasem_overrides.h +23 -0
- data/ext/mathematical/mathematical.c +119 -127
- data/ext/mathematical/mathematical.h +24 -0
- data/ext/mathematical/mtex2MML/ext/extconf.rb +1 -1
- data/ext/mathematical/mtex2MML/src/lex.yy.c +4488 -4032
- data/ext/mathematical/mtex2MML/src/mtex2MML.h +3 -0
- data/ext/mathematical/mtex2MML/src/parse_extras.c +14 -5
- data/ext/mathematical/mtex2MML/src/parse_extras.h +3 -1
- data/ext/mathematical/mtex2MML/src/string_extras.c +39 -0
- data/ext/mathematical/mtex2MML/src/string_extras.h +7 -0
- data/ext/mathematical/mtex2MML/src/y.tab.c +4408 -3175
- data/ext/mathematical/mtex2MML/src/y.tab.h +500 -422
- data/lib/mathematical.rb +112 -2
- data/lib/mathematical/corrections.rb +2 -2
- data/lib/mathematical/version.rb +2 -2
- data/mathematical.gemspec +4 -4
- data/test/mathematical/basic_test.rb +1 -1
- data/test/mathematical/corrections_test.rb +1 -1
- data/test/mathematical/fixtures/png/numeric_test_1.png +0 -0
- data/test/mathematical/fixtures/png/numeric_test_2.png +0 -0
- data/test/mathematical/fixtures/png/numeric_test_3.png +0 -0
- data/test/mathematical/fixtures_test.rb +7 -7
- data/test/mathematical/maliciousness_test.rb +44 -17
- data/test/mathematical/mathjax_test.rb +5 -13
- data/test/mathematical/mathml_test.rb +3 -3
- data/test/mathematical/multiples_test.rb +68 -0
- data/test/mathematical/performance_test.rb +2 -2
- data/test/mathematical/png_test.rb +5 -5
- data/test/test_helper.rb +36 -1
- metadata +26 -11
- data/lib/mathematical/render.rb +0 -74
data/lib/mathematical.rb
CHANGED
@@ -1,8 +1,118 @@
|
|
1
1
|
require 'mathematical/mathematical'
|
2
2
|
|
3
3
|
require 'mathematical/corrections'
|
4
|
-
require 'mathematical/render'
|
5
4
|
require 'mathematical/version'
|
6
5
|
|
7
|
-
|
6
|
+
require 'base64'
|
7
|
+
|
8
|
+
class Mathematical
|
9
|
+
include Corrections
|
10
|
+
|
11
|
+
FORMAT_TYPES = [:svg, :png, :mathml]
|
12
|
+
|
13
|
+
DEFAULT_OPTS = {
|
14
|
+
:ppi => 72.0,
|
15
|
+
:zoom => 1.0,
|
16
|
+
:base64 => false,
|
17
|
+
:maxsize => 0,
|
18
|
+
:format => :svg
|
19
|
+
}
|
20
|
+
|
21
|
+
XML_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
22
|
+
|
23
|
+
def initialize(opts = {})
|
24
|
+
@config = DEFAULT_OPTS.merge(opts)
|
25
|
+
|
26
|
+
validate_config
|
27
|
+
|
28
|
+
@config[:formatInt] = FORMAT_TYPES.index(@config[:format])
|
29
|
+
|
30
|
+
@processer = Mathematical::Process.new(@config)
|
31
|
+
end
|
32
|
+
|
33
|
+
def render(maths)
|
34
|
+
maths = validate_content(maths)
|
35
|
+
|
36
|
+
begin
|
37
|
+
data = @processer.process(maths)
|
38
|
+
fail RuntimeError if data.nil? || (!data.is_a?(Hash) && !data.is_a?(Array))
|
39
|
+
|
40
|
+
if data.is_a? Array
|
41
|
+
data.map { |d| format_data(d) }
|
42
|
+
else
|
43
|
+
format_data(data)
|
44
|
+
end
|
45
|
+
rescue ParseError, DocumentCreationError, DocumentReadError => e
|
46
|
+
# an error in the C code, probably a bad TeX parse
|
47
|
+
$stderr.puts "#{e.message}: #{maths}"
|
48
|
+
maths
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def validate_content(maths)
|
53
|
+
if !maths.is_a?(String) && !maths.is_a?(Array)
|
54
|
+
fail(TypeError, 'input must be a string or an array!')
|
55
|
+
end
|
56
|
+
|
57
|
+
if maths.is_a? String
|
58
|
+
validate_string(maths)
|
59
|
+
else
|
60
|
+
validate_array(maths)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def validate_config
|
67
|
+
fail(TypeError, 'maxsize must be an integer!') unless @config[:maxsize].is_a? Fixnum
|
68
|
+
fail(TypeError, 'maxsize cannot be less than 0!') if @config[:maxsize] < 0
|
69
|
+
fail(TypeError, 'format must be a symbol!') unless @config[:format].is_a? Symbol
|
70
|
+
fail(TypeError, "format type must be one of the following formats: #{FORMAT_TYPES.join(', ')}") unless FORMAT_TYPES.include?(@config[:format])
|
71
|
+
end
|
72
|
+
|
73
|
+
def validate_string(maths)
|
74
|
+
maths = maths.strip
|
75
|
+
unless valid_math_string(maths)
|
76
|
+
fail(ArgumentError, 'input must be in tex format (`$...$` or `$$...$$`)!')
|
77
|
+
end
|
78
|
+
|
79
|
+
maths
|
80
|
+
end
|
81
|
+
|
82
|
+
def validate_array(maths)
|
83
|
+
unless maths.all? { |m| m.is_a?(String) }
|
84
|
+
fail(ArgumentError, 'every element in array must be a string in tex format (`$...$` or `$$...$$`)!')
|
85
|
+
end
|
86
|
+
|
87
|
+
maths = maths.map(&:strip)
|
88
|
+
unless maths.all? { |m| valid_math_string(m) }
|
89
|
+
fail(ArgumentError, 'every element in array must be a string in tex format (`$...$` or `$$...$$`)!')
|
90
|
+
end
|
91
|
+
|
92
|
+
maths
|
93
|
+
end
|
94
|
+
|
95
|
+
def valid_math_string(maths)
|
96
|
+
maths =~ /\A\${1,2}/
|
97
|
+
end
|
98
|
+
|
99
|
+
def format_data(data)
|
100
|
+
# we passed in an array of math, and found an unprocessable element
|
101
|
+
return data unless data.is_a? Hash
|
102
|
+
|
103
|
+
case @config[:format]
|
104
|
+
when :svg
|
105
|
+
# remove starting <?xml...> tag
|
106
|
+
data['svg'] = data['svg'][XML_HEADER.length..-1]
|
107
|
+
data['svg'] = svg_to_base64(data['svg']) if @config[:base64]
|
108
|
+
|
109
|
+
data
|
110
|
+
when :png, :mathml # do nothing with these...for now?
|
111
|
+
data
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def svg_to_base64(contents)
|
116
|
+
"data:image/svg+xml;base64,#{Base64.strict_encode64(contents)}"
|
117
|
+
end
|
8
118
|
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
|
1
|
+
class Mathematical
|
2
2
|
module Corrections
|
3
3
|
def apply_corrections(maths)
|
4
4
|
adjust_lt_gt(maths)
|
5
5
|
end
|
6
6
|
|
7
|
-
# from the itex website:
|
7
|
+
# from the itex website: http://bit.ly/1Et74ed
|
8
8
|
# It is possible (though probably not recommended) to insert MathML markup
|
9
9
|
# inside itex equations. So "<" and ">" are significant.
|
10
10
|
# To obtain a less-than or greater-than sign, you should use \lt or \gt, respectively.
|
data/lib/mathematical/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
VERSION = '0.
|
1
|
+
class Mathematical
|
2
|
+
VERSION = '1.0.0'
|
3
3
|
end
|
data/mathematical.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Mathematical::VERSION
|
9
9
|
spec.authors = ['Garen Torikian']
|
10
10
|
spec.email = ['gjtorikian@gmail.com']
|
11
|
-
spec.summary = %
|
12
|
-
spec.description = %
|
11
|
+
spec.summary = %w(Quickly convert math equations into beautiful SVGs/PNGs/MathML.)
|
12
|
+
spec.description = %w(A very fast way to turn LaTeX math equations into beautifully rendered SVGs, to embed on the web. This library is mostly written in C and is a general purpose wrapper to GNOME's Lasem.)
|
13
13
|
spec.homepage = 'https://github.com/gjtorikian/mathematical'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
|
@@ -18,13 +18,13 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.files += Dir.glob('ext/**/*.{c,h}')
|
19
19
|
spec.files += Dir.glob('ext/**/extconf.rb')
|
20
20
|
spec.test_files = Dir.glob('test/**/*')
|
21
|
-
spec.require_paths =
|
21
|
+
spec.require_paths = %w(lib ext)
|
22
22
|
spec.extensions = ['ext/mathematical/extconf.rb']
|
23
23
|
|
24
24
|
spec.add_development_dependency 'rake', '~> 0.9'
|
25
25
|
spec.add_development_dependency 'rake-compiler', '~> 0.9'
|
26
26
|
spec.add_development_dependency 'bundler', '~> 1.5'
|
27
27
|
spec.add_development_dependency 'mocha', '~> 1.0'
|
28
|
-
spec.add_development_dependency 'math-to-itex', '
|
28
|
+
spec.add_development_dependency 'math-to-itex', '0.3.0'
|
29
29
|
spec.add_development_dependency 'nokogiri', '~> 1.6'
|
30
30
|
end
|
@@ -7,7 +7,7 @@ class Mathematical::BasicTest < Test::Unit::TestCase
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def test_multiple_calls
|
10
|
-
render = Mathematical
|
10
|
+
render = Mathematical.new
|
11
11
|
render.render('$\pi$')
|
12
12
|
output = render.render('$\pi$')['svg']
|
13
13
|
assert_equal 1, output.scan(/<svg/).size, 'should only contain one svg'
|
Binary file
|
Binary file
|
Binary file
|
@@ -15,30 +15,30 @@ class Mathematical::FixturesTest < Test::Unit::TestCase
|
|
15
15
|
if ENV['MATHEMATICAL_GENERATE_SAMPLE']
|
16
16
|
next unless name.match /compliance/
|
17
17
|
actual = MathToItex(source).convert do |eq, type|
|
18
|
-
svg_content = Mathematical
|
18
|
+
svg_content = Mathematical.new(:base64 => false).render(eq)
|
19
19
|
# remove \ and $, remove whitespace, keep alphanums, remove extraneous - and trailing -
|
20
20
|
filename = eq.gsub(/[\$\\]*/, '').gsub(/\s+/, '-').gsub(/[^a-zA-Z\d]/, '-').gsub(/-{2,}/, '-').gsub(/-$/, '')
|
21
|
-
File.open("samples/fixtures/#{filename}.svg",
|
21
|
+
File.open("samples/fixtures/#{filename}.svg", 'w') { |file| file.write svg_content['svg'] }
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
actual = MathToItex(source).convert do |eq, type|
|
26
|
-
svg_content = Mathematical
|
26
|
+
svg_content = Mathematical.new(:base64 => true).render(eq)
|
27
27
|
|
28
28
|
%|<img class="#{type.to_s}-math" data-math-type="#{type.to_s}-math" src="#{svg_content['svg']}"/>|
|
29
29
|
end.rstrip
|
30
30
|
|
31
|
-
expected_file = before.sub(/before/,
|
31
|
+
expected_file = before.sub(/before/, 'after').sub(/text/, 'html')
|
32
32
|
|
33
|
-
File.open(expected_file,
|
33
|
+
File.open(expected_file, 'w') { |file| file.write(actual) } unless ENV['DEBUG_MATHEMATICAL'].nil?
|
34
34
|
|
35
35
|
expected = File.read(expected_file)
|
36
36
|
|
37
|
-
expected = (MathToItex(expected).convert {|string| Mathematical
|
37
|
+
expected = (MathToItex(expected).convert {|string| Mathematical.new.render(string)}).rstrip
|
38
38
|
|
39
39
|
# Travis and OS X each render SVGs differently. For now, let's just be happy
|
40
40
|
# that something renders at all.
|
41
|
-
unless actual.match(
|
41
|
+
unless actual.match('PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My')
|
42
42
|
diff = IO.popen("diff -u - #{expected_file}", 'r+') do |f|
|
43
43
|
f.write actual
|
44
44
|
f.close_write
|
@@ -3,7 +3,7 @@ require "test_helper"
|
|
3
3
|
class Mathematical::MaliciousnessTest < Test::Unit::TestCase
|
4
4
|
|
5
5
|
def test_it_does_not_error_on_unrecognized_commands
|
6
|
-
render = Mathematical
|
6
|
+
render = Mathematical.new
|
7
7
|
output = nil
|
8
8
|
# In mtex2MML, we raise a ParseError, but Mathematical suppresses it and returns the string.
|
9
9
|
assert_nothing_raised { output = render.render('$not__thisisnotreal$') }
|
@@ -13,77 +13,104 @@ class Mathematical::MaliciousnessTest < Test::Unit::TestCase
|
|
13
13
|
def test_it_does_not_blow_up_on_bad_arguments
|
14
14
|
# need to pass a hash here
|
15
15
|
assert_raise TypeError do
|
16
|
-
render = Mathematical
|
16
|
+
render = Mathematical.new("not a hash")
|
17
17
|
end
|
18
18
|
|
19
19
|
# need to pass a string here
|
20
|
-
render = Mathematical
|
20
|
+
render = Mathematical.new
|
21
21
|
assert_raise TypeError do
|
22
|
-
Mathematical
|
22
|
+
Mathematical.new.render(123)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
26
|
def test_it_does_not_blow_up_on_bad_options
|
27
27
|
assert_raise TypeError do
|
28
|
-
render = Mathematical
|
28
|
+
render = Mathematical.new({:ppi => "not a number"})
|
29
29
|
end
|
30
30
|
|
31
31
|
assert_raise TypeError do
|
32
|
-
render = Mathematical
|
32
|
+
render = Mathematical.new({:zoom => "not a number"})
|
33
33
|
end
|
34
34
|
|
35
35
|
assert_raise TypeError do
|
36
|
-
render = Mathematical
|
36
|
+
render = Mathematical.new({:maxsize => "not a number"})
|
37
37
|
end
|
38
38
|
|
39
39
|
assert_raise TypeError do
|
40
|
-
render = Mathematical
|
40
|
+
render = Mathematical.new({:maxsize => -23})
|
41
41
|
end
|
42
42
|
|
43
43
|
assert_raise TypeError do
|
44
|
-
render = Mathematical
|
44
|
+
render = Mathematical.new({:maxsize => 5.3})
|
45
45
|
end
|
46
46
|
|
47
47
|
assert_raise TypeError do
|
48
|
-
render = Mathematical
|
48
|
+
render = Mathematical.new({:format => 123})
|
49
49
|
end
|
50
50
|
|
51
51
|
assert_raise TypeError do
|
52
|
-
render = Mathematical
|
52
|
+
render = Mathematical.new({:format => "something amazing"})
|
53
53
|
end
|
54
54
|
|
55
55
|
assert_raise Mathematical::MaxsizeError do
|
56
|
-
render = Mathematical
|
56
|
+
render = Mathematical.new({:maxsize => 2})
|
57
57
|
render.render('$a \ne b$')
|
58
58
|
end
|
59
59
|
|
60
60
|
assert_nothing_raised RangeError do
|
61
|
-
render = Mathematical
|
61
|
+
render = Mathematical.new({:maxsize => 2147483647}) # signed long max
|
62
62
|
render.render('$a \ne b$')
|
63
63
|
end
|
64
64
|
|
65
65
|
assert_raise RangeError do
|
66
|
-
render = Mathematical
|
66
|
+
render = Mathematical.new({ :maxsize => 4_294_967_295 }) # unsigned long max
|
67
67
|
render.render('$a \ne b$')
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
71
|
def test_it_does_not_blow_up_on_bad_input
|
72
72
|
assert_raise TypeError do
|
73
|
-
|
73
|
+
Mathematical.new.render(23)
|
74
74
|
end
|
75
75
|
|
76
76
|
assert_raise ArgumentError do
|
77
|
-
|
77
|
+
Mathematical.new.render('No dollars')
|
78
|
+
end
|
79
|
+
|
80
|
+
assert_raise ArgumentError do
|
81
|
+
array = %w(foof poof)
|
82
|
+
Mathematical.new.render(array)
|
83
|
+
end
|
84
|
+
|
85
|
+
assert_raise ArgumentError do
|
86
|
+
array = ['$foof$', nil, '$poof$']
|
87
|
+
Mathematical.new.render(array)
|
78
88
|
end
|
79
89
|
end
|
80
90
|
|
81
91
|
def test_it_returns_unmodified_string_for_max_parsing
|
82
|
-
render = Mathematical
|
92
|
+
render = Mathematical.new
|
83
93
|
output = nil
|
84
94
|
# Much like above, this fails in mtx2MML, but should do nothing here
|
85
95
|
text = '$\Huge \sqrt\sqrt\sqrt\sqrt\sqrt\sqrt\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{\sqrt{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}'
|
86
96
|
assert_nothing_raised { output = render.render(text) }
|
87
97
|
assert output == text
|
88
98
|
end
|
99
|
+
|
100
|
+
def test_it_parses_all_possible_array_elements
|
101
|
+
render = Mathematical.new
|
102
|
+
array = ['$foof$', '$/this___istotallyfake$', '$poof$']
|
103
|
+
output = nil
|
104
|
+
|
105
|
+
_, err = capture_subprocess_io do
|
106
|
+
output = render.render(array)
|
107
|
+
end
|
108
|
+
|
109
|
+
assert_equal 3, output.length
|
110
|
+
assert_equal Hash, output.first.class
|
111
|
+
assert_equal Hash, output.last.class
|
112
|
+
assert_equal '$/this___istotallyfake$', output[1]
|
113
|
+
# array errors output to STDERR
|
114
|
+
assert_match /Failed to parse mtex: \$\/this___istotallyfake\$/, err
|
115
|
+
end
|
89
116
|
end
|
@@ -3,7 +3,7 @@ require 'nokogiri'
|
|
3
3
|
|
4
4
|
class Mathematical::MathJaxTest < Test::Unit::TestCase
|
5
5
|
|
6
|
-
render_svg = Mathematical
|
6
|
+
render_svg = Mathematical.new
|
7
7
|
|
8
8
|
MATHJAX_TEST_TEST_DIR = File.join('ext', 'mathematical', 'mtex2MML', 'test', 'fixtures', 'MathJax')
|
9
9
|
MATHJAX_TEST_TEX_DIR = File.join(MATHJAX_TEST_TEST_DIR, 'LaTeXToMathML-tex')
|
@@ -15,18 +15,10 @@ class Mathematical::MathJaxTest < Test::Unit::TestCase
|
|
15
15
|
data = nil
|
16
16
|
assert_nothing_raised { data = render_svg.render(tex_contents) }
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
if mathml =~ /menclose/
|
23
|
-
puts "\n\nSKIPPING #{tex}\n\n"
|
24
|
-
else
|
25
|
-
# assert the SVG actually rendered
|
26
|
-
doc = Nokogiri::HTML(data['svg'])
|
27
|
-
assert_empty doc.search(%(//svg[@width='0pt']))
|
28
|
-
assert_empty doc.search(%(//svg[@height='0pt']))
|
29
|
-
end
|
18
|
+
# assert the SVG actually rendered
|
19
|
+
doc = Nokogiri::HTML(data['svg'])
|
20
|
+
assert_empty doc.search(%(//svg[@width='0pt']))
|
21
|
+
assert_empty doc.search(%(//svg[@height='0pt']))
|
30
22
|
end
|
31
23
|
end
|
32
24
|
end
|
@@ -13,9 +13,9 @@ class Mathematical::MathMLTest < Test::Unit::TestCase
|
|
13
13
|
\end{pmatrix}
|
14
14
|
$$
|
15
15
|
'''
|
16
|
-
render = Mathematical
|
17
|
-
mathml = render.render(string)[
|
16
|
+
render = Mathematical.new({:format => :mathml})
|
17
|
+
mathml = render.render(string)['mathml']
|
18
18
|
|
19
|
-
assert_match
|
19
|
+
assert_match %r{<math xmlns='http://www.w3.org/1998/Math/MathML' display='block'><semantics><mrow><mrow><mo>\(}, mathml
|
20
20
|
end
|
21
21
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class Mathematical::MultiplesTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@render = Mathematical.new(:base64 => true)
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_it_works_for_a_single_numbered_equation
|
10
|
+
string = '''
|
11
|
+
$$
|
12
|
+
\begin{equation}
|
13
|
+
f(x)=(x+a)(x+b)
|
14
|
+
\end{equation}
|
15
|
+
$$
|
16
|
+
'''
|
17
|
+
|
18
|
+
output = @render.render([string])
|
19
|
+
svg = output.first['svg']
|
20
|
+
|
21
|
+
assert_equal 1, svg.scan(/svg\+xml;/).size, 'should only contain one svg'
|
22
|
+
assert_match 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My', svg
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_it_works_for_many_equations
|
26
|
+
inputs = []
|
27
|
+
(1..1000).each do |i|
|
28
|
+
string = """
|
29
|
+
$$
|
30
|
+
\\begin{equation}
|
31
|
+
f(#{i})=(x+a)(x+b)
|
32
|
+
\\end{equation}
|
33
|
+
$$
|
34
|
+
"""
|
35
|
+
inputs << string
|
36
|
+
end
|
37
|
+
|
38
|
+
output = @render.render(inputs)
|
39
|
+
assert_equal 1000, output.length
|
40
|
+
output.each do |data|
|
41
|
+
assert_match 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My', data['svg']
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_it_properly_accounts_for_equations
|
46
|
+
inputs = []
|
47
|
+
[1, 2].each do |i|
|
48
|
+
string = """
|
49
|
+
$$
|
50
|
+
\\begin{equation}
|
51
|
+
f(#{i})=(x+a)(x+b)
|
52
|
+
\\end{equation}
|
53
|
+
$$
|
54
|
+
"""
|
55
|
+
inputs << string
|
56
|
+
end
|
57
|
+
|
58
|
+
inputs.insert(1, '$test$')
|
59
|
+
render = Mathematical.new({:format => :png})
|
60
|
+
output = render.render(inputs)
|
61
|
+
assert_equal 3, output.length
|
62
|
+
output.each_with_index do |data_hash, i|
|
63
|
+
header = data_hash['png'].unpack('H*').first.slice(0, 18)
|
64
|
+
File.open("#{fixtures_dir}/png/numeric_test_#{i + 1}.png", 'w') { |f| f.write(data_hash['png'])}
|
65
|
+
assert_equal header, '89504e470d0a1a0a00'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|