minad-creole 0.2

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,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,10 @@
1
+ require 'hoe'
2
+
3
+ $:.unshift 'lib'
4
+ require 'creole'
5
+
6
+ Hoe.new "creole", Creole::VERSION do |creole|
7
+ creole.developer 'Lars Christensen', 'larsch@belunktum.dk'
8
+ creole.developer 'Daniel Mendler', 'mail@daniel-mendler.de'
9
+ end
10
+
@@ -0,0 +1,371 @@
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.2"
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
+ def toggle_tag(tag, match)
102
+ if @stack.include?(tag)
103
+ if @stack.last == tag
104
+ @stack.pop
105
+ @out << '</' << tag << '>'
106
+ else
107
+ @out << escape_html(match)
108
+ end
109
+ else
110
+ @stack.push(tag)
111
+ @out << '<' << tag << '>'
112
+ end
113
+ end
114
+
115
+ def end_paragraph
116
+ while tag = @stack.pop
117
+ @out << "</#{tag}>"
118
+ end
119
+ @p = false
120
+ end
121
+
122
+ def start_paragraph
123
+ if not @p
124
+ end_paragraph
125
+ @out << '<p>'
126
+ @stack.push('p')
127
+ @p = true
128
+ else
129
+ @out << ' ' unless @out[-1,1] == ' '
130
+ end
131
+ end
132
+
133
+ # Create anchor markup for direct links. This
134
+ # method can be overridden to generate custom
135
+ # markup, for example to add html additional attributes.
136
+ private
137
+ def make_direct_anchor(uri, text)
138
+ '<a href="' << escape_html(uri) << '">' << escape_html(text) << '</a>'
139
+ end
140
+
141
+ # Create anchor markup for explicit links. This
142
+ # method can be overridden to generate custom
143
+ # markup, for example to add html additional attributes.
144
+ private
145
+ def make_explicit_anchor(uri, text)
146
+ '<a href="' << escape_html(uri) << '">' << escape_html(text) << '</a>'
147
+ end
148
+
149
+ # Translate an explicit local link to a desired URL that is
150
+ # properly URL-escaped. The default behaviour is to convert local
151
+ # links directly, escaping any characters that have special
152
+ # meaning in URLs. Relative URLs in local links are not handled.
153
+ #
154
+ # Examples:
155
+ #
156
+ # make_local_link("LocalLink") #=> "LocalLink"
157
+ # make_local_link("/Foo/Bar") #=> "%2FFoo%2FBar"
158
+ #
159
+ # Must ensure that the result is properly URL-escaped. The caller
160
+ # will handle HTML escaping as necessary. HTML links will not be
161
+ # inserted if the function returns nil.
162
+ #
163
+ # Example custom behaviour:
164
+ #
165
+ # make_local_link("LocalLink") #=> "/LocalLink"
166
+ # make_local_link("Wikipedia:Bread") #=> "http://en.wikipedia.org/wiki/Bread"
167
+ private
168
+ def make_local_link(link) #:doc:
169
+ escape_url(link)
170
+ end
171
+
172
+ # Sanatize a direct url (e.g. http://wikipedia.org/). The default
173
+ # behaviour returns the original link as-is.
174
+ #
175
+ # Must ensure that the result is properly URL-escaped. The caller
176
+ # will handle HTML escaping as necessary. Links will not be
177
+ # converted to HTML links if the function returns link.
178
+ #
179
+ # Custom versions of this function in inherited classes can
180
+ # implement specific link handling behaviour, such as redirection
181
+ # to intermediate pages (for example, for notifing the user that
182
+ # he is leaving the site).
183
+ private
184
+ def make_direct_link(url) #:doc:
185
+ return url
186
+ end
187
+
188
+ # Sanatize and prefix image URLs. When images are encountered in
189
+ # Creole text, this function is called to obtain the actual URL of
190
+ # the image. The default behaviour is to return the image link
191
+ # as-is. No image tags are inserted if the function returns nil.
192
+ #
193
+ # Custom version of the method can be used to sanatize URLs
194
+ # (e.g. remove query-parts), inhibit off-site images, or add a
195
+ # base URL, for example:
196
+ #
197
+ # def make_image_link(url)
198
+ # URI.join("http://mywiki.org/images/", url)
199
+ # end
200
+ private
201
+ def make_image_link(url) #:doc:
202
+ return url
203
+ end
204
+
205
+ # Create image markup. This
206
+ # method can be overridden to generate custom
207
+ # markup, for example to add html additional attributes or
208
+ # to put divs around the imgs.
209
+ private
210
+ def make_image(uri, alt)
211
+ if alt
212
+ '<img src="' << escape_html(uri) << '" alt="' << escape_html(alt) << '"/>'
213
+ else
214
+ '<img src="' << escape_html(uri) << '"/>'
215
+ end
216
+ end
217
+
218
+ private
219
+ def make_explicit_link(link)
220
+ begin
221
+ uri = URI.parse(link)
222
+ if uri.scheme and @allowed_schemes.include?(uri.scheme)
223
+ return uri.to_s
224
+ end
225
+ rescue URI::InvalidURIError
226
+ end
227
+ return make_local_link(link)
228
+ end
229
+
230
+ def parse_inline(str)
231
+ until str.empty?
232
+ case str
233
+ when /\A\r?\n/
234
+ return
235
+ when /\A(\~)?((https?|ftps?):\/\/\S+?)(?=([,.?!:;"'])?(\s|$))/
236
+ if $1
237
+ @out << escape_html($2)
238
+ else
239
+ if uri = make_direct_link($2)
240
+ @out << make_direct_anchor(uri, $2)
241
+ else
242
+ @out << escape_html($&)
243
+ end
244
+ end
245
+ when /\A\[\[\s*([^|]*?)\s*(\|\s*(.*?))?\s*\]\]/m
246
+ link = $1
247
+ if uri = make_explicit_link(link)
248
+ @out << make_explicit_anchor(uri, $3 || link)
249
+ else
250
+ @out << escape_html($&)
251
+ end
252
+ when /\A[^\/\\*\s{}~]+/
253
+ @out << escape_html($&)
254
+ when /\A\{\{\{(.*)\}\}\}/
255
+ @out << '<tt>' << escape_html($1) << '</tt>'
256
+ when /\A\{\{\s*(.*?)\s*(\|\s*(.*?)\s*)?\}\}/ # (|\s*(.*?)\s*)?*\}\}/
257
+ if uri = make_image_link($1)
258
+ @out << make_image(uri, $3)
259
+ else
260
+ @out << escape_html($&)
261
+ end
262
+ when /\A~([^\s])/
263
+ @out << escape_html($1)
264
+ when /\A[ \t]+/
265
+ @out << ' ' unless @out[-1,1] == ' '
266
+ when /\A\*\*/
267
+ toggle_tag 'strong', $&
268
+ when /\A\/\//
269
+ toggle_tag 'em', $&
270
+ when /\A\\\\/
271
+ @out << '<br/>'
272
+ when /./
273
+ @out << escape_html($&)
274
+ else
275
+ raise CreoleParseError, "Parse error at #{str[0,30].inspect}"
276
+ end
277
+ # p [$&, $']
278
+ str = $'
279
+ end
280
+ end
281
+
282
+ def parse_table_row(str)
283
+ @out << '<tr>'
284
+ str.scan(/\s*\|(=)?\s*(([^|~]|~.)*)(?=\||$)/) {
285
+ unless $2.empty? and $'.empty?
286
+ @out << ($1 ? '<th>' : '<td>')
287
+ parse_inline($2) if $2
288
+ until @stack.last == 'table'
289
+ @out << '</' << @stack.pop << '>'
290
+ end
291
+ @out << ($1 ? '</th>' : '</td>')
292
+ end
293
+ }
294
+ @out << '</tr>'
295
+ end
296
+
297
+ def make_nowikiblock(input)
298
+ input.gsub(/^ (?=\}\}\})/, '')
299
+ end
300
+
301
+ def ulol(x); x=='ul'||x=='ol'; end
302
+
303
+ def parse_block(str)
304
+ until str.empty?
305
+ case str
306
+ when /\A\{\{\{\r?\n(.*?)\r?\n\}\}\}/m
307
+ end_paragraph
308
+ nowikiblock = make_nowikiblock($1)
309
+ @out << '<pre>' << escape_html(nowikiblock) << '</pre>'
310
+ when /\A\s*-{4,}\s*$/
311
+ end_paragraph
312
+ @out << '<hr/>'
313
+ when /\A\s*(={1,6})\s*(.*?)\s*=*\s*$(\r?\n)?/
314
+ end_paragraph
315
+ level = $1.size
316
+ @out << "<h#{level}>" << escape_html($2) << "</h#{level}>"
317
+ when /\A[ \t]*\|.*$(\r?\n)?/
318
+ unless @stack.include?('table')
319
+ end_paragraph
320
+ @stack.push('table')
321
+ @out << '<table>'
322
+ end
323
+ parse_table_row($&)
324
+ when /\A\s*$(\r?\n)?/
325
+ end_paragraph
326
+ when /\A(\s*([*#]+)\s*(.*?))$(\r?\n)?/
327
+ line, bullet, item = $1, $2, $3
328
+ tag = (bullet[0,1] == '*' ? 'ul' : 'ol')
329
+ listre = /\A[ou]l\z/
330
+ if bullet[0,1] == '#' or bullet.size != 2 or @stack.find { |x| x=='ol' || x == 'ul' }
331
+ ulcount = @stack.inject(0) { |a,b| a + (ulol(b) ? 1 : 0) }
332
+ while ulcount > bullet.size or not (@stack.empty? or ulol(@stack.last))
333
+ @out << '</' + @stack.last << '>'
334
+ ulcount -= 1 if ulol(@stack.pop)
335
+ end
336
+
337
+ if ulcount == bullet.size and @stack.last != tag
338
+ @out << '</' << @stack.last << '>'
339
+ @stack.pop
340
+ ulcount -= 1
341
+ end
342
+
343
+ while ulcount < bullet.size
344
+ @out << '<' << tag << '>'
345
+ @stack.push tag
346
+ ulcount += 1
347
+ end
348
+ @p = true
349
+ @out << '<li>'
350
+ @stack.push('li')
351
+ parse_inline(item)
352
+ else
353
+ start_paragraph
354
+ parse_inline(line)
355
+ end
356
+ when /\A([ \t]*\S+.*?)$(\r?\n)?/
357
+ start_paragraph
358
+ parse_inline($1)
359
+ else
360
+ raise CreoleParseError, "Parse error at #{str[0,30].inspect}"
361
+ end
362
+ #p [$&, $']
363
+ str = $'
364
+ end
365
+ end_paragraph
366
+ return @out
367
+ end
368
+
369
+ end # class CreoleParser
370
+
371
+ 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,626 @@
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><ul><ul><li>Item 1</li></ul></ul></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</li><ul><li>Item 2</li></ul><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</li><ul><li>Item 2</li><ul><li>Item 3</li><ul><li>Item 4</li><ul><li>Item 5</li></ul></ul></ul></ul></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!</li><ul><li>Not bold</li></ul></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!</li><ul><li>Not bold</li></ul></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><ol><ol><li>Item 1</li></ol></ol></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</li><ol><li>Item 2</li></ol><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</li><ol><li>Item 2</li><ol><li>Item 3</li><ol><li>Item 4</li><ol><li>Item 5</li></ol></ol></ol></ol></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><ol><li>Item</li></ol></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</li><ol><li>Item 2</li></ol><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</li><ol><li>oitem</li></ol></ul>", "*uitem\n##oitem\n")
321
+
322
+ # 2ul following ol
323
+ tc("<ol><li>uitem</li><ul><li>oitem</li></ul></ol>", "#uitem\n**oitem\n")
324
+
325
+ # 3ol following 3ul
326
+ tc("<ul><ul><ul><li>uitem</li></ul><ol><li>oitem</li></ol></ul></ul>", "***uitem\n###oitem\n")
327
+
328
+ # 2ul following 2ol
329
+ tc("<ol><ol><li>uitem</li></ol><ul><li>oitem</li></ul></ol>", "##uitem\n**oitem\n")
330
+
331
+ # ol following 2ol
332
+ tc("<ol><ol><li>oitem1</li></ol><li>oitem2</li></ol>", "##oitem1\n#oitem2\n")
333
+ # ul following 2ol
334
+ tc("<ol><ol><li>oitem1</li></ol></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
+ end
350
+
351
+ def test_ambiguity_bold_and_lists
352
+ tc "<p><strong> bold text </strong></p>", "** bold text **"
353
+ tc "<p> <strong> bold text </strong></p>", " ** bold text **"
354
+ end
355
+
356
+ def test_nowiki
357
+ # ... works as block
358
+ tc "<pre>Hello</pre>", "{{{\nHello\n}}}\n"
359
+
360
+ # ... works inline
361
+ tc "<p>Hello <tt>world</tt>.</p>", "Hello {{{world}}}."
362
+
363
+ # Creole1.0: No wiki markup is interpreted inbetween
364
+ tc "<pre>**Hello**</pre>", "{{{\n**Hello**\n}}}\n"
365
+
366
+ # Creole1.0: Leading whitespaces are not permitted
367
+ tc("<p> {{{ Hello }}}</p>", " {{{\nHello\n}}}")
368
+ tc("<p>{{{ Hello }}}</p>", "{{{\nHello\n }}}")
369
+
370
+ # Assumed: Should preserve whitespace
371
+ tc("<pre> \t Hello, \t \n \t World \t </pre>",
372
+ "{{{\n \t Hello, \t \n \t World \t \n}}}\n")
373
+
374
+ # In preformatted blocks ... one leading space is removed
375
+ tc("<pre>nowikiblock\n}}}</pre>", "{{{\nnowikiblock\n }}}\n}}}\n")
376
+
377
+ # In inline nowiki, any trailing closing brace is included in the span
378
+ tc("<p>this is <tt>nowiki}</tt></p>", "this is {{{nowiki}}}}")
379
+ tc("<p>this is <tt>nowiki}}</tt></p>", "this is {{{nowiki}}}}}")
380
+ tc("<p>this is <tt>nowiki}}}</tt></p>", "this is {{{nowiki}}}}}}")
381
+ tc("<p>this is <tt>nowiki}}}}</tt></p>", "this is {{{nowiki}}}}}}}")
382
+ end
383
+
384
+ def test_html_escaping
385
+ # Special HTML chars should be escaped
386
+ tc("<p>&lt;b&gt;not bold&lt;/b&gt;</p>", "<b>not bold</b>")
387
+
388
+ # Image tags should be escape
389
+ tc("<p><img src=\"image.jpg\" alt=\"&quot;tag&quot;\"/></p>", "{{image.jpg|\"tag\"}}")
390
+
391
+ # Malicious links should not be converted.
392
+ tc("<p><a href=\"javascript%3Aalert%28%22Boo%21%22%29\">Click</a></p>", "[[javascript:alert(\"Boo!\")|Click]]")
393
+ end
394
+
395
+ def test_escape
396
+ tc "<p>** Not Bold **</p>", "~** Not Bold ~**"
397
+ tc "<p>// Not Italic //</p>", "~// Not Italic ~//"
398
+ tc "<p>* Not Bullet</p>", "~* Not Bullet"
399
+ # Following char is not a blank (space or line feed)
400
+ tc "<p>Hello ~ world</p>", "Hello ~ world\n"
401
+ tc "<p>Hello ~ world</p>", "Hello ~\nworld\n"
402
+ # Not escaping inside URLs (Creole1.0 not clear on this)
403
+ tc "<p><a href=\"http://example.org/~user/\">http://example.org/~user/</a></p>", "http://example.org/~user/"
404
+
405
+ # Escaping links
406
+ tc "<p>http://www.wikicreole.org/</p>", "~http://www.wikicreole.org/"
407
+ end
408
+
409
+ def test_horizontal_rule
410
+ # Creole: Four hyphens make a horizontal rule
411
+ tc "<hr/>", "----"
412
+
413
+ # Creole1.0: Whitespace around them is allowed
414
+ tc "<hr/>", " ----"
415
+ tc "<hr/>", "---- "
416
+ tc "<hr/>", " ---- "
417
+ tc "<hr/>", " \t ---- \t "
418
+
419
+ # Creole1.0: Nothing else than hyphens and whitespace is "allowed"
420
+ tc "<p>foo ----</p>", "foo ----\n"
421
+ tc "<p>---- foo</p>", "---- foo\n"
422
+
423
+ # Creole1.0: [...] no whitespace is allowed between them
424
+ tc "<p> -- -- </p>", " -- -- "
425
+ tc "<p> -- -- </p>", " --\t-- "
426
+ end
427
+
428
+ def test_table
429
+ tc "<table><tr><td>Hello, World!</td></tr></table>", "|Hello, World!|"
430
+ # Multiple columns
431
+ tc "<table><tr><td>c1</td><td>c2</td><td>c3</td></tr></table>", "|c1|c2|c3|"
432
+ # Multiple rows
433
+ 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"
434
+ # End pipe is optional
435
+ tc "<table><tr><td>c1</td><td>c2</td><td>c3</td></tr></table>", "|c1|c2|c3"
436
+ # Empty cells
437
+ tc "<table><tr><td>c1</td><td></td><td>c3</td></tr></table>", "|c1||c3"
438
+ # Escaping cell separator
439
+ tc "<table><tr><td>c1|c2</td><td>c3</td></tr></table>", "|c1~|c2|c3"
440
+ # Escape in last cell + empty cell
441
+ tc "<table><tr><td>c1</td><td>c2|</td></tr></table>", "|c1|c2~|"
442
+ tc "<table><tr><td>c1</td><td>c2|</td></tr></table>", "|c1|c2~||"
443
+ tc "<table><tr><td>c1</td><td>c2|</td><td></td></tr></table>", "|c1|c2~|||"
444
+ # Equal sign after pipe make a header
445
+ tc "<table><tr><th>Header</th></tr></table>", "|=Header|"
446
+ end
447
+
448
+ def test_following_table
449
+ # table followed by heading
450
+ tc("<table><tr><td>table</td></tr></table><h1>heading</h1>", "|table|\n=heading=\n")
451
+ tc("<table><tr><td>table</td></tr></table><h1>heading</h1>", "|table|\n\n=heading=\n")
452
+ # table followed by paragraph
453
+ tc("<table><tr><td>table</td></tr></table><p>par</p>", "|table|\npar\n")
454
+ tc("<table><tr><td>table</td></tr></table><p>par</p>", "|table|\n\npar\n")
455
+ # table followed by unordered list
456
+ tc("<table><tr><td>table</td></tr></table><ul><li>item</li></ul>", "|table|\n*item\n")
457
+ tc("<table><tr><td>table</td></tr></table><ul><li>item</li></ul>", "|table|\n\n*item\n")
458
+ # table followed by ordered list
459
+ tc("<table><tr><td>table</td></tr></table><ol><li>item</li></ol>", "|table|\n#item\n")
460
+ tc("<table><tr><td>table</td></tr></table><ol><li>item</li></ol>", "|table|\n\n#item\n")
461
+ # table followed by horizontal rule
462
+ tc("<table><tr><td>table</td></tr></table><hr/>", "|table|\n----\n")
463
+ tc("<table><tr><td>table</td></tr></table><hr/>", "|table|\n\n----\n")
464
+ # table followed by nowiki block
465
+ tc("<table><tr><td>table</td></tr></table><pre>pre</pre>", "|table|\n{{{\npre\n}}}\n")
466
+ tc("<table><tr><td>table</td></tr></table><pre>pre</pre>", "|table|\n\n{{{\npre\n}}}\n")
467
+ # table followed by table
468
+ tc("<table><tr><td>table</td></tr><tr><td>table</td></tr></table>", "|table|\n|table|\n")
469
+ tc("<table><tr><td>table</td></tr></table><table><tr><td>table</td></tr></table>", "|table|\n\n|table|\n")
470
+ end
471
+
472
+ def test_following_heading
473
+ # heading
474
+ tc("<h1>heading1</h1><h1>heading2</h1>", "=heading1=\n=heading2\n")
475
+ tc("<h1>heading1</h1><h1>heading2</h1>", "=heading1=\n\n=heading2\n")
476
+ # paragraph
477
+ tc("<h1>heading</h1><p>par</p>", "=heading=\npar\n")
478
+ tc("<h1>heading</h1><p>par</p>", "=heading=\n\npar\n")
479
+ # unordered list
480
+ tc("<h1>heading</h1><ul><li>item</li></ul>", "=heading=\n*item\n")
481
+ tc("<h1>heading</h1><ul><li>item</li></ul>", "=heading=\n\n*item\n")
482
+ # ordered list
483
+ tc("<h1>heading</h1><ol><li>item</li></ol>", "=heading=\n#item\n")
484
+ tc("<h1>heading</h1><ol><li>item</li></ol>", "=heading=\n\n#item\n")
485
+ # horizontal rule
486
+ tc("<h1>heading</h1><hr/>", "=heading=\n----\n")
487
+ tc("<h1>heading</h1><hr/>", "=heading=\n\n----\n")
488
+ # nowiki block
489
+ tc("<h1>heading</h1><pre>nowiki</pre>", "=heading=\n{{{\nnowiki\n}}}\n")
490
+ tc("<h1>heading</h1><pre>nowiki</pre>", "=heading=\n\n{{{\nnowiki\n}}}\n")
491
+ # table
492
+ tc("<h1>heading</h1><table><tr><td>table</td></tr></table>", "=heading=\n|table|\n")
493
+ tc("<h1>heading</h1><table><tr><td>table</td></tr></table>", "=heading=\n\n|table|\n")
494
+ end
495
+
496
+ def test_following_paragraph
497
+ # heading
498
+ tc("<p>par</p><h1>heading</h1>", "par\n=heading=")
499
+ tc("<p>par</p><h1>heading</h1>", "par\n\n=heading=")
500
+ # paragraph
501
+ tc("<p>par par</p>", "par\npar\n")
502
+ tc("<p>par</p><p>par</p>", "par\n\npar\n")
503
+ # unordered
504
+ tc("<p>par</p><ul><li>item</li></ul>", "par\n*item")
505
+ tc("<p>par</p><ul><li>item</li></ul>", "par\n\n*item")
506
+ # ordered
507
+ tc("<p>par</p><ol><li>item</li></ol>", "par\n#item\n")
508
+ tc("<p>par</p><ol><li>item</li></ol>", "par\n\n#item\n")
509
+ # horizontal
510
+ tc("<p>par</p><hr/>", "par\n----\n")
511
+ tc("<p>par</p><hr/>", "par\n\n----\n")
512
+ # nowiki
513
+ tc("<p>par</p><pre>nowiki</pre>", "par\n{{{\nnowiki\n}}}\n")
514
+ tc("<p>par</p><pre>nowiki</pre>", "par\n\n{{{\nnowiki\n}}}\n")
515
+ # table
516
+ tc("<p>par</p><table><tr><td>table</td></tr></table>", "par\n|table|\n")
517
+ tc("<p>par</p><table><tr><td>table</td></tr></table>", "par\n\n|table|\n")
518
+ end
519
+
520
+ def test_following_unordered_list
521
+ # heading
522
+ tc("<ul><li>item</li></ul><h1>heading</h1>", "*item\n=heading=")
523
+ tc("<ul><li>item</li></ul><h1>heading</h1>", "*item\n\n=heading=")
524
+ # paragraph
525
+ tc("<ul><li>item par</li></ul>", "*item\npar\n") # items may span multiple lines
526
+ tc("<ul><li>item</li></ul><p>par</p>", "*item\n\npar\n")
527
+ # unordered
528
+ tc("<ul><li>item</li><li>item</li></ul>", "*item\n*item\n")
529
+ tc("<ul><li>item</li></ul><ul><li>item</li></ul>", "*item\n\n*item\n")
530
+ # ordered
531
+ tc("<ul><li>item</li></ul><ol><li>item</li></ol>", "*item\n#item\n")
532
+ tc("<ul><li>item</li></ul><ol><li>item</li></ol>", "*item\n\n#item\n")
533
+ # horizontal rule
534
+ tc("<ul><li>item</li></ul><hr/>", "*item\n----\n")
535
+ tc("<ul><li>item</li></ul><hr/>", "*item\n\n----\n")
536
+ # nowiki
537
+ tc("<ul><li>item</li></ul><pre>nowiki</pre>", "*item\n{{{\nnowiki\n}}}\n")
538
+ tc("<ul><li>item</li></ul><pre>nowiki</pre>", "*item\n\n{{{\nnowiki\n}}}\n")
539
+ # table
540
+ tc("<ul><li>item</li></ul><table><tr><td>table</td></tr></table>", "*item\n|table|\n")
541
+ tc("<ul><li>item</li></ul><table><tr><td>table</td></tr></table>", "*item\n\n|table|\n")
542
+ end
543
+
544
+ def test_following_ordered_list
545
+ # heading
546
+ tc("<ol><li>item</li></ol><h1>heading</h1>", "#item\n=heading=")
547
+ tc("<ol><li>item</li></ol><h1>heading</h1>", "#item\n\n=heading=")
548
+ # paragraph
549
+ tc("<ol><li>item par</li></ol>", "#item\npar\n") # items may span multiple lines
550
+ tc("<ol><li>item</li></ol><p>par</p>", "#item\n\npar\n")
551
+ # unordered
552
+ tc("<ol><li>item</li></ol><ul><li>item</li></ul>", "#item\n*item\n")
553
+ tc("<ol><li>item</li></ol><ul><li>item</li></ul>", "#item\n\n*item\n")
554
+ # ordered
555
+ tc("<ol><li>item</li><li>item</li></ol>", "#item\n#item\n")
556
+ tc("<ol><li>item</li></ol><ol><li>item</li></ol>", "#item\n\n#item\n")
557
+ # horizontal role
558
+ tc("<ol><li>item</li></ol><hr/>", "#item\n----\n")
559
+ tc("<ol><li>item</li></ol><hr/>", "#item\n\n----\n")
560
+ # nowiki
561
+ tc("<ol><li>item</li></ol><pre>nowiki</pre>", "#item\n{{{\nnowiki\n}}}\n")
562
+ tc("<ol><li>item</li></ol><pre>nowiki</pre>", "#item\n\n{{{\nnowiki\n}}}\n")
563
+ # table
564
+ tc("<ol><li>item</li></ol><table><tr><td>table</td></tr></table>", "#item\n|table|\n")
565
+ tc("<ol><li>item</li></ol><table><tr><td>table</td></tr></table>", "#item\n\n|table|\n")
566
+ end
567
+
568
+ def test_following_horizontal_rule
569
+ # heading
570
+ tc("<hr/><h1>heading</h1>", "----\n=heading=")
571
+ tc("<hr/><h1>heading</h1>", "----\n\n=heading=")
572
+ # paragraph
573
+ tc("<hr/><p>par</p>", "----\npar\n")
574
+ tc("<hr/><p>par</p>", "----\n\npar\n")
575
+ # unordered
576
+ tc("<hr/><ul><li>item</li></ul>", "----\n*item")
577
+ tc("<hr/><ul><li>item</li></ul>", "----\n*item")
578
+ # ordered
579
+ tc("<hr/><ol><li>item</li></ol>", "----\n#item")
580
+ tc("<hr/><ol><li>item</li></ol>", "----\n#item")
581
+ # horizontal
582
+ tc("<hr/><hr/>", "----\n----\n")
583
+ tc("<hr/><hr/>", "----\n\n----\n")
584
+ # nowiki
585
+ tc("<hr/><pre>nowiki</pre>", "----\n{{{\nnowiki\n}}}\n")
586
+ tc("<hr/><pre>nowiki</pre>", "----\n\n{{{\nnowiki\n}}}\n")
587
+ # table
588
+ tc("<hr/><table><tr><td>table</td></tr></table>", "----\n|table|\n")
589
+ tc("<hr/><table><tr><td>table</td></tr></table>", "----\n\n|table|\n")
590
+ end
591
+
592
+ def test_following_nowiki_block
593
+ # heading
594
+ tc("<pre>nowiki</pre><h1>heading</h1>", "{{{\nnowiki\n}}}\n=heading=")
595
+ tc("<pre>nowiki</pre><h1>heading</h1>", "{{{\nnowiki\n}}}\n\n=heading=")
596
+ # paragraph
597
+ tc("<pre>nowiki</pre><p>par</p>", "{{{\nnowiki\n}}}\npar")
598
+ tc("<pre>nowiki</pre><p>par</p>", "{{{\nnowiki\n}}}\n\npar")
599
+ # unordered
600
+ tc("<pre>nowiki</pre><ul><li>item</li></ul>", "{{{\nnowiki\n}}}\n*item\n")
601
+ tc("<pre>nowiki</pre><ul><li>item</li></ul>", "{{{\nnowiki\n}}}\n\n*item\n")
602
+ # ordered
603
+ tc("<pre>nowiki</pre><ol><li>item</li></ol>", "{{{\nnowiki\n}}}\n#item\n")
604
+ tc("<pre>nowiki</pre><ol><li>item</li></ol>", "{{{\nnowiki\n}}}\n\n#item\n")
605
+ # horizontal
606
+ tc("<pre>nowiki</pre><hr/>", "{{{\nnowiki\n}}}\n----\n")
607
+ tc("<pre>nowiki</pre><hr/>", "{{{\nnowiki\n}}}\n\n----\n")
608
+ # nowiki
609
+ tc("<pre>nowiki</pre><pre>nowiki</pre>", "{{{\nnowiki\n}}}\n{{{\nnowiki\n}}}\n")
610
+ tc("<pre>nowiki</pre><pre>nowiki</pre>", "{{{\nnowiki\n}}}\n\n{{{\nnowiki\n}}}\n")
611
+ # table
612
+ tc("<pre>nowiki</pre><table><tr><td>table</td></tr></table>", "{{{\nnowiki\n}}}\n|table|\n")
613
+ tc("<pre>nowiki</pre><table><tr><td>table</td></tr></table>", "{{{\nnowiki\n}}}\n\n|table|\n")
614
+ end
615
+
616
+ def test_image
617
+ tc("<p><img src=\"image.jpg\"/></p>", "{{image.jpg}}")
618
+ tc("<p><img src=\"image.jpg\" alt=\"tag\"/></p>", "{{image.jpg|tag}}")
619
+ tc("<p><img src=\"http://example.org/image.jpg\"/></p>", "{{http://example.org/image.jpg}}")
620
+ end
621
+
622
+ def test_bold_combo
623
+ tc("<p><strong>bold and</strong></p><table><tr><td>table</td></tr></table><p>end<strong></strong></p>",
624
+ "**bold and\n|table|\nend**")
625
+ end
626
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: minad-creole
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.2"
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 -08: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://creole.rubyforge.org/
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.2.0
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