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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +48 -12
  3. data/Rakefile +3 -2
  4. data/ext/mathematical/cairo_callbacks.c +25 -0
  5. data/ext/mathematical/cairo_callbacks.h +7 -0
  6. data/ext/mathematical/extconf.rb +11 -11
  7. data/ext/mathematical/lasem/src/lsmmathmldocument.c +3 -0
  8. data/ext/mathematical/lasem/src/lsmmathmlencloseelement.c +142 -0
  9. data/ext/mathematical/lasem/src/lsmmathmlencloseelement.h +64 -0
  10. data/ext/mathematical/lasem/src/lsmmathmlenums.c +35 -0
  11. data/ext/mathematical/lasem/src/lsmmathmlenums.h +25 -1
  12. data/ext/mathematical/lasem/src/lsmmathmlpaddedelement.c +79 -0
  13. data/ext/mathematical/lasem/src/lsmmathmlpaddedelement.h +5 -0
  14. data/ext/mathematical/lasem/src/lsmmathmlstyleelement.c +6 -0
  15. data/ext/mathematical/lasem/src/lsmmathmltableelement.c +5 -5
  16. data/ext/mathematical/lasem/src/lsmmathmltraits.c +24 -0
  17. data/ext/mathematical/lasem/src/lsmmathmltraits.h +1 -0
  18. data/ext/mathematical/lasem/src/lsmmathmltypes.h +1 -0
  19. data/ext/mathematical/lasem/src/lsmmathmlutils.h +9 -2
  20. data/ext/mathematical/lasem/src/lsmmathmlview.c +283 -11
  21. data/ext/mathematical/lasem/src/lsmmathmlview.h +13 -0
  22. data/ext/mathematical/lasem_overrides.c +40 -0
  23. data/ext/mathematical/lasem_overrides.h +23 -0
  24. data/ext/mathematical/mathematical.c +119 -127
  25. data/ext/mathematical/mathematical.h +24 -0
  26. data/ext/mathematical/mtex2MML/ext/extconf.rb +1 -1
  27. data/ext/mathematical/mtex2MML/src/lex.yy.c +4488 -4032
  28. data/ext/mathematical/mtex2MML/src/mtex2MML.h +3 -0
  29. data/ext/mathematical/mtex2MML/src/parse_extras.c +14 -5
  30. data/ext/mathematical/mtex2MML/src/parse_extras.h +3 -1
  31. data/ext/mathematical/mtex2MML/src/string_extras.c +39 -0
  32. data/ext/mathematical/mtex2MML/src/string_extras.h +7 -0
  33. data/ext/mathematical/mtex2MML/src/y.tab.c +4408 -3175
  34. data/ext/mathematical/mtex2MML/src/y.tab.h +500 -422
  35. data/lib/mathematical.rb +112 -2
  36. data/lib/mathematical/corrections.rb +2 -2
  37. data/lib/mathematical/version.rb +2 -2
  38. data/mathematical.gemspec +4 -4
  39. data/test/mathematical/basic_test.rb +1 -1
  40. data/test/mathematical/corrections_test.rb +1 -1
  41. data/test/mathematical/fixtures/png/numeric_test_1.png +0 -0
  42. data/test/mathematical/fixtures/png/numeric_test_2.png +0 -0
  43. data/test/mathematical/fixtures/png/numeric_test_3.png +0 -0
  44. data/test/mathematical/fixtures_test.rb +7 -7
  45. data/test/mathematical/maliciousness_test.rb +44 -17
  46. data/test/mathematical/mathjax_test.rb +5 -13
  47. data/test/mathematical/mathml_test.rb +3 -3
  48. data/test/mathematical/multiples_test.rb +68 -0
  49. data/test/mathematical/performance_test.rb +2 -2
  50. data/test/mathematical/png_test.rb +5 -5
  51. data/test/test_helper.rb +36 -1
  52. metadata +26 -11
  53. 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
- module Mathematical
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
- module Mathematical
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.
@@ -1,3 +1,3 @@
1
- module Mathematical
2
- VERSION = '0.6.2'
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 = %q{Quickly convert math equations into beautiful SVGs/PNGs/MathML.}
12
- spec.description = %q{A very fast way to turn itex 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. }
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 = ['lib', 'ext']
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', '~> 0.3'
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::Render.new
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'
@@ -3,7 +3,7 @@ require "test_helper"
3
3
  class Mathematical::CorrectionsTest < Test::Unit::TestCase
4
4
 
5
5
  def setup
6
- @render = Mathematical::Render.new
6
+ @render = Mathematical.new
7
7
  end
8
8
 
9
9
  def test_adjust_lt_gt
@@ -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::Render.new(:base64 => false).render(eq)
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", "w") { |file| file.write svg_content["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::Render.new(:base64 => true).render(eq)
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/, "after").sub(/text/, "html")
31
+ expected_file = before.sub(/before/, 'after').sub(/text/, 'html')
32
32
 
33
- File.open(expected_file, "w") { |file| file.write(actual) } unless ENV['DEBUG_MATHEMATICAL'].nil?
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::Render.new.render(string)}).rstrip
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("PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My")
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::Render.new
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::Render.new("not a hash")
16
+ render = Mathematical.new("not a hash")
17
17
  end
18
18
 
19
19
  # need to pass a string here
20
- render = Mathematical::Render.new
20
+ render = Mathematical.new
21
21
  assert_raise TypeError do
22
- Mathematical::Render.new.render(123)
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::Render.new({:ppi => "not a number"})
28
+ render = Mathematical.new({:ppi => "not a number"})
29
29
  end
30
30
 
31
31
  assert_raise TypeError do
32
- render = Mathematical::Render.new({:zoom => "not a number"})
32
+ render = Mathematical.new({:zoom => "not a number"})
33
33
  end
34
34
 
35
35
  assert_raise TypeError do
36
- render = Mathematical::Render.new({:maxsize => "not a number"})
36
+ render = Mathematical.new({:maxsize => "not a number"})
37
37
  end
38
38
 
39
39
  assert_raise TypeError do
40
- render = Mathematical::Render.new({:maxsize => -23})
40
+ render = Mathematical.new({:maxsize => -23})
41
41
  end
42
42
 
43
43
  assert_raise TypeError do
44
- render = Mathematical::Render.new({:maxsize => 5.3})
44
+ render = Mathematical.new({:maxsize => 5.3})
45
45
  end
46
46
 
47
47
  assert_raise TypeError do
48
- render = Mathematical::Render.new({:format => 123})
48
+ render = Mathematical.new({:format => 123})
49
49
  end
50
50
 
51
51
  assert_raise TypeError do
52
- render = Mathematical::Render.new({:format => "something amazing"})
52
+ render = Mathematical.new({:format => "something amazing"})
53
53
  end
54
54
 
55
55
  assert_raise Mathematical::MaxsizeError do
56
- render = Mathematical::Render.new({:maxsize => 2})
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::Render.new({:maxsize => 2147483647}) # signed long max
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::Render.new({:maxsize => 4294967295}) # unsigned long max
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
- render = Mathematical::Render.new.render(23)
73
+ Mathematical.new.render(23)
74
74
  end
75
75
 
76
76
  assert_raise ArgumentError do
77
- render = Mathematical::Render.new.render("No dollars")
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::Render.new
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::Render.new
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
- render_mathml = Mathematical::Render.new({:format => "mathml"})
19
- mathml = render_mathml.render(tex_contents)['mathml']
20
-
21
- # TODO Lasem can't handle this node
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::Render.new({:format => "mathml"})
17
- mathml = render.render(string)["mathml"]
16
+ render = Mathematical.new({:format => :mathml})
17
+ mathml = render.render(string)['mathml']
18
18
 
19
- assert_match /<math xmlns='http:\/\/www.w3.org\/1998\/Math\/MathML' display='block'><semantics><mrow><mrow><mo>\(/, mathml
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