1986. What a great season.
\n"
var res = test.md_to_html.write_to_string
assert res == exp
end
fun test_process_escape3 do
var test = "Ben & Lux"
var exp = "AT&T has an ampersand in their name.
AT&T is another way to write it.
This & that.
4 < 5.
6 > 5.
* In a list?
*
* It should.
> Blockquoted:
Auto-links should not occur here: ``
or here:
"""
var exp = """
Link: http://example.com/.
With an ampersand: http://example.com/?foo=1&bar=2
Blockquoted: http://example.com/
Auto-links should not occur here: <http://example.com/>
or here: <http://example.com/>
"""
var res = test.md_to_html.write_to_string
assert res == exp
end
fun test_daring_escape do
var test = """
These should all get escaped:
Backslash: \\
Backtick: \`
Asterisk: \*
Underscore: \_
Left brace: \{
Right brace: \}
Left bracket: \[
Right bracket: \]
Left paren: \(
Right paren: \)
Greater-than: \>
Hash: \#
Period: \.
Bang: \!
Plus: \+
Minus: \-
These should not, because they occur within a code block:
Backslash: \\
Backtick: \`
Asterisk: \*
Underscore: \_
Left brace: \{
Right brace: \}
Left bracket: \[
Right bracket: \]
Left paren: \(
Right paren: \)
Greater-than: \>
Hash: \#
Period: \.
Bang: \!
Plus: \+
Minus: \-
Nor should these, which occur in code spans:
Backslash: `\\`
Backtick: `` \` ``
Asterisk: `\*`
Underscore: `\_`
Left brace: `\{`
Right brace: `\}`
Left bracket: `\[`
Right bracket: `\]`
Left paren: `\(`
Right paren: `\)`
Greater-than: `\>`
Hash: `\#`
Period: `\.`
Bang: `\!`
Plus: `\+`
Minus: `\-`
These should get escaped, even though they're matching pairs for
other Markdown constructs:
\\\*asterisks\\\*
\\\_underscores\\\_
\\\`backticks\\\`
This is a code span with a literal backslash-backtick sequence: `` \` ``
This is a tag with unescaped backticks bar.
This is a tag with backslashes bar.
"""
var exp = """
These should all get escaped:
Backslash: \\
Backtick: \`
Asterisk: \*
Underscore: \_
Left brace: \{
Right brace: \}
Left bracket: \[
Right bracket: \]
Left paren: \(
Right paren: \)
Greater-than: \>
Hash: \#
Period: \.
Bang: \!
Plus: \+
Minus: \-
These should not, because they occur within a code block:
Backslash: \\
Backtick: \`
Asterisk: \*
Underscore: \_
Left brace: \{
Right brace: \}
Left bracket: \[
Right bracket: \]
Left paren: \(
Right paren: \)
Greater-than: \>
Hash: \#
Period: \.
Bang: \!
Plus: \+
Minus: \-
Nor should these, which occur in code spans:
Backslash: \\
Backtick: \`
Asterisk: \*
Underscore: \_
Left brace: \{
Right brace: \}
Left bracket: \[
Right bracket: \]
Left paren: \(
Right paren: \)
Greater-than: \>
Hash: \#
Period: \.
Bang: \!
Plus: \+
Minus: \-
These should get escaped, even though they're matching pairs for
other Markdown constructs:
*asterisks*
_underscores_
`backticks`
This is a code span with a literal backslash-backtick sequence: \`
This is a tag with unescaped backticks bar.
This is a tag with backslashes bar.
"""
var res = test.md_to_html.write_to_string
assert res == exp
end
fun test_daring_blockquotes do
var test = """
> Example:
>
> sub status {
> print "working";
> }
>
> Or:
>
> sub status {
> return "working";
> }
"""
var exp = """
Example:
sub status {
print "working";
}
Or:
sub status {
return "working";
}
"""
var res = test.md_to_html.write_to_string
assert res == exp
end
fun test_daring_code_blocks do
var test = """
code block on the first line
Regular text.
code block indented by spaces
Regular text.
the lines in this block
all contain trailing spaces
Regular Text.
code block on the last line
"""
var exp = """
code block on the first line
Regular text.
code block indented by spaces
Regular text.
the lines in this block
all contain trailing spaces
Regular Text.
code block on the last line
"""
var res = test.md_to_html.write_to_string
assert res == exp
end
fun test_daring_code_spans do
var test = """
``
Fix for backticks within HTML tag: like this
Here's how you put `` `backticks` `` in a code span.
"""
var exp = """
<test a="
content of attribute ">
Fix for backticks within HTML tag: like this
Here's how you put `backticks`
in a code span.
"""
var res = test.md_to_html.write_to_string
assert res == exp
end
fun test_daring_pars do
var proc = new MarkdownProcessor
proc.ext_mode = false
var test = """
In Markdown 1.0.0 and earlier. Version
8. This line turns into a list item.
Because a hard-wrapped line in the
middle of a paragraph looked like a
list item.
Here's one with a bullet.
* criminey.
"""
var exp = """
In Markdown 1.0.0 and earlier. Version
8. This line turns into a list item.
Because a hard-wrapped line in the
middle of a paragraph looked like a
list item.
Here's one with a bullet.
* criminey.
"""
var res = proc.process(test).write_to_string
assert res == exp
end
fun test_daring_rules do
var test = """
Dashes:
---
---
---
---
---
- - -
- - -
- - -
- - -
- - -
Asterisks:
***
***
***
***
***
* * *
* * *
* * *
* * *
* * *
Underscores:
___
___
___
___
___
_ _ _
_ _ _
_ _ _
_ _ _
_ _ _
"""
var exp = """
Dashes:
---
- - -
Asterisks:
***
* * *
Underscores:
___
_ _ _
"""
var res = test.md_to_html.write_to_string
assert res == exp
end
fun test_daring_images do
var test = """
![Alt text](/path/to/img.jpg)
![Alt text](/path/to/img.jpg "Optional title")
Inline within a paragraph: [alt text](/url/).
![alt text](/url/ "title preceded by two spaces")
![alt text](/url/ "title has spaces afterward" )
![alt text]()
![alt text]( "with a title").
![Empty]()
![this is a stupid URL](http://example.com/(parens).jpg)
![alt text][foo]
[foo]: /url/
![alt text][bar]
[bar]: /url/ "Title here"
"""
var exp = """
Inline within a paragraph: alt text.
.
"""
var res = test.md_to_html.write_to_string
assert res == exp
end
fun test_daring_inline_html1 do
var test = """
Here's a simple block:
foo
This should be a code block, though:
foo
As should this:
foo
Now, nested:
This should just be an HTML comment:
Multiline:
Code block:
Just plain comment, with trailing spaces on the line:
Code:
Hr's:
"""
var exp = """
Here's a simple block:
foo
This should be a code block, though:
<div>
foo
</div>
As should this:
<div>foo</div>
Now, nested:
This should just be an HTML comment:
Multiline:
Code block:
<!-- Comment -->
Just plain comment, with trailing spaces on the line:
Code:
<hr />
Hr's:
"""
var res = test.md_to_html.write_to_string
assert res == exp
end
fun test_daring_inline_html2 do
var test = """
Simple block on one line:
foo
And nested without indentation:
And with attributes:
This was broken in 1.0.2b7:
"""
var exp = """
Simple block on one line:
foo
And nested without indentation:
And with attributes:
This was broken in 1.0.2b7:
"""
var res = test.md_to_html.write_to_string
assert res == exp
end
fun test_daring_inline_html3 do
var test = """
Paragraph one.
Paragraph two.
The end.
"""
var exp = """
Paragraph one.
Paragraph two.
The end.
"""
var res = test.md_to_html.write_to_string
assert res == exp
end
fun test_daring_links1 do
var test = """
Just a [URL](/url/).
[URL and title](/url/ "title").
[URL and title](/url/ "title preceded by two spaces").
[URL and title](/url/ "title preceded by a tab").
[URL and title](/url/ "title has spaces afterward" ).
[URL wrapped in angle brackets]().
[URL w/ angle brackets + title]( "Here's the title").
[Empty]().
[With parens in the URL](http://en.wikipedia.org/wiki/WIMP_(computing))
(With outer parens and [parens in url](/foo(bar)))
[With parens in the URL](/foo(bar) "and a title")
(With outer parens and [parens in url](/foo(bar) "and a title"))
"""
var exp = """
Just a URL.
URL and title.
URL and title.
URL and title.
URL and title.
URL wrapped in angle brackets.
URL w/ angle brackets + title.
Empty.
With parens in the URL
(With outer parens and parens in url)
With parens in the URL
(With outer parens and parens in url)
"""
var res = test.md_to_html.write_to_string
assert res == exp
end
fun test_daring_links2 do
var test = """
Foo [bar] [1].
Foo [bar][1].
Foo [bar]
[1].
[1]: /url/ "Title"
With [embedded [brackets]] [b].
Indented [once][].
Indented [twice][].
Indented [thrice][].
Indented [four][] times.
[once]: /url
[twice]: /url
[thrice]: /url
[four]: /url
[b]: /url/
* * *
[this] [this] should work
So should [this][this].
And [this] [].
And [this][].
And [this].
But not [that] [].
Nor [that][].
Nor [that].
[Something in brackets like [this][] should work]
[Same with [this].]
In this case, [this](/somethingelse/) points to something else.
Backslashing should suppress \\\[this] and [this\\\].
[this]: foo
* * *
Here's one where the [link
breaks] across lines.
Here's another where the [link
breaks] across lines, but with a line-ending space.
[link breaks]: /url/
"""
var exp = """
Foo bar.
Foo bar.
Foo bar.
With embedded [brackets].
Indented once.
Indented twice.
Indented thrice.
Indented [four][] times.
[four]: /url
this should work
So should this.
And this.
And this.
And this.
But not [that] [].
Nor [that][].
Nor [that].
[Something in brackets like this should work]
[Same with this.]
In this case, this points to something else.
Backslashing should suppress [this] and [this].
Here's one where the link
breaks across lines.
Here's another where the link
breaks across lines, but with a line-ending space.
"""
var res = test.md_to_html.write_to_string
assert res == exp
end
fun test_daring_links3 do
var test = """
This is the [simple case].
[simple case]: /simple
This one has a [line
break].
This one has a [line
break] with a line-ending space.
[line break]: /foo
[this] [that] and the [other]
[this]: /this
[that]: /that
[other]: /other
"""
var exp = """
This is the simple case.
This one has a line
break.
This one has a line
break with a line-ending space.
this and the other
"""
var res = test.md_to_html.write_to_string
assert res == exp
end
fun test_daring_nested do
var test = """
> foo
>
> > bar
>
> foo
"""
var exp = """
foo
bar
foo
"""
var res = test.md_to_html.write_to_string
assert res == exp
end
fun test_daring_list do
var test = """
## Unordered
Asterisks tight:
* asterisk 1
* asterisk 2
* asterisk 3
Asterisks loose:
* asterisk 1
* asterisk 2
* asterisk 3
* * *
Pluses tight:
+ Plus 1
+ Plus 2
+ Plus 3
Pluses loose:
+ Plus 1
+ Plus 2
+ Plus 3
* * *
Minuses tight:
- Minus 1
- Minus 2
- Minus 3
Minuses loose:
- Minus 1
- Minus 2
- Minus 3
## Ordered
Tight:
1. First
2. Second
3. Third
and:
1. One
2. Two
3. Three
Loose using tabs:
1. First
2. Second
3. Third
and using spaces:
1. One
2. Two
3. Three
Multiple paragraphs:
1. Item 1, graf one.
Item 2. graf two. The quick brown fox jumped over the lazy dog's
back.
2. Item 2.
3. Item 3.
## Nested
* Tab
* Tab
* Tab
Here's another:
1. First
2. Second:
* Fee
* Fie
* Foe
3. Third
Same thing but with paragraphs:
1. First
2. Second:
* Fee
* Fie
* Foe
3. Third
"""
var exp = """
Unordered
Asterisks tight:
- asterisk 1
- asterisk 2
- asterisk 3
Asterisks loose:
asterisk 1
asterisk 2
asterisk 3
Pluses tight:
Pluses loose:
Minuses tight:
Minuses loose:
Ordered
Tight:
- First
- Second
- Third
and:
- One
- Two
- Three
Loose using tabs:
First
Second
Third
and using spaces:
One
Two
Three
Multiple paragraphs:
Item 1, graf one.
Item 2. graf two. The quick brown fox jumped over the lazy dog's
back.
Item 2.
Item 3.
Nested
Here's another:
- First
- Second:
- Third
Same thing but with paragraphs:
First
Second:
Third
"""
var res = test.md_to_html.write_to_string
assert res == exp
end
fun test_daring_strong_em do
var test = """
***This is strong and em.***
So is ***this*** word.
___This is strong and em.___
So is ___this___ word.
"""
var exp = """
This is strong and em.
So is this word.
This is strong and em.
So is this word.
"""
var res = test.md_to_html.write_to_string
assert res == exp
end
fun test_daring_tabs do
var test = """
+ this is a list item
indented with tabs
+ this is a list item
indented with spaces
Code:
this code block is indented by one tab
And:
this code block is indented by two tabs
And:
+ this is an example list item
indented with tabs
+ this is an example list item
indented with spaces
"""
var exp = """
Code:
this code block is indented by one tab
And:
this code block is indented by two tabs
And:
+ this is an example list item
indented with tabs
+ this is an example list item
indented with spaces
"""
var res = test.md_to_html.write_to_string
assert res == exp
end
fun test_daring_tidyness do
var test = """
> A list within a blockquote:
>
> * asterisk 1
> * asterisk 2
> * asterisk 3
"""
var exp = """
A list within a blockquote:
- asterisk 1
- asterisk 2
- asterisk 3
"""
var res = test.md_to_html.write_to_string
assert res == exp
end
end
class TestBlock
super TestSuite
fun test_has_blocks do
var subject = new MDBlock
assert not subject.has_blocks
subject.first_block = new MDBlock
assert subject.has_blocks
end
fun test_count_blocks do
var subject = new MDBlock
assert subject.count_blocks == 0
subject.first_block = new MDBlock
assert subject.count_blocks == 1
subject.first_block.next = new MDBlock
assert subject.count_blocks == 2
end
fun test_has_lines do
var subject = new MDBlock
assert not subject.has_lines
subject.first_line = new MDLine("")
assert subject.has_lines
end
fun test_count_lines do
var subject = new MDBlock
assert subject.count_lines == 0
subject.first_line = new MDLine("")
assert subject.count_lines == 1
subject.first_line.next = new MDLine("")
assert subject.count_lines == 2
end
fun test_split do
var line1 = new MDLine("line1")
var line2 = new MDLine("line2")
var line3 = new MDLine("line3")
var subject = new MDBlock
subject.add_line line1
subject.add_line line2
subject.add_line line3
var block = subject.split(line2)
assert subject.count_blocks == 1
assert subject.count_lines == 1
assert subject.first_line == line3
assert block.count_blocks == 0
assert block.count_lines == 2
assert block.first_line == line1
assert block.last_line == line2
end
fun test_add_line do
var subject = new MDBlock
assert subject.count_lines == 0
subject.add_line new MDLine("")
assert subject.count_lines == 1
subject.add_line new MDLine("")
assert subject.count_lines == 2
end
fun test_remove_line do
var line1 = new MDLine("line1")
var line2 = new MDLine("line2")
var line3 = new MDLine("line3")
var subject = new MDBlock
subject.add_line line1
subject.add_line line2
subject.add_line line3
subject.remove_line(line2)
assert subject.count_lines == 2
subject.remove_line(line1)
assert subject.count_lines == 1
assert subject.first_line == line3
assert subject.last_line == line3
end
fun test_transform_headline1 do
var subject = new MDBlock
var kind = new BlockHeadline(subject)
subject.add_line new MDLine(" # Title 1 ")
kind.transform_headline(subject)
assert kind.depth == 1
assert subject.first_line.value == "Title 1"
end
fun test_transform_headline2 do
var subject = new MDBlock
var kind = new BlockHeadline(subject)
subject.add_line new MDLine(" #####Title 5 ")
kind.transform_headline(subject)
assert kind.depth == 5
assert subject.first_line.value == "Title 5"
end
fun test_remove_quote_prefix do
var subject = new MDBlock
var kind = new BlockQuote(subject)
subject.add_line new MDLine(" > line 1")
subject.add_line new MDLine(" > line 2")
subject.add_line new MDLine(" > line 3")
kind.remove_block_quote_prefix(subject)
assert subject.first_line.value == "line 1"
assert subject.first_line.next.value == "line 2"
assert subject.first_line.next.next.value == "line 3"
end
fun test_remove_leading_empty_lines_1 do
var block = new MDBlock
block.add_line new MDLine("")
block.add_line new MDLine("")
block.add_line new MDLine("")
block.add_line new MDLine("")
block.add_line new MDLine(" text")
block.add_line new MDLine("")
assert block.remove_leading_empty_lines
assert block.first_line.value == " text"
end
fun test_remove_leading_empty_lines_2 do
var block = new MDBlock
block.add_line new MDLine(" text")
block.remove_leading_empty_lines
assert block.first_line.value == " text"
end
fun test_remove_trailing_empty_lines_1 do
var block = new MDBlock
block.add_line new MDLine("")
block.add_line new MDLine("text")
block.add_line new MDLine("")
block.add_line new MDLine("")
block.add_line new MDLine("")
block.add_line new MDLine("")
assert block.remove_trailing_empty_lines
assert block.last_line.value == "text"
end
fun test_remove_trailing_empty_lines_2 do
var block = new MDBlock
block.add_line new MDLine("text ")
assert not block.remove_trailing_empty_lines
assert block.last_line.value == "text "
end
fun test_remove_surrounding_empty_lines do
var block = new MDBlock
block.add_line new MDLine("")
block.add_line new MDLine("text")
block.add_line new MDLine("")
block.add_line new MDLine("")
block.add_line new MDLine("")
block.add_line new MDLine("")
assert block.remove_surrounding_empty_lines
assert block.first_line.value == "text"
assert block.last_line.value == "text"
end
end
class TestLine
super TestSuite
var subject: MDLine
fun test_is_empty do
subject = new MDLine("")
assert subject.is_empty
subject = new MDLine(" ")
assert subject.is_empty
subject = new MDLine("test")
assert not subject.is_empty
subject = new MDLine(" test")
assert not subject.is_empty
end
fun test_leading do
subject = new MDLine("")
assert subject.leading == 0
subject = new MDLine(" ")
assert subject.leading == 4
subject = new MDLine("test")
assert subject.leading == 0
subject = new MDLine(" test")
assert subject.leading == 4
end
fun test_trailing do
subject = new MDLine("")
assert subject.trailing == 0
subject = new MDLine(" ")
assert subject.trailing == 0
subject = new MDLine("test ")
assert subject.trailing == 3
subject = new MDLine(" test ")
assert subject.trailing == 1
end
fun test_line_type do
var v = new MarkdownProcessor
subject = new MDLine("")
assert v.line_kind(subject) isa LineEmpty
subject = new MDLine(" ")
assert v.line_kind(subject) isa LineEmpty
subject = new MDLine("text ")
assert v.line_kind(subject) isa LineOther
subject = new MDLine(" # Title")
assert v.line_kind(subject) isa LineHeadline
subject = new MDLine(" ### Title")
assert v.line_kind(subject) isa LineHeadline
subject = new MDLine(" code")
assert v.line_kind(subject) isa LineCode
subject = new MDLine(" Title ")
subject.next = new MDLine("== ")
assert v.line_kind(subject) isa LineHeadline1
subject = new MDLine(" Title ")
subject.next = new MDLine("-- ")
assert v.line_kind(subject) isa LineHeadline2
subject = new MDLine(" * * * ")
assert v.line_kind(subject) isa LineHR
subject = new MDLine(" *** ")
assert v.line_kind(subject) isa LineHR
subject = new MDLine("- -- ")
assert v.line_kind(subject) isa LineHR
subject = new MDLine("--------- ")
assert v.line_kind(subject) isa LineHR
subject = new MDLine(" >")
assert v.line_kind(subject) isa LineBlockquote
subject = new MDLine("")
assert v.line_kind(subject) isa LineXML
subject = new MDLine("")
assert v.line_kind(subject) isa LineOther
subject = new MDLine(" * foo")
assert v.line_kind(subject) isa LineUList
subject = new MDLine("- foo")
assert v.line_kind(subject) isa LineUList
subject = new MDLine("+ foo")
assert v.line_kind(subject) isa LineUList
subject = new MDLine("1. foo")
assert v.line_kind(subject) isa LineOList
subject = new MDLine(" 11111. foo")
assert v.line_kind(subject) isa LineOList
end
fun test_line_type_ext do
var v = new MarkdownProcessor
subject = new MDLine(" ~~~")
assert v.line_kind(subject) isa LineFence
subject = new MDLine(" ```")
assert v.line_kind(subject) isa LineFence
end
fun test_count_chars do
subject = new MDLine("")
assert subject.count_chars('*') == 0
subject = new MDLine("* ")
assert subject.count_chars('*') == 1
subject = new MDLine(" * text")
assert subject.count_chars('*') == 0
subject = new MDLine(" * * *")
assert subject.count_chars('*') == 3
subject = new MDLine("text ** ")
assert subject.count_chars('*') == 0
end
fun test_count_chars_start do
subject = new MDLine("")
assert subject.count_chars_start('*') == 0
subject = new MDLine("* ")
assert subject.count_chars_start('*') == 1
subject = new MDLine(" * text")
assert subject.count_chars_start('*') == 1
subject = new MDLine(" * * * text")
assert subject.count_chars_start('*') == 3
subject = new MDLine("text ** ")
assert subject.count_chars_start('*') == 0
end
end
class TestHTMLDecorator
super TestSuite
fun test_headlines do
var test = """
# **a**
## a.a
### a.a.b
### a.a.b
## a.b
# [b](test)
## b.a
### b.a.c
## b.b
## b.c
# c
"""
var proc = new MarkdownProcessor
var decorator = proc.emitter.decorator.as(HTMLDecorator)
proc.process(test)
var res = ""
for id, headline in decorator.headlines do
res += "{headline.title}:{id}\n"
end
var exp = """
**a**:a
a.a:a.a
a.a.b:a.a.b
a.a.b:a.a.b_1
a.b:a.b
[b](test):btest
b.a:b.a
b.a.c:b.a.c
b.b:b.b
b.c:b.c
c:c
"""
assert res == exp
end
end