]> git.wincent.com - wikitext.git/blob - spec/blockquote_spec.rb
e67cbbadf7780a483939d3fdca66b4e0d451ee0b
[wikitext.git] / spec / blockquote_spec.rb
1 # Copyright 2007-2010 Wincent Colaiuta. 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 File.join(File.dirname(__FILE__), 'spec_helper.rb')
25
26 describe Wikitext::Parser, 'standard blockquotes (">" in first column)' do
27   before do
28     @parser = Wikitext::Parser.new
29   end
30
31   it 'should treat ">" in first column as a blockquote marker' do
32     expected = dedent <<-END
33       <blockquote>
34         <p>foo</p>
35       </blockquote>
36     END
37     @parser.parse('>foo').should == expected
38   end
39
40   it 'should accept (and ignore) one optional space after the ">"' do
41     expected = dedent <<-END
42       <blockquote>
43         <p>foo</p>
44       </blockquote>
45     END
46     @parser.parse('> foo').should == expected
47   end
48
49   it 'should recognize consecutive ">" as continuance of blockquote section' do
50     expected = dedent <<-END
51       <blockquote>
52         <p>foo bar</p>
53       </blockquote>
54     END
55     @parser.parse("> foo\n> bar").should == expected
56   end
57
58   it 'should not give ">" special treatment when not on the far left' do
59     @parser.parse('foo > bar').should == "<p>foo &gt; bar</p>\n"
60   end
61
62   it 'should allow nesting of blockquotes' do
63     expected = dedent <<-END
64       <blockquote>
65         <blockquote>
66           <p>foo</p>
67         </blockquote>
68       </blockquote>
69     END
70     @parser.parse('> > foo').should == expected
71   end
72
73   it 'should allow opening of a nested blockquote after other content' do
74     expected = dedent <<-END
75       <blockquote>
76         <p>foo</p>
77         <blockquote>
78           <p>bar</p>
79         </blockquote>
80       </blockquote>
81     END
82     @parser.parse("> foo\n> > bar").should == expected
83   end
84
85   it 'should allow opening of a nested blockquote before other content' do
86     expected = dedent <<-END
87       <blockquote>
88         <blockquote>
89           <p>foo</p>
90         </blockquote>
91         <p>bar</p>
92       </blockquote>
93     END
94     @parser.parse("> > foo\n> bar").should == expected
95   end
96
97   it 'should accept an empty blockquote' do
98     expected = dedent <<-END
99       <blockquote>
100       </blockquote>
101     END
102     @parser.parse('>').should == expected
103   end
104
105   it 'should jump out of blockquote mode on seeing a normal line of text' do
106     expected =  dedent <<-END
107       <blockquote>
108         <p>foo</p>
109       </blockquote>
110       <p>bar</p>
111     END
112     @parser.parse("> foo\nbar").should == expected
113   end
114
115   it 'should allow nesting of h1 blocks' do
116     expected = dedent <<-END
117       <blockquote>
118         <h1>foo</h1>
119       </blockquote>
120     END
121     @parser.parse('> = foo =').should == expected
122   end
123
124   it 'should allow nesting of h2 blocks' do
125     expected =  dedent <<-END
126       <blockquote>
127         <h2>foo</h2>
128       </blockquote>
129     END
130     @parser.parse('> == foo ==').should == expected
131   end
132
133   it 'should allow nesting of h3 blocks' do
134     expected = dedent <<-END
135       <blockquote>
136         <h3>foo</h3>
137       </blockquote>
138     END
139     @parser.parse('> === foo ===').should == expected
140   end
141
142   it 'should allow nesting of h4 blocks' do
143     expected = dedent <<-END
144       <blockquote>
145         <h4>foo</h4>
146       </blockquote>
147     END
148     @parser.parse('> ==== foo ====').should == expected
149   end
150
151   it 'should allow nesting of h5 blocks' do
152     expected = dedent <<-END
153       <blockquote>
154         <h5>foo</h5>
155       </blockquote>
156     END
157     @parser.parse('> ===== foo =====').should == expected
158   end
159
160   it 'should allow nesting of h6 blocks' do
161      expected = dedent <<-END
162       <blockquote>
163         <h6>foo</h6>
164       </blockquote>
165     END
166     @parser.parse('> ====== foo ======').should == expected
167   end
168
169   it 'should allow alternating nested paragraphs and pre blocks' do
170     # was a bug
171     input = dedent <<-END
172       > para 1
173       >
174       >  pre 1
175       >  pre 2
176       >
177       > para 2
178     END
179     expected = dedent <<-END
180       <blockquote>
181         <p>para 1</p>
182         <pre>pre 1
183       pre 2</pre>
184         <p>para 2</p>
185       </blockquote>
186     END
187     @parser.parse(input).should == expected
188   end
189
190   it 'should allow nesting of styled spans inside blockquotes' do
191     input = dedent <<-END
192       > link to [[something]], and ''other''
193       > `styled` '''spans'''.
194     END
195     expected = dedent <<-END
196       <blockquote>
197         <p>link to <a href="/wiki/something">something</a>, and <em>other</em> <tt>styled</tt> <strong>spans</strong>.</p>
198       </blockquote>
199     END
200     @parser.parse(input).should == expected
201   end
202
203   it 'should allow complex nestings inside blockquotes' do
204     # was a bug: further reduced in the following example, "should handle TT spans inside blockquotes"
205     input = dedent <<-END
206        code block
207       
208       a normal para
209       
210       > will nest
211       >
212       >  line 1
213       >  line 2
214       >
215       > other
216       >
217       > * here
218       > * is
219       > * a
220       > * list
221       >
222       > outer para with ''styled''
223       > `stuff` in it
224       >
225       > > inner
226       > > blockquote
227       > > # inner list
228       > > ## nested list
229       
230       follow-up para
231     END
232     expected = dedent <<-END
233       <pre>code block</pre>
234       <p>a normal para</p>
235       <blockquote>
236         <p>will nest</p>
237         <pre>line 1
238       line 2</pre>
239         <p>other</p>
240         <ul>
241           <li>here</li>
242           <li>is</li>
243           <li>a</li>
244           <li>list</li>
245         </ul>
246         <p>outer para with <em>styled</em> <tt>stuff</tt> in it</p>
247         <blockquote>
248           <p>inner blockquote</p>
249           <ol>
250             <li>inner list
251               <ol>
252                 <li>nested list</li>
253               </ol>
254             </li>
255           </ol>
256         </blockquote>
257       </blockquote>
258       <p>follow-up para</p>
259     END
260     @parser.parse(input).should == expected
261   end
262
263   it 'should handle TT spans inside blockquotes' do
264     # was a bug: this is a minimally reduced test case extracted from the integration tests
265     input = dedent <<-END
266       > some
267       > `styled`
268     END
269     expected = dedent <<-END
270       <blockquote>
271         <p>some <tt>styled</tt></p>
272       </blockquote>
273     END
274     @parser.parse(input).should == expected
275   end
276
277
278   it 'should handled nested lists which immediately follow paragraphs' do
279     # was a bug: this is a minimally reduced test case extracted from the integration tests
280     input = dedent <<-END
281       > Finally
282       > # Which
283     END
284     expected = dedent <<-END
285       <blockquote>
286         <p>Finally</p>
287         <ol>
288           <li>Which</li>
289         </ol>
290       </blockquote>
291     END
292     @parser.parse(input).should == expected
293   end
294
295   # TODO: tests for nesting other types of blocks
296 end
297
298 describe Wikitext::Parser, 'literal BLOCKQUOTE_START/BLOCKQUOTE_END tags' do
299   before do
300     @parser = Wikitext::Parser.new
301   end
302
303   it 'should accept literal BLOCKQUOTE_START/BLOCKQUOTE_END tags as an alternative to the standard syntax' do
304     input = '<blockquote>hello</blockquote>'
305     expected = dedent <<-END
306       <blockquote>
307         <p>hello</p>
308       </blockquote>
309     END
310     @parser.parse(input).should == expected
311
312     # alternative 1
313     input = dedent <<-END
314       <blockquote>
315       hello
316       </blockquote>
317     END
318     expected = dedent <<-END
319       <blockquote>
320         <p>hello</p>
321       </blockquote>
322     END
323     @parser.parse(input).should == expected
324
325     # alternative 2
326     input = dedent <<-END
327       <blockquote>hello
328       </blockquote>
329     END
330     expected = dedent <<-END
331       <blockquote>
332         <p>hello</p>
333       </blockquote>
334     END
335     @parser.parse(input).should == expected
336
337     # alternative 3
338     input = dedent <<-END
339       <blockquote>
340       hello</blockquote>
341     END
342     expected = dedent <<-END
343       <blockquote>
344         <p>hello</p>
345       </blockquote>
346     END
347     @parser.parse(input).should == expected
348
349     # note what happens if we indent (whitespace gets carried through; it is not identified as a PRE block
350     # in reality you'd never indent when editing wikitext anyway; the idea is to free yourself from details like that
351     input = dedent <<-END
352       <blockquote>
353         hello
354       </blockquote>
355     END
356     expected = dedent <<-END
357       <blockquote>
358         <p>  hello</p>
359       </blockquote>
360     END
361     @parser.parse(input).should == expected
362   end
363
364   it 'should merge consecutive lines into a single paragraph' do
365     input = dedent <<-END
366       <blockquote>foo
367       bar
368       baz</blockquote>
369     END
370     expected = dedent <<-END
371       <blockquote>
372         <p>foo bar baz</p>
373       </blockquote>
374     END
375     @parser.parse(input).should == expected
376   end
377
378   it 'should process paragraph breaks' do
379     input = dedent <<-END
380       <blockquote>foo
381       
382       baz</blockquote>
383     END
384     expected = dedent <<-END
385       <blockquote>
386         <p>foo</p>
387         <p>baz</p>
388       </blockquote>
389     END
390     @parser.parse(input).should == expected
391   end
392
393   it 'should pass through PRE tokens unaltered' do
394     input = dedent <<-END
395       <blockquote>foo
396        bar</blockquote>
397     END
398
399     # note the extra space: one for the CRLF and another for the PRE token
400     expected = dedent <<-END
401       <blockquote>
402         <p>foo  bar</p>
403       </blockquote>
404     END
405     @parser.parse(input).should == expected
406   end
407
408   it 'should terminate open span-level elements on hitting the newline' do
409     # for now just test with EM; potentially add more examples later
410     input = dedent <<-END
411       <blockquote>foo ''bar
412       baz</blockquote>
413     END
414     expected = dedent <<-END
415       <blockquote>
416         <p>foo <em>bar</em> baz</p>
417       </blockquote>
418     END
419     @parser.parse(input).should == expected
420   end
421
422   it 'should pass through BLOCKQUOTE tokens escaped' do
423     input = dedent <<-END
424       <blockquote>foo
425       > bar
426       baz</blockquote>
427     END
428     expected = dedent <<-END
429       <blockquote>
430         <p>foo &gt; bar baz</p>
431       </blockquote>
432     END
433     @parser.parse(input).should == expected
434   end
435
436   it 'should be able to nest single-item unordered lists' do
437     input = '<blockquote>* foo</blockquote>'
438     expected = dedent <<-END
439       <blockquote>
440         <ul>
441           <li>foo</li>
442         </ul>
443       </blockquote>
444     END
445     @parser.parse(input).should == expected
446   end
447
448   it 'should be able to nest multi-item unordered lists' do
449     input = dedent <<-END
450       <blockquote>
451       * foo
452       * bar
453       * baz
454       </blockquote>
455     END
456     expected = dedent <<-END
457       <blockquote>
458         <ul>
459           <li>foo</li>
460           <li>bar</li>
461           <li>baz</li>
462         </ul>
463       </blockquote>
464     END
465     @parser.parse(input).should == expected
466   end
467
468   it 'should be able to nest nested unordered lists' do
469     input = dedent <<-END
470       <blockquote>
471       * foo
472       ** bar
473       * baz
474       </blockquote>
475     END
476     expected = dedent <<-END
477       <blockquote>
478         <ul>
479           <li>foo
480             <ul>
481               <li>bar</li>
482             </ul>
483           </li>
484           <li>baz</li>
485         </ul>
486       </blockquote>
487     END
488     @parser.parse(input).should == expected
489
490     # note that the exact placement of the closing tag doesn't matter
491     input = dedent <<-END
492       <blockquote>
493       * foo
494       ** bar
495       * baz</blockquote>
496     END
497     @parser.parse(input).should == expected
498
499     # likewise for the opening tag
500     input = dedent <<-END
501       <blockquote>* foo
502       ** bar
503       * baz
504       </blockquote>
505     END
506     @parser.parse(input).should == expected
507   end
508
509   it 'should be able to nest blockquotes' do
510     input = dedent <<-END
511       <blockquote>
512       foo
513       <blockquote>
514       bar
515       </blockquote>
516       baz
517       </blockquote>
518     END
519     expected = dedent <<-END
520       <blockquote>
521         <p>foo</p>
522         <blockquote>
523           <p>bar</p>
524         </blockquote>
525         <p>baz</p>
526       </blockquote>
527     END
528     @parser.parse(input).should == expected
529   end
530
531   it 'should be able to nest pre blocks' do
532     input = dedent <<-END
533       <blockquote>
534       outer 1
535       <pre>inner 1
536       inner 2</pre>
537       outer 2
538       </blockquote>
539     END
540     expected = dedent <<-END
541       <blockquote>
542         <p>outer 1</p>
543         <pre>inner 1
544       inner 2</pre>
545         <p>outer 2</p>
546       </blockquote>
547     END
548     @parser.parse(input).should == expected
549   end
550
551   it 'should support nesting of H1 spans' do
552     input = dedent <<-END
553       <blockquote>
554       = foo =
555       bar
556       </blockquote>
557     END
558
559     expected = dedent <<-END
560       <blockquote>
561         <h1>foo</h1>
562         <p>bar</p>
563       </blockquote>
564     END
565     @parser.parse(input).should == expected
566
567     # but note that this won't work
568     # the second "=" is not recognized as an H1_END because the scanner has no lookahead at the token level
569     input = '<blockquote>= foo =</blockquote>'
570     expected = dedent <<-END
571       <blockquote>
572         <h1>foo =</h1>
573       </blockquote>
574     END
575     @parser.parse(input).should == expected
576   end
577 end