wikitext 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/ary.h +99 -0
- data/ext/depend +22 -0
- data/ext/extconf.rb +23 -0
- data/ext/parser.c +2174 -0
- data/ext/parser.h +31 -0
- data/ext/str.h +135 -0
- data/ext/token.c +109 -0
- data/ext/token.h +95 -0
- data/ext/wikitext.c +60 -0
- data/ext/wikitext.h +30 -0
- data/ext/wikitext_ragel.c +3354 -0
- data/ext/wikitext_ragel.h +17 -0
- data/spec/autolinking_spec.rb +122 -0
- data/spec/blockquote_spec.rb +570 -0
- data/spec/em_spec.rb +97 -0
- data/spec/encoding_spec.rb +124 -0
- data/spec/entity_spec.rb +40 -0
- data/spec/external_link_spec.rb +289 -0
- data/spec/h1_spec.rb +59 -0
- data/spec/h2_spec.rb +59 -0
- data/spec/h3_spec.rb +59 -0
- data/spec/h4_spec.rb +59 -0
- data/spec/h5_spec.rb +59 -0
- data/spec/h6_spec.rb +59 -0
- data/spec/indentation_spec.rb +70 -0
- data/spec/integration_spec.rb +265 -0
- data/spec/internal_link_spec.rb +445 -0
- data/spec/line_endings_spec.rb +81 -0
- data/spec/link_encoding_spec.rb +132 -0
- data/spec/link_sanitizing_spec.rb +228 -0
- data/spec/nowiki_spec.rb +155 -0
- data/spec/p_spec.rb +44 -0
- data/spec/pre_spec.rb +411 -0
- data/spec/regressions_spec.rb +45 -0
- data/spec/spec_helper.rb +77 -0
- data/spec/strong_em_spec.rb +89 -0
- data/spec/strong_spec.rb +99 -0
- data/spec/tokenizing_spec.rb +190 -0
- data/spec/tt_spec.rb +100 -0
- data/spec/ul_spec.rb +307 -0
- data/spec/wikitext_spec.rb +50 -0
- metadata +93 -0
@@ -0,0 +1,445 @@
|
|
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, 'internal links' do
|
20
|
+
before do
|
21
|
+
@parser = Wikitext::Parser.new
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should pass through unexpected link end tokens literally' do
|
25
|
+
@parser.parse('foo ]] bar').should == "<p>foo ]] bar</p>\n" # in plain scope
|
26
|
+
@parser.parse("foo '']]'' bar").should == "<p>foo <em>]]</em> bar</p>\n" # in EM scope
|
27
|
+
@parser.parse("foo ''']]''' bar").should == "<p>foo <strong>]]</strong> bar</p>\n" # in STRONG scope
|
28
|
+
@parser.parse("foo ''''']]''''' bar").should == "<p>foo <strong><em>]]</em></strong> bar</p>\n" # in STRONG_EM scope
|
29
|
+
@parser.parse('foo <tt>]]</tt> bar').should == "<p>foo <tt>]]</tt> bar</p>\n" # in TT scope
|
30
|
+
@parser.parse('= foo ]] bar =').should == "<h1>foo ]] bar</h1>\n" # in H1 scope
|
31
|
+
@parser.parse('== foo ]] bar ==').should == "<h2>foo ]] bar</h2>\n" # in H2 scope
|
32
|
+
@parser.parse('=== foo ]] bar ===').should == "<h3>foo ]] bar</h3>\n" # in H3 scope
|
33
|
+
@parser.parse('==== foo ]] bar ====').should == "<h4>foo ]] bar</h4>\n" # in H4 scope
|
34
|
+
@parser.parse('===== foo ]] bar =====').should == "<h5>foo ]] bar</h5>\n" # in H5 scope
|
35
|
+
@parser.parse('====== foo ]] bar ======').should == "<h6>foo ]] bar</h6>\n" # in H6 scope
|
36
|
+
@parser.parse('> ]]').should == "<blockquote>\n <p>]]</p>\n</blockquote>\n" # in BLOCKQUOTE scope
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should turn single words into links' do
|
40
|
+
@parser.parse('[[foo]]').should == %Q{<p><a href="/wiki/foo">foo</a></p>\n}
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should turn multiple words into links' do
|
44
|
+
@parser.parse('[[foo bar]]').should == %Q{<p><a href="/wiki/foo%20bar">foo bar</a></p>\n}
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should trim leading whitespace' do
|
48
|
+
@parser.parse('[[ foo]]').should == %Q{<p><a href="/wiki/foo">foo</a></p>\n}
|
49
|
+
@parser.parse('[[ foo]]').should == %Q{<p><a href="/wiki/foo">foo</a></p>\n}
|
50
|
+
@parser.parse('[[ foo]]').should == %Q{<p><a href="/wiki/foo">foo</a></p>\n}
|
51
|
+
@parser.parse('[[ foo]]').should == %Q{<p><a href="/wiki/foo">foo</a></p>\n}
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should trim trailing whitespace' do
|
55
|
+
@parser.parse('[[foo ]]').should == %Q{<p><a href="/wiki/foo">foo</a></p>\n}
|
56
|
+
@parser.parse('[[foo ]]').should == %Q{<p><a href="/wiki/foo">foo</a></p>\n}
|
57
|
+
@parser.parse('[[foo ]]').should == %Q{<p><a href="/wiki/foo">foo</a></p>\n}
|
58
|
+
@parser.parse('[[foo ]]').should == %Q{<p><a href="/wiki/foo">foo</a></p>\n} # was a bug (exception)
|
59
|
+
@parser.parse('[[foo ]]').should == %Q{<p><a href="/wiki/foo">foo</a></p>\n} # was a bug (crash)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should trim leading and trailing whitespace (combined)' do
|
63
|
+
@parser.parse('[[ foo ]]').should == %Q{<p><a href="/wiki/foo">foo</a></p>\n}
|
64
|
+
@parser.parse('[[ foo ]]').should == %Q{<p><a href="/wiki/foo">foo</a></p>\n}
|
65
|
+
@parser.parse('[[ foo ]]').should == %Q{<p><a href="/wiki/foo">foo</a></p>\n}
|
66
|
+
@parser.parse('[[ foo ]]').should == %Q{<p><a href="/wiki/foo">foo</a></p>\n}
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should leave embedded whitespace intact' do
|
70
|
+
@parser.parse('[[ foo bar ]]').should == %Q{<p><a href="/wiki/foo%20bar">foo bar</a></p>\n}
|
71
|
+
@parser.parse('[[foo bar ]]').should == %Q{<p><a href="/wiki/foo%20bar">foo bar</a></p>\n}
|
72
|
+
@parser.parse('[[ foo bar ]]').should == %Q{<p><a href="/wiki/foo%20bar">foo bar</a></p>\n}
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should encode and sanitize quotes' do
|
76
|
+
# note how percent encoding is used in the href, and named entities in the link text
|
77
|
+
@parser.parse('[[hello "world"]]').should == %Q{<p><a href="/wiki/hello%20%22world%22">hello "world"</a></p>\n}
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should encode and sanitize ampersands' do
|
81
|
+
@parser.parse('[[a & b]]').should == %Q{<p><a href="/wiki/a%20%26%20b">a & b</a></p>\n}
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should allow ampersand entities (special exception)' do
|
85
|
+
@parser.parse('[[a & b]]').should == %Q{<p><a href="/wiki/a%20%26%20b">a & b</a></p>\n}
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should allow quote entities (special exception)' do
|
89
|
+
@parser.parse('[[a " b]]').should == %Q{<p><a href="/wiki/a%20%22%20b">a " b</a></p>\n}
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should handle mixed scenarios (quotes, ampersands, non-ASCII characers)' do
|
93
|
+
expected = %Q{<p><a href="/wiki/foo%2c%20%22bar%22%20%26%20baz%20%e2%82%ac">foo, "bar" & baz €</a></p>\n}
|
94
|
+
@parser.parse('[[foo, "bar" & baz €]]').should == expected
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should handle links in paragraph flows' do
|
98
|
+
expected = %Q{<p>foo <a href="/wiki/bar">bar</a> baz</p>\n}
|
99
|
+
@parser.parse('foo [[bar]] baz').should == expected # was a bug
|
100
|
+
end
|
101
|
+
|
102
|
+
describe 'custom link text' do
|
103
|
+
it 'should recognize link text placed after the separator' do
|
104
|
+
@parser.parse('[[foo|bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should trim whitespace to the left of the separator' do
|
108
|
+
@parser.parse('[[foo |bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
109
|
+
@parser.parse('[[foo |bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
110
|
+
@parser.parse('[[foo |bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
111
|
+
@parser.parse('[[foo |bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
112
|
+
@parser.parse('[[foo |bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
113
|
+
@parser.parse('[[foo |bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should trim whitespace to the right of the separator' do
|
117
|
+
@parser.parse('[[foo| bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
118
|
+
@parser.parse('[[foo| bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
119
|
+
@parser.parse('[[foo| bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
120
|
+
@parser.parse('[[foo| bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
121
|
+
@parser.parse('[[foo| bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
122
|
+
@parser.parse('[[foo| bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should trim whitespace on both sides of the separator (at the same time)' do
|
126
|
+
@parser.parse('[[foo | bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
127
|
+
@parser.parse('[[foo | bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
128
|
+
@parser.parse('[[foo | bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
129
|
+
@parser.parse('[[foo | bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
130
|
+
@parser.parse('[[foo | bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
131
|
+
@parser.parse('[[foo | bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should trim trailing whitespace from the link text' do
|
135
|
+
@parser.parse('[[foo|bar ]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
136
|
+
@parser.parse('[[foo|bar ]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
137
|
+
@parser.parse('[[foo|bar ]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
138
|
+
@parser.parse('[[foo|bar ]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
139
|
+
@parser.parse('[[foo|bar ]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
140
|
+
@parser.parse('[[foo|bar ]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'should trim leading and trailing whitespace from the link text' do
|
144
|
+
@parser.parse('[[foo| bar ]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
145
|
+
@parser.parse('[[foo| bar ]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
146
|
+
@parser.parse('[[foo| bar ]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
147
|
+
@parser.parse('[[foo| bar ]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
148
|
+
@parser.parse('[[foo| bar ]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
149
|
+
@parser.parse('[[foo| bar ]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'should treat a separator inside the link text as part of the link text' do
|
153
|
+
@parser.parse('[[foo|bar|baz]]').should == %Q{<p><a href="/wiki/foo">bar|baz</a></p>\n}
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'should treat separators outside of links as normal text' do
|
157
|
+
@parser.parse('foo|bar').should == %Q{<p>foo|bar</p>\n}
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'should allow em markup in the custom link text' do
|
161
|
+
expected = %Q{<p><a href="/wiki/foo">bar <em>baz</em></a></p>\n}
|
162
|
+
@parser.parse("[[foo|bar ''baz'']]").should == expected
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'should automatically close unclosed em markup in the custom link text' do
|
166
|
+
expected = %Q{<p><a href="/wiki/foo">bar <em>baz</em></a></p>\n}
|
167
|
+
@parser.parse("[[foo|bar ''baz]]").should == expected
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'should allow strong markup in the custom link text' do
|
171
|
+
expected = %Q{<p><a href="/wiki/foo">bar <strong>baz</strong></a></p>\n}
|
172
|
+
@parser.parse("[[foo|bar '''baz''']]").should == expected
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'should automatically close unclosed strong markup in the custom link text' do
|
176
|
+
expected = %Q{<p><a href="/wiki/foo">bar <strong>baz</strong></a></p>\n}
|
177
|
+
@parser.parse("[[foo|bar '''baz]]").should == expected
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should allow strong/em markup in the custom link text' do
|
181
|
+
expected = %Q{<p><a href="/wiki/foo">bar <strong><em>baz</em></strong></a></p>\n}
|
182
|
+
@parser.parse("[[foo|bar '''''baz''''']]").should == expected
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'should automatically close unclosed strong/em markup in the custom link text' do
|
186
|
+
expected = %Q{<p><a href="/wiki/foo">bar <strong><em>baz</em></strong></a></p>\n}
|
187
|
+
@parser.parse("[[foo|bar '''''baz]]").should == expected
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'should allow tt markup in the custom link text' do
|
191
|
+
expected = %Q{<p><a href="/wiki/foo">bar <tt>baz</tt></a></p>\n}
|
192
|
+
@parser.parse('[[foo|bar <tt>baz</tt>]]').should == expected
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'should automatically close unclosed tt markup in the custom link text' do
|
196
|
+
expected = %Q{<p><a href="/wiki/foo">bar <tt>baz</tt></a></p>\n}
|
197
|
+
@parser.parse('[[foo|bar <tt>baz]]').should == expected
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'should allow named entities in the custom link text' do
|
201
|
+
expected = %Q{<p><a href="/wiki/foo">bar ©</a></p>\n}
|
202
|
+
@parser.parse('[[foo|bar ©]]').should == expected
|
203
|
+
|
204
|
+
# explicitly test " because it is tokenized separately from the other named entities
|
205
|
+
expected = %Q{<p><a href="/wiki/foo">bar "</a></p>\n}
|
206
|
+
@parser.parse('[[foo|bar "]]').should == expected
|
207
|
+
|
208
|
+
# explicitly test & because it is tokenized separately from the other named entities
|
209
|
+
expected = %Q{<p><a href="/wiki/foo">bar &</a></p>\n}
|
210
|
+
@parser.parse('[[foo|bar &]]').should == expected
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'should allow decimal entities in the custom link text' do
|
214
|
+
expected = %Q{<p><a href="/wiki/foo">bar €</a></p>\n}
|
215
|
+
@parser.parse('[[foo|bar €]]').should == expected
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'should allow hexadecimal entities in the custom link text' do
|
219
|
+
expected = %Q{<p><a href="/wiki/foo">bar €</a></p>\n}
|
220
|
+
@parser.parse('[[foo|bar €]]').should == expected
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'should sanitize non-ASCII characters in the custom link text' do
|
224
|
+
expected = %Q{<p><a href="/wiki/foo">bar €</a></p>\n}
|
225
|
+
@parser.parse('[[foo|bar €]]').should == expected
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'should sanitize characters that have special meaning in HTML in the custom link text' do
|
229
|
+
expected = %Q{<p><a href="/wiki/foo">bar <</a></p>\n}
|
230
|
+
@parser.parse('[[foo|bar <]]').should == expected
|
231
|
+
|
232
|
+
expected = %Q{<p><a href="/wiki/foo">bar ></a></p>\n}
|
233
|
+
@parser.parse('[[foo|bar >]]').should == expected
|
234
|
+
|
235
|
+
expected = %Q{<p><a href="/wiki/foo">bar &</a></p>\n}
|
236
|
+
@parser.parse('[[foo|bar &]]').should == expected
|
237
|
+
|
238
|
+
expected = %Q{<p><a href="/wiki/foo">bar "baz"</a></p>\n}
|
239
|
+
@parser.parse('[[foo|bar "baz"]]').should == expected
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'should allow nowiki markup in the custom link text' do
|
243
|
+
expected = %Q{<p><a href="/wiki/foo">bar [[</a></p>\n}
|
244
|
+
@parser.parse("[[foo|bar <nowiki>[[</nowiki>]]").should == expected
|
245
|
+
|
246
|
+
expected = %Q{<p><a href="/wiki/foo">bar [</a></p>\n}
|
247
|
+
@parser.parse("[[foo|bar <nowiki>[</nowiki>]]").should == expected
|
248
|
+
|
249
|
+
expected = %Q{<p><a href="/wiki/foo">bar ]]</a></p>\n}
|
250
|
+
@parser.parse("[[foo|bar <nowiki>]]</nowiki>]]").should == expected
|
251
|
+
|
252
|
+
expected = %Q{<p><a href="/wiki/foo">bar ]</a></p>\n}
|
253
|
+
@parser.parse("[[foo|bar <nowiki>]</nowiki>]]").should == expected
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
describe 'overriding the link prefix' do
|
258
|
+
it 'should be able to override the link prefix' do
|
259
|
+
@parser.internal_link_prefix = '/custom/'
|
260
|
+
@parser.parse('[[foo]]').should == %Q{<p><a href="/custom/foo">foo</a></p>\n}
|
261
|
+
end
|
262
|
+
|
263
|
+
it 'should interpet a nil link prefix as meaning no prefix' do
|
264
|
+
@parser.internal_link_prefix = nil
|
265
|
+
@parser.parse('[[foo]]').should == %Q{<p><a href="foo">foo</a></p>\n}
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
describe 'special links' do
|
270
|
+
it 'should recognize links of the form "bug/10" as special links' do
|
271
|
+
@parser.parse('[[bug/10]]').should == %Q{<p><a href="/bug/10">bug/10</a></p>\n}
|
272
|
+
@parser.parse('[[issue/25]]').should == %Q{<p><a href="/issue/25">issue/25</a></p>\n}
|
273
|
+
@parser.parse('[[post/7]]').should == %Q{<p><a href="/post/7">post/7</a></p>\n}
|
274
|
+
end
|
275
|
+
|
276
|
+
it 'should not recognize special links when "treat_slash_as_special" is set to false' do
|
277
|
+
@parser.treat_slash_as_special = false
|
278
|
+
@parser.parse('[[bug/10]]').should == %Q{<p><a href="/wiki/bug%2f10">bug/10</a></p>\n}
|
279
|
+
@parser.parse('[[issue/25]]').should == %Q{<p><a href="/wiki/issue%2f25">issue/25</a></p>\n}
|
280
|
+
@parser.parse('[[post/7]]').should == %Q{<p><a href="/wiki/post%2f7">post/7</a></p>\n}
|
281
|
+
end
|
282
|
+
|
283
|
+
it 'should accept custom link text in conjunction with special links' do
|
284
|
+
@parser.parse('[[bug/10|bug #10]]').should == %Q{<p><a href="/bug/10">bug #10</a></p>\n}
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'should ignore link prefix overrides when emitting special links' do
|
288
|
+
@parser.internal_link_prefix = '/custom/'
|
289
|
+
@parser.parse('[[bug/10]]').should == %Q{<p><a href="/bug/10">bug/10</a></p>\n}
|
290
|
+
end
|
291
|
+
|
292
|
+
it 'should not classify links as special merely because of the presence of a slash' do
|
293
|
+
# we want the syntax to be tight to minimize false positives
|
294
|
+
@parser.parse('[[foo/bar]]').should == %Q{<p><a href="/wiki/foo%2fbar">foo/bar</a></p>\n}
|
295
|
+
end
|
296
|
+
|
297
|
+
it 'should not accept special links which have a leading forward slash' do
|
298
|
+
# this is a syntax error
|
299
|
+
@parser.parse('[[/bug/10]]').should == %Q{<p><a href="/wiki/%2fbug%2f10">/bug/10</a></p>\n}
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
describe 'invalid links' do
|
304
|
+
it 'should not allow entities in the link text' do
|
305
|
+
@parser.parse('[[a € b]]').should == "<p>[[a € b]]</p>\n"
|
306
|
+
end
|
307
|
+
|
308
|
+
it 'should not allow URIs in the link text' do
|
309
|
+
expected = %Q{<p>[[hello <a href="http://example.com/" class="external">http://example.com/</a> world]]</p>\n}
|
310
|
+
@parser.parse('[[hello http://example.com/ world]]').should == expected
|
311
|
+
end
|
312
|
+
|
313
|
+
it 'should handle embedded [[ inside links' do
|
314
|
+
# note how first part "[[foo " in itself is invalid and so gets rejected and echoed literally
|
315
|
+
expected = %Q{<p>[[foo <a href="/wiki/bar">bar</a></p>\n}
|
316
|
+
@parser.parse('[[foo [[bar]]').should == expected
|
317
|
+
end
|
318
|
+
|
319
|
+
it 'should handled embedded ]] inside links' do
|
320
|
+
# note how the link gets terminated early and the trailing part is rejected and echoed literally
|
321
|
+
expected = %Q{<p><a href="/wiki/foo">foo</a>bar]]</p>\n}
|
322
|
+
@parser.parse('[[foo ]]bar]]').should == expected
|
323
|
+
end
|
324
|
+
|
325
|
+
it 'should handle embedded [ inside links' do
|
326
|
+
# [ is not allowed at all so the entire link is rendered invalid
|
327
|
+
expected = "<p>[[foo [bar]]</p>\n"
|
328
|
+
@parser.parse('[[foo [bar]]').should == expected
|
329
|
+
end
|
330
|
+
|
331
|
+
it 'should handle embedded ] inside links' do
|
332
|
+
# [ is not allowed at all so the entire link is rendered invalid
|
333
|
+
expected = "<p>[[foo ]bar]]</p>\n"
|
334
|
+
@parser.parse('[[foo ]bar]]').should == expected
|
335
|
+
end
|
336
|
+
|
337
|
+
describe 'unterminated link targets (end-of-file)' do
|
338
|
+
it 'should rollback and show the unterminated link' do
|
339
|
+
@parser.parse('[[foo').should == %Q{<p>[[foo</p>\n}
|
340
|
+
end
|
341
|
+
|
342
|
+
it 'should not trim leading whitespace when rolling back' do
|
343
|
+
@parser.parse('[[ foo').should == %Q{<p>[[ foo</p>\n}
|
344
|
+
@parser.parse('[[ foo').should == %Q{<p>[[ foo</p>\n}
|
345
|
+
@parser.parse('[[ foo').should == %Q{<p>[[ foo</p>\n}
|
346
|
+
@parser.parse('[[ foo').should == %Q{<p>[[ foo</p>\n}
|
347
|
+
end
|
348
|
+
|
349
|
+
it 'should not trim trailing whitespace when rolling back' do
|
350
|
+
@parser.parse('[[foo ').should == %Q{<p>[[foo </p>\n}
|
351
|
+
@parser.parse('[[foo ').should == %Q{<p>[[foo </p>\n}
|
352
|
+
@parser.parse('[[foo ').should == %Q{<p>[[foo </p>\n}
|
353
|
+
@parser.parse('[[foo ').should == %Q{<p>[[foo </p>\n}
|
354
|
+
end
|
355
|
+
|
356
|
+
it 'should not trim leadig and trailing whitespace (combined) when rolling back' do
|
357
|
+
@parser.parse('[[ foo ').should == %Q{<p>[[ foo </p>\n}
|
358
|
+
@parser.parse('[[ foo ').should == %Q{<p>[[ foo </p>\n}
|
359
|
+
@parser.parse('[[ foo ').should == %Q{<p>[[ foo </p>\n}
|
360
|
+
@parser.parse('[[ foo ').should == %Q{<p>[[ foo </p>\n}
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
describe 'unterminated link targets (end-of-line)' do
|
365
|
+
it 'should rollback and show the unterminated link' do
|
366
|
+
@parser.parse("[[foo\n").should == %Q{<p>[[foo</p>\n}
|
367
|
+
end
|
368
|
+
|
369
|
+
it 'should not trim leading whitespace when rolling back' do
|
370
|
+
@parser.parse("[[ foo\n").should == %Q{<p>[[ foo</p>\n}
|
371
|
+
@parser.parse("[[ foo\n").should == %Q{<p>[[ foo</p>\n}
|
372
|
+
@parser.parse("[[ foo\n").should == %Q{<p>[[ foo</p>\n}
|
373
|
+
@parser.parse("[[ foo\n").should == %Q{<p>[[ foo</p>\n}
|
374
|
+
end
|
375
|
+
|
376
|
+
it 'should not trim trailing whitespace when rolling back' do
|
377
|
+
@parser.parse("[[foo \n").should == %Q{<p>[[foo </p>\n}
|
378
|
+
@parser.parse("[[foo \n").should == %Q{<p>[[foo </p>\n}
|
379
|
+
@parser.parse("[[foo \n").should == %Q{<p>[[foo </p>\n}
|
380
|
+
@parser.parse("[[foo \n").should == %Q{<p>[[foo </p>\n}
|
381
|
+
end
|
382
|
+
|
383
|
+
it 'should not trim leading and trailing whitespace (combined) when rolling back' do
|
384
|
+
@parser.parse("[[ foo \n").should == %Q{<p>[[ foo </p>\n}
|
385
|
+
@parser.parse("[[ foo \n").should == %Q{<p>[[ foo </p>\n}
|
386
|
+
@parser.parse("[[ foo \n").should == %Q{<p>[[ foo </p>\n}
|
387
|
+
@parser.parse("[[ foo \n").should == %Q{<p>[[ foo </p>\n}
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
describe 'missing link text' do
|
392
|
+
it 'should use link target' do
|
393
|
+
@parser.parse('[[foo|]]').should == %Q{<p><a href="/wiki/foo">foo</a></p>\n}
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
describe 'link cut off at separator (end-of-file)' do
|
398
|
+
it 'should rollback and show the unterminated link' do
|
399
|
+
@parser.parse('[[foo|').should == %Q{<p>[[foo|</p>\n}
|
400
|
+
@parser.parse('[[foo| ').should == %Q{<p>[[foo| </p>\n}
|
401
|
+
@parser.parse('[[foo| ').should == %Q{<p>[[foo| </p>\n}
|
402
|
+
@parser.parse('[[foo| ').should == %Q{<p>[[foo| </p>\n}
|
403
|
+
@parser.parse('[[foo| ').should == %Q{<p>[[foo| </p>\n}
|
404
|
+
@parser.parse('[[foo| ').should == %Q{<p>[[foo| </p>\n}
|
405
|
+
@parser.parse('[[foo| ').should == %Q{<p>[[foo| </p>\n}
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
describe 'link cut off at separator (end-of-line)' do
|
410
|
+
it 'should rollback and show the unterminated link' do
|
411
|
+
@parser.parse("[[foo|\n").should == %Q{<p>[[foo|</p>\n}
|
412
|
+
@parser.parse("[[foo| \n").should == %Q{<p>[[foo| </p>\n}
|
413
|
+
@parser.parse("[[foo| \n").should == %Q{<p>[[foo| </p>\n}
|
414
|
+
@parser.parse("[[foo| \n").should == %Q{<p>[[foo| </p>\n}
|
415
|
+
@parser.parse("[[foo| \n").should == %Q{<p>[[foo| </p>\n}
|
416
|
+
@parser.parse("[[foo| \n").should == %Q{<p>[[foo| </p>\n}
|
417
|
+
@parser.parse("[[foo| \n").should == %Q{<p>[[foo| </p>\n}
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
describe 'unterminated link text (end-of-file)' do
|
422
|
+
it 'should rollback and show the unterminated link' do
|
423
|
+
@parser.parse('[[foo|hello').should == %Q{<p>[[foo|hello</p>\n}
|
424
|
+
@parser.parse('[[foo|hello ').should == %Q{<p>[[foo|hello </p>\n}
|
425
|
+
@parser.parse('[[foo|hello ').should == %Q{<p>[[foo|hello </p>\n}
|
426
|
+
@parser.parse('[[foo|hello ').should == %Q{<p>[[foo|hello </p>\n}
|
427
|
+
@parser.parse('[[foo|hello ').should == %Q{<p>[[foo|hello </p>\n}
|
428
|
+
@parser.parse('[[foo|hello ').should == %Q{<p>[[foo|hello </p>\n}
|
429
|
+
@parser.parse('[[foo|hello ').should == %Q{<p>[[foo|hello </p>\n}
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
describe 'unterminated link text (end-of-line)' do
|
434
|
+
it 'should rollback and show the unterminated link' do
|
435
|
+
@parser.parse("[[foo|hello\n").should == %Q{<p>[[foo|hello</p>\n}
|
436
|
+
@parser.parse("[[foo|hello \n").should == %Q{<p>[[foo|hello </p>\n}
|
437
|
+
@parser.parse("[[foo|hello \n").should == %Q{<p>[[foo|hello </p>\n}
|
438
|
+
@parser.parse("[[foo|hello \n").should == %Q{<p>[[foo|hello </p>\n}
|
439
|
+
@parser.parse("[[foo|hello \n").should == %Q{<p>[[foo|hello </p>\n}
|
440
|
+
@parser.parse("[[foo|hello \n").should == %Q{<p>[[foo|hello </p>\n}
|
441
|
+
@parser.parse("[[foo|hello \n").should == %Q{<p>[[foo|hello </p>\n}
|
442
|
+
end
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|
@@ -0,0 +1,81 @@
|
|
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 do
|
20
|
+
before do
|
21
|
+
@parser = Wikitext::Parser.new
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should default to UNIX line endings' do
|
25
|
+
@parser.line_ending.should == "\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should greedily match Mac line endings in input if possible' do
|
29
|
+
# note how the embedded "\r\n" is interpreted as a single token (and converted to exactly one space)
|
30
|
+
# it is not treated as two separate tokens
|
31
|
+
@parser.parse("foo\r\nbar").should == "<p>foo bar</p>\n"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe Wikitext::Parser, 'with UNIX line endings' do
|
36
|
+
before do
|
37
|
+
@parser = Wikitext::Parser.new
|
38
|
+
@parser.line_ending = "\n"
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should convert line endings within spans to a single space' do
|
42
|
+
@parser.parse("foo\nbar").should == "<p>foo bar</p>\n"
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should normalize non-UNIX line endings' do
|
46
|
+
@parser.parse("foo\rbar").should == "<p>foo bar</p>\n"
|
47
|
+
@parser.parse("foo\r\nbar").should == "<p>foo bar</p>\n"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe Wikitext::Parser, 'with Windows line endings' do
|
52
|
+
before do
|
53
|
+
@parser = Wikitext::Parser.new
|
54
|
+
@parser.line_ending = "\r"
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should convert line endings within spans to a single space' do
|
58
|
+
@parser.parse("foo\rbar").should == "<p>foo bar</p>\r"
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should normalize non-Windows line endings' do
|
62
|
+
@parser.parse("foo\nbar").should == "<p>foo bar</p>\r"
|
63
|
+
@parser.parse("foo\r\nbar").should == "<p>foo bar</p>\r"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe Wikitext::Parser, 'with Mac line endings' do
|
68
|
+
before do
|
69
|
+
@parser = Wikitext::Parser.new
|
70
|
+
@parser.line_ending = "\r\n"
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should convert line endings within spans to a single space' do
|
74
|
+
@parser.parse("foo\r\nbar").should == "<p>foo bar</p>\r\n"
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should normalize non-Mac line endings' do
|
78
|
+
@parser.parse("foo\nbar").should == "<p>foo bar</p>\r\n"
|
79
|
+
@parser.parse("foo\rbar").should == "<p>foo bar</p>\r\n"
|
80
|
+
end
|
81
|
+
end
|