]> git.wincent.com - wikitext.git/blob - spec/pre_spec.rb
Remove some references to Rails
[wikitext.git] / spec / pre_spec.rb
1 # Copyright 2007-present Greg Hurrell. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are met:
5 #
6 # 1. Redistributions of source code must retain the above copyright notice,
7 #    this list of conditions and the following disclaimer.
8 # 2. Redistributions in binary form must reproduce the above copyright notice,
9 #    this list of conditions and the following disclaimer in the documentation
10 #    and/or other materials provided with the distribution.
11 #
12 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
13 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
16 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
18 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
19 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
22 # POSSIBILITY OF SUCH DAMAGE.
23
24 require 'spec_helper'
25
26 describe Wikitext::Parser, 'parsing PRE blocks' do
27   before do
28     @parser = Wikitext::Parser.new
29   end
30
31   it 'should recognize a single-line <pre> block' do
32     @parser.parse(' foo').should == "<pre>foo</pre>\n"
33   end
34
35   it 'should recognize a multiline <pre> block' do
36     @parser.parse(" foo\n bar").should == "<pre>foo\nbar</pre>\n"
37   end
38
39   it 'should handle "empty" lines in the middle of multiline PRE blocks' do
40     input = dedent <<-END
41        foo
42        
43        bar
44     END
45     expected = dedent <<-END
46       <pre>foo
47       
48       bar</pre>
49     END
50     @parser.parse(input).should == expected
51   end
52
53   it 'should render an empty block for an empty PRE block' do
54     @parser.parse(' ').should == "<pre></pre>\n"
55   end
56
57   it 'should sanely handle a leading empty line' do
58     @parser.parse(" \n foo").should == "<pre>\nfoo</pre>\n"
59   end
60
61   it 'should sanely handle a trailing empty line' do
62     @parser.parse(" foo\n \n").should == "<pre>foo\n</pre>\n"
63     @parser.parse(" foo\n ").should == "<pre>foo\n</pre>\n"
64   end
65
66   it 'should allow nesting inside a <blockquote> block' do
67     # nesting inside single blockquotes
68     @parser.parse(">  foo").should == "<blockquote>\n  <pre>foo</pre>\n</blockquote>\n"
69
70     # same, but continued over multiple lines
71     @parser.parse(">  foo\n>  bar").should == "<blockquote>\n  <pre>foo\nbar</pre>\n</blockquote>\n"
72
73     # nesting inside double blockquotes
74     expected = dedent <<-END
75       <blockquote>
76         <blockquote>
77           <pre>foo</pre>
78         </blockquote>
79       </blockquote>
80     END
81     @parser.parse("> >  foo").should == expected
82
83     # same, but continued over multiple lines
84     expected = dedent <<-END
85       <blockquote>
86         <blockquote>
87           <pre>foo
88       bar</pre>
89         </blockquote>
90       </blockquote>
91     END
92     @parser.parse("> >  foo\n> >  bar").should == expected
93   end
94
95   it 'should automatically close preceding blocks at the same depth' do
96     @parser.parse("> foo\n bar").should == "<blockquote>\n  <p>foo</p>\n</blockquote>\n<pre>bar</pre>\n"
97     expected = dedent <<-END
98       <blockquote>
99         <blockquote>
100           <p>foo</p>
101         </blockquote>
102       </blockquote>
103       <pre>bar</pre>
104     END
105     @parser.parse("> > foo\n bar").should == expected
106   end
107
108   it 'should pass <tt> and </tt> tags through without any special meaning' do
109     @parser.parse(' foo <tt>bar</tt>').should == "<pre>foo &lt;tt&gt;bar&lt;/tt&gt;</pre>\n"
110   end
111
112   it 'should pass <em> and </em> tags through without any special meaning' do
113     @parser.parse(" foo ''bar''").should == "<pre>foo ''bar''</pre>\n"
114   end
115
116   it 'should pass <strong> and </strong> tags through without any special meaning' do
117     @parser.parse(" foo '''bar'''").should == "<pre>foo '''bar'''</pre>\n"
118   end
119
120   it 'should pass combined <strong>/<em> and </strong>/</em> tags through without any special meaning' do
121     @parser.parse(" foo '''''bar'''''").should == "<pre>foo '''''bar'''''</pre>\n"
122   end
123
124   it 'should pass named entities through unchanged' do
125     @parser.parse(' &euro;').should == "<pre>&euro;</pre>\n"
126   end
127
128   it 'should pass numeric (decimal) entities through unchanged' do
129     @parser.parse(' &#8364;').should == "<pre>&#8364;</pre>\n"
130   end
131
132   it 'should pass numeric (hexadecimal) entities through unchanged' do
133     @parser.parse(' &#x20ac;').should == "<pre>&#x20ac;</pre>\n"
134     @parser.parse(' &#X20aC;').should == "<pre>&#x20ac;</pre>\n"
135   end
136
137   it 'should convert non-ASCII characters to numeric entities' do
138     @parser.parse(' €').should == "<pre>&#x20ac;</pre>\n"
139   end
140 end
141
142 describe Wikitext::Parser, 'parsing PRE_START/PRE_END blocks' do
143   before do
144     @parser = Wikitext::Parser.new
145   end
146
147   it 'should accept PRE_START/PRE_END as an alternative to the standard syntax' do
148     @parser.parse('<pre>foo</pre>').should == "<pre>foo</pre>\n"
149   end
150
151   it 'should pass through PRE unchanged in PRE_START/PRE_END blocks' do
152     input = dedent <<-END
153       <pre>line 1
154        next line</pre>
155     END
156     expected = dedent <<-END
157       <pre>line 1
158        next line</pre>
159     END
160     @parser.parse(input).should == expected
161   end
162
163   it 'should pass through short BLOCKQUOTE tokens as named entities in PRE_START/PRE_END blocks' do
164     input = dedent <<-END
165       <pre>line 1
166       >next line</pre>
167     END
168     expected = dedent <<-END
169       <pre>line 1
170       &gt;next line</pre>
171     END
172     @parser.parse(input).should == expected
173   end
174
175   it 'should pass through long BLOCKQUOTE tokens as named entities in PRE_START/PRE_END blocks' do
176     input = dedent <<-END
177       <pre>line 1
178       > next line</pre>
179     END
180     expected = dedent <<-END
181       <pre>line 1
182       &gt; next line</pre>
183     END
184     @parser.parse(input).should == expected
185   end
186
187   it 'should pass through EM unchanged in PRE_START/PRE_END blocks' do
188     @parser.parse("<pre>''</pre>").should == "<pre>''</pre>\n"
189   end
190
191   it 'should pass through STRONG unchanged in PRE_START/PRE_END blocks' do
192     @parser.parse("<pre>'''</pre>").should == "<pre>'''</pre>\n"
193   end
194
195   it 'should pass through STRONG_EM unchanged in PRE_START/PRE_END blocks' do
196     @parser.parse("<pre>'''''</pre>").should == "<pre>'''''</pre>\n"
197   end
198
199   it 'should pass through EM_START escaped in PRE_START/PRE_END blocks' do
200     @parser.parse("<pre><em></pre>").should == "<pre>&lt;em&gt;</pre>\n"
201   end
202
203   it 'should pass through EM_END escaped in PRE_START/PRE_END blocks' do
204     @parser.parse("<pre></em></pre>").should == "<pre>&lt;/em&gt;</pre>\n"
205   end
206
207   it 'should pass through STRONG_START escaped in PRE_START/PRE_END blocks' do
208     @parser.parse("<pre><strong></pre>").should == "<pre>&lt;strong&gt;</pre>\n"
209   end
210
211   it 'should pass through STRONG_END escaped in PRE_START/PRE_END blocks' do
212     @parser.parse("<pre></strong></pre>").should == "<pre>&lt;/strong&gt;</pre>\n"
213   end
214
215   it 'should pass through TT unchanged in PRE_START/PRE_END blocks' do
216     @parser.parse("<pre>`</pre>").should == "<pre>`</pre>\n"
217   end
218
219   it 'should pass through TT_START escaped in PRE_START/PRE_END blocks' do
220     @parser.parse("<pre><tt></pre>").should == "<pre>&lt;tt&gt;</pre>\n"
221   end
222
223   it 'should pass through TT_END escaped in PRE_START/PRE_END blocks' do
224     @parser.parse("<pre></tt></pre>").should == "<pre>&lt;/tt&gt;</pre>\n"
225   end
226
227   it 'should pass through UL unchanged in PRE_START/PRE_END blocks' do
228     @parser.parse("<pre>\n#</pre>").should == "<pre>\n#</pre>\n"
229   end
230
231   it 'should pass through OL unchanged in PRE_START/PRE_END blocks' do
232     @parser.parse("<pre>\n*</pre>").should == "<pre>\n*</pre>\n"
233   end
234
235   it 'should ignore PRE_START inside <nowiki> spans' do
236     @parser.parse('<nowiki><pre></nowiki>').should == "<p>&lt;pre&gt;</p>\n"
237   end
238
239   it 'should ignore PRE_END inside <nowiki> spans' do
240     @parser.parse('<nowiki></pre></nowiki>').should == "<p>&lt;/pre&gt;</p>\n"
241   end
242
243   it 'should ignore PRE_START inside standard PRE blocks' do
244     @parser.parse(' <pre>').should == "<pre>&lt;pre&gt;</pre>\n"
245   end
246
247   it 'should ignore PRE_END inside standard PRE blocks' do
248     @parser.parse(' </pre>').should == "<pre>&lt;/pre&gt;</pre>\n"
249   end
250
251   it 'should ignore PRE_START inside already open PRE_START blocks' do
252     @parser.parse('<pre><pre></pre>').should == "<pre>&lt;pre&gt;</pre>\n"
253   end
254
255   it 'should ignore PRE_START inside BLOCKQUOTE blocks' do
256     expected = dedent <<-END
257       <blockquote>
258         <p>&lt;pre&gt;</p>
259       </blockquote>
260     END
261     @parser.parse('> <pre>').should == expected
262   end
263
264   it 'should ignore PRE_END inside BLOCKQUOTE blocks' do
265     expected = dedent <<-END
266       <blockquote>
267         <p>&lt;/pre&gt;</p>
268       </blockquote>
269     END
270     @parser.parse('> </pre>').should == expected
271   end
272
273   it 'should break out of UL blocks on seeing PRE_START' do
274     expected = dedent <<-END
275       <ul>
276         <li>foo</li>
277       </ul>
278       <pre>bar</pre>
279     END
280     @parser.parse('* foo<pre>bar</pre>').should == expected
281   end
282
283   it 'should ignore PRE_END inside UL blocks' do
284     expected = dedent <<-END
285       <ul>
286         <li>&lt;/pre&gt;</li>
287       </ul>
288     END
289     @parser.parse('* </pre>').should == expected
290   end
291
292   it 'should break out of OL blocks on seeing PRE_START' do
293     expected = dedent <<-END
294       <ol>
295         <li>foo</li>
296       </ol>
297       <pre>bar</pre>
298     END
299     @parser.parse('# foo<pre>bar</pre>').should == expected
300   end
301
302   it 'should ignore PRE_END inside OL blocks' do
303     expected = dedent <<-END
304       <ol>
305         <li>&lt;/pre&gt;</li>
306       </ol>
307     END
308     @parser.parse('# </pre>').should == expected
309   end
310
311   it 'should break out of H1 blocks on seeing PRE_START' do
312     expected = dedent <<-END
313       <h1>foo</h1>
314       <pre>bar</pre>
315       <p> =</p>
316     END
317     @parser.parse('= foo<pre>bar</pre> =').should == expected
318   end
319
320   it 'should ignore PRE_END inside H1 blocks' do
321     @parser.parse('= </pre> =').should == "<h1>&lt;/pre&gt;</h1>\n"
322   end
323
324   it 'should break out of H2 blocks on seeing PRE_START' do
325     expected = dedent <<-END
326       <h2>foo</h2>
327       <pre>bar</pre>
328       <p> ==</p>
329     END
330     @parser.parse('== foo<pre>bar</pre> ==').should == expected
331   end
332
333   it 'should ignore PRE_END inside H2 blocks' do
334     @parser.parse('== </pre> ==').should == "<h2>&lt;/pre&gt;</h2>\n"
335   end
336
337   it 'should break out of H3 blocks on seeing PRE_START' do
338     expected = dedent <<-END
339       <h3>foo</h3>
340       <pre>bar</pre>
341       <p> ===</p>
342     END
343     @parser.parse('=== foo<pre>bar</pre> ===').should == expected
344   end
345
346   it 'should ignore PRE_END inside H3 blocks' do
347     @parser.parse('=== </pre> ===').should == "<h3>&lt;/pre&gt;</h3>\n"
348   end
349
350   it 'should break out of H4 blocks on seeing PRE_START' do
351     expected = dedent <<-END
352       <h4>foo</h4>
353       <pre>bar</pre>
354       <p> ====</p>
355     END
356     @parser.parse('==== foo<pre>bar</pre> ====').should == expected
357   end
358
359   it 'should ignore PRE_END inside H4 blocks' do
360     @parser.parse('==== </pre> ====').should == "<h4>&lt;/pre&gt;</h4>\n"
361   end
362
363   it 'should break out of H5 blocks on seeing PRE_START' do
364     expected = dedent <<-END
365       <h5>foo</h5>
366       <pre>bar</pre>
367       <p> =====</p>
368     END
369     @parser.parse('===== foo<pre>bar</pre> =====').should == expected
370   end
371
372   it 'should ignore PRE_END inside H5 blocks' do
373     @parser.parse('===== </pre> =====').should == "<h5>&lt;/pre&gt;</h5>\n"
374   end
375
376   it 'should break out of H6 blocks on seeing PRE_START' do
377     expected = dedent <<-END
378       <h6>foo</h6>
379       <pre>bar</pre>
380       <p> ======</p>
381     END
382     @parser.parse('====== foo<pre>bar</pre> ======').should == expected
383   end
384
385   it 'should ignore PRE_END inside H6 blocks' do
386     @parser.parse('====== </pre> ======').should == "<h6>&lt;/pre&gt;</h6>\n"
387   end
388
389   it 'should start a <pre> block on seeing PRE_START partway through a P block' do
390     # the trailing space after "hello" is preserved just like it would be if the input were "hello " and nothing else
391     expected = dedent <<-END
392       <p>hello </p>
393       <pre>world</pre>
394     END
395     @parser.parse('hello <pre>world</pre>').should == expected
396   end
397
398   it 'should close any open spans while starting a <pre> block on seeing PRE_START partway through a P block' do
399     # ''
400     expected = dedent <<-END
401       <p>hello <em>my </em></p>
402       <pre>world</pre>
403     END
404     @parser.parse("hello ''my <pre>world</pre>").should == expected
405
406     # '''
407     expected = dedent <<-END
408       <p>hello <strong>my </strong></p>
409       <pre>world</pre>
410     END
411     @parser.parse("hello '''my <pre>world</pre>").should == expected
412
413     # '''''
414     expected = dedent <<-END
415       <p>hello <strong><em>my </em></strong></p>
416       <pre>world</pre>
417     END
418     @parser.parse("hello '''''my <pre>world</pre>").should == expected
419
420     # `
421     expected = dedent <<-END
422       <p>hello <code>my </code></p>
423       <pre>world</pre>
424     END
425     @parser.parse("hello `my <pre>world</pre>").should == expected
426
427     # <em>
428     expected = dedent <<-END
429       <p>hello <em>my </em></p>
430       <pre>world</pre>
431     END
432     @parser.parse("hello <em>my <pre>world</pre>").should == expected
433
434     # <strong>
435     expected = dedent <<-END
436       <p>hello <strong>my </strong></p>
437       <pre>world</pre>
438     END
439     @parser.parse("hello <strong>my <pre>world</pre>").should == expected
440
441     # <strong><em>
442     expected = dedent <<-END
443       <p>hello <strong><em>my </em></strong></p>
444       <pre>world</pre>
445     END
446     @parser.parse("hello <strong><em>my <pre>world</pre>").should == expected
447
448     # <tt>
449     expected = dedent <<-END
450       <p>hello <code>my </code></p>
451       <pre>world</pre>
452     END
453     @parser.parse("hello <tt>my <pre>world</pre>").should == expected
454   end
455
456   it 'should rollback open internal link spans on encountering a PRE_START in the link target' do
457     expected = dedent <<-END
458       <p>[[hello </p>
459       <pre>world</pre>
460       <p>]]</p>
461     END
462     @parser.parse('[[hello <pre>world</pre>]]').should == expected
463   end
464
465   it 'should rollback open internal link spans on encountering a PRE_START in the link text' do
466     expected = dedent <<-END
467       <p>[[hello | there</p>
468       <pre>world</pre>
469       <p>]]</p>
470     END
471     @parser.parse('[[hello | there<pre>world</pre>]]').should == expected
472   end
473
474   it 'should automatically close open PRE_START blocks on hitting the end-of-file' do
475     @parser.parse('<pre>foo').should == "<pre>foo</pre>\n"
476   end
477
478   it 'should handle an optional "lang" attribute' do
479     @parser.parse('<pre lang="ruby">foo</pre>').should == %Q{<pre class="ruby-syntax">foo</pre>\n}
480   end
481
482   it 'should reject excess internal whitespace in PRE_START tags which have a "lang" attribute' do
483     @parser.parse('<pre  lang="ruby">foo</pre>').should == %Q{<p>&lt;pre  lang=&quot;ruby&quot;&gt;foo&lt;/pre&gt;</p>\n}
484     @parser.parse('<pre lang ="ruby">foo</pre>').should == %Q{<p>&lt;pre lang =&quot;ruby&quot;&gt;foo&lt;/pre&gt;</p>\n}
485     @parser.parse('<pre lang= "ruby">foo</pre>').should == %Q{<p>&lt;pre lang= &quot;ruby&quot;&gt;foo&lt;/pre&gt;</p>\n}
486     @parser.parse('<pre lang="ruby" >foo</pre>').should == %Q{<p>&lt;pre lang=&quot;ruby&quot; &gt;foo&lt;/pre&gt;</p>\n}
487   end
488
489   it 'should reject non-alpha characters in "lang" attribute' do
490     @parser.parse('<pre lang="obj-c">foo</pre>').should == %Q{<p>&lt;pre lang=&quot;obj-c&quot;&gt;foo&lt;/pre&gt;</p>\n}
491   end
492
493   it 'should reject empty "lang" attributes' do
494     @parser.parse('<pre lang="">foo</pre>').should == %Q{<p>&lt;pre lang=&quot;&quot;&gt;foo&lt;/pre&gt;</p>\n}
495   end
496 end