require 'trac_wiki' class Bacon::Context def tc(html, wiki, options = {}) TracWiki.render(wiki, options).should.equal html end def tce(html, wiki) tc(html, wiki, :extensions => true) end end describe TracWiki::Parser do it 'should parse bold' do # 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" # Bold can be used inside list items tc "", "* This is **bold**" # Bold can be used inside table cells tc("
This is bold
", "||This is **bold**||") # Links can appear inside bold text: tc("

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

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

This is bold

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

This is

bold maybe

", "This **is\n\nbold** maybe") # Bold should be able to cross lines tc "

This is bold

", "This **is\nbold**" end it 'should parse italic' do # 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") # Italic can be used inside list items tc "", "* This is ''italic''" # Italic can be used inside table cells tc("
This is italic
", "||This is ''italic''||") # Links can appear inside italic text: tc("

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

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

This is italic

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

This is

italic maybe

", "This ''is\n\nitalic'' maybe") # Italic should be able to cross lines tc "

This is italic

", "This ''is\nitalic''" end it 'should parse bold italics' do # By example tc "

bold italics

", "**''bold italics''**" # By example tc "

bold italics

", "''**bold italics**''" # By example tc "

This is also good.

", "''This is **also** good.''" end it 'should parse headings' do # 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 tc "

Heading 4

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

Heading 1

", "=Heading 1" tc "

Heading 2

", "== Heading 2" tc "

Heading 3

", " === Heading 3" # 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 ===========" # Whitespace is allowed before the left-side equal signs. tc "

Heading 1

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

Heading 2

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

Heading 1

", " = Heading 1 = " tc "

Heading 2

", " == Heading 2 == \t " # WARNING: !! XXX 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" # Line must start with equal sign tc "

foo = Heading 1 =

", "foo = Heading 1 =" end it 'should parse links' do # Links tc "

link

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

Hello, world

", "Hello, [[world]]" # Named links tc "

Go to my page

", "[[MyBigPage|Go to my page]]" # URLs tc "

http://www.example.org/

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

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

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

Visit the Example website

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

Weird Stuff

", "[[Weird Stuff|**Weird** ''Stuff'']]" tc("

", "[[http://example.org/|{{image.jpg}}]]") # 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 it 'should parse freestanding urls' do # Free-standing URL's should be turned into links tc "

http://www.example.org/

", "http://www.example.org/" # URL ending in . tc "

Text http://example.org. other text

", "Text http://example.org. other text" # URL ending in ), tc "

Text (http://example.org), other text

", "Text (http://example.org), other text" # URL ending in ). tc "

Text (http://example.org). other text

", "Text (http://example.org). other text" # URL ending in ). tc "

Text (http://example.org).

", "Text (http://example.org)." # URL ending in ) tc "

Text (http://example.org)

", "Text (http://example.org)" end it 'should parse paragraphs' do # 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." # A list end paragraphs too. tc "

Hello

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

Hello

Cell
", "Hello\n||Cell||" # 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 it 'should parse linebreaks' do # \\ (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 it 'should parse unordered_lists' do # List items begin with a * at the beginning of a line. # An item ends at the next * tc "", "* Item 1\n *Item 2\n *\t\tItem 3\n" # Whitespace is optional before and after the *. tc("", " * Item 1\n*Item 2\n \t*\t\tItem 3\n") # A space is required if if the list element starts with bold text. tc("", "***Item 1") tc("", "* **Item 1") # An item ends at blank line tc("

Par

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

Heading

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

Not bold

", "*Hello,\nWorld!\n\n**Not bold\n") end it 'should parse ordered lists' do # List items begin with a * at the beginning of a line. # 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" # 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") # 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") # An item ends at blank line tc("
  1. Item

Par

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

Heading

", "# Item\n= Heading =\n") # An item ends at a table tc("
  1. Item
Cell
", "# Item\n||Cell||\n") # An item ends at a nowiki block tc("
  1. Item
Code
", "# Item\n{{{\nCode\n}}}\n") # 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.") # An item can contain line breaks tc("
  1. The quick brown
    fox jumps over lazy dog.
", "# The quick brown\\\\fox jumps over lazy dog.") # Nested tc "
  1. Item 1
    1. Item 2
  2. Item 3
", "# Item 1\n ##Item 2\n #\t\tItem 3\n" # 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") # The two-bullet rule only applies to **. tc("
    1. Item
", "##Item") end it 'should parse ordered lists #2' do 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 it 'should parse ambiguious mixed lists' do # 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 it 'should parse ambiguious italics and url' do # 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 tc("

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

", "Formatted fruits, for example:''apples'', oranges, **pears** ...") end it 'should parse ambiguious bold and lists' do tc "

bold text

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

bold text

", " ** bold text **" end it 'should parse nowiki' do # ... works as block tc "
Hello
", "{{{\nHello\n}}}\n" # ... works inline tc "

Hello world.

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

Hello world.

", "{{{Hello}}} {{{world}}}." # No wiki markup is interpreted inbetween tc "
**Hello**
", "{{{\n**Hello**\n}}}\n" # 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 it 'should escape html' do # 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 it 'should support character escape' do 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 tc "

http://example.org/~user/

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

http://www.example.org/

", "~http://www.example.org/" end it 'should parse horizontal rule' do # Four hyphens make a horizontal rule tc "
", "----" # Whitespace around them is allowed tc "
", " ----" tc "
", "---- " tc "
", " ---- " tc "
", " \t ---- \t " # Nothing else than hyphens and whitespace is "allowed" tc "

foo ----

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

---- foo

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

-- --

", " -- -- " tc "

-- --

", " --\t-- " end it 'should parse table' do tc "
Hello, World!
", "||Hello, World!||" tc "
Hello, Right World!
", "|| Hello, Right World!||" tc "
Hello, Right World!
", "||= Hello, Right World!=||" tc "
Hello, Centered World!
", "|| Hello, Centered World! ||" tc "
Hello, Centered World!
", "||= Hello, Centered 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 "
c1c2
", "||c1|| ||c2" # 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 it 'should parse following table' do # 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 it 'should parse following heading' do # 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 it 'should parse following paragraph' do # 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 it 'should parse following unordered list' do # 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 it 'should parse following ordered list' do # 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 it 'should parse following horizontal rule' do # 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 it 'should parse following nowiki block' do # 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 it 'should parse image' do tc("

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

\"tag\"/

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

", "{{http://example.org/image.jpg}}") end it 'should parse bold combo' do tc("

bold and

table

end

", "**bold and\n||table||\nend**") end it 'should support extensions' do tce("

This is underlined

", "This is __underlined__") tce("

This is deleted

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

This is super

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

This is sub

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

®

", "(R)") tce("

®

", "(r)") tce("

©

", "(C)") tce("

©

", "(c)") end it 'should support no_escape' do tc("

a/b/c

", "[[a/b/c]]") tc("

a/b/c

", "[[a/b/c]]", :no_escape => true) end end