mathemagical 0.0.1

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.
@@ -0,0 +1,202 @@
1
+ require "mathemagical"
2
+
3
+ describe Mathemagical::LaTeX::Scanner do
4
+ def new_scanner(src)
5
+ Mathemagical::LaTeX::Scanner.new(src)
6
+ end
7
+
8
+ it "#done, #rest" do
9
+ s = new_scanner("0123")
10
+ s.pos = 2
11
+ s.done.should == "01"
12
+ s.rest.should == "23"
13
+ end
14
+
15
+ it "#_check" do
16
+ s = new_scanner(" ")
17
+ s._check(/\s/).should == " "
18
+ s.pos.should == 0
19
+ end
20
+
21
+ it "#_scan" do
22
+ s = new_scanner(" ")
23
+ s._scan(/\s/).should == " "
24
+ s.pos.should == 1
25
+ end
26
+
27
+ it "#check" do
28
+ s = new_scanner(" a")
29
+ s.check(/a/).should == "a"
30
+ s.pos.should == 0
31
+ end
32
+
33
+ it "#scan, #reset" do
34
+ s = new_scanner(" a")
35
+ s.scan(/a/).should == "a"
36
+ s.pos.should == 2
37
+
38
+ s.reset
39
+ s.pos.should == 0
40
+ s.scan(/b/).should be_nil
41
+ s.pos.should == 0
42
+
43
+ s = new_scanner(" %comment\na")
44
+ s.scan(/a/).should == "a"
45
+ s.pos.should == 11
46
+
47
+ s.reset
48
+ s.scan(/b/).should be_nil
49
+ s.pos.should == 0
50
+ end
51
+
52
+ it "#eos" do
53
+ new_scanner("").should be_eos
54
+ new_scanner(" ").should be_eos
55
+ new_scanner(" %test\n%test").should be_eos
56
+ new_scanner(" a").should_not be_eos
57
+ new_scanner(" \\command").should_not be_eos
58
+ end
59
+
60
+ it "#check_command" do
61
+ '\t'.should == '\\t'
62
+
63
+ new_scanner("test").check_command.should be_nil
64
+ s = new_scanner(' \test')
65
+ s.check_command.should == '\\test'
66
+ s[1].should == "test"
67
+
68
+ new_scanner(' \test next').check_command.should == '\test'
69
+ new_scanner(' \test_a').check_command.should == '\test'
70
+ end
71
+
72
+ it "#scan_command" do
73
+ new_scanner("test").scan_command.should be_nil
74
+
75
+ s = new_scanner(' \test')
76
+ s.scan_command.should == '\test'
77
+ s[1].should == "test"
78
+ s.pos.should == 6
79
+
80
+ s = new_scanner(' \test rest')
81
+ s.scan_command.should == '\test'
82
+ s.pos.should == 6
83
+
84
+ s = new_scanner(' \test_a')
85
+ s.scan_command.should == '\test'
86
+ s.pos.should == 6
87
+
88
+ s = new_scanner(' \_test')
89
+ s.check_command.should == '\_'
90
+ s.scan_command.should == '\_'
91
+ s.rest.should == "test"
92
+ end
93
+
94
+ it "#scan_block" do
95
+ new_scanner(" a").scan_block.should == nil
96
+ new_scanner(" a").check_block.should == nil
97
+
98
+ i = " {{}{}{{}{}}} "
99
+ e = "{#{i}}"
100
+ s = new_scanner(" #{e} test")
101
+ s.check_block.should == e
102
+ s.matched.should == e
103
+ s[1].should == i
104
+ s.scan_block.should == e
105
+ s.matched.should == e
106
+ s[1].should == i
107
+ s.rest.should == " test"
108
+
109
+ new_scanner(' \command test').scan_block.should == nil
110
+ new_scanner(' \command test').check_block.should == nil
111
+
112
+ new_scanner("").scan_block.should == nil
113
+ new_scanner("").check_block.should == nil
114
+
115
+ new_scanner(" ").scan_block.should == nil
116
+ new_scanner(" ").check_block.should == nil
117
+
118
+ s = new_scanner("{test")
119
+ lambda{s.scan_block}.should raise_error(Mathemagical::LaTeX::BlockNotClosed)
120
+ end
121
+
122
+ it "#scan_any" do
123
+ s0 = " %comment\n "
124
+ s1 = "{}"
125
+ s = new_scanner(s0+s1)
126
+ s.scan_any.should == s1
127
+ s.reset
128
+ s.scan_any(true).should == s0+s1
129
+ s.matched.should == s1
130
+
131
+ s1 = '\command'
132
+ s = new_scanner(s0+s1)
133
+ s.scan_any.should == s1
134
+ s.reset
135
+ s.scan_any(true).should == s0+s1
136
+
137
+ s1 = 'a'
138
+ s = new_scanner(s0+s1)
139
+ s.scan_any.should == s1
140
+ s.reset
141
+ s.scan_any(true).should == s0+s1
142
+
143
+ s = new_scanner(" ")
144
+ s.scan_any.should == nil
145
+ s.reset
146
+ s.scan_any(true).should == " "
147
+
148
+ s = new_scanner('\begin{env}test\end{env}')
149
+ s.scan_any.should == '\begin'
150
+ end
151
+
152
+ it "#peek_command" do
153
+ new_scanner(' \test').peek_command.should == "test"
154
+ new_scanner("").peek_command.should == nil
155
+ new_scanner(" ").peek_command.should == nil
156
+ new_scanner(" a").peek_command.should == nil
157
+ end
158
+
159
+ it "#scan_option" do
160
+ s = new_scanner(" []")
161
+ s.scan_option.should == "[]"
162
+ s[1].should == ""
163
+ s.pos.should == 3
164
+
165
+ s = new_scanner(" [ opt ]")
166
+ s.scan_option.should == "[ opt ]"
167
+ s[1].should == " opt "
168
+ s.pos.should == 8
169
+
170
+ s = new_scanner(" [[]]")
171
+ s.scan_option.should == "[[]"
172
+ s[1].should == "["
173
+
174
+ s = new_scanner(" [{[]}]")
175
+ s.scan_option.should == "[{[]}]"
176
+ s[1].should == "{[]}"
177
+
178
+ lambda{new_scanner("[").scan_option}.should raise_error(Mathemagical::LaTeX::OptionNotClosed)
179
+ end
180
+
181
+ it "#check_option" do
182
+ s = new_scanner(" []")
183
+ s.check_option.should == "[]"
184
+ s[1].should == ""
185
+ s.pos.should == 0
186
+
187
+ s = new_scanner(" [ opt ]")
188
+ s.check_option.should == "[ opt ]"
189
+ s[1].should == " opt "
190
+ s.pos.should == 0
191
+
192
+ s = new_scanner(" [[]]")
193
+ s.check_option.should == "[[]"
194
+ s[1].should == "["
195
+
196
+ s = new_scanner(" [{[]}]")
197
+ s.check_option.should == "[{[]}]"
198
+ s[1].should == "{[]}"
199
+
200
+ lambda{new_scanner("[").check_option}.should raise_error(Mathemagical::LaTeX::OptionNotClosed)
201
+ end
202
+ end
@@ -0,0 +1,29 @@
1
+ require "mathemagical/string"
2
+
3
+ describe Mathemagical::String do
4
+ it ".mathml_latex_parser" do
5
+ Mathemagical::String.mathml_latex_parser.should be_kind_of(Mathemagical::LaTeX::Parser)
6
+ mlp = Mathemagical::LaTeX::Parser.new
7
+ Mathemagical::String.mathml_latex_parser = mlp
8
+ Mathemagical::String.mathml_latex_parser.should equal(mlp)
9
+ lambda{Mathemagical::String.mathml_latex_parser=String}.should raise_error(TypeError)
10
+ Mathemagical::String.mathml_latex_parser.should equal(mlp)
11
+
12
+ Mathemagical::String.mathml_latex_parser = nil
13
+ Mathemagical::String.mathml_latex_parser.should be_kind_of(Mathemagical::LaTeX::Parser)
14
+ Mathemagical::String.mathml_latex_parser.should_not equal(mlp)
15
+ end
16
+ end
17
+
18
+ describe String do
19
+ it "#parse" do
20
+ mlp = Mathemagical::LaTeX::Parser.new
21
+ "".to_mathml.to_s.should == mlp.parse("").to_s
22
+ "".to_mathml(true).to_s.should == mlp.parse("", true).to_s
23
+
24
+ Mathemagical::String.mathml_latex_parser.macro.parse(<<'EOT')
25
+ \newcommand{\test}{x}
26
+ EOT
27
+ '\test'.to_mathml.to_s.should == mlp.parse("x").to_s
28
+ end
29
+ end
@@ -0,0 +1,700 @@
1
+ require "mathemagical/util"
2
+
3
+ describe Mathemagical::Util do
4
+ include Mathemagical::Util
5
+
6
+ it "#escapeXML" do
7
+ escapeXML("<>&\"'").should == "&lt;&gt;&amp;&quot;&apos;"
8
+ escapeXML("\n").should == "\n"
9
+ escapeXML("\n", true).should == "<br />\n"
10
+ end
11
+
12
+ it ".escapeXML" do
13
+ Mathemagical::Util.escapeXML("<>&\"'").should == "&lt;&gt;&amp;&quot;&apos;"
14
+ Mathemagical::Util.escapeXML("\n").should == "\n"
15
+ Mathemagical::Util.escapeXML("\n", true).should == "<br />\n"
16
+ end
17
+
18
+ it "#collect_regexp" do
19
+ collect_regexp([/a/, /b/, /c/]).should == /#{/a/}|#{/b/}|#{/c/}/
20
+ collect_regexp([[/a/, /b/, /c/]]).should == /#{/a/}|#{/b/}|#{/c/}/
21
+ collect_regexp([]).should == /(?!)/
22
+ collect_regexp(/a/).should == /#{/a/}/
23
+ end
24
+
25
+ it ".collect_regexp" do
26
+ Mathemagical::Util.collect_regexp([/a/, /b/, /c/]).should == /#{/a/}|#{/b/}|#{/c/}/
27
+ Mathemagical::Util.collect_regexp([[/a/, /b/, /c/]]).should == /#{/a/}|#{/b/}|#{/c/}/
28
+ Mathemagical::Util.collect_regexp([]).should == /(?!)/
29
+ Mathemagical::Util.collect_regexp(/a/).should == /#{/a/}/
30
+
31
+ Mathemagical::Util.collect_regexp([nil, /a/, "text", /b/]).should == /#{/a/}|#{/b/}/
32
+
33
+ Mathemagical::Util.collect_regexp([nil, [/a/, [/b/, /c/]]]).should == /#{/a/}|#{/b/}|#{/c/}/
34
+ end
35
+
36
+ it "::INVALID_RE" do
37
+ Mathemagical::Util::INVALID_RE.should == /(?!)/
38
+ end
39
+ end
40
+
41
+ describe Mathemagical::Util::MathData do
42
+ it "#<< and #update" do
43
+ m = Mathemagical::Util::MathData.new
44
+ m.math_list << "ml1"
45
+ m.msrc_list << "sl1"
46
+ m.dmath_list << "dml1"
47
+ m.dsrc_list << "dsl1"
48
+ m.escape_list << "el1"
49
+ m.esrc_list << "es1"
50
+ m.user_list << "ul1"
51
+ m.usrc_list << "usl1"
52
+ m.math_list.should == ["ml1"]
53
+ m.msrc_list.should == ["sl1"]
54
+ m.dmath_list.should == ["dml1"]
55
+ m.dsrc_list.should == ["dsl1"]
56
+ m.escape_list.should == ["el1"]
57
+ m.esrc_list.should == ["es1"]
58
+ m.user_list.should == ["ul1"]
59
+ m.usrc_list.should == ["usl1"]
60
+
61
+ m2 = Mathemagical::Util::MathData.new
62
+ m2.math_list << "ml2"
63
+ m2.msrc_list << "sl2"
64
+ m2.dmath_list << "dml2"
65
+ m2.dsrc_list << "dsl2"
66
+ m2.escape_list << "el2"
67
+ m2.esrc_list << "es2"
68
+ m2.user_list << "ul2"
69
+ m2.usrc_list << "usl2"
70
+
71
+ m.update(m2)
72
+
73
+ m.math_list.should == ["ml1", "ml2"]
74
+ m.msrc_list.should == ["sl1", "sl2"]
75
+ m.dmath_list.should == ["dml1", "dml2"]
76
+ m.dsrc_list.should == ["dsl1", "dsl2"]
77
+ m.escape_list.should == ["el1", "el2"]
78
+ m.esrc_list.should == ["es1", "es2"]
79
+ m.user_list.should == ["ul1", "ul2"]
80
+ m.usrc_list.should == ["usl1", "usl2"]
81
+ end
82
+ end
83
+
84
+ describe Mathemagical::Util::SimpleLaTeX do
85
+ def strip_math(s)
86
+ s.gsub(/>\s*/, ">").gsub(/\s*</, "<")[/<math.*?>(.*)<\/math>/m, 1]
87
+ end
88
+
89
+ def sma(a) # Stripped Mathml Array
90
+ r = []
91
+ a.each do |i|
92
+ r << strip_math(i.to_s)
93
+ end
94
+ r
95
+ end
96
+
97
+ def simplify_math(src)
98
+ attr = []
99
+ r = src.gsub(/<math(\s+[^>]+)>/) do |m|
100
+ attr << $1.scan(/\s+[^\s]+/).map{|i| i[/\A\s*(.*)/, 1]}.sort
101
+ "<math>"
102
+ end
103
+ attr.unshift(r)
104
+ end
105
+
106
+ def assert_data(src,
107
+ expected_math, expected_src,
108
+ expected_dmath, expected_dsrc,
109
+ expected_escaped, expected_esrc,
110
+ expected_encoded, expected_decoded,
111
+ simple_latex = Mathemagical::Util::SimpleLaTeX)
112
+ encoded, data = simple_latex.encode(src)
113
+
114
+ data.math_list.each do |i|
115
+ i.attributes[:display].should == "inline"
116
+ end
117
+ data.dmath_list.each do |i|
118
+ i.attributes[:display].should == "block"
119
+ end
120
+
121
+ sma(data.math_list).should == expected_math
122
+ data.msrc_list.should == expected_src
123
+ sma(data.dmath_list).should == expected_dmath
124
+ data.dsrc_list.should == expected_dsrc
125
+ data.escape_list.should == expected_escaped
126
+ data.esrc_list.should == expected_esrc
127
+ encoded.should == expected_encoded
128
+ target = simple_latex.decode(encoded, data)
129
+ simplify_math(target).should == simplify_math(expected_decoded)
130
+ end
131
+
132
+ it "(spec for helper)" do
133
+ simplify_math("<math c='d' a='b'>..</math><math g='h' e='f'></math>").should == ["<math>..</math><math></math>", %w[a='b' c='d'], %w[e='f' g='h']]
134
+ end
135
+
136
+ it "should parse math environment" do
137
+ assert_data("a\n$\nb\n$\nc\\(\nd\n\\)e",
138
+ ["<mi>b</mi>", "<mi>d</mi>"],
139
+ ["$\nb\n$", "\\(\nd\n\\)"],
140
+ [], [], [], [],
141
+ "a\n\001m0\001\nc\001m1\001e",
142
+ "a\n<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>b</mi></math>\nc<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>d</mi></math>e")
143
+
144
+ assert_data('$\\$$',
145
+ ["<mo stretchy='false'>$</mo>"],
146
+ ['$\$$'], [], [], [], [], "\001m0\001",
147
+ "<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mo stretchy='false'>$</mo></math>")
148
+ end
149
+
150
+ it "should parse dmath environment" do
151
+ assert_data("a\n$$\nb\n$$\nc\\[\nd\n\\]e",
152
+ [], [],
153
+ ["<mi>b</mi>", "<mi>d</mi>"],
154
+ ["$$\nb\n$$", "\\[\nd\n\\]"],
155
+ [], [],
156
+ "a\n\001d0\001\nc\001d1\001e",
157
+ "a\n<math display='block' xmlns='http://www.w3.org/1998/Math/MathML'><mi>b</mi></math>\nc<math display='block' xmlns='http://www.w3.org/1998/Math/MathML'><mi>d</mi></math>e")
158
+ end
159
+
160
+ it "should parse math and dmath environment" do
161
+ assert_data('a$b$c$$d$$e\(f\)g\[h\]i',
162
+ ["<mi>b</mi>", "<mi>f</mi>"],
163
+ ["$b$", '\(f\)'],
164
+ ["<mi>d</mi>", "<mi>h</mi>"],
165
+ ["$$d$$", '\[h\]'],
166
+ [], [],
167
+ "a\001m0\001c\001d0\001e\001m1\001g\001d1\001i",
168
+ "a<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>b</mi></math>c<math display='block' xmlns='http://www.w3.org/1998/Math/MathML'><mi>d</mi></math>e<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>f</mi></math>g<math display='block' xmlns='http://www.w3.org/1998/Math/MathML'><mi>h</mi></math>i")
169
+ end
170
+
171
+ it "should parse escaping" do
172
+ assert_data('a\bc\d\e', [], [], [], [], ['b', 'd', 'e'], ['\b', '\d', '\e'], "a\001e0\001c\001e1\001\001e2\001", 'abcde')
173
+ assert_data('\$a$$b$$', [], [], ["<mi>b</mi>"], ["$$b$$"], [%[$]], ['\$'], "\001e0\001a\001d0\001",
174
+ "$a<math display='block' xmlns='http://www.w3.org/1998/Math/MathML'><mi>b</mi></math>")
175
+
176
+ assert_data("\\<\\\n", [], [], [], [], ["&lt;", "<br />\n"], ["\\<", "\\\n"], "\001e0\001\001e1\001", "&lt;<br />\n")
177
+ end
178
+
179
+ it "should accept through_list option" do
180
+ s = Mathemagical::Util::SimpleLaTeX.new(:through_list=>[/\{\{.*\}\}/, /\(.*\)/])
181
+ assert_data("{{$a$}}($b$)", [], [], [], [], [], [], "{{$a$}}($b$)", "{{$a$}}($b$)", s)
182
+
183
+ s = Mathemagical::Util::SimpleLaTeX.new(:through_list=>/\{.*\}/)
184
+ assert_data("{$a$}", [], [], [], [], [], [], "{$a$}", "{$a$}", s)
185
+ end
186
+
187
+ it "should accept parser option" do
188
+ ps = Mathemagical::LaTeX::Parser.new
189
+ ps.macro.parse('\newcommand{\test}{t}')
190
+ s = Mathemagical::Util::SimpleLaTeX.new(:parser=>ps)
191
+ assert_data('$\test$', ["<mi>t</mi>"], ['$\test$'], [], [], [], [], "\001m0\001",
192
+ "<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>t</mi></math>", s)
193
+ end
194
+
195
+ it "should accept escape option" do
196
+ s = Mathemagical::Util::SimpleLaTeX.new(:escape_list=>[/\/(.)/, /(\^.)/])
197
+ assert_data('\$a$', ["<mi>a</mi>"], ['$a$'], [], [], [], [], "\\\001m0\001",
198
+ "\\<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi></math>", s)
199
+ assert_data(%[/$a/$], [], [], [], [], [%[$], %[$]], [%[/$], %[/$]], "\001e0\001a\001e1\001", "$a$", s)
200
+ assert_data('^\(a^\)', [], [], [], [], ['^\\', '^\\'], ['^\\', '^\\'], "\001e0\001(a\001e1\001)", '^\(a^\)', s)
201
+
202
+ s = Mathemagical::Util::SimpleLaTeX.new(:escape_list=>/_(.)/)
203
+ assert_data("_$a$", [], [], [], [], ['$'], ["_$"], %[\001e0\001a$], '$a$', s)
204
+ end
205
+
206
+ it "should accept delimiter option" do
207
+ s = Mathemagical::Util::SimpleLaTeX.new(:delimiter=>"\002\003")
208
+ assert_data("a$b$c", ["<mi>b</mi>"], ["$b$"], [], [], [], [], "a\002\003m0\002\003c",
209
+ "a<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>b</mi></math>c", s)
210
+
211
+ s = Mathemagical::Util::SimpleLaTeX.new(:delimiter=>%[$])
212
+ assert_data("a$b$c", ["<mi>b</mi>"], ["$b$"], [], [], [], [], "a$m0$c",
213
+ "a<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>b</mi></math>c", s)
214
+ end
215
+
216
+ it "should accept (d)math_env_list option" do
217
+ s = Mathemagical::Util::SimpleLaTeX.new(:math_env_list=>/%(.*?)%/, :dmath_env_list=>/\[(.*?)\]/)
218
+ assert_data("a$b$c%d%e[f]", ["<mi>d</mi>"], ["%d%"], ["<mi>f</mi>"], ["[f]"], [], [],
219
+ "a$b$c\001m0\001e\001d0\001",
220
+ "a$b$c<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>d</mi></math>e<math display='block' xmlns='http://www.w3.org/1998/Math/MathML'><mi>f</mi></math>", s)
221
+
222
+ s = Mathemagical::Util::SimpleLaTeX.new(:math_env_list=>[/!(.*?)!/, /"(.*)"/], :dmath_env_list=>[/\#(.*)\#/, /&(.*)&/])
223
+ assert_data('a!b!c"d"e#f#g&h&i',
224
+ ["<mi>b</mi>", "<mi>d</mi>"], ['!b!', '"d"'],
225
+ ["<mi>f</mi>", "<mi>h</mi>"], ['#f#', '&h&'],
226
+ [], [],
227
+ "a\001m0\001c\001m1\001e\001d0\001g\001d1\001i",
228
+ "a<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>b</mi></math>c<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>d</mi></math>e<math display='block' xmlns='http://www.w3.org/1998/Math/MathML'><mi>f</mi></math>g<math display='block' xmlns='http://www.w3.org/1998/Math/MathML'><mi>h</mi></math>i", s)
229
+ end
230
+
231
+ it "should accept throu_list option" do
232
+ s = Mathemagical::Util::SimpleLaTeX.new(:through_list=>[/<%=.*?%>/m, /\(\(.*?\)\)/m])
233
+ assert_data("<%=$a$%>(($b$))", [], [], [], [], [], [], "<%=$a$%>(($b$))", "<%=$a$%>(($b$))", s)
234
+
235
+ s = Mathemagical::Util::SimpleLaTeX.new(:through_list=>/<%=.*?%>/)
236
+ assert_data("<%=$a$%>", [], [], [], [], [], [], "<%=$a$%>", "<%=$a$%>", s)
237
+ end
238
+
239
+ it "should accept through_list=>[]" do
240
+ s = Mathemagical::Util::SimpleLaTeX.new(:through_list=>[])
241
+ assert_data("$a$", ["<mi>a</mi>"], [%[$a$]], [], [], [], [], "\001m0\001",
242
+ "<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi></math>", s)
243
+ end
244
+
245
+ it "should accept without_parse option" do
246
+ s = Mathemagical::Util::SimpleLaTeX.new(:without_parse=>true)
247
+ encoded, data = s.encode("$a$ $$b$$")
248
+ data.math_list.should == []
249
+ data.msrc_list.should == ["$a$"]
250
+ data.dmath_list.should == []
251
+ data.dsrc_list.should == ["$$b$$"]
252
+ encoded.should == "\001m0\001 \001d0\001"
253
+
254
+ s.parse(data)
255
+ data.math_list[0].attributes[:display].should == "inline"
256
+ data.dmath_list[0].attributes[:display].should == "block"
257
+ sma(data.math_list).should == ["<mi>a</mi>"]
258
+ sma(data.dmath_list).should == ["<mi>b</mi>"]
259
+ simplify_math(s.decode(encoded, data)).should == simplify_math("<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi></math> <math display='block' xmlns='http://www.w3.org/1998/Math/MathML'><mi>b</mi></math>")
260
+ end
261
+
262
+ it "#set_encode_proc" do
263
+ s = Mathemagical::Util::SimpleLaTeX.new
264
+ s.set_encode_proc(/\{\{/) do |scanner|
265
+ if scanner.scan(/\{\{(.*?)\}\}/m)
266
+ "<%=#{scanner[1]}%>"
267
+ end
268
+ end
269
+ src = "{{$a$}}{{$$b$$}}{{"
270
+ assert_data(src, [], [], [], [], [], [], "\001u0\001\001u1\001{{", "<%=$a$%><%=$$b$$%>{{", s)
271
+ encoded, data = s.encode(src)
272
+ data.user_list.should == ["<%=$a$%>", "<%=$$b$$%>"]
273
+ data.usrc_list.should == ["{{$a$}}", "{{$$b$$}}"]
274
+
275
+ s.set_encode_proc(/\{\{/) do |scanner|
276
+ end
277
+ src = "{{a"
278
+ assert_data(src, [], [], [], [], [], [], "{{a", "{{a", s)
279
+ encoded, data = s.encode(src)
280
+ data.user_list.should == []
281
+ data.usrc_list.should == []
282
+ end
283
+
284
+ it "#set_encode_proc with arrayed regexp" do
285
+ s = Mathemagical::Util::SimpleLaTeX.new
286
+ src = "{{a}}((b)){{(("
287
+ encoded, data = s.encode(src, /\{\{/, /\(\(/) do |scanner|
288
+ case
289
+ when scanner.scan(/\{\{.*?\}\}/)
290
+ "brace"
291
+ when scanner.scan(/\(\(.*?\)\)/)
292
+ "parenthesis"
293
+ end
294
+ end
295
+ encoded.should == "\001u0\001\001u1\001{{(("
296
+ s.decode(encoded, data).should == "braceparenthesis{{(("
297
+
298
+ s.set_encode_proc(/\{\{/, /\(\(/) do |scanner|
299
+ case
300
+ when scanner.scan(/\{\{.*?\}\}/)
301
+ "brace"
302
+ when scanner.scan(/\(\(.*?\)\)/)
303
+ "parenthesis"
304
+ end
305
+ end
306
+ encoded, data = s.encode(src)
307
+ encoded.should == "\001u0\001\001u1\001{{(("
308
+ s.decode(encoded, data).should == "braceparenthesis{{(("
309
+ end
310
+
311
+ it "#encode accept block" do
312
+ s = Mathemagical::Util::SimpleLaTeX.new
313
+ src = "{{$a$}}{{$$b$$}}{{"
314
+ encoded, data = s.encode(src, /\{\{/) do |scanner|
315
+ if scanner.scan(/\{\{(.*?)\}\}/m)
316
+ "<%=#{scanner[1]}%>"
317
+ end
318
+ end
319
+ data.math_list.should == []
320
+ data.dmath_list.should == []
321
+ data.escape_list.should == []
322
+ encoded.should == "\001u0\001\001u1\001{{"
323
+ s.decode(encoded, data).should == "<%=$a$%><%=$$b$$%>{{"
324
+ end
325
+
326
+ it "#encode should accept block with #set_encode_proc" do
327
+ s = Mathemagical::Util::SimpleLaTeX.new
328
+ src = "{{$a$}}{{$$b$$}}{{"
329
+ s.set_encode_proc(/\{\{/) do |scanner|
330
+ if scanner.scan(/\{\{(.*?)\}\}/m)
331
+ "<%=#{scanner[1]}%>"
332
+ end
333
+ end
334
+ encoded, data = s.encode(src, /\{\{/) do |scanner|
335
+ if scanner.scan(/\{\{(.*?)\}\}/m)
336
+ "<$=#{scanner[1]}$>"
337
+ end
338
+ end
339
+ data.math_list.should == []
340
+ data.dmath_list.should == []
341
+ data.escape_list.should == []
342
+ encoded.should == "\001u0\001\001u1\001{{"
343
+ s.decode(encoded, data).should == "<$=$a$$><$=$$b$$$>{{"
344
+ end
345
+
346
+ it "#unencode" do
347
+ src = "$\na\n$\n$$\nb\n$$"
348
+ s = Mathemagical::Util::SimpleLaTeX.new
349
+ encoded, data = s.encode(src)
350
+ s.unencode(encoded, data).should == "$<br />\na<br />\n$\n$$<br />\nb<br />\n$$"
351
+
352
+ s = Mathemagical::Util::SimpleLaTeX.new(:delimiter=>%[$])
353
+ e, d = s.encode("$a$")
354
+ s.unencode(e, d).should == "$a$"
355
+ end
356
+
357
+ it "#set_rescue_proc" do
358
+ src = '$a\test$ $$b\dummy$$'
359
+ s = Mathemagical::Util::SimpleLaTeX.new
360
+ encoded, data = s.encode(src)
361
+ data.math_list[0].should == "<br />\nUndefined command: test<br />\n<code>a<strong>\\test</strong></code><br />"
362
+ data.dmath_list[0].should == "<br />\nUndefined command: dummy<br />\n<code>b<strong>\\dummy</strong></code><br />"
363
+
364
+ s.set_rescue_proc do |e|
365
+ e
366
+ end
367
+ encoded, data = s.encode(src)
368
+ data.math_list[0].should be_kind_of(Mathemagical::LaTeX::ParseError)
369
+ data.math_list[0].done.should == "a"
370
+ data.dmath_list[0].should be_kind_of(Mathemagical::LaTeX::ParseError)
371
+ data.dmath_list[0].done.should == "b"
372
+ end
373
+
374
+ it "#decode with block" do
375
+ s = Mathemagical::Util::SimpleLaTeX.new
376
+ encoded, data = s.encode('$a$$b$$$c$$$$d$$\e\\\\')
377
+ r = s.decode(encoded, data) do |item, opt|
378
+ case opt[:type]
379
+ when :dmath
380
+ item.attributes[:display].should == "block"
381
+ i = strip_math(item.to_s)
382
+ when :math
383
+ item.attributes[:display].should == "inline"
384
+ i = strip_math(item.to_s)
385
+ else
386
+ i = item
387
+ end
388
+ r = "t#{opt[:type]}i#{opt[:index]}s#{opt[:src]}#{i}"
389
+ end
390
+ r.should == "tmathi0s$a$<mi>a</mi>tmathi1s$b$<mi>b</mi>tdmathi0s$$c$$<mi>c</mi>tdmathi1s$$d$$<mi>d</mi>tescapei0s\\eetescapei1s\\\\\\"
391
+
392
+ r = s.decode(encoded, data) do |item, opt|
393
+ nil
394
+ end
395
+ r.should == s.decode(encoded, data)
396
+
397
+ s.set_encode_proc(/\{\{/) do |scanner|
398
+ "<%=#{scanner[1]}%>" if scanner.scan(/\{\{(.*?)\}\}/m)
399
+ end
400
+ encoded, data = s.encode("{{a}}{{")
401
+ r = s.decode(encoded, data) do |item, opt|
402
+ item.should == "<%=a%>"
403
+ opt[:type].should == :user
404
+ opt[:index].should == 0
405
+ opt[:src].should == "{{a}}"
406
+ nil
407
+ end
408
+ r.should == "<%=a%>{{"
409
+
410
+ s.set_decode_proc do |item, opt|
411
+ "dummy"
412
+ end
413
+ s.decode(encoded, data).should == "dummy{{"
414
+ r = s.decode(encoded, data) do |item, opt|
415
+ nil
416
+ end
417
+ r.should == "<%=a%>{{"
418
+ end
419
+
420
+ it "#set_decode_proc" do
421
+ s = Mathemagical::Util::SimpleLaTeX.new
422
+ src = '$a$$b$$$c$$$$d$$\e\\\\'
423
+ encoded, data = s.encode(src)
424
+ original_decoded = s.decode(encoded, data)
425
+ s.set_decode_proc do |item, opt|
426
+ case opt[:type]
427
+ when :dmath
428
+ item.attributes[:display].should == "block"
429
+ i = strip_math(item.to_s)
430
+ when :math
431
+ item.attributes[:display].should == "inline"
432
+ i = strip_math(item.to_s)
433
+ else
434
+ i = item
435
+ end
436
+ r = "t#{opt[:type]}i#{opt[:index]}s#{opt[:src]}#{i}"
437
+ end
438
+ encoded, data = s.encode(src)
439
+ r = s.decode(encoded, data)
440
+ r.should == "tmathi0s$a$<mi>a</mi>tmathi1s$b$<mi>b</mi>tdmathi0s$$c$$<mi>c</mi>tdmathi1s$$d$$<mi>d</mi>tescapei0s\\eetescapei1s\\\\\\"
441
+
442
+ s.reset_decode_proc
443
+ s.decode(encoded, data).should == original_decoded
444
+ end
445
+
446
+ it "#unencode with block" do
447
+ s = Mathemagical::Util::SimpleLaTeX.new
448
+ src = '$a$$b$$$c$$$$d$$\e\\\\'
449
+ encoded, data = s.encode(src)
450
+ r = s.unencode(encoded, data) do |item, opt|
451
+ r = "t#{opt[:type]}i#{opt[:index]}#{item.to_s}"
452
+ end
453
+ r.should == "tmathi0$a$tmathi1$b$tdmathi0$$c$$tdmathi1$$d$$tescapei0\\etescapei1\\\\"
454
+
455
+ r = s.unencode(encoded, data) do |item, opt|
456
+ nil
457
+ end
458
+ r.should == s.unencode(encoded, data)
459
+
460
+ s.set_encode_proc(/\{\{/) do |scanner|
461
+ "<%=#{scanner[1]}%>" if scanner.scan(/\{\{(.*?)\}\}/m)
462
+ end
463
+ encoded, data = s.encode("{{a}}{{")
464
+ r = s.unencode(encoded, data) do |item, opt|
465
+ item.should == "{{a}}"
466
+ opt[:type].should == :user
467
+ opt[:index].should == 0
468
+ nil
469
+ end
470
+ r.should == "{{a}}{{"
471
+ end
472
+
473
+ it "#set_unencode_proc" do
474
+ s = Mathemagical::Util::SimpleLaTeX.new
475
+ src = '$a$$b$$$c$$$$d$$\e\\\\'
476
+ encoded, data = s.encode(src)
477
+ original_unencoded = s.unencode(encoded, data)
478
+
479
+ s.set_unencode_proc do |item, opt|
480
+ r = "t#{opt[:type]}i#{opt[:index]}#{item.to_s}"
481
+ end
482
+ r = s.unencode(encoded, data)
483
+ r.should == "tmathi0$a$tmathi1$b$tdmathi0$$c$$tdmathi1$$d$$tescapei0\\etescapei1\\\\"
484
+
485
+ s.set_unencode_proc do |item, opt|
486
+ nil
487
+ end
488
+ s.unencode(encoded, data).should == original_unencoded
489
+
490
+ s.set_encode_proc(/\{\{/) do |scanner|
491
+ "<%=#{scanner[1]}%>" if scanner.scan(/\{\{(.*?)\}\}/m)
492
+ end
493
+ encoded, data = s.encode("{{a}}{{")
494
+ s.set_unencode_proc do |item, opt|
495
+ item.should == "{{a}}"
496
+ opt[:type].should == :user
497
+ opt[:index].should == 0
498
+ nil
499
+ end
500
+ r = s.unencode(encoded, data)
501
+ r.should == "{{a}}{{"
502
+ end
503
+
504
+ it "#reset_unencode_proc" do
505
+ s = Mathemagical::Util::SimpleLaTeX.new
506
+ s.set_unencode_proc do |item, opt|
507
+ "dummy"
508
+ end
509
+ encoded, data = s.encode("$a$ $$b$$")
510
+ s.unencode(encoded, data).should == "dummy dummy"
511
+
512
+ s.reset_unencode_proc
513
+ s.unencode(encoded, data).should == "$a$ $$b$$"
514
+ end
515
+
516
+ it "#unencode without escaping" do
517
+ s = Mathemagical::Util::SimpleLaTeX.new
518
+ src = %[$<>&'"\n$ $$<>&"'\n$$]
519
+ encoded, data = s.encode(src)
520
+ s.unencode(encoded, data).should == "$&lt;&gt;&amp;&apos;&quot;<br />\n$ $$&lt;&gt;&amp;&quot;&apos;<br />\n$$"
521
+ s.unencode(encoded, data, true).should == src
522
+ end
523
+
524
+ it "#decode without parsed" do
525
+ s = Mathemagical::Util::SimpleLaTeX.new
526
+ src = '$a$$$b$$\a'
527
+ encoded, data = s.encode(src)
528
+ s.decode(encoded, data, true).should == "$a$$$b$$a"
529
+ s.decode(encoded, data, true) do |item, opt|
530
+ case opt[:type]
531
+ when :math
532
+ item.should == "$a$"
533
+ when :dmath
534
+ item.should == "$$b$$"
535
+ when :escape
536
+ item.should == "a"
537
+ end
538
+ end
539
+
540
+ encoded, data = s.encode("$<\n$ $$<\n$$")
541
+ s.decode(encoded, data, true).should == "$&lt;<br />\n$ $$&lt;<br />\n$$"
542
+ end
543
+
544
+ it "#decode_partial" do
545
+ s = Mathemagical::Util::SimpleLaTeX.new
546
+ encoded, data = s.encode("$a$$b$")
547
+ simplify_math(s.decode_partial(:math, encoded, data)).should == simplify_math("<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi></math><math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>b</mi></math>")
548
+
549
+ s.set_encode_proc(/\\</) do |scanner|
550
+ if scanner.scan(/\\<(.)(.*?)\1>/)
551
+ scanner[2]
552
+ end
553
+ end
554
+ src='$a$$$b$$\c\<.$d$.>'
555
+ encoded, data = s.encode(src)
556
+ simplify_math(s.decode_partial(:math, encoded, data)).should == simplify_math("<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi></math>\001d0\001\001e0\001\001u0\001")
557
+ simplify_math(s.decode_partial(:dmath, encoded, data)).should == simplify_math("\001m0\001<math display='block' xmlns='http://www.w3.org/1998/Math/MathML'><mi>b</mi></math>\001e0\001\001u0\001")
558
+ simplify_math(s.decode_partial(:escape, encoded, data)).should == simplify_math("\001m0\001\001d0\001c\001u0\001")
559
+ simplify_math(s.decode_partial(:user, encoded, data)).should == simplify_math("\001m0\001\001d0\001\001e0\001$d$")
560
+
561
+ r = s.decode_partial(:math, encoded, data) do |item, opt|
562
+ opt[:type].should == :math
563
+ opt[:src].should == "$a$"
564
+ simplify_math(item.to_s).should == simplify_math("<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi></math>")
565
+ item
566
+ end
567
+ simplify_math(r).should == simplify_math("<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi></math>\001d0\001\001e0\001\001u0\001")
568
+
569
+ r = s.decode_partial(:dmath, encoded, data) do |item, opt|
570
+ opt[:type].should == :dmath
571
+ opt[:src].should == "$$b$$"
572
+ simplify_math(item.to_s).should == simplify_math("<math display='block' xmlns='http://www.w3.org/1998/Math/MathML'><mi>b</mi></math>")
573
+ item
574
+ end
575
+ simplify_math(r).should == simplify_math("\001m0\001<math display='block' xmlns='http://www.w3.org/1998/Math/MathML'><mi>b</mi></math>\001e0\001\001u0\001")
576
+
577
+ r = s.decode_partial(:escape, encoded, data) do |item, opt|
578
+ opt[:type].should == :escape
579
+ opt[:src].should == "\\c"
580
+ item.should == "c"
581
+ item
582
+ end
583
+ r.should == "\001m0\001\001d0\001c\001u0\001"
584
+
585
+ r = s.decode_partial(:user, encoded, data) do |item, opt|
586
+ opt[:type].should == :user
587
+ opt[:src].should == "\\<.$d$.>"
588
+ item.should == "$d$"
589
+ item
590
+ end
591
+ r.should == "\001m0\001\001d0\001\001e0\001$d$"
592
+
593
+ s = Mathemagical::Util::SimpleLaTeX.new
594
+ encoded, data = s.encode("\\a")
595
+ s.decode_partial(:escape, encoded, data).should == "a"
596
+ r = s.decode_partial(:escape, encoded, data) do |item, opt|
597
+ end
598
+ r.should == "\001e0\001"
599
+
600
+ s = Mathemagical::Util::SimpleLaTeX.new(:delimiter=>%[$])
601
+ encoded, data = s.encode("$a$")
602
+ s.decode_partial(:math, encoded, data).should =~ /^<math.*<\/math>/m
603
+ end
604
+
605
+ it "should keep regexp order" do
606
+ s = Mathemagical::Util::SimpleLaTeX.new
607
+ s.set_encode_proc(/\$/) do |sc|
608
+ if sc.scan(/\$(.*)\z/)
609
+ sc[1]+"is rest"
610
+ end
611
+ end
612
+
613
+ encoded, data = s.encode("$a$$b")
614
+ encoded.should == "\001m0\001\001u0\001"
615
+ end
616
+
617
+ it "parse eqnarray" do
618
+ s = Mathemagical::Util::SimpleLaTeX.new
619
+ src = <<'EOT'
620
+ test
621
+ \begin
622
+ {eqnarray}
623
+ a&=&b\\
624
+ c&=&d
625
+ \end
626
+ {eqnarray}
627
+ end
628
+ EOT
629
+ encoded, data = s.encode(src, Mathemagical::Util::EQNARRAY_RE) do |scanner|
630
+ if scanner.scan(Mathemagical::Util::EQNARRAY_RE)
631
+ s.parse_eqnarray(scanner[1])
632
+ end
633
+ end
634
+ encoded.should == "test\n\001u0\001\nend\n"
635
+ simplify_math(s.decode(encoded, data)).should == simplify_math("test\n<math display='block' xmlns='http://www.w3.org/1998/Math/MathML'><mtable><mtr><mtd><mi>a</mi></mtd><mtd><mo stretchy='false'>=</mo></mtd><mtd><mi>b</mi></mtd></mtr><mtr><mtd><mi>c</mi></mtd><mtd><mo stretchy='false'>=</mo></mtd><mtd><mi>d</mi></mtd></mtr></mtable></math>\nend\n")
636
+
637
+ encoded, data = s.encode('\begin{eqnarray}a\end{eqnarray}', Mathemagical::Util::EQNARRAY_RE) do |scanner|
638
+ s.parse_eqnarray(scanner[1]) if scanner.scan(Mathemagical::Util::EQNARRAY_RE)
639
+ end
640
+ s.decode(encoded, data).should == "<br />\nNeed more column.<br />\n<code>\\begin{eqnarray}a<strong>\\end{eqnarray}</strong></code><br />"
641
+ end
642
+
643
+ # TODO COME BACK AND FIX THIS TEST
644
+ # it "should parse single command" do
645
+ # s = Mathemagical::Util::SimpleLaTeX.new
646
+ # encoded, data = s.encode(%q[\alpha\|\<\>\&\"\'\test], Mathemagical::Util::SINGLE_COMMAND_RE) do |scanner|
647
+ # if scanner.scan(Mathemagical::Util::SINGLE_COMMAND_RE)
648
+ # s.parse_single_command(scanner.matched)
649
+ # end
650
+ # end
651
+ # encoded.should == "\001u0\001\001e0\001\001e1\001\001e2\001\001e3\001\001e4\001\001e5\001\001u1\001"
652
+ # simplify_math(s.decode(encoded, data)).should == simplify_math("<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>&alpha;</mi></math>|&lt;&gt;&amp;&quot;&apos;test")
653
+ # encoded, data = s.encode('\alpha test', Mathemagical::Util::SINGLE_COMMAND_RE) do |scanner|
654
+ # if scanner.scan(Mathemagical::Util::SINGLE_COMMAND_RE)
655
+ # s.parse_single_command(scanner.matched)
656
+ # end
657
+ # end
658
+ # encoded.should == "\001u0\001test"
659
+ # simplify_math(s.decode(encoded, data)).should == simplify_math("<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>&alpha;</mi></math>test")
660
+
661
+ # encoded, data = s.encode('\alpha test', Mathemagical::Util::SINGLE_COMMAND_RE) do |scanner|
662
+ # if scanner.scan(Mathemagical::Util::SINGLE_COMMAND_RE)
663
+ # s.parse_single_command(scanner.matched)
664
+ # end
665
+ # end
666
+ # encoded.should == "\001u0\001 test"
667
+ # simplify_math(s.decode(encoded, data)).should == simplify_math("<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'><mi>&alpha;</mi></math> test")
668
+
669
+ # encoded, data = s.encode("\\alpha\ntest", Mathemagical::Util::SINGLE_COMMAND_RE) do |scanner|
670
+ # if scanner.scan(Mathemagical::Util::SINGLE_COMMAND_RE)
671
+ # s.parse_single_command(scanner.matched)
672
+ # end
673
+ # end
674
+ # encoded.should == "\001u0\001\ntest"
675
+ # end
676
+
677
+ it "#encode can be called twice or more times" do
678
+ s = Mathemagical::Util::SimpleLaTeX.new
679
+ encoded, data = s.encode('$a$')
680
+ encoded, data = s.encode('$b$', data)
681
+ encoded.should == "\001m1\001"
682
+ data.msrc_list.should == ["$a$", '$b$']
683
+ data.math_list.size.should == 2
684
+ strip_math(data.math_list[0].to_s).should == "<mi>a</mi>"
685
+ strip_math(data.math_list[1].to_s).should == "<mi>b</mi>"
686
+
687
+ encoded, data = s.encode('a', data, /a/) do |sc|
688
+ sc.scan(/a/)
689
+ end
690
+ encoded.should == "\001u0\001"
691
+ data.msrc_list.should == ["$a$", '$b$']
692
+ data.usrc_list.should == ["a"]
693
+
694
+ encoded, data = s.encode('a', nil, /a/) do |s|
695
+ s.scan(/a/)
696
+ end
697
+ encoded.should == "\001u0\001"
698
+ data.usrc_list.should == ["a"]
699
+ end
700
+ end