require 'test/unit' require 'creole' require 'cgi' class TestCreole < Test::Unit::TestCase def tc(html, creole, options = {}) output = Creole.creolize(creole, options) assert html === output, "Parsing: #{creole.inspect}\nExpected: #{html.inspect}\n Was: #{output.inspect}" end def tce(html, creole) tc(html, creole, :extensions => true) end def run_file(file) html = File.read(file.sub('.creole', '.html')) output = Creole.creolize(File.read(file)) puts html puts output assert html === output, "Parsing #{file} failed" end def escape_html(html) CGI::escapeHTML(html) end def test_bold # Creole1.0: Bold can be used inside paragraphs tc "

This is bold

", "This **is** bold" tc "

This is bold and boldish

", "This **is** bold and **bold**ish" # Creole1.0: Bold can be used inside list items tc "", "* This is **bold**" # Creole1.0: Bold can be used inside table cells tc("
This is bold
", "|This is **bold**|") # Creole1.0: Links can appear inside bold text: tc("

A bold link: http://wikicreole.org/ nice!

", "A bold link: **http://wikicreole.org/ nice!**") # Creole1.0: Bold will end at the end of paragraph tc "

This is bold

", "This **is bold" # Creole1.0: Bold will end at the end of list items tc("", "* Item **bold\n* Item normal") # Creole1.0: Bold will end at the end of table cells tc("
Item boldAnother bold
", "|Item **bold|Another **bold") # Creole1.0: Bold should not cross paragraphs tc("

This is

bold maybe

", "This **is\n\nbold** maybe") # Creole1.0-Implied: Bold should be able to cross lines tc "

This is bold

", "This **is\nbold**" end def test_italic # Creole1.0: Italic can be used inside paragraphs tc("

This is italic

", "This //is// italic") tc("

This is italic and italicish

", "This //is// italic and //italic//ish") # Creole1.0: Italic can be used inside list items tc "", "* This is //italic//" # Creole1.0: Italic can be used inside table cells tc("
This is italic
", "|This is //italic//|") # Creole1.0: Links can appear inside italic text: tc("

A italic link: http://wikicreole.org/ nice!

", "A italic link: //http://wikicreole.org/ nice!//") # Creole1.0: Italic will end at the end of paragraph tc "

This is italic

", "This //is italic" # Creole1.0: Italic will end at the end of list items tc("", "* Item //italic\n* Item normal") # Creole1.0: Italic will end at the end of table cells tc("
Item italicAnother italic
", "|Item //italic|Another //italic") # Creole1.0: Italic should not cross paragraphs tc("

This is

italic maybe

", "This //is\n\nitalic// maybe") # Creole1.0-Implied: Italic should be able to cross lines tc "

This is italic

", "This //is\nitalic//" end def test_bold_italics # Creole1.0: By example tc "

bold italics

", "**//bold italics//**" # Creole1.0: By example tc "

bold italics

", "//**bold italics**//" # Creole1.0: By example tc "

This is also good.

", "//This is **also** good.//" end def test_headings # Creole1.0: Only three differed sized levels of heading are required. tc "

Heading 1

", "= Heading 1 =" tc "

Heading 2

", "== Heading 2 ==" tc "

Heading 3

", "=== Heading 3 ===" # WARNING: Optional feature, not specified in creole 1.0 tc "

Heading 4

", "==== Heading 4 ====" tc "
Heading 5
", "===== Heading 5 =====" tc "
Heading 6
", "====== Heading 6 ======" # Creole1.0: Closing (right-side) equal signs are optional tc "

Heading 1

", "=Heading 1" tc "

Heading 2

", "== Heading 2" tc "

Heading 3

", " === Heading 3" # Creole1.0: Closing (right-side) equal signs don't need to be balanced and don't impact the kind of heading generated tc "

Heading 1

", "=Heading 1 ===" tc "

Heading 2

", "== Heading 2 =" tc "

Heading 3

", " === Heading 3 ===========" # Creole1.0: Whitespace is allowed before the left-side equal signs. tc "

Heading 1

", " \t= Heading 1 =" tc "

Heading 2

", " \t== Heading 2 ==" # Creole1.0: Only white-space characters are permitted after the closing equal signs. tc "

Heading 1

", " = Heading 1 = " tc "

Heading 2

", " == Heading 2 == \t " # WARNING: !!Creole1.0 doesn't specify if text after closing equal signs # !!becomes part of the heading or invalidates the entire heading. # tc "

== Heading 2 == foo

", " == Heading 2 == foo" tc "

Heading 2 == foo

", " == Heading 2 == foo" # Creole1.0-Implied: Line must start with equal sign tc "

foo = Heading 1 =

", "foo = Heading 1 =" end def test_links # Creole1.0: Links tc "

link

", "[[link]]" # Creole1.0: Links can appear in paragraphs (i.e. inline item) tc "

Hello, world

", "Hello, [[world]]" # Creole1.0: Named links tc "

Go to my page

", "[[MyBigPage|Go to my page]]" # Creole1.0: URLs tc "

http://www.wikicreole.org/

", "[[http://www.wikicreole.org/]]" # Creole1.0: Free-standing URL's should be turned into links tc "

http://www.wikicreole.org/

", "http://www.wikicreole.org/" # Creole1.0: Single punctuation characters at the end of URLs # should not be considered a part of the URL. [',','.','?','!',':',';','\'','"'].each { |punct| esc_punct = escape_html(punct) tc "

http://www.wikicreole.org/#{esc_punct}

", "http://www.wikicreole.org/#{punct}" } # Creole1.0: Nameds URLs (by example) tc("

Visit the WikiCreole website

", "[[http://www.wikicreole.org/|Visit the WikiCreole website]]") # WARNING: Parsing markup within a link is optional tc "

**Weird** //Stuff//

", "[[Weird Stuff|**Weird** //Stuff//]]" # Inside bold tc "

link

", "**[[link]]**" # Whitespace inside [[ ]] should be ignored tc("

link

", "[[ link ]]") tc("

link me

", "[[ link me ]]") tc("

dot.com

", "[[ http://dot.com/ \t| \t dot.com ]]") tc("

dot.com

", "[[ http://dot.com/ | dot.com ]]") end def test_paragraph # Creole1.0: One or more blank lines end paragraphs. tc "

This is my text.

This is more text.

", "This is\nmy text.\n\nThis is\nmore text." tc "

This is my text.

This is more text.

", "This is\nmy text.\n\n\nThis is\nmore text." tc "

This is my text.

This is more text.

", "This is\nmy text.\n\n\n\nThis is\nmore text." # Creole1.0: A list end paragraphs too. tc "

Hello

", "Hello\n* Item\n" # Creole1.0: A table end paragraphs too. tc "

Hello

Cell
", "Hello\n|Cell|" # Creole1.0: A nowiki end paragraphs too. tc "

Hello

nowiki
", "Hello\n{{{\nnowiki\n}}}\n" # WARNING: A heading ends a paragraph (not specced) tc "

Hello

Heading

", "Hello\n= Heading =\n" end def test_linebreak # Creole1.0: \\ (wiki-style) for line breaks. tc "

This is the first line,
and this is the second.

", "This is the first line,\\\\and this is the second." end def test_unordered_lists # Creole1.0: List items begin with a * at the beginning of a line. # Creole1.0: An item ends at the next * tc "", "* Item 1\n *Item 2\n *\t\tItem 3\n" # Creole1.0: Whitespace is optional before and after the *. tc("", " * Item 1\n*Item 2\n \t*\t\tItem 3\n") # Creole1.0: A space is required if if the list element starts with bold text. tc("", "***Item 1") tc("", "* **Item 1") # Creole1.0: An item ends at blank line tc("

Par

", "* Item\n\nPar\n") # Creole1.0: An item ends at a heading tc("

Heading

", "* Item\n= Heading =\n") # Creole1.0: An item ends at a table tc("
Cell
", "* Item\n|Cell|\n") # Creole1.0: An item ends at a nowiki block tc("
Code
", "* Item\n{{{\nCode\n}}}\n") # Creole1.0: An item can span multiple lines tc("", "* The quick\nbrown fox\n\tjumps over\nlazy dog.\n*Humpty Dumpty\nsat\t\non a wall.") # Creole1.0: An item can contain line breaks tc("", "* The quick brown\\\\fox jumps over lazy dog.") # Creole1.0: Nested tc "", "* Item 1\n **Item 2\n *\t\tItem 3\n" # Creole1.0: Nested up to 5 levels tc("", "*Item 1\n**Item 2\n***Item 3\n****Item 4\n*****Item 5\n") # Creole1.0: ** immediatly following a list element will be treated as a nested unordered element. tc("", "*Hello,\nWorld!\n**Not bold\n") # Creole1.0: ** immediatly following a list element will be treated as a nested unordered element. tc("
  1. Hello, World!
", "#Hello,\nWorld!\n**Not bold\n") # Creole1.0: [...] otherwise it will be treated as the beginning of bold text. tc("

Not bold

", "*Hello,\nWorld!\n\n**Not bold\n") end def test_ordered_lists # Creole1.0: List items begin with a * at the beginning of a line. # Creole1.0: An item ends at the next * tc "
  1. Item 1
  2. Item 2
  3. Item 3
", "# Item 1\n #Item 2\n #\t\tItem 3\n" # Creole1.0: Whitespace is optional before and after the #. tc("
  1. Item 1
  2. Item 2
  3. Item 3
", " # Item 1\n#Item 2\n \t#\t\tItem 3\n") # Creole1.0: A space is required if if the list element starts with bold text. tc("
      1. Item 1
", "###Item 1") tc("
  1. Item 1
", "# **Item 1") # Creole1.0: An item ends at blank line tc("
  1. Item

Par

", "# Item\n\nPar\n") # Creole1.0: An item ends at a heading tc("
  1. Item

Heading

", "# Item\n= Heading =\n") # Creole1.0: An item ends at a table tc("
  1. Item
Cell
", "# Item\n|Cell|\n") # Creole1.0: An item ends at a nowiki block tc("
  1. Item
Code
", "# Item\n{{{\nCode\n}}}\n") # Creole1.0: An item can span multiple lines tc("
  1. The quick brown fox jumps over lazy dog.
  2. Humpty Dumpty sat on a wall.
", "# The quick\nbrown fox\n\tjumps over\nlazy dog.\n#Humpty Dumpty\nsat\t\non a wall.") # Creole1.0: An item can contain line breaks tc("
  1. The quick brown
    fox jumps over lazy dog.
", "# The quick brown\\\\fox jumps over lazy dog.") # Creole1.0: Nested tc "
  1. Item 1
    1. Item 2
  2. Item 3
", "# Item 1\n ##Item 2\n #\t\tItem 3\n" # Creole1.0: Nested up to 5 levels tc("
  1. Item 1
    1. Item 2
      1. Item 3
        1. Item 4
          1. Item 5
", "#Item 1\n##Item 2\n###Item 3\n####Item 4\n#####Item 5\n") # Creole1.0_Infered: The two-bullet rule only applies to **. tc("
    1. Item
", "##Item") end def test_ordered_lists2 tc "
  1. Item 1
  2. Item 2
  3. Item 3
", "# Item 1\n #Item 2\n #\t\tItem 3\n" # Nested tc "
  1. Item 1
    1. Item 2
  2. Item 3
", "# Item 1\n ##Item 2\n #\t\tItem 3\n" # Multiline tc "
  1. Item 1 on multiple lines
", "# Item 1\non multiple lines" end def test_ambiguity_mixed_lists # ol following ul tc("
  1. oitem
", "*uitem\n#oitem\n") # ul following ol tc("
  1. uitem
", "#uitem\n*oitem\n") # 2ol following ul tc("", "*uitem\n##oitem\n") # 2ul following ol tc("
  1. uitem
", "#uitem\n**oitem\n") # 3ol following 3ul tc("", "***uitem\n###oitem\n") # 2ul following 2ol tc("
    1. uitem
", "##uitem\n**oitem\n") # ol following 2ol tc("
    1. oitem1
  1. oitem2
", "##oitem1\n#oitem2\n") # ul following 2ol tc("
    1. oitem1
", "##oitem1\n*oitem2\n") end def test_ambiguity_italics_and_url # Uncommon URL schemes should not be parsed as URLs tc("

This is what can go wrong:this should be an italic text.

", "This is what can go wrong://this should be an italic text//.") # A link inside italic text tc("

How about a link, like http://example.org, in italic text?

", "How about //a link, like http://example.org, in italic// text?") # Another test from Creole Wiki tc("

Formatted fruits, for example:apples, oranges, pears ...

", "Formatted fruits, for example://apples//, oranges, **pears** ...") tc("

Blablabala (http://blub.de)

", "Blablabala (http://blub.de)") end def test_ambiguity_bold_and_lists tc "

bold text

", "** bold text **" tc "

bold text

", " ** bold text **" end def test_nowiki # ... works as block tc "
Hello
", "{{{\nHello\n}}}\n" # ... works inline tc "

Hello world.

", "Hello {{{world}}}." tc "

Hello world.

", "{{{Hello}}} {{{world}}}." # Creole1.0: No wiki markup is interpreted inbetween tc "
**Hello**
", "{{{\n**Hello**\n}}}\n" # Creole1.0: Leading whitespaces are not permitted tc("

{{{ Hello }}}

", " {{{\nHello\n}}}") tc("

{{{ Hello }}}

", "{{{\nHello\n }}}") # Assumed: Should preserve whitespace tc("
 \t Hello, \t \n \t World \t 
", "{{{\n \t Hello, \t \n \t World \t \n}}}\n") # In preformatted blocks ... one leading space is removed tc("
nowikiblock\n}}}
", "{{{\nnowikiblock\n }}}\n}}}\n") # In inline nowiki, any trailing closing brace is included in the span tc("

this is nowiki}

", "this is {{{nowiki}}}}") tc("

this is nowiki}}

", "this is {{{nowiki}}}}}") tc("

this is nowiki}}}

", "this is {{{nowiki}}}}}}") tc("

this is nowiki}}}}

", "this is {{{nowiki}}}}}}}") end def test_html_escaping # Special HTML chars should be escaped tc("

<b>not bold</b>

", "not bold") # Image tags should be escape tc("

\""tag"\"/

", "{{image.jpg|\"tag\"}}") # Malicious links should not be converted. tc("

Click

", "[[javascript:alert(\"Boo!\")|Click]]") end def test_escape tc "

** Not Bold **

", "~** Not Bold ~**" tc "

// Not Italic //

", "~// Not Italic ~//" tc "

* Not Bullet

", "~* Not Bullet" # Following char is not a blank (space or line feed) tc "

Hello ~ world

", "Hello ~ world\n" tc "

Hello ~ world

", "Hello ~\nworld\n" # Not escaping inside URLs (Creole1.0 not clear on this) tc "

http://example.org/~user/

", "http://example.org/~user/" # Escaping links tc "

http://www.wikicreole.org/

", "~http://www.wikicreole.org/" end def test_horizontal_rule # Creole: Four hyphens make a horizontal rule tc "
", "----" # Creole1.0: Whitespace around them is allowed tc "
", " ----" tc "
", "---- " tc "
", " ---- " tc "
", " \t ---- \t " # Creole1.0: Nothing else than hyphens and whitespace is "allowed" tc "

foo ----

", "foo ----\n" tc "

---- foo

", "---- foo\n" # Creole1.0: [...] no whitespace is allowed between them tc "

-- --

", " -- -- " tc "

-- --

", " --\t-- " end def test_table tc "
Hello, World!
", "|Hello, World!|" # Multiple columns tc "
c1c2c3
", "|c1|c2|c3|" # Multiple rows tc "
c11c12
c21c22
", "|c11|c12|\n|c21|c22|\n" # End pipe is optional tc "
c1c2c3
", "|c1|c2|c3" # Empty cells tc "
c1c3
", "|c1||c3" # Escaping cell separator tc "
c1|c2c3
", "|c1~|c2|c3" # Escape in last cell + empty cell tc "
c1c2|
", "|c1|c2~|" tc "
c1c2|
", "|c1|c2~||" tc "
c1c2|
", "|c1|c2~|||" # Equal sign after pipe make a header tc "
Header
", "|=Header|" tc "
c1Link text\"Image
", "|c1|[[Link|Link text]]|{{Image|Image text}}|" end def test_following_table # table followed by heading tc("
table

heading

", "|table|\n=heading=\n") tc("
table

heading

", "|table|\n\n=heading=\n") # table followed by paragraph tc("
table

par

", "|table|\npar\n") tc("
table

par

", "|table|\n\npar\n") # table followed by unordered list tc("
table
", "|table|\n*item\n") tc("
table
", "|table|\n\n*item\n") # table followed by ordered list tc("
table
  1. item
", "|table|\n#item\n") tc("
table
  1. item
", "|table|\n\n#item\n") # table followed by horizontal rule tc("
table

", "|table|\n----\n") tc("
table

", "|table|\n\n----\n") # table followed by nowiki block tc("
table
pre
", "|table|\n{{{\npre\n}}}\n") tc("
table
pre
", "|table|\n\n{{{\npre\n}}}\n") # table followed by table tc("
table
table
", "|table|\n|table|\n") tc("
table
table
", "|table|\n\n|table|\n") end def test_following_heading # heading tc("

heading1

heading2

", "=heading1=\n=heading2\n") tc("

heading1

heading2

", "=heading1=\n\n=heading2\n") # paragraph tc("

heading

par

", "=heading=\npar\n") tc("

heading

par

", "=heading=\n\npar\n") # unordered list tc("

heading

", "=heading=\n*item\n") tc("

heading

", "=heading=\n\n*item\n") # ordered list tc("

heading

  1. item
", "=heading=\n#item\n") tc("

heading

  1. item
", "=heading=\n\n#item\n") # horizontal rule tc("

heading


", "=heading=\n----\n") tc("

heading


", "=heading=\n\n----\n") # nowiki block tc("

heading

nowiki
", "=heading=\n{{{\nnowiki\n}}}\n") tc("

heading

nowiki
", "=heading=\n\n{{{\nnowiki\n}}}\n") # table tc("

heading

table
", "=heading=\n|table|\n") tc("

heading

table
", "=heading=\n\n|table|\n") end def test_following_paragraph # heading tc("

par

heading

", "par\n=heading=") tc("

par

heading

", "par\n\n=heading=") # paragraph tc("

par par

", "par\npar\n") tc("

par

par

", "par\n\npar\n") # unordered tc("

par

", "par\n*item") tc("

par

", "par\n\n*item") # ordered tc("

par

  1. item
", "par\n#item\n") tc("

par

  1. item
", "par\n\n#item\n") # horizontal tc("

par


", "par\n----\n") tc("

par


", "par\n\n----\n") # nowiki tc("

par

nowiki
", "par\n{{{\nnowiki\n}}}\n") tc("

par

nowiki
", "par\n\n{{{\nnowiki\n}}}\n") # table tc("

par

table
", "par\n|table|\n") tc("

par

table
", "par\n\n|table|\n") end def test_following_unordered_list # heading tc("

heading

", "*item\n=heading=") tc("

heading

", "*item\n\n=heading=") # paragraph tc("", "*item\npar\n") # items may span multiple lines tc("

par

", "*item\n\npar\n") # unordered tc("", "*item\n*item\n") tc("", "*item\n\n*item\n") # ordered tc("
  1. item
", "*item\n#item\n") tc("
  1. item
", "*item\n\n#item\n") # horizontal rule tc("
", "*item\n----\n") tc("
", "*item\n\n----\n") # nowiki tc("
nowiki
", "*item\n{{{\nnowiki\n}}}\n") tc("
nowiki
", "*item\n\n{{{\nnowiki\n}}}\n") # table tc("
table
", "*item\n|table|\n") tc("
table
", "*item\n\n|table|\n") end def test_following_ordered_list # heading tc("
  1. item

heading

", "#item\n=heading=") tc("
  1. item

heading

", "#item\n\n=heading=") # paragraph tc("
  1. item par
", "#item\npar\n") # items may span multiple lines tc("
  1. item

par

", "#item\n\npar\n") # unordered tc("
  1. item
", "#item\n*item\n") tc("
  1. item
", "#item\n\n*item\n") # ordered tc("
  1. item
  2. item
", "#item\n#item\n") tc("
  1. item
  1. item
", "#item\n\n#item\n") # horizontal role tc("
  1. item

", "#item\n----\n") tc("
  1. item

", "#item\n\n----\n") # nowiki tc("
  1. item
nowiki
", "#item\n{{{\nnowiki\n}}}\n") tc("
  1. item
nowiki
", "#item\n\n{{{\nnowiki\n}}}\n") # table tc("
  1. item
table
", "#item\n|table|\n") tc("
  1. item
table
", "#item\n\n|table|\n") end def test_following_horizontal_rule # heading tc("

heading

", "----\n=heading=") tc("

heading

", "----\n\n=heading=") # paragraph tc("

par

", "----\npar\n") tc("

par

", "----\n\npar\n") # unordered tc("
", "----\n*item") tc("
", "----\n*item") # ordered tc("
  1. item
", "----\n#item") tc("
  1. item
", "----\n#item") # horizontal tc("

", "----\n----\n") tc("

", "----\n\n----\n") # nowiki tc("
nowiki
", "----\n{{{\nnowiki\n}}}\n") tc("
nowiki
", "----\n\n{{{\nnowiki\n}}}\n") # table tc("
table
", "----\n|table|\n") tc("
table
", "----\n\n|table|\n") end def test_following_nowiki_block # heading tc("
nowiki

heading

", "{{{\nnowiki\n}}}\n=heading=") tc("
nowiki

heading

", "{{{\nnowiki\n}}}\n\n=heading=") # paragraph tc("
nowiki

par

", "{{{\nnowiki\n}}}\npar") tc("
nowiki

par

", "{{{\nnowiki\n}}}\n\npar") # unordered tc("
nowiki
", "{{{\nnowiki\n}}}\n*item\n") tc("
nowiki
", "{{{\nnowiki\n}}}\n\n*item\n") # ordered tc("
nowiki
  1. item
", "{{{\nnowiki\n}}}\n#item\n") tc("
nowiki
  1. item
", "{{{\nnowiki\n}}}\n\n#item\n") # horizontal tc("
nowiki

", "{{{\nnowiki\n}}}\n----\n") tc("
nowiki

", "{{{\nnowiki\n}}}\n\n----\n") # nowiki tc("
nowiki
nowiki
", "{{{\nnowiki\n}}}\n{{{\nnowiki\n}}}\n") tc("
nowiki
nowiki
", "{{{\nnowiki\n}}}\n\n{{{\nnowiki\n}}}\n") # table tc("
nowiki
table
", "{{{\nnowiki\n}}}\n|table|\n") tc("
nowiki
table
", "{{{\nnowiki\n}}}\n\n|table|\n") end def test_image tc("

", "{{image.jpg}}") tc("

\"tag\"/

", "{{image.jpg|tag}}") tc("

", "{{http://example.org/image.jpg}}") end def test_bold_combo tc("

bold and

table

end

", "**bold and\n|table|\nend**") end def test_extensions tc("

This is not __underlined__

", "This is not __underlined__") tce("

This is underlined

", "This is __underlined__") tce("

This is deleted

", "This is --deleted--") tce("

This is inserted

", "This is ++inserted++") tce("

This is super

", "This is ^^super^^") tce("

This is sub

", "This is ~~sub~~") tce("

®

", "(R)") tce("

®

", "(r)") tce("

©

", "(C)") tce("

©

", "(c)") end end