creole 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ Manifest.txt
2
+ README.txt
3
+ Rakefile
4
+ lib/creole.rb
5
+ test/test_creole.rb
6
+ test/testcases.rb
@@ -0,0 +1,28 @@
1
+ = Creole
2
+
3
+ * http://creole.rubyforge.org/
4
+ * http://rubyforge.org/projects/creole/
5
+
6
+ == DESCRIPTION:
7
+
8
+ Creole is a Creole-to-HTML converter for Creole, the lightwight markup
9
+ language (http://wikicreole.org/).
10
+
11
+ == SYNOPSIS:
12
+
13
+ gem 'creole'
14
+ require 'creole'
15
+ html = Creole.creolize( ... )
16
+
17
+ == BUGS:
18
+
19
+ If you found a bug, please report it at the Creole project's tracker
20
+ on RubyForge:
21
+
22
+ http://rubyforge.org/tracker/?group_id=6344
23
+
24
+ == LICENSE:
25
+
26
+ RDoc is Copyright (c) 2008 Lars Christensen. It is free software, and
27
+ may be redistributed under the terms specified in the README file of
28
+ the Ruby distribution.
@@ -0,0 +1,11 @@
1
+ require 'hoe'
2
+
3
+ $:.unshift 'lib'
4
+ require 'creole'
5
+
6
+ Hoe.spec "creole" do |creole|
7
+ version = Creole::VERSION
8
+ developer 'Lars Christensen', 'larsch@belunktum.dk'
9
+ developer 'Daniel Mendler', 'mail@daniel-mendler.de'
10
+ end
11
+
@@ -0,0 +1,372 @@
1
+ require 'cgi'
2
+ require 'uri'
3
+
4
+ # :main: Creole
5
+
6
+ # The Creole parses and translates Creole formatted text into
7
+ # XHTML. Creole is a lightwight markup syntax similar to what many
8
+ # WikiWikiWebs use. Example syntax:
9
+ #
10
+ # = Heading 1 =
11
+ # == Heading 2 ==
12
+ # === Heading 3 ===
13
+ # **Bold text**
14
+ # //Italic text//
15
+ # [[Links]]
16
+ # |=Table|=Heading|
17
+ # |Table |Cells |
18
+ # {{image.png}}
19
+ #
20
+ # The simplest interface is Creole.creolize. The default handling of
21
+ # links allow explicit local links using the [[link]] syntax. External
22
+ # links will only be allowed if specified using http(s) and ftp(s)
23
+ # schemes. If special link handling is needed, such as inter-wiki or
24
+ # hierachical local links, you must inherit Creole::CreoleParser and
25
+ # override make_local_link.
26
+ #
27
+ # You can customize the created anchor/image markup by overriding
28
+ # make_*_anchor/make_image.
29
+
30
+ module Creole
31
+
32
+ VERSION = '0.3.3'
33
+
34
+ # CreoleParseError is raised when the Creole parser encounters
35
+ # something unexpected. This is generally now thrown unless there is
36
+ # a bug in the parser.
37
+ class CreoleParseError < Exception; end
38
+
39
+ # Convert the argument in Creole format to HTML and return the
40
+ # result. Example:
41
+ #
42
+ # Creole.creolize("**Hello //World//**")
43
+ # #=> "<p><strong>Hello <em>World</em></strong></p>"
44
+ #
45
+ # This is an alias for calling CreoleParser#parse:
46
+ # CreoleParser.new.parse(creole)
47
+ def self.creolize(creole)
48
+ CreoleParser.new.parse(creole)
49
+ end
50
+
51
+ # Main Creole parser class. Call CreoleParser#parse to parse Creole
52
+ # formatted text.
53
+ #
54
+ # This class is not reentrant. A separate instance is needed for
55
+ # each thread that needs to convert Creole to HTML.
56
+ #
57
+ # Inherit this to provide custom handling of links. The overrideable
58
+ # methods are: make_local_link
59
+ class CreoleParser
60
+
61
+ # Create a new CreoleParser instance.
62
+ def initialize
63
+ @base = nil
64
+ @allowed_schemes = [ 'http', 'https', 'ftp', 'ftps' ]
65
+ @uri_scheme_re = @allowed_schemes.join('|')
66
+ end
67
+
68
+ # Parse and convert the argument in Creole text to HTML and return
69
+ # the result. The resulting HTML does not contain <html> and
70
+ # <body> tags.
71
+ #
72
+ # Example:
73
+ #
74
+ # parser = CreoleParser.new
75
+ # parser.parse("**Hello //World//**")
76
+ # #=> "<p><strong>Hello <em>World</em></strong></p>"
77
+ def parse(string)
78
+ @out = ""
79
+ @strong = false
80
+ @p = false
81
+ @stack = []
82
+ parse_block(string)
83
+ return @out
84
+ end
85
+
86
+ # Escape any characters with special meaning in HTML using HTML
87
+ # entities.
88
+ private
89
+ def escape_html(string)
90
+ CGI::escapeHTML(string)
91
+ end
92
+
93
+ # Escape any characters with special meaning in URLs using URL
94
+ # encoding.
95
+ private
96
+ def escape_url(string)
97
+ CGI::escape(string)
98
+ end
99
+
100
+ private
101
+
102
+ def start_tag(tag)
103
+ @stack.push(tag)
104
+ @out << '<' << tag << '>'
105
+ end
106
+
107
+ def end_tag
108
+ @out << '</' << @stack.pop << '>'
109
+ end
110
+
111
+ def toggle_tag(tag, match)
112
+ if @stack.include?(tag)
113
+ if @stack.last == tag
114
+ end_tag
115
+ else
116
+ @out << escape_html(match)
117
+ end
118
+ else
119
+ start_tag(tag)
120
+ end
121
+ end
122
+
123
+ def end_paragraph
124
+ end_tag while !@stack.empty?
125
+ @p = false
126
+ end
127
+
128
+ def start_paragraph
129
+ if @p
130
+ @out << ' ' if @out[-1,1] != ' '
131
+ else
132
+ end_paragraph
133
+ start_tag('p')
134
+ @p = true
135
+ end
136
+ end
137
+
138
+ # Create anchor markup for direct links. This
139
+ # method can be overridden to generate custom
140
+ # markup, for example to add html additional attributes.
141
+ private
142
+ def make_direct_anchor(uri, text)
143
+ '<a href="' << escape_html(uri) << '">' << escape_html(text) << '</a>'
144
+ end
145
+
146
+ # Create anchor markup for explicit links. This
147
+ # method can be overridden to generate custom
148
+ # markup, for example to add html additional attributes.
149
+ private
150
+ def make_explicit_anchor(uri, text)
151
+ '<a href="' << escape_html(uri) << '">' << escape_html(text) << '</a>'
152
+ end
153
+
154
+ # Translate an explicit local link to a desired URL that is
155
+ # properly URL-escaped. The default behaviour is to convert local
156
+ # links directly, escaping any characters that have special
157
+ # meaning in URLs. Relative URLs in local links are not handled.
158
+ #
159
+ # Examples:
160
+ #
161
+ # make_local_link("LocalLink") #=> "LocalLink"
162
+ # make_local_link("/Foo/Bar") #=> "%2FFoo%2FBar"
163
+ #
164
+ # Must ensure that the result is properly URL-escaped. The caller
165
+ # will handle HTML escaping as necessary. HTML links will not be
166
+ # inserted if the function returns nil.
167
+ #
168
+ # Example custom behaviour:
169
+ #
170
+ # make_local_link("LocalLink") #=> "/LocalLink"
171
+ # make_local_link("Wikipedia:Bread") #=> "http://en.wikipedia.org/wiki/Bread"
172
+ private
173
+ def make_local_link(link) #:doc:
174
+ escape_url(link)
175
+ end
176
+
177
+ # Sanatize a direct url (e.g. http://wikipedia.org/). The default
178
+ # behaviour returns the original link as-is.
179
+ #
180
+ # Must ensure that the result is properly URL-escaped. The caller
181
+ # will handle HTML escaping as necessary. Links will not be
182
+ # converted to HTML links if the function returns link.
183
+ #
184
+ # Custom versions of this function in inherited classes can
185
+ # implement specific link handling behaviour, such as redirection
186
+ # to intermediate pages (for example, for notifing the user that
187
+ # he is leaving the site).
188
+ private
189
+ def make_direct_link(url) #:doc:
190
+ return url
191
+ end
192
+
193
+ # Sanatize and prefix image URLs. When images are encountered in
194
+ # Creole text, this function is called to obtain the actual URL of
195
+ # the image. The default behaviour is to return the image link
196
+ # as-is. No image tags are inserted if the function returns nil.
197
+ #
198
+ # Custom version of the method can be used to sanatize URLs
199
+ # (e.g. remove query-parts), inhibit off-site images, or add a
200
+ # base URL, for example:
201
+ #
202
+ # def make_image_link(url)
203
+ # URI.join("http://mywiki.org/images/", url)
204
+ # end
205
+ private
206
+ def make_image_link(url) #:doc:
207
+ return url
208
+ end
209
+
210
+ # Create image markup. This
211
+ # method can be overridden to generate custom
212
+ # markup, for example to add html additional attributes or
213
+ # to put divs around the imgs.
214
+ private
215
+ def make_image(uri, alt)
216
+ if alt
217
+ '<img src="' << escape_html(uri) << '" alt="' << escape_html(alt) << '"/>'
218
+ else
219
+ '<img src="' << escape_html(uri) << '"/>'
220
+ end
221
+ end
222
+
223
+ private
224
+ def make_explicit_link(link)
225
+ begin
226
+ uri = URI.parse(link)
227
+ return uri.to_s if uri.scheme && @allowed_schemes.include?(uri.scheme)
228
+ rescue URI::InvalidURIError
229
+ end
230
+ return make_local_link(link)
231
+ end
232
+
233
+ def parse_inline(str)
234
+ until str.empty?
235
+ case str
236
+ when /\A(\~)?((https?|ftps?):\/\/\S+?)(?=([,.?!:;"'\)])?(\s|$))/
237
+ if $1
238
+ @out << escape_html($2)
239
+ else
240
+ if uri = make_direct_link($2)
241
+ @out << make_direct_anchor(uri, $2)
242
+ else
243
+ @out << escape_html($&)
244
+ end
245
+ end
246
+ when /\A\[\[\s*([^|]*?)\s*(\|\s*(.*?))?\s*\]\]/m
247
+ link = $1
248
+ if uri = make_explicit_link(link)
249
+ @out << make_explicit_anchor(uri, $3 || link)
250
+ else
251
+ @out << escape_html($&)
252
+ end
253
+ when /\A\{\{\{(.*)\}\}\}/
254
+ @out << '<tt>' << escape_html($1) << '</tt>'
255
+ when /\A\{\{\s*(.*?)\s*(\|\s*(.*?)\s*)?\}\}/
256
+ if uri = make_image_link($1)
257
+ @out << make_image(uri, $3)
258
+ else
259
+ @out << escape_html($&)
260
+ end
261
+ when /\A~([^\s])/
262
+ @out << escape_html($1)
263
+ when /\A\w+/
264
+ @out << $&
265
+ when /\A\s+/
266
+ @out << ' ' if @out[-1,1] != ' '
267
+ when /\A\*\*/
268
+ toggle_tag 'strong', $&
269
+ when /\A\/\//
270
+ toggle_tag 'em', $&
271
+ when /\A\\\\/
272
+ @out << '<br/>'
273
+ when /./
274
+ @out << escape_html($&)
275
+ else
276
+ raise CreoleParseError, "Parse error at #{str[0,30].inspect}"
277
+ end
278
+ str = $'
279
+ end
280
+ end
281
+
282
+ def parse_table_row(str)
283
+ @out << '<tr>'
284
+ str.scan(/\s*\|(=)?\s*((\[\[.*?\]\]|\{\{.*?\}\}|[^|~]|~.)*)(?=\||$)/) do
285
+ if !$2.empty? || !$'.empty?
286
+ @out << ($1 ? '<th>' : '<td>')
287
+ parse_inline($2) if $2
288
+ end_tag while @stack.last != 'table'
289
+ @out << ($1 ? '</th>' : '</td>')
290
+ end
291
+ end
292
+ @out << '</tr>'
293
+ end
294
+
295
+ def make_nowikiblock(input)
296
+ input.gsub(/^ (?=\}\}\})/, '')
297
+ end
298
+
299
+ def ulol?(x); x == 'ul' || x == 'ol'; end
300
+
301
+ def parse_block(str)
302
+ until str.empty?
303
+ case str
304
+ when /\A\{\{\{\r?\n(.*?)\r?\n\}\}\}/m
305
+ end_paragraph
306
+ nowikiblock = make_nowikiblock($1)
307
+ @out << '<pre>' << escape_html(nowikiblock) << '</pre>'
308
+ when /\A\s*-{4,}\s*$/
309
+ end_paragraph
310
+ @out << '<hr/>'
311
+ when /\A\s*(={1,6})\s*(.*?)\s*=*\s*$(\r?\n)?/
312
+ end_paragraph
313
+ level = $1.size
314
+ @out << "<h#{level}>" << escape_html($2) << "</h#{level}>"
315
+ when /\A[ \t]*\|.*$(\r?\n)?/
316
+ if !@stack.include?('table')
317
+ end_paragraph
318
+ start_tag('table')
319
+ end
320
+ parse_table_row($&)
321
+ when /\A\s*$(\r?\n)?/
322
+ end_paragraph
323
+ when /\A(\s*([*#]+)\s*(.*?))$(\r?\n)?/
324
+ line, bullet, item = $1, $2, $3
325
+ tag = (bullet[0,1] == '*' ? 'ul' : 'ol')
326
+ if bullet[0,1] == '#' || bullet.size != 2 || @stack.find {|x| ulol?(x) }
327
+ count = @stack.select { |x| ulol?(x) }.size
328
+
329
+ while !@stack.empty? && count > bullet.size
330
+ count -= 1 if ulol?(@stack.last)
331
+ end_tag
332
+ end
333
+
334
+ end_tag while !@stack.empty? && @stack.last != 'li'
335
+
336
+ if @stack.last == 'li' && count == bullet.size
337
+ end_tag
338
+ if @stack.last != tag
339
+ end_tag
340
+ count -= 1
341
+ end
342
+ end
343
+
344
+ while count < bullet.size
345
+ start_tag tag
346
+ count += 1
347
+ start_tag 'li' if count < bullet.size
348
+ end
349
+
350
+ @p = true
351
+ start_tag('li')
352
+ parse_inline(item)
353
+ else
354
+ start_paragraph
355
+ parse_inline(line)
356
+ end
357
+ when /\A([ \t]*\S+.*?)$(\r?\n)?/
358
+ start_paragraph
359
+ parse_inline($1)
360
+ else
361
+ raise CreoleParseError, "Parse error at #{str[0,30].inspect}"
362
+ end
363
+ #p [$&, $']
364
+ str = $'
365
+ end
366
+ end_paragraph
367
+ return @out
368
+ end
369
+
370
+ end # class CreoleParser
371
+
372
+ end # module Creole
@@ -0,0 +1,15 @@
1
+ require 'test/unit'
2
+ require 'creole'
3
+ require 'cgi'
4
+ require 'testcases'
5
+
6
+ $strict = false
7
+
8
+ class TestC < Test::Unit::TestCase
9
+ include TestCases
10
+
11
+ def tc(html, creole)
12
+ output = Creole.creolize(creole)
13
+ assert html === output, "Parsing: #{creole.inspect}\nExpected: #{html.inspect}\n Was: #{output.inspect}"
14
+ end
15
+ end
@@ -0,0 +1,631 @@
1
+ require 'cgi'
2
+
3
+ # Test cases for the creole converter. These are included into the
4
+ # unittests, but is implemented as a separated module to be able to
5
+ # import them into demo wikis.
6
+ #
7
+ # Each test case should simply call the 'tc' method with the expected
8
+ # HTML and input Creole formatted text as arguments. The expected HTML
9
+ # should contain minimal amount of whitespace (only the absolutely
10
+ # required).
11
+
12
+ module TestCases
13
+ def escape_html(html)
14
+ CGI::escapeHTML(html)
15
+ end
16
+
17
+ def test_bold
18
+ # Creole1.0: Bold can be used inside paragraphs
19
+ tc "<p>This <strong>is</strong> bold</p>", "This **is** bold"
20
+ tc "<p>This <strong>is</strong> bold and <strong>bold</strong>ish</p>", "This **is** bold and **bold**ish"
21
+
22
+ # Creole1.0: Bold can be used inside list items
23
+ tc "<ul><li>This is <strong>bold</strong></li></ul>", "* This is **bold**"
24
+
25
+ # Creole1.0: Bold can be used inside table cells
26
+ tc("<table><tr><td>This is <strong>bold</strong></td></tr></table>",
27
+ "|This is **bold**|")
28
+
29
+ # Creole1.0: Links can appear inside bold text:
30
+ tc("<p>A bold link: <strong><a href=\"http://wikicreole.org/\">http://wikicreole.org/</a> nice!</strong></p>",
31
+ "A bold link: **http://wikicreole.org/ nice!**")
32
+
33
+ # Creole1.0: Bold will end at the end of paragraph
34
+ tc "<p>This <strong>is bold</strong></p>", "This **is bold"
35
+
36
+ # Creole1.0: Bold will end at the end of list items
37
+ tc("<ul><li>Item <strong>bold</strong></li><li>Item normal</li></ul>",
38
+ "* Item **bold\n* Item normal")
39
+
40
+ # Creole1.0: Bold will end at the end of table cells
41
+ tc("<table><tr><td>Item <strong>bold</strong></td><td>Another <strong>bold</strong></td></tr></table>",
42
+ "|Item **bold|Another **bold")
43
+
44
+ # Creole1.0: Bold should not cross paragraphs
45
+ tc("<p>This <strong>is</strong></p><p>bold<strong> maybe</strong></p>",
46
+ "This **is\n\nbold** maybe")
47
+
48
+ # Creole1.0-Implied: Bold should be able to cross lines
49
+ tc "<p>This <strong>is bold</strong></p>", "This **is\nbold**"
50
+ end
51
+
52
+ def test_italic
53
+ # Creole1.0: Italic can be used inside paragraphs
54
+ tc("<p>This <em>is</em> italic</p>",
55
+ "This //is// italic")
56
+ tc("<p>This <em>is</em> italic and <em>italic</em>ish</p>",
57
+ "This //is// italic and //italic//ish")
58
+
59
+ # Creole1.0: Italic can be used inside list items
60
+ tc "<ul><li>This is <em>italic</em></li></ul>", "* This is //italic//"
61
+
62
+ # Creole1.0: Italic can be used inside table cells
63
+ tc("<table><tr><td>This is <em>italic</em></td></tr></table>",
64
+ "|This is //italic//|")
65
+
66
+ # Creole1.0: Links can appear inside italic text:
67
+ tc("<p>A italic link: <em><a href=\"http://wikicreole.org/\">http://wikicreole.org/</a> nice!</em></p>",
68
+ "A italic link: //http://wikicreole.org/ nice!//")
69
+
70
+ # Creole1.0: Italic will end at the end of paragraph
71
+ tc "<p>This <em>is italic</em></p>", "This //is italic"
72
+
73
+ # Creole1.0: Italic will end at the end of list items
74
+ tc("<ul><li>Item <em>italic</em></li><li>Item normal</li></ul>",
75
+ "* Item //italic\n* Item normal")
76
+
77
+ # Creole1.0: Italic will end at the end of table cells
78
+ tc("<table><tr><td>Item <em>italic</em></td><td>Another <em>italic</em></td></tr></table>",
79
+ "|Item //italic|Another //italic")
80
+
81
+ # Creole1.0: Italic should not cross paragraphs
82
+ tc("<p>This <em>is</em></p><p>italic<em> maybe</em></p>",
83
+ "This //is\n\nitalic// maybe")
84
+
85
+ # Creole1.0-Implied: Italic should be able to cross lines
86
+ tc "<p>This <em>is italic</em></p>", "This //is\nitalic//"
87
+ end
88
+
89
+ def test_bold_italics
90
+ # Creole1.0: By example
91
+ tc "<p><strong><em>bold italics</em></strong></p>", "**//bold italics//**"
92
+
93
+ # Creole1.0: By example
94
+ tc "<p><em><strong>bold italics</strong></em></p>", "//**bold italics**//"
95
+
96
+ # Creole1.0: By example
97
+ tc "<p><em>This is <strong>also</strong> good.</em></p>", "//This is **also** good.//"
98
+ end
99
+
100
+ def test_headings
101
+ # Creole1.0: Only three differed sized levels of heading are required.
102
+ tc "<h1>Heading 1</h1>", "= Heading 1 ="
103
+ tc "<h2>Heading 2</h2>", "== Heading 2 =="
104
+ tc "<h3>Heading 3</h3>", "=== Heading 3 ==="
105
+ unless $strict
106
+ tc "<h4>Heading 4</h4>", "==== Heading 4 ===="
107
+ tc "<h5>Heading 5</h5>", "===== Heading 5 ====="
108
+ tc "<h6>Heading 6</h6>", "====== Heading 6 ======"
109
+ end
110
+
111
+ # Creole1.0: Closing (right-side) equal signs are optional
112
+ tc "<h1>Heading 1</h1>", "=Heading 1"
113
+ tc "<h2>Heading 2</h2>", "== Heading 2"
114
+ tc "<h3>Heading 3</h3>", " === Heading 3"
115
+
116
+ # Creole1.0: Closing (right-side) equal signs don't need to be balanced and don't impact the kind of heading generated
117
+ tc "<h1>Heading 1</h1>", "=Heading 1 ==="
118
+ tc "<h2>Heading 2</h2>", "== Heading 2 ="
119
+ tc "<h3>Heading 3</h3>", " === Heading 3 ==========="
120
+
121
+ # Creole1.0: Whitespace is allowed before the left-side equal signs.
122
+ tc "<h1>Heading 1</h1>", " \t= Heading 1 ="
123
+ tc "<h2>Heading 2</h2>", " \t== Heading 2 =="
124
+
125
+ # Creole1.0: Only white-space characters are permitted after the closing equal signs.
126
+ tc "<h1>Heading 1</h1>", " = Heading 1 = "
127
+ tc "<h2>Heading 2</h2>", " == Heading 2 == \t "
128
+
129
+ # !!Creole1.0 doesn't specify if text after closing equal signs
130
+ # !!becomes part of the heading or invalidates the entire heading.
131
+ # tc "<p> == Heading 2 == foo</p>", " == Heading 2 == foo"
132
+ unless $strict
133
+ tc "<h2>Heading 2 == foo</h2>", " == Heading 2 == foo"
134
+ end
135
+
136
+ # Creole1.0-Implied: Line must start with equal sign
137
+ tc "<p>foo = Heading 1 =</p>", "foo = Heading 1 ="
138
+ end
139
+
140
+ def test_links
141
+ # Creole1.0: Links
142
+ tc "<p><a href=\"link\">link</a></p>", "[[link]]"
143
+
144
+ # Creole1.0: Links can appear in paragraphs (i.e. inline item)
145
+ tc "<p>Hello, <a href=\"world\">world</a></p>", "Hello, [[world]]"
146
+
147
+ # Creole1.0: Named links
148
+ tc "<p><a href=\"MyBigPage\">Go to my page</a></p>", "[[MyBigPage|Go to my page]]"
149
+
150
+ # Creole1.0: URLs
151
+ tc "<p><a href=\"http://www.wikicreole.org/\">http://www.wikicreole.org/</a></p>", "[[http://www.wikicreole.org/]]"
152
+
153
+ # Creole1.0: Free-standing URL's should be turned into links
154
+ tc "<p><a href=\"http://www.wikicreole.org/\">http://www.wikicreole.org/</a></p>", "http://www.wikicreole.org/"
155
+
156
+ # Creole1.0: Single punctuation characters at the end of URLs
157
+ # should not be considered a part of the URL.
158
+ [',','.','?','!',':',';','\'','"'].each { |punct|
159
+ esc_punct = escape_html(punct)
160
+ tc "<p><a href=\"http://www.wikicreole.org/\">http://www.wikicreole.org/</a>#{esc_punct}</p>", "http://www.wikicreole.org/#{punct}"
161
+ }
162
+ # Creole1.0: Nameds URLs (by example)
163
+ tc("<p><a href=\"http://www.wikicreole.org/\">Visit the WikiCreole website</a></p>",
164
+ "[[http://www.wikicreole.org/|Visit the WikiCreole website]]")
165
+
166
+ unless $strict
167
+ # Parsing markup within a link is optional
168
+ tc "<p><a href=\"Weird+Stuff\">**Weird** //Stuff//</a></p>", "[[Weird Stuff|**Weird** //Stuff//]]"
169
+ end
170
+
171
+ # Inside bold
172
+ tc "<p><strong><a href=\"link\">link</a></strong></p>", "**[[link]]**"
173
+
174
+ # Whitespace inside [[ ]] should be ignored
175
+ tc("<p><a href=\"link\">link</a></p>", "[[ link ]]")
176
+ tc("<p><a href=\"link+me\">link me</a></p>", "[[ link me ]]")
177
+ tc("<p><a href=\"http://dot.com/\">dot.com</a></p>", "[[ http://dot.com/ \t| \t dot.com ]]")
178
+ tc("<p><a href=\"http://dot.com/\">dot.com</a></p>", "[[ http://dot.com/ | dot.com ]]")
179
+ end
180
+
181
+ def test_paragraph
182
+ # Creole1.0: One or more blank lines end paragraphs.
183
+ tc "<p>This is my text.</p><p>This is more text.</p>", "This is\nmy text.\n\nThis is\nmore text."
184
+ tc "<p>This is my text.</p><p>This is more text.</p>", "This is\nmy text.\n\n\nThis is\nmore text."
185
+ tc "<p>This is my text.</p><p>This is more text.</p>", "This is\nmy text.\n\n\n\nThis is\nmore text."
186
+
187
+ # Creole1.0: A list end paragraphs too.
188
+ tc "<p>Hello</p><ul><li>Item</li></ul>", "Hello\n* Item\n"
189
+
190
+ # Creole1.0: A table end paragraphs too.
191
+ tc "<p>Hello</p><table><tr><td>Cell</td></tr></table>", "Hello\n|Cell|"
192
+
193
+ # Creole1.0: A nowiki end paragraphs too.
194
+ tc "<p>Hello</p><pre>nowiki</pre>", "Hello\n{{{\nnowiki\n}}}\n"
195
+
196
+ unless $strict
197
+ # A heading ends a paragraph (not specced)
198
+ tc "<p>Hello</p><h1>Heading</h1>", "Hello\n= Heading =\n"
199
+ end
200
+ end
201
+
202
+ def test_linebreak
203
+ # Creole1.0: \\ (wiki-style) for line breaks.
204
+ tc "<p>This is the first line,<br/>and this is the second.</p>", "This is the first line,\\\\and this is the second."
205
+ end
206
+
207
+ def test_unordered_lists
208
+ # Creole1.0: List items begin with a * at the beginning of a line.
209
+ # Creole1.0: An item ends at the next *
210
+ tc "<ul><li>Item 1</li><li>Item 2</li><li>Item 3</li></ul>", "* Item 1\n *Item 2\n *\t\tItem 3\n"
211
+
212
+ # Creole1.0: Whitespace is optional before and after the *.
213
+ tc("<ul><li>Item 1</li><li>Item 2</li><li>Item 3</li></ul>",
214
+ " * Item 1\n*Item 2\n \t*\t\tItem 3\n")
215
+
216
+ # Creole1.0: A space is required if if the list element starts with bold text.
217
+ tc("<ul><li><ul><li><ul><li>Item 1</li></ul></li></ul></li></ul>", "***Item 1")
218
+ tc("<ul><li><strong>Item 1</strong></li></ul>", "* **Item 1")
219
+
220
+ # Creole1.0: An item ends at blank line
221
+ tc("<ul><li>Item</li></ul><p>Par</p>", "* Item\n\nPar\n")
222
+
223
+ # Creole1.0: An item ends at a heading
224
+ tc("<ul><li>Item</li></ul><h1>Heading</h1>", "* Item\n= Heading =\n")
225
+
226
+ # Creole1.0: An item ends at a table
227
+ tc("<ul><li>Item</li></ul><table><tr><td>Cell</td></tr></table>", "* Item\n|Cell|\n")
228
+
229
+ # Creole1.0: An item ends at a nowiki block
230
+ tc("<ul><li>Item</li></ul><pre>Code</pre>", "* Item\n{{{\nCode\n}}}\n")
231
+
232
+ # Creole1.0: An item can span multiple lines
233
+ tc("<ul><li>The quick brown fox jumps over lazy dog.</li><li>Humpty Dumpty sat on a wall.</li></ul>",
234
+ "* The quick\nbrown fox\n\tjumps over\nlazy dog.\n*Humpty Dumpty\nsat\t\non a wall.")
235
+
236
+ # Creole1.0: An item can contain line breaks
237
+ tc("<ul><li>The quick brown<br/>fox jumps over lazy dog.</li></ul>",
238
+ "* The quick brown\\\\fox jumps over lazy dog.")
239
+
240
+ # Creole1.0: Nested
241
+ tc "<ul><li>Item 1<ul><li>Item 2</li></ul></li><li>Item 3</li></ul>", "* Item 1\n **Item 2\n *\t\tItem 3\n"
242
+
243
+ # Creole1.0: Nested up to 5 levels
244
+ tc("<ul><li>Item 1<ul><li>Item 2<ul><li>Item 3<ul><li>Item 4<ul><li>Item 5</li></ul></li></ul></li></ul></li></ul></li></ul>",
245
+ "*Item 1\n**Item 2\n***Item 3\n****Item 4\n*****Item 5\n")
246
+
247
+ # Creole1.0: ** immediatly following a list element will be treated as a nested unordered element.
248
+ tc("<ul><li>Hello, World!<ul><li>Not bold</li></ul></li></ul>",
249
+ "*Hello,\nWorld!\n**Not bold\n")
250
+
251
+ # Creole1.0: ** immediatly following a list element will be treated as a nested unordered element.
252
+ tc("<ol><li>Hello, World!<ul><li>Not bold</li></ul></li></ol>",
253
+ "#Hello,\nWorld!\n**Not bold\n")
254
+
255
+ # Creole1.0: [...] otherwise it will be treated as the beginning of bold text.
256
+ tc("<ul><li>Hello, World!</li></ul><p><strong>Not bold</strong></p>",
257
+ "*Hello,\nWorld!\n\n**Not bold\n")
258
+ end
259
+
260
+ def test_ordered_lists
261
+ # Creole1.0: List items begin with a * at the beginning of a line.
262
+ # Creole1.0: An item ends at the next *
263
+ tc "<ol><li>Item 1</li><li>Item 2</li><li>Item 3</li></ol>", "# Item 1\n #Item 2\n #\t\tItem 3\n"
264
+
265
+ # Creole1.0: Whitespace is optional before and after the #.
266
+ tc("<ol><li>Item 1</li><li>Item 2</li><li>Item 3</li></ol>",
267
+ " # Item 1\n#Item 2\n \t#\t\tItem 3\n")
268
+
269
+ # Creole1.0: A space is required if if the list element starts with bold text.
270
+ tc("<ol><li><ol><li><ol><li>Item 1</li></ol></li></ol></li></ol>", "###Item 1")
271
+ tc("<ol><li><strong>Item 1</strong></li></ol>", "# **Item 1")
272
+
273
+ # Creole1.0: An item ends at blank line
274
+ tc("<ol><li>Item</li></ol><p>Par</p>", "# Item\n\nPar\n")
275
+
276
+ # Creole1.0: An item ends at a heading
277
+ tc("<ol><li>Item</li></ol><h1>Heading</h1>", "# Item\n= Heading =\n")
278
+
279
+ # Creole1.0: An item ends at a table
280
+ tc("<ol><li>Item</li></ol><table><tr><td>Cell</td></tr></table>", "# Item\n|Cell|\n")
281
+
282
+ # Creole1.0: An item ends at a nowiki block
283
+ tc("<ol><li>Item</li></ol><pre>Code</pre>", "# Item\n{{{\nCode\n}}}\n")
284
+
285
+ # Creole1.0: An item can span multiple lines
286
+ tc("<ol><li>The quick brown fox jumps over lazy dog.</li><li>Humpty Dumpty sat on a wall.</li></ol>",
287
+ "# The quick\nbrown fox\n\tjumps over\nlazy dog.\n#Humpty Dumpty\nsat\t\non a wall.")
288
+
289
+ # Creole1.0: An item can contain line breaks
290
+ tc("<ol><li>The quick brown<br/>fox jumps over lazy dog.</li></ol>",
291
+ "# The quick brown\\\\fox jumps over lazy dog.")
292
+
293
+ # Creole1.0: Nested
294
+ tc "<ol><li>Item 1<ol><li>Item 2</li></ol></li><li>Item 3</li></ol>", "# Item 1\n ##Item 2\n #\t\tItem 3\n"
295
+
296
+ # Creole1.0: Nested up to 5 levels
297
+ tc("<ol><li>Item 1<ol><li>Item 2<ol><li>Item 3<ol><li>Item 4<ol><li>Item 5</li></ol></li></ol></li></ol></li></ol></li></ol>",
298
+ "#Item 1\n##Item 2\n###Item 3\n####Item 4\n#####Item 5\n")
299
+
300
+ # Creole1.0_Infered: The two-bullet rule only applies to **.
301
+ tc("<ol><li><ol><li>Item</li></ol></li></ol>", "##Item")
302
+ end
303
+
304
+ def test_ordered_lists2
305
+ tc "<ol><li>Item 1</li><li>Item 2</li><li>Item 3</li></ol>", "# Item 1\n #Item 2\n #\t\tItem 3\n"
306
+ # Nested
307
+ tc "<ol><li>Item 1<ol><li>Item 2</li></ol></li><li>Item 3</li></ol>", "# Item 1\n ##Item 2\n #\t\tItem 3\n"
308
+ # Multiline
309
+ tc "<ol><li>Item 1 on multiple lines</li></ol>", "# Item 1\non multiple lines"
310
+ end
311
+
312
+ def test_ambiguity_mixed_lists
313
+ # ol following ul
314
+ tc("<ul><li>uitem</li></ul><ol><li>oitem</li></ol>", "*uitem\n#oitem\n")
315
+
316
+ # ul following ol
317
+ tc("<ol><li>uitem</li></ol><ul><li>oitem</li></ul>", "#uitem\n*oitem\n")
318
+
319
+ # 2ol following ul
320
+ tc("<ul><li>uitem<ol><li>oitem</li></ol></li></ul>", "*uitem\n##oitem\n")
321
+
322
+ # 2ul following ol
323
+ tc("<ol><li>uitem<ul><li>oitem</li></ul></li></ol>", "#uitem\n**oitem\n")
324
+
325
+ # 3ol following 3ul
326
+ tc("<ul><li><ul><li><ul><li>uitem</li></ul><ol><li>oitem</li></ol></li></ul></li></ul>", "***uitem\n###oitem\n")
327
+
328
+ # 2ul following 2ol
329
+ tc("<ol><li><ol><li>uitem</li></ol><ul><li>oitem</li></ul></li></ol>", "##uitem\n**oitem\n")
330
+
331
+ # ol following 2ol
332
+ tc("<ol><li><ol><li>oitem1</li></ol></li><li>oitem2</li></ol>", "##oitem1\n#oitem2\n")
333
+ # ul following 2ol
334
+ tc("<ol><li><ol><li>oitem1</li></ol></li></ol><ul><li>oitem2</li></ul>", "##oitem1\n*oitem2\n")
335
+ end
336
+
337
+ def test_ambiguity_italics_and_url
338
+ # Uncommon URL schemes should not be parsed as URLs
339
+ tc("<p>This is what can go wrong:<em>this should be an italic text</em>.</p>",
340
+ "This is what can go wrong://this should be an italic text//.")
341
+
342
+ # A link inside italic text
343
+ tc("<p>How about <em>a link, like <a href=\"http://example.org\">http://example.org</a>, in italic</em> text?</p>",
344
+ "How about //a link, like http://example.org, in italic// text?")
345
+
346
+ # Another test from Creole Wiki
347
+ tc("<p>Formatted fruits, for example:<em>apples</em>, oranges, <strong>pears</strong> ...</p>",
348
+ "Formatted fruits, for example://apples//, oranges, **pears** ...")
349
+
350
+ tc("<p>Blablabala (<a href=\"http://blub.de\">http://blub.de</a>)</p>",
351
+ "Blablabala (http://blub.de)")
352
+ end
353
+
354
+ def test_ambiguity_bold_and_lists
355
+ tc "<p><strong> bold text </strong></p>", "** bold text **"
356
+ tc "<p> <strong> bold text </strong></p>", " ** bold text **"
357
+ end
358
+
359
+ def test_nowiki
360
+ # ... works as block
361
+ tc "<pre>Hello</pre>", "{{{\nHello\n}}}\n"
362
+
363
+ # ... works inline
364
+ tc "<p>Hello <tt>world</tt>.</p>", "Hello {{{world}}}."
365
+
366
+ # Creole1.0: No wiki markup is interpreted inbetween
367
+ tc "<pre>**Hello**</pre>", "{{{\n**Hello**\n}}}\n"
368
+
369
+ # Creole1.0: Leading whitespaces are not permitted
370
+ tc("<p> {{{ Hello }}}</p>", " {{{\nHello\n}}}")
371
+ tc("<p>{{{ Hello }}}</p>", "{{{\nHello\n }}}")
372
+
373
+ # Assumed: Should preserve whitespace
374
+ tc("<pre> \t Hello, \t \n \t World \t </pre>",
375
+ "{{{\n \t Hello, \t \n \t World \t \n}}}\n")
376
+
377
+ # In preformatted blocks ... one leading space is removed
378
+ tc("<pre>nowikiblock\n}}}</pre>", "{{{\nnowikiblock\n }}}\n}}}\n")
379
+
380
+ # In inline nowiki, any trailing closing brace is included in the span
381
+ tc("<p>this is <tt>nowiki}</tt></p>", "this is {{{nowiki}}}}")
382
+ tc("<p>this is <tt>nowiki}}</tt></p>", "this is {{{nowiki}}}}}")
383
+ tc("<p>this is <tt>nowiki}}}</tt></p>", "this is {{{nowiki}}}}}}")
384
+ tc("<p>this is <tt>nowiki}}}}</tt></p>", "this is {{{nowiki}}}}}}}")
385
+ end
386
+
387
+ def test_html_escaping
388
+ # Special HTML chars should be escaped
389
+ tc("<p>&lt;b&gt;not bold&lt;/b&gt;</p>", "<b>not bold</b>")
390
+
391
+ # Image tags should be escape
392
+ tc("<p><img src=\"image.jpg\" alt=\"&quot;tag&quot;\"/></p>", "{{image.jpg|\"tag\"}}")
393
+
394
+ # Malicious links should not be converted.
395
+ tc("<p><a href=\"javascript%3Aalert%28%22Boo%21%22%29\">Click</a></p>", "[[javascript:alert(\"Boo!\")|Click]]")
396
+ end
397
+
398
+ def test_escape
399
+ tc "<p>** Not Bold **</p>", "~** Not Bold ~**"
400
+ tc "<p>// Not Italic //</p>", "~// Not Italic ~//"
401
+ tc "<p>* Not Bullet</p>", "~* Not Bullet"
402
+ # Following char is not a blank (space or line feed)
403
+ tc "<p>Hello ~ world</p>", "Hello ~ world\n"
404
+ tc "<p>Hello ~ world</p>", "Hello ~\nworld\n"
405
+ # Not escaping inside URLs (Creole1.0 not clear on this)
406
+ tc "<p><a href=\"http://example.org/~user/\">http://example.org/~user/</a></p>", "http://example.org/~user/"
407
+
408
+ # Escaping links
409
+ tc "<p>http://www.wikicreole.org/</p>", "~http://www.wikicreole.org/"
410
+ end
411
+
412
+ def test_horizontal_rule
413
+ # Creole: Four hyphens make a horizontal rule
414
+ tc "<hr/>", "----"
415
+
416
+ # Creole1.0: Whitespace around them is allowed
417
+ tc "<hr/>", " ----"
418
+ tc "<hr/>", "---- "
419
+ tc "<hr/>", " ---- "
420
+ tc "<hr/>", " \t ---- \t "
421
+
422
+ # Creole1.0: Nothing else than hyphens and whitespace is "allowed"
423
+ tc "<p>foo ----</p>", "foo ----\n"
424
+ tc "<p>---- foo</p>", "---- foo\n"
425
+
426
+ # Creole1.0: [...] no whitespace is allowed between them
427
+ tc "<p> -- -- </p>", " -- -- "
428
+ tc "<p> -- -- </p>", " --\t-- "
429
+ end
430
+
431
+ def test_table
432
+ tc "<table><tr><td>Hello, World!</td></tr></table>", "|Hello, World!|"
433
+ # Multiple columns
434
+ tc "<table><tr><td>c1</td><td>c2</td><td>c3</td></tr></table>", "|c1|c2|c3|"
435
+ # Multiple rows
436
+ tc "<table><tr><td>c11</td><td>c12</td></tr><tr><td>c21</td><td>c22</td></tr></table>", "|c11|c12|\n|c21|c22|\n"
437
+ # End pipe is optional
438
+ tc "<table><tr><td>c1</td><td>c2</td><td>c3</td></tr></table>", "|c1|c2|c3"
439
+ # Empty cells
440
+ tc "<table><tr><td>c1</td><td></td><td>c3</td></tr></table>", "|c1||c3"
441
+ # Escaping cell separator
442
+ tc "<table><tr><td>c1|c2</td><td>c3</td></tr></table>", "|c1~|c2|c3"
443
+ # Escape in last cell + empty cell
444
+ tc "<table><tr><td>c1</td><td>c2|</td></tr></table>", "|c1|c2~|"
445
+ tc "<table><tr><td>c1</td><td>c2|</td></tr></table>", "|c1|c2~||"
446
+ tc "<table><tr><td>c1</td><td>c2|</td><td></td></tr></table>", "|c1|c2~|||"
447
+ # Equal sign after pipe make a header
448
+ tc "<table><tr><th>Header</th></tr></table>", "|=Header|"
449
+
450
+ tc "<table><tr><td>c1</td><td><a href=\"Link\">Link text</a></td><td><img src=\"Image\" alt=\"Image text\"/></td></tr></table>", "|c1|[[Link|Link text]]|{{Image|Image text}}|"
451
+ end
452
+
453
+ def test_following_table
454
+ # table followed by heading
455
+ tc("<table><tr><td>table</td></tr></table><h1>heading</h1>", "|table|\n=heading=\n")
456
+ tc("<table><tr><td>table</td></tr></table><h1>heading</h1>", "|table|\n\n=heading=\n")
457
+ # table followed by paragraph
458
+ tc("<table><tr><td>table</td></tr></table><p>par</p>", "|table|\npar\n")
459
+ tc("<table><tr><td>table</td></tr></table><p>par</p>", "|table|\n\npar\n")
460
+ # table followed by unordered list
461
+ tc("<table><tr><td>table</td></tr></table><ul><li>item</li></ul>", "|table|\n*item\n")
462
+ tc("<table><tr><td>table</td></tr></table><ul><li>item</li></ul>", "|table|\n\n*item\n")
463
+ # table followed by ordered list
464
+ tc("<table><tr><td>table</td></tr></table><ol><li>item</li></ol>", "|table|\n#item\n")
465
+ tc("<table><tr><td>table</td></tr></table><ol><li>item</li></ol>", "|table|\n\n#item\n")
466
+ # table followed by horizontal rule
467
+ tc("<table><tr><td>table</td></tr></table><hr/>", "|table|\n----\n")
468
+ tc("<table><tr><td>table</td></tr></table><hr/>", "|table|\n\n----\n")
469
+ # table followed by nowiki block
470
+ tc("<table><tr><td>table</td></tr></table><pre>pre</pre>", "|table|\n{{{\npre\n}}}\n")
471
+ tc("<table><tr><td>table</td></tr></table><pre>pre</pre>", "|table|\n\n{{{\npre\n}}}\n")
472
+ # table followed by table
473
+ tc("<table><tr><td>table</td></tr><tr><td>table</td></tr></table>", "|table|\n|table|\n")
474
+ tc("<table><tr><td>table</td></tr></table><table><tr><td>table</td></tr></table>", "|table|\n\n|table|\n")
475
+ end
476
+
477
+ def test_following_heading
478
+ # heading
479
+ tc("<h1>heading1</h1><h1>heading2</h1>", "=heading1=\n=heading2\n")
480
+ tc("<h1>heading1</h1><h1>heading2</h1>", "=heading1=\n\n=heading2\n")
481
+ # paragraph
482
+ tc("<h1>heading</h1><p>par</p>", "=heading=\npar\n")
483
+ tc("<h1>heading</h1><p>par</p>", "=heading=\n\npar\n")
484
+ # unordered list
485
+ tc("<h1>heading</h1><ul><li>item</li></ul>", "=heading=\n*item\n")
486
+ tc("<h1>heading</h1><ul><li>item</li></ul>", "=heading=\n\n*item\n")
487
+ # ordered list
488
+ tc("<h1>heading</h1><ol><li>item</li></ol>", "=heading=\n#item\n")
489
+ tc("<h1>heading</h1><ol><li>item</li></ol>", "=heading=\n\n#item\n")
490
+ # horizontal rule
491
+ tc("<h1>heading</h1><hr/>", "=heading=\n----\n")
492
+ tc("<h1>heading</h1><hr/>", "=heading=\n\n----\n")
493
+ # nowiki block
494
+ tc("<h1>heading</h1><pre>nowiki</pre>", "=heading=\n{{{\nnowiki\n}}}\n")
495
+ tc("<h1>heading</h1><pre>nowiki</pre>", "=heading=\n\n{{{\nnowiki\n}}}\n")
496
+ # table
497
+ tc("<h1>heading</h1><table><tr><td>table</td></tr></table>", "=heading=\n|table|\n")
498
+ tc("<h1>heading</h1><table><tr><td>table</td></tr></table>", "=heading=\n\n|table|\n")
499
+ end
500
+
501
+ def test_following_paragraph
502
+ # heading
503
+ tc("<p>par</p><h1>heading</h1>", "par\n=heading=")
504
+ tc("<p>par</p><h1>heading</h1>", "par\n\n=heading=")
505
+ # paragraph
506
+ tc("<p>par par</p>", "par\npar\n")
507
+ tc("<p>par</p><p>par</p>", "par\n\npar\n")
508
+ # unordered
509
+ tc("<p>par</p><ul><li>item</li></ul>", "par\n*item")
510
+ tc("<p>par</p><ul><li>item</li></ul>", "par\n\n*item")
511
+ # ordered
512
+ tc("<p>par</p><ol><li>item</li></ol>", "par\n#item\n")
513
+ tc("<p>par</p><ol><li>item</li></ol>", "par\n\n#item\n")
514
+ # horizontal
515
+ tc("<p>par</p><hr/>", "par\n----\n")
516
+ tc("<p>par</p><hr/>", "par\n\n----\n")
517
+ # nowiki
518
+ tc("<p>par</p><pre>nowiki</pre>", "par\n{{{\nnowiki\n}}}\n")
519
+ tc("<p>par</p><pre>nowiki</pre>", "par\n\n{{{\nnowiki\n}}}\n")
520
+ # table
521
+ tc("<p>par</p><table><tr><td>table</td></tr></table>", "par\n|table|\n")
522
+ tc("<p>par</p><table><tr><td>table</td></tr></table>", "par\n\n|table|\n")
523
+ end
524
+
525
+ def test_following_unordered_list
526
+ # heading
527
+ tc("<ul><li>item</li></ul><h1>heading</h1>", "*item\n=heading=")
528
+ tc("<ul><li>item</li></ul><h1>heading</h1>", "*item\n\n=heading=")
529
+ # paragraph
530
+ tc("<ul><li>item par</li></ul>", "*item\npar\n") # items may span multiple lines
531
+ tc("<ul><li>item</li></ul><p>par</p>", "*item\n\npar\n")
532
+ # unordered
533
+ tc("<ul><li>item</li><li>item</li></ul>", "*item\n*item\n")
534
+ tc("<ul><li>item</li></ul><ul><li>item</li></ul>", "*item\n\n*item\n")
535
+ # ordered
536
+ tc("<ul><li>item</li></ul><ol><li>item</li></ol>", "*item\n#item\n")
537
+ tc("<ul><li>item</li></ul><ol><li>item</li></ol>", "*item\n\n#item\n")
538
+ # horizontal rule
539
+ tc("<ul><li>item</li></ul><hr/>", "*item\n----\n")
540
+ tc("<ul><li>item</li></ul><hr/>", "*item\n\n----\n")
541
+ # nowiki
542
+ tc("<ul><li>item</li></ul><pre>nowiki</pre>", "*item\n{{{\nnowiki\n}}}\n")
543
+ tc("<ul><li>item</li></ul><pre>nowiki</pre>", "*item\n\n{{{\nnowiki\n}}}\n")
544
+ # table
545
+ tc("<ul><li>item</li></ul><table><tr><td>table</td></tr></table>", "*item\n|table|\n")
546
+ tc("<ul><li>item</li></ul><table><tr><td>table</td></tr></table>", "*item\n\n|table|\n")
547
+ end
548
+
549
+ def test_following_ordered_list
550
+ # heading
551
+ tc("<ol><li>item</li></ol><h1>heading</h1>", "#item\n=heading=")
552
+ tc("<ol><li>item</li></ol><h1>heading</h1>", "#item\n\n=heading=")
553
+ # paragraph
554
+ tc("<ol><li>item par</li></ol>", "#item\npar\n") # items may span multiple lines
555
+ tc("<ol><li>item</li></ol><p>par</p>", "#item\n\npar\n")
556
+ # unordered
557
+ tc("<ol><li>item</li></ol><ul><li>item</li></ul>", "#item\n*item\n")
558
+ tc("<ol><li>item</li></ol><ul><li>item</li></ul>", "#item\n\n*item\n")
559
+ # ordered
560
+ tc("<ol><li>item</li><li>item</li></ol>", "#item\n#item\n")
561
+ tc("<ol><li>item</li></ol><ol><li>item</li></ol>", "#item\n\n#item\n")
562
+ # horizontal role
563
+ tc("<ol><li>item</li></ol><hr/>", "#item\n----\n")
564
+ tc("<ol><li>item</li></ol><hr/>", "#item\n\n----\n")
565
+ # nowiki
566
+ tc("<ol><li>item</li></ol><pre>nowiki</pre>", "#item\n{{{\nnowiki\n}}}\n")
567
+ tc("<ol><li>item</li></ol><pre>nowiki</pre>", "#item\n\n{{{\nnowiki\n}}}\n")
568
+ # table
569
+ tc("<ol><li>item</li></ol><table><tr><td>table</td></tr></table>", "#item\n|table|\n")
570
+ tc("<ol><li>item</li></ol><table><tr><td>table</td></tr></table>", "#item\n\n|table|\n")
571
+ end
572
+
573
+ def test_following_horizontal_rule
574
+ # heading
575
+ tc("<hr/><h1>heading</h1>", "----\n=heading=")
576
+ tc("<hr/><h1>heading</h1>", "----\n\n=heading=")
577
+ # paragraph
578
+ tc("<hr/><p>par</p>", "----\npar\n")
579
+ tc("<hr/><p>par</p>", "----\n\npar\n")
580
+ # unordered
581
+ tc("<hr/><ul><li>item</li></ul>", "----\n*item")
582
+ tc("<hr/><ul><li>item</li></ul>", "----\n*item")
583
+ # ordered
584
+ tc("<hr/><ol><li>item</li></ol>", "----\n#item")
585
+ tc("<hr/><ol><li>item</li></ol>", "----\n#item")
586
+ # horizontal
587
+ tc("<hr/><hr/>", "----\n----\n")
588
+ tc("<hr/><hr/>", "----\n\n----\n")
589
+ # nowiki
590
+ tc("<hr/><pre>nowiki</pre>", "----\n{{{\nnowiki\n}}}\n")
591
+ tc("<hr/><pre>nowiki</pre>", "----\n\n{{{\nnowiki\n}}}\n")
592
+ # table
593
+ tc("<hr/><table><tr><td>table</td></tr></table>", "----\n|table|\n")
594
+ tc("<hr/><table><tr><td>table</td></tr></table>", "----\n\n|table|\n")
595
+ end
596
+
597
+ def test_following_nowiki_block
598
+ # heading
599
+ tc("<pre>nowiki</pre><h1>heading</h1>", "{{{\nnowiki\n}}}\n=heading=")
600
+ tc("<pre>nowiki</pre><h1>heading</h1>", "{{{\nnowiki\n}}}\n\n=heading=")
601
+ # paragraph
602
+ tc("<pre>nowiki</pre><p>par</p>", "{{{\nnowiki\n}}}\npar")
603
+ tc("<pre>nowiki</pre><p>par</p>", "{{{\nnowiki\n}}}\n\npar")
604
+ # unordered
605
+ tc("<pre>nowiki</pre><ul><li>item</li></ul>", "{{{\nnowiki\n}}}\n*item\n")
606
+ tc("<pre>nowiki</pre><ul><li>item</li></ul>", "{{{\nnowiki\n}}}\n\n*item\n")
607
+ # ordered
608
+ tc("<pre>nowiki</pre><ol><li>item</li></ol>", "{{{\nnowiki\n}}}\n#item\n")
609
+ tc("<pre>nowiki</pre><ol><li>item</li></ol>", "{{{\nnowiki\n}}}\n\n#item\n")
610
+ # horizontal
611
+ tc("<pre>nowiki</pre><hr/>", "{{{\nnowiki\n}}}\n----\n")
612
+ tc("<pre>nowiki</pre><hr/>", "{{{\nnowiki\n}}}\n\n----\n")
613
+ # nowiki
614
+ tc("<pre>nowiki</pre><pre>nowiki</pre>", "{{{\nnowiki\n}}}\n{{{\nnowiki\n}}}\n")
615
+ tc("<pre>nowiki</pre><pre>nowiki</pre>", "{{{\nnowiki\n}}}\n\n{{{\nnowiki\n}}}\n")
616
+ # table
617
+ tc("<pre>nowiki</pre><table><tr><td>table</td></tr></table>", "{{{\nnowiki\n}}}\n|table|\n")
618
+ tc("<pre>nowiki</pre><table><tr><td>table</td></tr></table>", "{{{\nnowiki\n}}}\n\n|table|\n")
619
+ end
620
+
621
+ def test_image
622
+ tc("<p><img src=\"image.jpg\"/></p>", "{{image.jpg}}")
623
+ tc("<p><img src=\"image.jpg\" alt=\"tag\"/></p>", "{{image.jpg|tag}}")
624
+ tc("<p><img src=\"http://example.org/image.jpg\"/></p>", "{{http://example.org/image.jpg}}")
625
+ end
626
+
627
+ def test_bold_combo
628
+ tc("<p><strong>bold and</strong></p><table><tr><td>table</td></tr></table><p>end<strong></strong></p>",
629
+ "**bold and\n|table|\nend**")
630
+ end
631
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: creole
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.3
5
+ platform: ruby
6
+ authors:
7
+ - Lars Christensen
8
+ - Daniel Mendler
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-02-16 00:00:00 +01:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: hoe
18
+ type: :development
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: 1.8.3
25
+ version:
26
+ description: Creole is a Creole-to-HTML converter for Creole, the lightwight markup language (http://wikicreole.org/).
27
+ email:
28
+ - larsch@belunktum.dk
29
+ - mail@daniel-mendler.de
30
+ executables: []
31
+
32
+ extensions: []
33
+
34
+ extra_rdoc_files:
35
+ - Manifest.txt
36
+ - README.txt
37
+ files:
38
+ - Manifest.txt
39
+ - README.txt
40
+ - Rakefile
41
+ - lib/creole.rb
42
+ - test/test_creole.rb
43
+ - test/testcases.rb
44
+ has_rdoc: true
45
+ homepage: http://github.com/minad/creole
46
+ post_install_message:
47
+ rdoc_options:
48
+ - --main
49
+ - README.txt
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ requirements: []
65
+
66
+ rubyforge_project: creole
67
+ rubygems_version: 1.3.1
68
+ signing_key:
69
+ specification_version: 2
70
+ summary: Creole is a Creole-to-HTML converter for Creole, the lightwight markup language (http://wikicreole.org/).
71
+ test_files:
72
+ - test/test_creole.rb