1 # Copyright 2007-present Greg Hurrell. All rights reserved.
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are met:
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.
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.
26 describe Wikitext::Parser, 'parsing PRE blocks' do
28 @parser = Wikitext::Parser.new
31 it 'should recognize a single-line <pre> block' do
32 @parser.parse(' foo').should == "<pre>foo</pre>\n"
35 it 'should recognize a multiline <pre> block' do
36 @parser.parse(" foo\n bar").should == "<pre>foo\nbar</pre>\n"
39 it 'should handle "empty" lines in the middle of multiline PRE blocks' do
45 expected = dedent <<-END
50 @parser.parse(input).should == expected
53 it 'should render an empty block for an empty PRE block' do
54 @parser.parse(' ').should == "<pre></pre>\n"
57 it 'assumes PRE blocks are code when :pre_code is set' do
59 new(:pre_code => true).
61 should == "<pre><code>foo</code></pre>\n"
64 it 'should sanely handle a leading empty line' do
65 @parser.parse(" \n foo").should == "<pre>\nfoo</pre>\n"
68 it 'should sanely handle a trailing empty line' do
69 @parser.parse(" foo\n \n").should == "<pre>foo\n</pre>\n"
70 @parser.parse(" foo\n ").should == "<pre>foo\n</pre>\n"
73 it 'should allow nesting inside a <blockquote> block' do
74 # nesting inside single blockquotes
75 @parser.parse("> foo").should == "<blockquote>\n <pre>foo</pre>\n</blockquote>\n"
77 # same, but continued over multiple lines
78 @parser.parse("> foo\n> bar").should == "<blockquote>\n <pre>foo\nbar</pre>\n</blockquote>\n"
80 # nesting inside double blockquotes
81 expected = dedent <<-END
88 @parser.parse("> > foo").should == expected
90 # same, but continued over multiple lines
91 expected = dedent <<-END
99 @parser.parse("> > foo\n> > bar").should == expected
102 it 'should automatically close preceding blocks at the same depth' do
103 @parser.parse("> foo\n bar").should == "<blockquote>\n <p>foo</p>\n</blockquote>\n<pre>bar</pre>\n"
104 expected = dedent <<-END
112 @parser.parse("> > foo\n bar").should == expected
115 it 'should pass <tt> and </tt> tags through without any special meaning' do
116 @parser.parse(' foo <tt>bar</tt>').should == "<pre>foo <tt>bar</tt></pre>\n"
119 it 'should pass <em> and </em> tags through without any special meaning' do
120 @parser.parse(" foo ''bar''").should == "<pre>foo ''bar''</pre>\n"
123 it 'should pass <strong> and </strong> tags through without any special meaning' do
124 @parser.parse(" foo '''bar'''").should == "<pre>foo '''bar'''</pre>\n"
127 it 'should pass combined <strong>/<em> and </strong>/</em> tags through without any special meaning' do
128 @parser.parse(" foo '''''bar'''''").should == "<pre>foo '''''bar'''''</pre>\n"
131 it 'should pass named entities through unchanged' do
132 @parser.parse(' €').should == "<pre>€</pre>\n"
135 it 'should pass numeric (decimal) entities through unchanged' do
136 @parser.parse(' €').should == "<pre>€</pre>\n"
139 it 'should pass numeric (hexadecimal) entities through unchanged' do
140 @parser.parse(' €').should == "<pre>€</pre>\n"
141 @parser.parse(' €').should == "<pre>€</pre>\n"
144 it 'should convert non-ASCII characters to numeric entities' do
145 @parser.parse(' €').should == "<pre>€</pre>\n"
149 describe Wikitext::Parser, 'parsing PRE_START/PRE_END blocks' do
151 @parser = Wikitext::Parser.new
154 it 'should accept PRE_START/PRE_END as an alternative to the standard syntax' do
155 @parser.parse('<pre>foo</pre>').should == "<pre>foo</pre>\n"
158 it 'assumes PRE_START/PRE_END blocks are code when :pre_code is set' do
160 new(:pre_code => true).
161 parse('<pre>foo</pre>').
162 should == "<pre><code>foo</code></pre>\n"
165 it 'should pass through PRE unchanged in PRE_START/PRE_END blocks' do
166 input = dedent <<-END
170 expected = dedent <<-END
174 @parser.parse(input).should == expected
177 it 'should pass through short BLOCKQUOTE tokens as named entities in PRE_START/PRE_END blocks' do
178 input = dedent <<-END
182 expected = dedent <<-END
186 @parser.parse(input).should == expected
189 it 'should pass through long BLOCKQUOTE tokens as named entities in PRE_START/PRE_END blocks' do
190 input = dedent <<-END
194 expected = dedent <<-END
198 @parser.parse(input).should == expected
201 it 'should pass through EM unchanged in PRE_START/PRE_END blocks' do
202 @parser.parse("<pre>''</pre>").should == "<pre>''</pre>\n"
205 it 'should pass through STRONG unchanged in PRE_START/PRE_END blocks' do
206 @parser.parse("<pre>'''</pre>").should == "<pre>'''</pre>\n"
209 it 'should pass through STRONG_EM unchanged in PRE_START/PRE_END blocks' do
210 @parser.parse("<pre>'''''</pre>").should == "<pre>'''''</pre>\n"
213 it 'should pass through EM_START escaped in PRE_START/PRE_END blocks' do
214 @parser.parse("<pre><em></pre>").should == "<pre><em></pre>\n"
217 it 'should pass through EM_END escaped in PRE_START/PRE_END blocks' do
218 @parser.parse("<pre></em></pre>").should == "<pre></em></pre>\n"
221 it 'should pass through STRONG_START escaped in PRE_START/PRE_END blocks' do
222 @parser.parse("<pre><strong></pre>").should == "<pre><strong></pre>\n"
225 it 'should pass through STRONG_END escaped in PRE_START/PRE_END blocks' do
226 @parser.parse("<pre></strong></pre>").should == "<pre></strong></pre>\n"
229 it 'should pass through TT unchanged in PRE_START/PRE_END blocks' do
230 @parser.parse("<pre>`</pre>").should == "<pre>`</pre>\n"
233 it 'should pass through TT_START escaped in PRE_START/PRE_END blocks' do
234 @parser.parse("<pre><tt></pre>").should == "<pre><tt></pre>\n"
237 it 'should pass through TT_END escaped in PRE_START/PRE_END blocks' do
238 @parser.parse("<pre></tt></pre>").should == "<pre></tt></pre>\n"
241 it 'should pass through UL unchanged in PRE_START/PRE_END blocks' do
242 @parser.parse("<pre>\n#</pre>").should == "<pre>\n#</pre>\n"
245 it 'should pass through OL unchanged in PRE_START/PRE_END blocks' do
246 @parser.parse("<pre>\n*</pre>").should == "<pre>\n*</pre>\n"
249 it 'should ignore PRE_START inside <nowiki> spans' do
250 @parser.parse('<nowiki><pre></nowiki>').should == "<p><pre></p>\n"
253 it 'should ignore PRE_END inside <nowiki> spans' do
254 @parser.parse('<nowiki></pre></nowiki>').should == "<p></pre></p>\n"
257 it 'should ignore PRE_START inside standard PRE blocks' do
258 @parser.parse(' <pre>').should == "<pre><pre></pre>\n"
261 it 'should ignore PRE_END inside standard PRE blocks' do
262 @parser.parse(' </pre>').should == "<pre></pre></pre>\n"
265 it 'should ignore PRE_START inside already open PRE_START blocks' do
266 @parser.parse('<pre><pre></pre>').should == "<pre><pre></pre>\n"
269 it 'should ignore PRE_START inside BLOCKQUOTE blocks' do
270 expected = dedent <<-END
275 @parser.parse('> <pre>').should == expected
278 it 'should ignore PRE_END inside BLOCKQUOTE blocks' do
279 expected = dedent <<-END
284 @parser.parse('> </pre>').should == expected
287 it 'should break out of UL blocks on seeing PRE_START' do
288 expected = dedent <<-END
294 @parser.parse('* foo<pre>bar</pre>').should == expected
297 it 'should ignore PRE_END inside UL blocks' do
298 expected = dedent <<-END
300 <li></pre></li>
303 @parser.parse('* </pre>').should == expected
306 it 'should break out of OL blocks on seeing PRE_START' do
307 expected = dedent <<-END
313 @parser.parse('# foo<pre>bar</pre>').should == expected
316 it 'should ignore PRE_END inside OL blocks' do
317 expected = dedent <<-END
319 <li></pre></li>
322 @parser.parse('# </pre>').should == expected
325 it 'should break out of H1 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 H1 blocks' do
335 @parser.parse('= </pre> =').should == "<h1></pre></h1>\n"
338 it 'should break out of H2 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 H2 blocks' do
348 @parser.parse('== </pre> ==').should == "<h2></pre></h2>\n"
351 it 'should break out of H3 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 H3 blocks' do
361 @parser.parse('=== </pre> ===').should == "<h3></pre></h3>\n"
364 it 'should break out of H4 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 H4 blocks' do
374 @parser.parse('==== </pre> ====').should == "<h4></pre></h4>\n"
377 it 'should break out of H5 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 H5 blocks' do
387 @parser.parse('===== </pre> =====').should == "<h5></pre></h5>\n"
390 it 'should break out of H6 blocks on seeing PRE_START' do
391 expected = dedent <<-END
396 @parser.parse('====== foo<pre>bar</pre> ======').should == expected
399 it 'should ignore PRE_END inside H6 blocks' do
400 @parser.parse('====== </pre> ======').should == "<h6></pre></h6>\n"
403 it 'should start a <pre> block on seeing PRE_START partway through a P block' do
404 # the trailing space after "hello" is preserved just like it would be if the input were "hello " and nothing else
405 expected = dedent <<-END
409 @parser.parse('hello <pre>world</pre>').should == expected
412 it 'should close any open spans while starting a <pre> block on seeing PRE_START partway through a P block' do
414 expected = dedent <<-END
415 <p>hello <em>my </em></p>
418 @parser.parse("hello ''my <pre>world</pre>").should == expected
421 expected = dedent <<-END
422 <p>hello <strong>my </strong></p>
425 @parser.parse("hello '''my <pre>world</pre>").should == expected
428 expected = dedent <<-END
429 <p>hello <strong><em>my </em></strong></p>
432 @parser.parse("hello '''''my <pre>world</pre>").should == expected
435 expected = dedent <<-END
436 <p>hello <code>my </code></p>
439 @parser.parse("hello `my <pre>world</pre>").should == expected
442 expected = dedent <<-END
443 <p>hello <em>my </em></p>
446 @parser.parse("hello <em>my <pre>world</pre>").should == expected
449 expected = dedent <<-END
450 <p>hello <strong>my </strong></p>
453 @parser.parse("hello <strong>my <pre>world</pre>").should == expected
456 expected = dedent <<-END
457 <p>hello <strong><em>my </em></strong></p>
460 @parser.parse("hello <strong><em>my <pre>world</pre>").should == expected
463 expected = dedent <<-END
464 <p>hello <code>my </code></p>
467 @parser.parse("hello <tt>my <pre>world</pre>").should == expected
470 it 'should rollback open internal link spans on encountering a PRE_START in the link target' do
471 expected = dedent <<-END
476 @parser.parse('[[hello <pre>world</pre>]]').should == expected
479 it 'should rollback open internal link spans on encountering a PRE_START in the link text' do
480 expected = dedent <<-END
481 <p>[[hello | there</p>
485 @parser.parse('[[hello | there<pre>world</pre>]]').should == expected
488 it 'should automatically close open PRE_START blocks on hitting the end-of-file' do
489 @parser.parse('<pre>foo').should == "<pre>foo</pre>\n"
492 it 'should handle an optional "lang" attribute' do
493 @parser.parse('<pre lang="ruby">foo</pre>').should == %Q{<pre class="ruby-syntax">foo</pre>\n}
496 it 'should reject excess internal whitespace in PRE_START tags which have a "lang" attribute' do
497 @parser.parse('<pre lang="ruby">foo</pre>').should == %Q{<p><pre lang="ruby">foo</pre></p>\n}
498 @parser.parse('<pre lang ="ruby">foo</pre>').should == %Q{<p><pre lang ="ruby">foo</pre></p>\n}
499 @parser.parse('<pre lang= "ruby">foo</pre>').should == %Q{<p><pre lang= "ruby">foo</pre></p>\n}
500 @parser.parse('<pre lang="ruby" >foo</pre>').should == %Q{<p><pre lang="ruby" >foo</pre></p>\n}
503 it 'should reject non-alpha characters in "lang" attribute' do
504 @parser.parse('<pre lang="obj-c">foo</pre>').should == %Q{<p><pre lang="obj-c">foo</pre></p>\n}
507 it 'should reject empty "lang" attributes' do
508 @parser.parse('<pre lang="">foo</pre>').should == %Q{<p><pre lang="">foo</pre></p>\n}