// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. package markdown import ( "testing" "github.com/stretchr/testify/assert" ) func TestCommonMarkReferenceStrings(t *testing.T) { // For the most part, we aim for CommonMark compliance with the features that we support. We // also support some GitHub flavored extensions. // // You can find most of the references used here: https://github.github.com/gfm/ // CommonMark handles leading tabs that aren't on 4-character boundaries differently, so the // following reference strings will fail. The current implementation is much closer to our // webapp's behavior though, so I'm leaving it as is for now. It doesn't really impact anything // we use this package for anyways. // // " \tfoo\tbaz\t\tbim\n": "
foo\tbaz\t\tbim\n
",
// ">\t\tfoo": "", for name, tc := range map[string]struct { Markdown string ExpectedHTML string }{ "0.28-gfm-1": { Markdown: "\tfoo\tbaz\t\tbim\n", ExpectedHTML: "foo
foo\tbaz\t\tbim\n
",
},
"0.28-gfm-3": {
Markdown: " a\ta\n ὐ\ta\n",
ExpectedHTML: "a\ta\nὐ\ta\n
",
},
"0.28-gfm-4": {
Markdown: " - foo\n\n\tbar\n",
ExpectedHTML: "foo
bar
foo
bar
foo\nbar
",
},
"0.28-gfm-9": {
Markdown: " - foo\n - bar\n\t - baz",
ExpectedHTML: "a simple\n indented code block
",
},
"0.28-gfm-77": {
Markdown: " - foo\n\n bar",
ExpectedHTML: "foo
bar
foo
<a/>\n*hi*\n\n- one
",
},
"0.28-gfm-80": {
Markdown: " chunk1\n\n chunk2\n \n \n \n chunk3",
ExpectedHTML: "chunk1\n\nchunk2\n\n\n\nchunk3
",
},
"0.28-gfm-81": {
Markdown: " chunk1\n \n chunk2",
ExpectedHTML: "chunk1\n \n chunk2
",
},
"0.28-gfm-82": {
Markdown: "Foo\n bar",
ExpectedHTML: "Foo\nbar
", }, "0.28-gfm-83": { Markdown: " foo\nbar", ExpectedHTML: "foo\n
bar
", }, "0.28-gfm-85": { Markdown: " foo\n bar", ExpectedHTML: " foo\nbar
",
},
"0.28-gfm-86": {
Markdown: "\n \n foo\n ",
ExpectedHTML: "foo\n
",
},
"0.28-gfm-87": {
Markdown: " foo ",
ExpectedHTML: "foo
",
},
"0.28-gfm-88": {
Markdown: "```\n<\n >\n```",
ExpectedHTML: "<\n >\n
",
},
"0.28-gfm-89": {
Markdown: "~~~\n<\n >\n~~~",
ExpectedHTML: "<\n >\n
",
},
"0.28-gfm-91": {
Markdown: "```\naaa\n~~~\n```",
ExpectedHTML: "aaa\n~~~\n
",
},
"0.28-gfm-92": {
Markdown: "~~~\naaa\n```\n~~~",
ExpectedHTML: "aaa\n```\n
",
},
"0.28-gfm-93": {
Markdown: "````\naaa\n```\n``````",
ExpectedHTML: "aaa\n```\n
",
},
"0.28-gfm-94": {
Markdown: "~~~~\naaa\n~~~\n~~~~",
ExpectedHTML: "aaa\n~~~\n
",
},
"0.28-gfm-95": {
Markdown: "```",
ExpectedHTML: "
",
},
"0.28-gfm-96": {
Markdown: "`````\n\n```\naaa",
ExpectedHTML: "\n```\naaa
",
},
"0.28-gfm-97": {
Markdown: "> ```\n> aaa\n\nbbb",
ExpectedHTML: "aaa\n
bbb
", }, "0.28-gfm-98": { Markdown: "```\n\n \n```", ExpectedHTML: "\n \n
",
},
"0.28-gfm-99": {
Markdown: "```\n```",
ExpectedHTML: "
",
},
"0.28-gfm-100": {
Markdown: " ```\n aaa\naaa\n```",
ExpectedHTML: "aaa\naaa\n
",
},
"0.28-gfm-101": {
Markdown: " ```\naaa\n aaa\naaa\n ```",
ExpectedHTML: "aaa\naaa\naaa\n
",
},
"0.28-gfm-102": {
Markdown: " ```\n aaa\n aaa\n aaa\n ```",
ExpectedHTML: "aaa\n aaa\naaa\n
",
},
"0.28-gfm-103": {
Markdown: " ```\n aaa\n ```",
ExpectedHTML: "```\naaa\n```
",
},
"0.28-gfm-104": {
Markdown: "```\naaa\n ```",
ExpectedHTML: "aaa\n
",
},
"0.28-gfm-105": {
Markdown: " ```\naaa\n ```",
ExpectedHTML: "aaa\n
",
},
"0.28-gfm-106": {
Markdown: "```\naaa\n ```",
ExpectedHTML: "aaa\n ```
",
},
"0.28-gfm-108": {
Markdown: "~~~~~~\naaa\n~~~ ~~",
ExpectedHTML: "aaa\n~~~ ~~
",
},
"0.28-gfm-109": {
Markdown: "foo\n```\nbar\n```\nbaz",
ExpectedHTML: "foo
bar\n
baz
", }, "0.28-gfm-111": { Markdown: "```ruby\ndef foo(x)\n return 3\nend\n```", ExpectedHTML: "def foo(x)\n return 3\nend\n
",
},
"0.28-gfm-112": {
Markdown: "```ruby startline=3 $%@#$\ndef foo(x)\n return 3\nend\n```",
ExpectedHTML: "def foo(x)\n return 3\nend\n
",
},
"0.28-gfm-113": {
Markdown: "````;\n````",
ExpectedHTML: "
",
},
"0.28-gfm-115": {
Markdown: "```\n``` aaa\n```",
ExpectedHTML: "``` aaa\n
",
},
"0.28-gfm-159": {
Markdown: "[foo]: /url \"title\"\n\n[foo]",
ExpectedHTML: ``,
},
"0.28-gfm-160": {
Markdown: " [foo]: \n /url \n 'the title' \n\n[foo]",
ExpectedHTML: ``,
},
"0.28-gfm-161": {
Markdown: "[Foo*bar\\]]:my_(url) 'title (with parens)'\n\n[Foo*bar\\]]",
ExpectedHTML: ``,
},
"0.28-gfm-162": {
Markdown: "[Foo bar]:\n[foo]: /url 'title
with blank line'
[foo]
", }, "0.28-gfm-165": { Markdown: "[foo]:\n/url\n\n[foo]", ExpectedHTML: ``, }, "0.28-gfm-166": { Markdown: "[foo]:\n\n[foo]", ExpectedHTML: `[foo]:
[foo]
`, }, "0.28-gfm-167": { Markdown: "[foo]: /url\\bar\\*baz \"foo\\\"bar\\baz\"\n\n[foo]", ExpectedHTML: ``, }, "0.28-gfm-168": { Markdown: "[foo]\n\n[foo]: url", ExpectedHTML: ``, }, "0.28-gfm-169": { Markdown: "[foo]\n\n[foo]: first\n[foo]: second", ExpectedHTML: ``, }, "0.28-gfm-170": { Markdown: "[FOO]: /url\n\n[Foo]", ExpectedHTML: ``, }, "0.28-gfm-171": { Markdown: "[ΑΓΩ]: /φου\n\n[αγω]", ExpectedHTML: ``, }, "0.28-gfm-172": { Markdown: "[foo]: /url", ExpectedHTML: ``, }, "0.28-gfm-173": { Markdown: "[\nfoo\n]: /url\nbar", ExpectedHTML: `bar
`, }, "0.28-gfm-174": { Markdown: `[foo]: /url "title" ok`, ExpectedHTML: `[foo]: /url "title" ok
`, }, "0.28-gfm-175": { Markdown: "[foo]: /url\n\"title\" ok", ExpectedHTML: `"title" ok
`, }, "0.28-gfm-176": { Markdown: " [foo]: /url \"title\"\n\n[foo]", ExpectedHTML: "[foo]: /url "title"\n
[foo]
", }, "0.28-gfm-177": { Markdown: "```\n[foo]: /url\n```\n\n[foo]", ExpectedHTML: "[foo]: /url\n
[foo]
", }, "0.28-gfm-178": { Markdown: "Foo\n[bar]: /baz\n\n[bar]", ExpectedHTML: "Foo\n[bar]: /baz
[bar]
", }, "0.28-gfm-180": { Markdown: "[foo]: /foo-url \"foo\"\n[bar]: /bar-url\n\"bar\"\n[baz]: /baz-url\n\n[foo],\n[bar],\n[baz]", ExpectedHTML: ``, }, "0.28-gfm-181": { Markdown: "[foo]\n\n> [foo]: /url", ExpectedHTML: ``, }, "0.28-gfm-182": { Markdown: "aaa\n\nbbb", ExpectedHTML: "aaa
bbb
", }, "0.28-gfm-183": { Markdown: "aaa\nbbb\n\nccc\nddd", ExpectedHTML: "aaa\nbbb
ccc\nddd
", }, "0.28-gfm-184": { Markdown: "aaa\n\n\nbbb", ExpectedHTML: "aaa
bbb
", }, "0.28-gfm-185": { Markdown: " aaa\n bbb", ExpectedHTML: "aaa\nbbb
", }, "0.28-gfm-186": { Markdown: "aaa\n bbb\n ccc", ExpectedHTML: "aaa\nbbb\nccc
", }, "0.28-gfm-187": { Markdown: " aaa\nbbb", ExpectedHTML: "aaa\nbbb
", }, "0.28-gfm-188": { Markdown: " aaa\nbbb", ExpectedHTML: "aaa\n
bbb
", }, "0.28-gfm-189": { Markdown: "aaa \nbbb \n", ExpectedHTML: "aaa
bbb
", }, "0.28-gfm-206": { Markdown: "> - foo\n- bar", ExpectedHTML: "bar\nbaz\nfoo
- foo
foo\n
bar
",
},
"0.28-gfm-208": {
Markdown: "> ```\nfoo\n```",
ExpectedHTML: "foo
",
},
"0.28-gfm-209": {
Markdown: "> foo\n - bar",
ExpectedHTML: "", }, "0.28-gfm-210": { Markdown: ">", ExpectedHTML: "", }, "0.28-gfm-211": { Markdown: ">\n> \n> ", ExpectedHTML: "", }, "0.28-gfm-212": { Markdown: ">\n> foo\n> ", ExpectedHTML: "foo\n- bar
", }, "0.28-gfm-213": { Markdown: "> foo\n\n> bar", ExpectedHTML: "foo
foo
", }, "0.28-gfm-214": { Markdown: "> foo\n> bar", ExpectedHTML: "bar
", }, "0.28-gfm-215": { Markdown: "> foo\n>\n> bar", ExpectedHTML: "foo\nbar
", }, "0.28-gfm-216": { Markdown: "foo\n> bar", ExpectedHTML: "foo
bar
foo
", }, "0.28-gfm-218": { Markdown: "> bar\nbaz", ExpectedHTML: "bar
", }, "0.28-gfm-219": { Markdown: "> bar\n\nbaz", ExpectedHTML: "bar\nbaz
bar
baz
", }, "0.28-gfm-220": { Markdown: "> bar\n>\nbaz", ExpectedHTML: "bar
baz
", }, "0.28-gfm-221": { Markdown: "> > > foo\nbar", ExpectedHTML: "", }, "0.28-gfm-222": { Markdown: ">>> foo\n> bar\n>>baz", ExpectedHTML: "foo\nbar
", }, "0.28-gfm-223": { Markdown: "> code\n\n> not code", ExpectedHTML: "foo\nbar\nbaz
code\n
", }, "0.28-gfm-224": { Markdown: "A paragraph\nwith two lines.\n\n indented code\n\n> A block quote.", ExpectedHTML: "not code
A paragraph\nwith two lines.
indented code\n
", }, "0.28-gfm-225": { Markdown: "1. A paragraph\n with two lines.\n\n indented code\n\n > A block quote.", ExpectedHTML: "A block quote.
A paragraph\nwith two lines.
indented code\n
A block quote.
two
", }, "0.28-gfm-227": { Markdown: "- one\n\n two", ExpectedHTML: "one
two
two
",
},
"0.28-gfm-229": {
Markdown: " - one\n\n two",
ExpectedHTML: "one
two
", }, "0.28-gfm-231": { Markdown: ">>- one\n>>\n > > two", ExpectedHTML: "
one
two
", }, "0.28-gfm-232": { Markdown: "-one\n\n2.two", ExpectedHTML: "
- one
two
-one
2.two
", }, "0.28-gfm-233": { Markdown: "- foo\n\n\n bar", ExpectedHTML: "foo
bar
foo
bar\n
baz
bam
Foo
bar\n\n\nbaz
1234567890. not ok
", }, "0.28-gfm-238": { Markdown: "0. ok", ExpectedHTML: `-1. not ok
", }, "0.28-gfm-241": { Markdown: "- foo\n\n bar", ExpectedHTML: "foo
bar
foo
bar
indented code\n
paragraph
more code
",
},
"0.28-gfm-244": {
Markdown: "1. indented code\n\n paragraph\n\n more code",
ExpectedHTML: "indented code\n
paragraph
more code
indented code\n
paragraph
more code
foo
bar
", }, "0.28-gfm-247": { Markdown: "- foo\n\n bar", ExpectedHTML: "bar
", }, "0.28-gfm-248": { Markdown: "- foo\n\n bar", ExpectedHTML: "foo
bar
bar\n
baz
foo
", }, "0.28-gfm-252": { Markdown: "- foo\n-\n- bar", ExpectedHTML: "foo\n*
foo\n1.
", }, "0.28-gfm-257": { Markdown: " 1. A paragraph\n with two lines.\n\n indented code\n\n > A block quote.", ExpectedHTML: "A paragraph\nwith two lines.
indented code\n
A block quote.
A paragraph\nwith two lines.
indented code\n
A block quote.
A paragraph\nwith two lines.
indented code\n
A block quote.
1. A paragraph\n with two lines.\n\n indented code\n\n > A block quote.
",
},
"0.28-gfm-261": {
Markdown: " 1. A paragraph\nwith two lines.\n\n indented code\n\n > A block quote.",
ExpectedHTML: "A paragraph\nwith two lines.
indented code\n
A block quote.
", }, "0.28-gfm-264": { Markdown: "> 1. > Blockquote\n> continued here.", ExpectedHTML: "
Blockquote\ncontinued here.
", }, "0.28-gfm-265": { Markdown: "- foo\n - bar\n - baz\n - boo", ExpectedHTML: "
Blockquote\ncontinued here.
Foo
The number of windows in my house is\n14. The number of doors is 6.
", }, "0.28-gfm-278": { Markdown: "The number of windows in my house is\n1. The number of doors is 6.", ExpectedHTML: "The number of windows in my house is
foo
bar
baz
baz
bim
a
b
c
a
b
c
a
c
a
b
c
d
a
b
d
b\n\n\n
b
c
b
b
c\n
foo\n
bar
foo
baz
a
d
hi
lo`
!"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~
", }, "0.28-gfm-300": { Markdown: `\→\A\a\ \3\φ\«`, ExpectedHTML: `\→\A\a\ \3\φ\«
`, }, "0.28-gfm-301": { Markdown: `\*not emphasized* \*not emphasized* <br/> not a tag [not a link](/foo) ` + "`not code`" + ` 1. not a list * not a list # not a heading [foo]: /url "not a reference"
`, }, "0.28-gfm-304": { Markdown: "`` \\[\\` ``", ExpectedHTML: "\\[\\`
\[\]
`,
},
"0.28-gfm-306": {
Markdown: "~~~\n\\[\\]\n~~~",
ExpectedHTML: "\\[\\]\n
",
},
"0.28-gfm-309": {
Markdown: `[foo](/bar\* "ti\*tle")`,
ExpectedHTML: ``,
},
"0.28-gfm-310": {
Markdown: `[foo]
[foo]: /bar\* "ti\*tle"`,
ExpectedHTML: ``,
},
"0.28-gfm-311": {
Markdown: "``` foo\\+bar\nfoo\n```",
ExpectedHTML: "foo\n
",
},
"0.28-gfm-312": {
Markdown: " & © Æ Ď\n¾ ℋ ⅆ\n∲ ≧̸",
ExpectedHTML: "\u00a0 & © Æ Ď\n¾ ℋ ⅆ\n∲ ≧̸
", }, "0.28-gfm-313": { Markdown: "# Ӓ Ϡ ", ExpectedHTML: "# Ӓ Ϡ � �
", }, "0.28-gfm-314": { Markdown: "" ആ ಫ", ExpectedHTML: "" ആ ಫ
", }, "0.28-gfm-315": { Markdown: "  &x; \n&ThisIsNotDefined; &hi?;", ExpectedHTML: "  &x; &#; &#x;\n&ThisIsNotDefined; &hi?;
", }, "0.28-gfm-316": { Markdown: "©", ExpectedHTML: "©
", }, "0.28-gfm-317": { Markdown: "&MadeUpEntity;", ExpectedHTML: "&MadeUpEntity;
", }, "0.28-gfm-319": { Markdown: `[foo](/föö "föö")`, ExpectedHTML: ``, }, "0.28-gfm-320": { Markdown: "[foo]\n\n[foo]: /föö \"föö\"", ExpectedHTML: ``, }, "0.28-gfm-321": { Markdown: "``` föö\nfoo\n```", ExpectedHTML: "foo\n
",
},
"0.28-gfm-322": {
Markdown: "`föö`",
ExpectedHTML: "föö
föfö
",
},
"0.28-gfm-324": {
Markdown: "`foo`",
ExpectedHTML: "foo
foo ` bar
``
foo
foo bar baz
a\xa0\xa0b
foo `` bar
foo\\
bar`
*foo*
[not a link](/foo
)
<a href="
">`
<http://foo.bar.
baz>`
```foo``
", }, "0.28-gfm-339": { Markdown: "`foo", ExpectedHTML: "`foo
", }, "0.28-gfm-340": { Markdown: "`foo``bar``", ExpectedHTML: "`foobar
[link](/my uri)
`, }, "0.28-gfm-477": { Markdown: `[link]([link](</my uri>)
`, }, "0.28-gfm-478": { Markdown: "[link](foo\nbar)", ExpectedHTML: "[link](foo\nbar)
", }, "0.28-gfm-480": { Markdown: `[link](\(foo\))`, ExpectedHTML: ``, }, "0.28-gfm-481": { Markdown: `[link](foo(and(bar)))`, ExpectedHTML: ``, }, "0.28-gfm-482": { Markdown: `[link](foo\(and\(bar\))`, ExpectedHTML: ``, }, "0.28-gfm-483": { Markdown: `[link]([link](/url "title "and" title")
`, }, "0.28-gfm-493": { Markdown: `[link](/url 'title "and" title')`, ExpectedHTML: ``, }, "0.28-gfm-494": { Markdown: "[link]( /uri\n \"title\" )", ExpectedHTML: ``, }, "0.28-gfm-495": { Markdown: "[link] (/uri)", ExpectedHTML: `[link] (/uri)
`, }, "0.28-gfm-496": { Markdown: "[link [foo [bar]]](/uri)", ExpectedHTML: ``, }, "0.28-gfm-497": { Markdown: "[link] bar](/uri)", ExpectedHTML: `[link] bar](/uri)
`, }, "0.28-gfm-498": { Markdown: "[link [bar](/uri)", ExpectedHTML: `[link bar
`, }, "0.28-gfm-499": { Markdown: `[link \[bar](/uri)`, ExpectedHTML: ``, }, "0.28-gfm-501": { Markdown: "[![moon](moon.jpg)](/uri)", ExpectedHTML: ``, }, "0.28-gfm-502": { Markdown: "[foo [bar](/uri)](/uri)", ExpectedHTML: `[foo bar](/uri)
`, }, "0.28-gfm-504": { Markdown: "![[[foo](uri1)](uri2)](uri3)", ExpectedHTML: ``, }, "0.28-gfm-505": { Markdown: "*[foo*](/uri)", ExpectedHTML: `*foo*
`, }, "0.28-gfm-506": { Markdown: "[foo *bar](baz*)", ExpectedHTML: ``, }, "0.28-gfm-509": { Markdown: "[foo`](/uri)`", ExpectedHTML: `[foo](/uri)
My
`, }, "0.28-gfm-564": { Markdown: `![foo](hello $.;'there
", }, "0.28-gfm-648": { Markdown: "Foo χρῆν", ExpectedHTML: "Foo χρῆν
", }, "0.28-gfm-649": { Markdown: "Multiple spaces", ExpectedHTML: "Multiple spaces
", }, } { t.Run(name, func(t *testing.T) { assert.Equal(t, tc.ExpectedHTML, RenderHTML(tc.Markdown)) }) } } func TestCommonMarkReferenceAutolinks(t *testing.T) { // These tests are adapted from the GitHub-flavoured CommonMark extension tests located at // https://github.com/github/cmark/blob/master/test/extensions.txt for name, tc := range map[string]struct { Markdown string ExpectedHTML string }{ "autolinks-1": { Markdown: `: http://google.com https://google.com http://google.com/å www.github.com www.github.com/á www.google.com/a_b ![http://inline.com/image](http://inline.com/image) Full stop outside parens shouldn't be included http://google.com/ok. (Full stop inside parens shouldn't be included http://google.com/ok.) "http://google.com" 'http://google.com' http://🍄.ga/ http://x🍄.ga/`, ExpectedHTML: `: http://google.com https://google.com
www.github.com www.github.com/á
Full stop outside parens shouldn't be included http://google.com/ok.
(Full stop inside parens shouldn't be included http://google.com/ok.)
`, }, "autolinks-2": { Markdown: `These should not link: * @a.b.c@. x * n@. b`, ExpectedHTML: `These should not link: