2 # Copyright 2007-2010 Wincent Colaiuta. All rights reserved.
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are met:
7 # 1. Redistributions of source code must retain the above copyright notice,
8 # this list of conditions and the following disclaimer.
9 # 2. Redistributions in binary form must reproduce the above copyright notice,
10 # this list of conditions and the following disclaimer in the documentation
11 # and/or other materials provided with the distribution.
13 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
17 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
23 # POSSIBILITY OF SUCH DAMAGE.
25 require File.join(File.dirname(__FILE__), 'spec_helper.rb')
27 describe Wikitext::Parser, 'parsing PRE blocks' do
29 @parser = Wikitext::Parser.new
32 it 'should recognize a single-line <pre> block' do
33 @parser.parse(' foo').should == "<pre>foo</pre>\n"
36 it 'should recognize a multiline <pre> block' do
37 @parser.parse(" foo\n bar").should == "<pre>foo\nbar</pre>\n"
40 it 'should handle "empty" lines in the middle of multiline PRE blocks' do
46 expected = dedent <<-END
51 @parser.parse(input).should == expected
54 it 'should render an empty block for an empty PRE block' do
55 @parser.parse(' ').should == "<pre></pre>\n"
58 it 'should sanely handle a leading empty line' do
59 @parser.parse(" \n foo").should == "<pre>\nfoo</pre>\n"
62 it 'should sanely handle a trailing empty line' do
63 @parser.parse(" foo\n \n").should == "<pre>foo\n</pre>\n"
64 @parser.parse(" foo\n ").should == "<pre>foo\n</pre>\n"
67 it 'should allow nesting inside a <blockquote> block' do
68 # nesting inside single blockquotes
69 @parser.parse("> foo").should == "<blockquote>\n <pre>foo</pre>\n</blockquote>\n"
71 # same, but continued over multiple lines
72 @parser.parse("> foo\n> bar").should == "<blockquote>\n <pre>foo\nbar</pre>\n</blockquote>\n"
74 # nesting inside double blockquotes
75 expected = dedent <<-END
82 @parser.parse("> > foo").should == expected
84 # same, but continued over multiple lines
85 expected = dedent <<-END
93 @parser.parse("> > foo\n> > bar").should == expected
96 it 'should automatically close preceding blocks at the same depth' do
97 @parser.parse("> foo\n bar").should == "<blockquote>\n <p>foo</p>\n</blockquote>\n<pre>bar</pre>\n"
98 expected = dedent <<-END
106 @parser.parse("> > foo\n bar").should == expected
109 it 'should pass <tt> and </tt> tags through without any special meaning' do
110 @parser.parse(' foo <tt>bar</tt>').should == "<pre>foo <tt>bar</tt></pre>\n"
113 it 'should pass <em> and </em> tags through without any special meaning' do
114 @parser.parse(" foo ''bar''").should == "<pre>foo ''bar''</pre>\n"
117 it 'should pass <strong> and </strong> tags through without any special meaning' do
118 @parser.parse(" foo '''bar'''").should == "<pre>foo '''bar'''</pre>\n"
121 it 'should pass combined <strong>/<em> and </strong>/</em> tags through without any special meaning' do
122 @parser.parse(" foo '''''bar'''''").should == "<pre>foo '''''bar'''''</pre>\n"
125 it 'should pass named entities through unchanged' do
126 @parser.parse(' €').should == "<pre>€</pre>\n"
129 it 'should pass numeric (decimal) entities through unchanged' do
130 @parser.parse(' €').should == "<pre>€</pre>\n"
133 it 'should pass numeric (hexadecimal) entities through unchanged' do
134 @parser.parse(' €').should == "<pre>€</pre>\n"
135 @parser.parse(' €').should == "<pre>€</pre>\n"
138 it 'should convert non-ASCII characters to numeric entities' do
139 @parser.parse(' €').should == "<pre>€</pre>\n"
143 describe Wikitext::Parser, 'parsing PRE_START/PRE_END blocks' do
145 @parser = Wikitext::Parser.new
148 it 'should accept PRE_START/PRE_END as an alternative to the standard syntax' do
149 @parser.parse('<pre>foo</pre>').should == "<pre>foo</pre>\n"
152 it 'should pass through PRE unchanged in PRE_START/PRE_END blocks' do
153 input = dedent <<-END
157 expected = dedent <<-END
161 @parser.parse(input).should == expected
164 it 'should pass through short BLOCKQUOTE tokens as named entities in PRE_START/PRE_END blocks' do
165 input = dedent <<-END
169 expected = dedent <<-END
173 @parser.parse(input).should == expected
176 it 'should pass through long BLOCKQUOTE tokens as named entities in PRE_START/PRE_END blocks' do
177 input = dedent <<-END
181 expected = dedent <<-END
185 @parser.parse(input).should == expected
188 it 'should pass through EM unchanged in PRE_START/PRE_END blocks' do
189 @parser.parse("<pre>''</pre>").should == "<pre>''</pre>\n"
192 it 'should pass through STRONG unchanged in PRE_START/PRE_END blocks' do
193 @parser.parse("<pre>'''</pre>").should == "<pre>'''</pre>\n"
196 it 'should pass through STRONG_EM unchanged in PRE_START/PRE_END blocks' do
197 @parser.parse("<pre>'''''</pre>").should == "<pre>'''''</pre>\n"
200 it 'should pass through EM_START escaped in PRE_START/PRE_END blocks' do
201 @parser.parse("<pre><em></pre>").should == "<pre><em></pre>\n"
204 it 'should pass through EM_END escaped in PRE_START/PRE_END blocks' do
205 @parser.parse("<pre></em></pre>").should == "<pre></em></pre>\n"
208 it 'should pass through STRONG_START escaped in PRE_START/PRE_END blocks' do
209 @parser.parse("<pre><strong></pre>").should == "<pre><strong></pre>\n"
212 it 'should pass through STRONG_END escaped in PRE_START/PRE_END blocks' do
213 @parser.parse("<pre></strong></pre>").should == "<pre></strong></pre>\n"
216 it 'should pass through TT unchanged in PRE_START/PRE_END blocks' do
217 @parser.parse("<pre>`</pre>").should == "<pre>`</pre>\n"
220 it 'should pass through TT_START escaped in PRE_START/PRE_END blocks' do
221 @parser.parse("<pre><tt></pre>").should == "<pre><tt></pre>\n"
224 it 'should pass through TT_END escaped in PRE_START/PRE_END blocks' do
225 @parser.parse("<pre></tt></pre>").should == "<pre></tt></pre>\n"
228 it 'should pass through UL unchanged in PRE_START/PRE_END blocks' do
229 @parser.parse("<pre>\n#</pre>").should == "<pre>\n#</pre>\n"
232 it 'should pass through OL unchanged in PRE_START/PRE_END blocks' do
233 @parser.parse("<pre>\n*</pre>").should == "<pre>\n*</pre>\n"
236 it 'should ignore PRE_START inside <nowiki> spans' do
237 @parser.parse('<nowiki><pre></nowiki>').should == "<p><pre></p>\n"
240 it 'should ignore PRE_END inside <nowiki> spans' do
241 @parser.parse('<nowiki></pre></nowiki>').should == "<p></pre></p>\n"
244 it 'should ignore PRE_START inside standard PRE blocks' do
245 @parser.parse(' <pre>').should == "<pre><pre></pre>\n"
248 it 'should ignore PRE_END inside standard PRE blocks' do
249 @parser.parse(' </pre>').should == "<pre></pre></pre>\n"
252 it 'should ignore PRE_START inside already open PRE_START blocks' do
253 @parser.parse('<pre><pre></pre>').should == "<pre><pre></pre>\n"
256 it 'should ignore PRE_START inside BLOCKQUOTE blocks' do
257 expected = dedent <<-END
262 @parser.parse('> <pre>').should == expected
265 it 'should ignore PRE_END inside BLOCKQUOTE blocks' do
266 expected = dedent <<-END
271 @parser.parse('> </pre>').should == expected
274 it 'should break out of UL blocks on seeing PRE_START' do
275 expected = dedent <<-END
281 @parser.parse('* foo<pre>bar</pre>').should == expected
284 it 'should ignore PRE_END inside UL blocks' do
285 expected = dedent <<-END
287 <li></pre></li>
290 @parser.parse('* </pre>').should == expected
293 it 'should break out of OL blocks on seeing PRE_START' do
294 expected = dedent <<-END
300 @parser.parse('# foo<pre>bar</pre>').should == expected
303 it 'should ignore PRE_END inside OL blocks' do
304 expected = dedent <<-END
306 <li></pre></li>
309 @parser.parse('# </pre>').should == expected
312 it 'should break out of H1 blocks on seeing PRE_START' do
313 expected = dedent <<-END
318 @parser.parse('= foo<pre>bar</pre> =').should == expected
321 it 'should ignore PRE_END inside H1 blocks' do
322 @parser.parse('= </pre> =').should == "<h1></pre></h1>\n"
325 it 'should break out of H2 blocks on seeing PRE_START' do
326 expected = dedent <<-END
331 @parser.parse('== foo<pre>bar</pre> ==').should == expected
334 it 'should ignore PRE_END inside H2 blocks' do
335 @parser.parse('== </pre> ==').should == "<h2></pre></h2>\n"
338 it 'should break out of H3 blocks on seeing PRE_START' do
339 expected = dedent <<-END
344 @parser.parse('=== foo<pre>bar</pre> ===').should == expected
347 it 'should ignore PRE_END inside H3 blocks' do
348 @parser.parse('=== </pre> ===').should == "<h3></pre></h3>\n"
351 it 'should break out of H4 blocks on seeing PRE_START' do
352 expected = dedent <<-END
357 @parser.parse('==== foo<pre>bar</pre> ====').should == expected
360 it 'should ignore PRE_END inside H4 blocks' do
361 @parser.parse('==== </pre> ====').should == "<h4></pre></h4>\n"
364 it 'should break out of H5 blocks on seeing PRE_START' do
365 expected = dedent <<-END
370 @parser.parse('===== foo<pre>bar</pre> =====').should == expected
373 it 'should ignore PRE_END inside H5 blocks' do
374 @parser.parse('===== </pre> =====').should == "<h5></pre></h5>\n"
377 it 'should break out of H6 blocks on seeing PRE_START' do
378 expected = dedent <<-END
383 @parser.parse('====== foo<pre>bar</pre> ======').should == expected
386 it 'should ignore PRE_END inside H6 blocks' do
387 @parser.parse('====== </pre> ======').should == "<h6></pre></h6>\n"
390 it 'should start a <pre> block on seeing PRE_START partway through a P block' do
391 # the trailing space after "hello" is preserved just like it would be if the input were "hello " and nothing else
392 expected = dedent <<-END
396 @parser.parse('hello <pre>world</pre>').should == expected
399 it 'should close any open spans while starting a <pre> block on seeing PRE_START partway through a P block' do
401 expected = dedent <<-END
402 <p>hello <em>my </em></p>
405 @parser.parse("hello ''my <pre>world</pre>").should == expected
408 expected = dedent <<-END
409 <p>hello <strong>my </strong></p>
412 @parser.parse("hello '''my <pre>world</pre>").should == expected
415 expected = dedent <<-END
416 <p>hello <strong><em>my </em></strong></p>
419 @parser.parse("hello '''''my <pre>world</pre>").should == expected
422 expected = dedent <<-END
423 <p>hello <code>my </code></p>
426 @parser.parse("hello `my <pre>world</pre>").should == expected
429 expected = dedent <<-END
430 <p>hello <em>my </em></p>
433 @parser.parse("hello <em>my <pre>world</pre>").should == expected
436 expected = dedent <<-END
437 <p>hello <strong>my </strong></p>
440 @parser.parse("hello <strong>my <pre>world</pre>").should == expected
443 expected = dedent <<-END
444 <p>hello <strong><em>my </em></strong></p>
447 @parser.parse("hello <strong><em>my <pre>world</pre>").should == expected
450 expected = dedent <<-END
451 <p>hello <code>my </code></p>
454 @parser.parse("hello <tt>my <pre>world</pre>").should == expected
457 it 'should rollback open internal link spans on encountering a PRE_START in the link target' do
458 expected = dedent <<-END
463 @parser.parse('[[hello <pre>world</pre>]]').should == expected
466 it 'should rollback open internal link spans on encountering a PRE_START in the link text' do
467 expected = dedent <<-END
468 <p>[[hello | there</p>
472 @parser.parse('[[hello | there<pre>world</pre>]]').should == expected
475 it 'should automatically close open PRE_START blocks on hitting the end-of-file' do
476 @parser.parse('<pre>foo').should == "<pre>foo</pre>\n"
479 it 'should handle an optional "lang" attribute' do
480 @parser.parse('<pre lang="ruby">foo</pre>').should == %Q{<pre class="ruby-syntax">foo</pre>\n}
483 it 'should reject excess internal whitespace in PRE_START tags which have a "lang" attribute' do
484 @parser.parse('<pre lang="ruby">foo</pre>').should == %Q{<p><pre lang="ruby">foo</pre></p>\n}
485 @parser.parse('<pre lang ="ruby">foo</pre>').should == %Q{<p><pre lang ="ruby">foo</pre></p>\n}
486 @parser.parse('<pre lang= "ruby">foo</pre>').should == %Q{<p><pre lang= "ruby">foo</pre></p>\n}
487 @parser.parse('<pre lang="ruby" >foo</pre>').should == %Q{<p><pre lang="ruby" >foo</pre></p>\n}
490 it 'should reject non-alpha characters in "lang" attribute' do
491 @parser.parse('<pre lang="obj-c">foo</pre>').should == %Q{<p><pre lang="obj-c">foo</pre></p>\n}
494 it 'should reject empty "lang" attributes' do
495 @parser.parse('<pre lang="">foo</pre>').should == %Q{<p><pre lang="">foo</pre></p>\n}