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