{ "regular_tests": [ { "name": "codeblock_hilite", "input": "Hamlet said:\n~~~~.python \ndef speak(self):\n x = 1\n~~~~", "expected_output": "

Hamlet said:

\n
def speak(self):\n    x = 1\n
", "marked_expected_output": "

Hamlet said:

\n
def speak(self):\n    x = 1\n
", "text_content": "Hamlet said:\ndef speak(self):\n x = 1\n" }, { "name": "codeblock_hilite", "input": "``` inventedlanguage\ndef speak(self):\n x = 1\n```", "expected_output": "
def speak(self):\n    x = 1\n
", "text_content": "def speak(self):\n x = 1\n" }, { "name": "codeblock_canonicalize_lang_alias", "input": "``` py2\ndef speak(self):\n x = 1\n```", "expected_output": "
def speak(self):\n    x = 1\n
", "marked_expected_output": "
def speak(self):\n    x = 1\n
", "text_content": "def speak(self):\n x = 1\n" }, { "name": "ampampamp", "input": "& & &\n~~~~\n& & &\n~~~~\n & & &", "expected_output": "

& & &

\n
& & &\n
\n
& & &\n
" }, { "name": "basic_paragraph", "input": "test_input", "expected_output": "

test_input

", "text_content": "test_input" }, { "name": "codeblock_multiline", "input": "Hamlet once said\n~~~~\ndef func():\n x = 1\n\n y = 2\n\n z = 3\n~~~~\nAnd all was good.", "expected_output": "

Hamlet once said

\n
def func():\n    x = 1\n\n    y = 2\n\n    z = 3\n
\n

And all was good.

", "text_content": "Hamlet once said\ndef func():\n x = 1\n\n y = 2\n\n z = 3\n\nAnd all was good." }, { "name": "test", "input": "it's lunch time", "expected_output": "

it's lunch time

" }, { "name": "codeblock_trailing_whitespace", "input": "Hamlet once said\n~~~~\ndef func():\n x = 1\n\n y = 2\t\t\n\n z = 3 \n~~~~\nAnd all was good.", "expected_output": "

Hamlet once said

\n
def func():\n    x = 1\n\n    y = 2\n\n    z = 3\n
\n

And all was good.

", "text_content": "Hamlet once said\ndef func():\n x = 1\n\n y = 2\n\n z = 3\n\nAnd all was good." }, { "name": "inline_code_spaces", "input": "` outer ` ``` space ```", "expected_output": "

outer space

", "text_content": " outer space " }, { "name": "inline_code_html_entities", "input": "`< >`", "expected_output": "

<&nbsp;>

", "text_content": "< >" }, { "name": "codeblock_backticks", "input": "\n```\nfenced code\n```\n\n```inline code```\n", "expected_output": "
fenced code\n
\n

inline code

", "text_content": "fenced code\n\ninline code" }, { "name": "hanging_multi_codeblock", "input": "Hamlet said:\n~~~~\ndef speak(self):\n x = 1\n# Comment to make this code block longer to test Trac #1162\n~~~~\n\nThen he mentioned ````y = 4 + x**2```` and\n~~~~\ndef foobar(self):\n return self.baz()", "expected_output": "

Hamlet said:

\n
def speak(self):\n    x = 1\n# Comment to make this code block longer to test Trac #1162\n
\n

Then he mentioned y = 4 + x**2 and

\n
def foobar(self):\n    return self.baz()\n
", "text_content": "Hamlet said:\ndef speak(self):\n x = 1\n# Comment to make this code block longer to test Trac #1162\n\nThen he mentioned y = 4 + x**2 and\ndef foobar(self):\n return self.baz()\n" }, { "name": "fenced_quote", "input": "Hamlet said:\n~~~ quote\nTo be or **not** to be.\n\nThat is the question\n~~~", "expected_output": "

Hamlet said:

\n
\n

To be or not to be.

\n

That is the question

\n
", "text_content": "Hamlet said:\n> To be or not to be.\n> That is the question\n" }, { "name": "fenced_nested_quote", "input": "Hamlet said:\n~~~ quote\nPolonius said:\n> This above all: to thine ownself be true,\nAnd it must follow, as the night the day,\nThou canst not then be false to any man.\n\nWhat good advice!\n~~~", "expected_output": "

Hamlet said:

\n
\n

Polonius said:

\n
\n

This above all: to thine ownself be true,
\nAnd it must follow, as the night the day,
\nThou canst not then be false to any man.

\n
\n

What good advice!

\n
", "text_content": "Hamlet said:\n> Polonius said:\n> > This above all: to thine ownself be true,\n> > And it must follow, as the night the day,\n> > Thou canst not then be false to any man.\n> What good advice!\n" }, { "name": "complexly_nested_quote", "input": "I heard about this second hand...\n~~~ quote\n\nHe said:\n~~~ quote\nThe customer is complaining.\n\nThey looked at this code:\n``` \ndef hello(): print 'hello\n```\nThey would prefer:\n~~~\ndef hello()\n puts 'hello'\nend\n~~~\n\nPlease advise.\n~~~\n\nShe said:\n~~~ quote\nJust send them this:\n```\necho \"hello\n\"\n```\n~~~", "expected_output": "

I heard about this second hand...

\n
\n

He said:

\n
\n

The customer is complaining.

\n

They looked at this code:

\n
def hello(): print 'hello\n
\n

They would prefer:

\n
\n

def hello()
\n puts 'hello'
\nend

\n
\n

Please advise.

\n
She said:\n~~~ quote\nJust send them this:\n```\necho "hello\n"\n```\n
", "text_content": "I heard about this second hand...\n> He said:\n> > The customer is complaining.\n> > They looked at this code:\n> > def hello(): print 'hello\n> > They would prefer:\n> def hello()\n> puts 'hello'\n> end\n\nPlease advise.\nShe said:\n~~~ quote\nJust send them this:\n```\necho \"hello\n\"\n```\n" }, { "name": "fenced_quotes_inside_mathblock", "input": "```math\n````js\nvar x;\n````\n```", "expected_output": "

jsvarx;````js\nvar x;\n````‘‘‘‘jsvarx;‘‘‘‘

" }, { "name": "empty_single_blockquote", "input": ">", "expected_output": "

>

" }, { "name": "empty_multiple_blockquote", "input": ">>>>>", "expected_output": "
\n
\n
\n
\n

>

\n
\n
\n
\n
" }, { "name": "non_empty_blockquote", "input": ">\n>\ntext", "expected_output": "
\n

text

\n
" }, { "name": "multiple_blockquote", "input": "> Hello world!\n\n> Hello universe!", "expected_output": "
\n

Hello world!

\n
\n
\n

Hello universe!

\n
" }, { "name": "multiple_blockquote", "input": "```quote\nText in\nmultiple lines.\n```\n\n> Text in a single line.", "expected_output": "
\n

Text in
\nmultiple lines.

\n
\n
\n

Text in a single line.

\n
" }, { "name": "multiple_blockquote_with_quote_and_reply", "input": "Hamlet said:\n~~~quote\nCan we talk ?\n~~~\n> Yes !!\n\nWelcome to Open Source.", "expected_output": "

Hamlet said:

\n
\n

Can we talk ?

\n
\n
\n

Yes !!

\n
\n

Welcome to Open Source.

", "text_content": "Hamlet said:\n> Can we talk ?\n\n> Yes !!\n\nWelcome to Open Source." }, { "name": "fenced_quote_with_hashtag", "input": "```quote\n# line 1\n#line 2\n```", "expected_output": "
\n

line 1

\n

#line 2

\n
", "text_content": "> line 1\n> #line 2\n" }, { "name": "fenced_quote_and_list", "input": "Before:\n* One.\n* Two.\n\n```quote\nLists should work after a quote\n```\n\nAfter:\n* One.\n* Two.", "expected_output": "

Before:

\n\n
\n

Lists should work after a quote

\n
\n

After:

\n", "text_content": "Before:\n\nOne.\nTwo.\n\n> Lists should work after a quote\n\nAfter:\n\nOne.\nTwo.\n" }, { "name": "dangerous_block", "input": "xxxxxx xxxxx xxxxxxxx xxxx. x xxxx xxxxxxxxxx:\n\n```\"xxxx xxxx\\xxxxx\\xxxxxx\"```\n\nxxx xxxx xxxxx:```xx.xxxxxxx(x'^xxxx$', xx.xxxxxxxxx)```\n\nxxxxxxx'x xxxx xxxxxxxxxx ```'xxxx'```, xxxxx xxxxxxxxx xxxxx ^ xxx $ xxxxxx xxxxx xxxxxxxxxxxx xxx xxxx xx x xxxx xx xxxx xx xxx xxxxx xxxxxx?", "expected_output": "

xxxxxx xxxxx xxxxxxxx xxxx. x xxxx xxxxxxxxxx:

\n

\"xxxx xxxx\\xxxxx\\xxxxxx\"

\n

xxx xxxx xxxxx:xx.xxxxxxx(x'^xxxx$', xx.xxxxxxxxx)

\n

xxxxxxx'x xxxx xxxxxxxxxx 'xxxx', xxxxx xxxxxxxxx xxxxx ^ xxx $ xxxxxx xxxxx xxxxxxxxxxxx xxx xxxx xx x xxxx xx xxxx xx xxx xxxxx xxxxxx?

", "text_content": "xxxxxx xxxxx xxxxxxxx xxxx. x xxxx xxxxxxxxxx:\n\"xxxx xxxx\\xxxxx\\xxxxxx\"\nxxx xxxx xxxxx:xx.xxxxxxx(x'^xxxx$', xx.xxxxxxxxx)\nxxxxxxx'x xxxx xxxxxxxxxx 'xxxx', xxxxx xxxxxxxxx xxxxx ^ xxx $ xxxxxx xxxxx xxxxxxxxxxxx xxx xxxx xx x xxxx xx xxxx xx xxx xxxxx xxxxxx?" }, { "name": "dangerous_block", "input": "``` one ```\n\n``` two ```\n\n~~~~\nx = 1", "expected_output": "

one

\n

two

\n
x = 1\n
", "text_content": " one \n two \nx = 1\n" }, { "name": "four_space_code_block", "input": " def foo(): pass", "expected_output": "
def foo(): pass\n
", "text_content": "def foo(): pass\n" }, { "name": "two_space_not_code_block", "input": " notcode", "expected_output": "

notcode

", "marked_expected_output": "

notcode

", "text_content": "notcode" }, { "name": "hashheading_enabled", "input": "# Hello world", "expected_output": "

Hello world

" }, { "name": "hashheading_needs_spaces", "input": "#Hello world", "expected_output": "

#Hello world

" }, { "name": "hashheading_multiple_spaces", "input": "# Hello world", "expected_output": "

Hello world

" }, { "name": "hashheading_6_levels", "input": "###### Hello world", "expected_output": "
Hello world
" }, { "name": "hashheading_7_levels", "input": "####### Hello world", "expected_output": "

####### Hello world

" }, { "name": "reference_links_disabled", "input": "Hello [world]\n\n[world]: https://google.com", "expected_output": "

Hello [world]

\n

[world]: https://google.com

" }, { "name": "reference_links_disabled_2", "input": "Hello [world][ref-name]\n\n[ref-name]: https://google.com", "expected_output": "

Hello [world][ref-name]

\n

[ref-name]: https://google.com

" }, { "name": "ulist_standard_1", "input": "Some text with a list:\n\n* One item\n* Two items\n* Three items", "expected_output": "

Some text with a list:

\n", "text_content": "Some text with a list:\n\nOne item\nTwo items\nThree items\n" }, { "name": "ulist_standard_2", "input": "Some text with a list:\n\n- One item\n- Two items\n- Three items", "expected_output": "

Some text with a list:

\n", "text_content": "Some text with a list:\n\nOne item\nTwo items\nThree items\n" }, { "name": "ulist_standard_3", "input": "Some text with a list:\n\n+ One item\n+ Two items\n+ Three items", "expected_output": "

Some text with a list:

\n", "text_content": "Some text with a list:\n\nOne item\nTwo items\nThree items\n" }, { "name": "list_complexly_nested", "input": "This is a heavily nested OL\n1. level-1\n 2. level-2\n 3. level-3\n 3. level-3a\n 2. level-2a\n2. level-1a\n", "expected_output": "

This is a heavily nested OL

\n
    \n
  1. level-1
      \n
    1. level-2
        \n
      1. level-3
      2. \n
      3. level-3a
      4. \n
      \n
    2. \n
    3. level-2a
    4. \n
    \n
  2. \n
  3. level-1a
  4. \n
" }, { "name": "list_codeblock_interference", "input": "para:\n\n 1. list-1\n 2. list-2\n 1. list-2a\n 3. list-3\n", "expected_output": "

para:

\n
1. list-1\n2. list-2\n  1. list-2a\n3. list-3\n
" }, { "name": "ulist_mixed_bullets", "input": "Combine four lists:\n\n* One\n- Two\n+ Three\n- Four\n- Five", "expected_output": "

Combine four lists:

\n", "marked_expected_output": "

Combine four lists:

\n\n\n\n", "text_content": "Combine four lists:\n\nOne\nTwo\nThree\nFour\nFive\n" }, { "name": "ulist_hanging", "input": "Some text with a hanging list:\n* One item\n* Two items\n* Three items", "expected_output": "

Some text with a hanging list:

\n", "text_content": "Some text with a hanging list:\n\nOne item\nTwo items\nThree items\n" }, { "name": "ulist_codeblock_interference", "input": "* One \n * Two\n\n Two continued\n This shouldn't be a code block\n", "expected_output": "", "marked_expected_output":"", "text_content": "\nOne \n\nTwo\nTwo continued\nThis shouldn't be a code block\n\n\n\n" }, { "name": "ulist_hanging_mixed", "input": "Plain list\n\n* Alpha\n\n* Beta\n\nThen hang it off:\n* Ypsilon\n* Zeta", "expected_output": "

Plain list

\n\n

Then hang it off:

\n", "marked_expected_output": "

Plain list

\n\n

Then hang it off:

\n", "text_content": "Plain list\n\n\nAlpha\n\n\nBeta\n\n\nThen hang it off:\n\nYpsilon\nZeta\n" }, { "name": "ulist_hanging_multi", "input": "Plain list\n* Alpha\n* Beta\n\nAnd again:\n* A\n* B\n* C\n\nOnce more for feeling:\n* Q\n* E\n* D", "expected_output": "

Plain list

\n\n

And again:

\n\n

Once more for feeling:

\n", "text_content": "Plain list\n\nAlpha\nBeta\n\nAnd again:\n\nA\nB\nC\n\nOnce more for feeling:\n\nQ\nE\nD\n" }, { "name": "ulist_hanging_quoted", "input": "```quote\nSome text with a hanging list inside quote:\n* one\n* two\n* three\n```", "expected_output": "
\n

Some text with a hanging list inside quote:

\n\n
", "text_content": "> Some text with a hanging list inside quote:\n> one\n> two\n> three\n" }, { "name": "ulist_nested_ulist_two_space_indent", "input": "Nested list\n* I am outer list\n * I am inner nested list first item\n * I am inner nested list second item", "expected_output": "

Nested list

\n", "text_content": "Nested list\n\nI am outer list\nI am inner nested list first item\nI am inner nested list second item\n\n\n" }, { "name": "ulist_list_two_space_indent", "input": "* I am outer list\n I am something inside", "expected_output": "", "marked_expected_output": "", "text_content": "\nI am outer list\n I am something inside\n" }, { "name": "ulist_codeblock", "input": "~~~\nint x = 3\n* 4;\n~~~", "expected_output": "
int x = 3\n* 4;\n
", "text_content": "int x = 3\n* 4;\n" }, { "name": "malformed_fence", "input": "~~~~~~~~xxxxxxxxx: xxxxxxxxxxxx xxxxx x xxxxxxxx~~~~~~", "expected_output": "

~~~~~~~~xxxxxxxxx: xxxxxxxxxxxx xxxxx x xxxxxxxx~~~~~~

", "text_content": "~~~~~~~~xxxxxxxxx: xxxxxxxxxxxx xxxxx x xxxxxxxx~~~~~~" }, { "name": "strikthrough_basic", "input": "I like ~~software~~ hardware", "expected_output": "

I like software hardware

", "text_content": "I like software hardware" }, { "name": "strikthrough_multiword", "input": "I ~~like software~~ love hardware", "expected_output": "

I like software love hardware

", "text_content": "I like software love hardware" }, { "name": "strikthrough_multiword", "input": "I ~~ like software ~~ love hardware", "expected_output": "

I like software love hardware

", "text_content": "I like software love hardware" }, { "name": "strikthrough_link", "input": "~~test http://xx.xx link~~", "expected_output": "

test http://xx.xx link

", "text_content": "test http://xx.xx link" }, { "name": "underscore_disabled", "input": "_foo_", "expected_output": "

_foo_

" }, { "name": "emphasis_text", "input": "*foo*", "expected_output": "

foo

", "text_content": "foo" }, { "name": "emphasis_code", "input": "const char *x = (char *)y", "expected_output": "

const char *x = (char *)y

" }, { "name": "emphasis_with_space", "input": "A *foo bar* is a *baz quux*", "expected_output": "

A foo bar is a baz quux

", "text_content": "A foo bar is a baz quux" }, { "name": "emphasis_with_html", "input": "*

Hello world

*", "expected_output": "

<h1>Hello world</h1>

" }, { "name": "underscore_strong_disabled", "input": "__foo__", "expected_output": "

__foo__

" }, { "name": "star_strong", "input": "**foo**", "expected_output": "

foo

", "text_content": "foo" }, { "name": "star_emoji", "input": "**:smile:**", "expected_output": "

:smile:

", "text_content": "\ud83d\ude42" }, { "name": "star_strong_em", "input": "***foo***", "expected_output": "

foo

", "text_content": "foo" }, { "name": "strong_with_html", "input": "**

Hello world

**", "expected_output": "

<h1>Hello world</h1>

" }, { "name": "numbered_list", "input": "1. A\n2. B\n 3. C", "expected_output": "
    \n
  1. A
  2. \n
  3. B
      \n
    1. C
    2. \n
    \n
  4. \n
", "text_content": "1. A\n2. B\n 3. C" }, { "name": "auto_renumbered_list_trick", "input": "1. A\n1. B\n 1. C\n1. D", "expected_output": "
    \n
  1. A
  2. \n
  3. B
      \n
    1. C
    2. \n
    \n
  4. \n
  5. D
  6. \n
", "text_content": "1. A\n2. B\n 1. C\n3. D" }, { "name": "auto_renumbered_list_from", "input": "3. A\n3. B\n3. C\n3. D", "expected_output": "
    \n
  1. A
  2. \n
  3. B
  4. \n
  5. C
  6. \n
  7. D
  8. \n
", "text_content": "3. A\n4. B\n5. C\n6. D" }, { "name": "two_auto_renumbered_lists", "input": "1. A\n3. B\n 2. C\n1. D", "expected_output": "
    \n
  1. A
  2. \n
  3. B
      \n
    1. C
    2. \n
    \n
  4. \n
  5. D
  6. \n
", "text_content": "1. A\n2. B\n 2. C\n3. D" }, { "name": "linkify_interference", "input": "link: xx, x xxxxx xx xxxx xx\n\n[xxxxx #xx](http://xxxxxxxxx:xxxx/xxx/xxxxxx%78xxxx/xx/):**xxxxxxx**\n\nxxxxxxx xxxxx xxxx xxxxx:\n`xxxxxx`: xxxxxxx\n`xxxxxx`: xxxxx\n`xxxxxx`: xxxxx xxxxx", "expected_output": "

link: xx, x xxxxx xx xxxx xx

\n

xxxxx #xx:xxxxxxx

\n

xxxxxxx xxxxx xxxx xxxxx:
\nxxxxxx: xxxxxxx
\nxxxxxx: xxxxx
\nxxxxxx: xxxxx xxxxx

", "text_content": "link: xx, x xxxxx xx xxxx xx\nxxxxx #xx:xxxxxxx\nxxxxxxx xxxxx xxxx xxxxx:\nxxxxxx: xxxxxxx\nxxxxxx: xxxxx\nxxxxxx: xxxxx xxxxx" }, { "name": "inline_image", "input": "Google logo today: https://www.google.com/images/srpr/logo4w.png\nKinda boring", "expected_output": "

Google logo today: https://www.google.com/images/srpr/logo4w.png
\nKinda boring

\n
", "backend_only_rendering": true, "text_content": "Google logo today: https:\/\/www.google.com\/images\/srpr\/logo4w.png\nKinda boring\n" }, { "name": "blockquote_inline_image", "input": ">Google logo today:\n>https://www.google.com/images/srpr/logo4w.png\n>Kinda boring", "expected_output": "
\n

Google logo today:
\nhttps://www.google.com/images/srpr/logo4w.png
\nKinda boring

\n
", "backend_only_rendering": true, "text_content": "> Google logo today:\n> https:\/\/www.google.com\/images\/srpr\/logo4w.png\n> Kinda boring\n" }, { "name": "two_inline_images", "input": "Google logo today: https://www.google.com/images/srpr/logo4w.png\nKinda boring\nZulip logo: https://zulip.com/static/images/landing-page/zulip-octopus.png", "expected_output": "

Google logo today: https:\/\/www.google.com\/images\/srpr\/logo4w.png<\/a>
\nKinda boring
\nZulip logo:
https:\/\/zulip.com\/static\/images\/landing-page\/zulip-octopus.png<\/a><\/p>\n

<\/a><\/div>
<\/a><\/div>", "backend_only_rendering": true, "text_content": "Google logo today: https:\/\/www.google.com\/images\/srpr\/logo4w.png\nKinda boring\nZulip logo: https:\/\/zulip.com\/static\/images\/landing-page\/zulip-octopus.png\n" }, { "name": "deduplicate_inline_previews", "input": "Google logo today: https://www.google.com/images/srpr/logo4w.png\nKinda boringGoogle logo today: https://www.google.com/images/srpr/logo4w.png\nKinda boring", "expected_output": "

Google logo today: https://www.google.com/images/srpr/logo4w.png
\nKinda boringGoogle logo today: https://www.google.com/images/srpr/logo4w.png
\nKinda boring

\n
", "backend_only_rendering": true, "text_content": "Google logo today: https:\/\/www.google.com\/images\/srpr\/logo4w.png\nKinda boringGoogle logo today: https:\/\/www.google.com\/images\/srpr\/logo4w.png\nKinda boring\n" }, { "name": "bulleted_list_inlining", "input": "* Google?\n* Google. https://www.google.com/images/srpr/logo4w.png\n* Google!", "expected_output": "", "backend_only_rendering": true, "text_content": "\nGoogle?\nGoogle. https://www.google.com/images/srpr/logo4w.png\nGoogle!\n" }, { "name": "only_inline_image", "input": "https://www.google.com/images/srpr/logo4w.png", "expected_output": "
", "backend_only_rendering": true }, { "name": "only_named_inline_image", "input": "[Google link](https://www.google.com/images/srpr/logo4w.png)", "expected_output": "

Google link

\n
", "backend_only_rendering": true, "text_content": "Google link\n" }, { "name": "only_non_image_link", "input": "https://github.com", "expected_output": "

https://github.com

" }, { "name": "link_with_text", "input": "[hello](https://github.com)", "expected_output": "

hello

" }, { "name": "link_without_text", "input": "[](https://github.com)", "expected_output": "

https://github.com

" }, { "name": "link_with_empty_text", "input": "[ ](https://github.com)", "expected_output": "

https://github.com

" }, { "name": "fragment_link", "input": "[foo](http://zulip.testserver/#narrow/stream/1-Denmark)", "expected_output": "

foo

", "marked_expected_output": "

foo

" }, { "name": "not_fragment_link", "input": "[foo](http://zulip.testserver/https://example.com)", "expected_output": "

foo

" }, { "name": "nl2br", "input": "test\nbar", "expected_output": "

test
\nbar

", "text_content": "test\nbar" }, { "name": "nl2br_trailing_space", "input": "test ", "expected_output": "

test

", "text_content": "test " }, { "name": "tables", "input": "This is a table:\n\nFirst header | Second header\n------------- | -------------\nContent cell | Content cell\nContent cell | Content cell\n", "expected_output": "

This is a table:

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
First headerSecond header
Content cellContent cell
Content cellContent cell
", "text_content": "This is a table:\n\n\n\nFirst header\nSecond header\n\n\n\n\nContent cell\nContent cell\n\n\nContent cell\nContent cell\n\n\n" }, { "name": "multiline_strong", "input": "You can check out **any time you'd like\nBut you can never leave**", "expected_output": "

You can check out **any time you'd like
\nBut you can never leave**

", "marked_expected_output": "

You can check out any time you'd like
\nBut you can never leave

", "text_content": "You can check out **any time you'd like\nBut you can never leave**" }, { "name": "many_emoji", "input": "test :smile: again :poop:\n:) foo:)bar x::y::z :wasted waste: :fakeemojithisshouldnotrender:", "expected_output": "

test :smile: again :poop:
\n:) foo:)bar x::y::z :wasted waste: :fakeemojithisshouldnotrender:

", "text_content": "test \ud83d\ude42 again \ud83d\udca9\n:) foo:)bar x::y::z :wasted waste: :fakeemojithisshouldnotrender:" }, { "name": "translate_emoticons_not_enabled", "input": ":)", "expected_output": "

:)

", "text_content": ":)", "translate_emoticons": false }, { "name": "translate_emoticons_enabled", "input": ":)", "expected_output": "

:smile:

", "text_content": "\ud83d\ude42", "translate_emoticons": true }, { "name": "translate_emoticons", "input": ":) foo :( bar <3 with space : ) real emoji :smile:", "expected_output": "

:smile: foo :frown: bar :heart: with space : ) real emoji :smile:

", "text_content": "\ud83d\ude42 foo \ud83d\ude41 bar \u2764 with space : ) real emoji \ud83d\ude42", "translate_emoticons": true }, { "name": "translate_emoticons_whitepsace", "input": "a:) ;)b", "expected_output": "

a:) ;)b

", "text_content": "a:) ;)b", "translate_emoticons": true }, { "name": "translate_emoticons_newline", "input": ":) test\n:) test", "expected_output": "

:smile: test
\n:smile: test

", "text_content": "\ud83d\ude42 test\n\ud83d\ude42 test", "translate_emoticons": true }, { "name": "translate_emoticons_in_code", "input": "`:)`", "expected_output": "

:)

", "text_content": ":)", "translate_emoticons": true }, { "name": "translate_emoticons_at_sentence_end", "input": "Translate this :).", "expected_output": "

Translate this :smile:.

", "text_content": "Translate this \ud83d\ude42.", "translate_emoticons": true }, { "name": "translate_emoticons_between_symbols", "input": "Translate this !:)?", "expected_output": "

Translate this !:smile:?

", "marked_expected_output": "

Translate this !:)?

", "text_content": "Translate this !\ud83d\ude42?", "translate_emoticons": true }, { "name": "random_emoji_1", "input": ":airplane:", "expected_output": "

:airplane:

" }, { "name": "zulip_emoji", "input": ":zulip:", "expected_output": "

\":zulip:\"

", "text_content": ":zulip:" }, { "name": "random_emoji_2", "input": ":poop:", "expected_output": "

:poop:

" }, { "name": "emojis_without_space", "input": ":cat:hello:dog::rabbit:", "expected_output": "

:cat:hello:dog::rabbit:

", "text_content": "\ud83d\udc08hello\ud83d\udc15\ud83d\udc07" }, { "name": "emojis_newline", "input": ":cat:\n:dog:", "expected_output": "

:cat:
\n:dog:

", "text_content": "\ud83d\udc08\n\ud83d\udc15" }, { "name": "not_emoji", "input": ":not_an_emoji:", "expected_output": "

:not_an_emoji:

", "text_content": ":not_an_emoji:" }, { "name": "unicode_emoji", "input": "\ud83d\udca9", "expected_output":"

:poop:

", "text_content": "\ud83d\udca9" }, { "name": "two_unicode_emoji", "input": "\ud83d\udca9\ud83d\udca9", "expected_output":"

:poop::poop:<\/p>", "text_content": "\ud83d\udca9\ud83d\udca9" }, { "name": "two_unicode_emoji_separated_by_text", "input": "\ud83d\udca9 word \ud83d\udca9", "expected_output":"

:poop: word :poop:<\/p>", "text_content": "\ud83d\udca9 word \ud83d\udca9" }, { "name": "miscellaneous_symbols_and_pictographs", "input": "Merry Christmas!!\ud83c\udf84", "expected_output":"

Merry Christmas!!:holiday_tree:<\/p>", "text_content": "Merry Christmas!!\ud83c\udf84" }, { "name": "miscellaneous_and_dingbats_emoji", "input": "\u2693\u2797", "expected_output":"

:anchor::division:<\/p>" }, { "name": "supplemental_symbols_and_pictographs", "input": "I am a robot \ud83e\udd16.", "expected_output":"

I am a robot :robot:.<\/p>" }, { "name": "miscellaneous_symbols_and_arrows", "input": "Black upward arrow \u2b06", "expected_output":"

Black upward arrow :up:<\/p>" }, { "name": "unicode_emoji_without_space", "input": "Extra\ud83d\udc7dTerrestrial", "expected_output":"

Extra:alien:Terrestrial<\/p>" }, { "name": "unicode_emojis_new_line", "input": "\ud83d\udc7d\n\ud83d\udc7d", "expected_output":"

:alien:
\n:alien:

", "text_content": "\ud83d\udc7d\n\ud83d\udc7d" }, { "name": "emoji_alongside_punctuation", "input": ":smile:, :smile:; :smile:", "expected_output": "

:smile:, :smile:; :smile:

" }, { "name": "new_emoji_test", "input": ":avocado:, :kiwi:, :selfie:, :gear:, :comet:, :gold:", "expected_output": "

:avocado:, :kiwi:, :selfie:, :gear:, :comet:, :gold:

" }, { "name": "emoji_pipeline_newline", "input": "The winner is:\nsmiley:smiley:", "expected_output": "

The winner is:
\nsmiley:smiley:

" }, { "name": "emoji_pipeline_emphasis", "input": "Testing *:smiley*: :sm*iley*: Testing", "expected_output": "

Testing :smiley: :smiley: Testing

" }, { "name": "emoji_pipeline_link", "input": "Visit https:smiley://google.com.", "expected_output": "

Visit https:smiley://google.com.

" }, { "name": "skin_tones_are_banned", "input": ":skin-tone-2: :skin-tone-3:", "expected_output": "

:skin-tone-2: :skin-tone-3:

" }, { "name": "fried_egg", "input": "new :fried_egg: emoji is banned for now.", "expected_output": "

new :fried_egg: emoji is banned for now.

" }, { "name": "emojis_with_zwj_are_banned", "input": "Emojis like :man-girl-girl: which have ZWJ are banned for now.", "expected_output": "

Emojis like :man-girl-girl: which have ZWJ are banned for now.

", "text_content": "Emojis like :man-girl-girl: which have ZWJ are banned for now." }, { "name": "valid_emoji_preceded_by_invalid_emoji", "input": "This is :invalidemoji: which should not prevent rendering :smile:", "expected_output": "

This is :invalidemoji: which should not prevent rendering :smile:

" }, { "name": "safe_html", "input": "

stay normal

thanks", "expected_output": "

<h1>stay normal</h1> thanks

", "text_content": "

stay normal<\/h1> thanks" }, { "name": "safe_html_with_simple_script_tag", "input": "", "expected_output": "

<script>alert(1)</script>

", "marked_expected_output": "

<script>alert(1)</script>\n\n

", "text_content": "/script>", "expected_output": "

<<script>script>evil()<</script>/script>

", "text_content": "<ipt type=\"text/javascript\">alert(\"foo\");script>", "expected_output": "

<scr<script></script>ipt type=\"text/javascript\">alert(\"foo\");</<script></script>script<del></del>>

" }, { "name": "safe_html_unclosed_tag", "input": "$$\n\n~~~math\n\n~~~", "expected_output": "

<scripttype=\u2032text/javascript\u2032>alert(\u2032xss\u2032);</script><script type='text/javascript'>alert('xss');</script><scripttype=\u2032text/javascript\u2032>alert(\u2032xss\u2032);</script>

\n

<scripttype=\u2032text/javascript\u2032>alert(\u2032xss\u2032);</script><script type='text/javascript'>alert('xss');</script><scripttype=\u2032text/javascript\u2032>alert(\u2032xss\u2032);</script>

" }, { "name": "tex_error_safe_script_tag", "input": "$$\\$$\n\n~~~math\n\\\n~~~", "expected_output": "

$$\\<script type='text/javascript'>alert('xss');</script>$$

\n

\\<script type='text/javascript'>alert('xss');</script>

" }, { "name": "tex_inline_no_markdown_inside", "input": "$$\\text{**a**}$$", "expected_output": "

**a**\\text{**a**}**a**

" }, { "name": "tex_display_no_markdown_inside", "input": "~~~math\n\\text{**a**}\n~~~", "expected_output": "

**a**\\text{**a**}**a**

" }, { "name": "tex_inline_error_no_markdown_inside", "input": "$$\\error{**a**}$$", "expected_output": "

$$\\error{**a**}$$

" }, { "name": "tex_display_error_no_markdown_inside", "input": "~~~math\n\\error{**a**}\n~~~", "expected_output": "

\\error{**a**}

" }, { "name": "auto_renumbered_list_blankline", "input": "1. A\n\n1. B\n\n1. C\n\n1. D\nordinary paragraph\n1. AA\n\n1. BB", "expected_output": "
    \n
  1. \n

    A

    \n
  2. \n
  3. \n

    B

    \n
  4. \n
  5. \n

    C

    \n
  6. \n
  7. \n

    D
    \nordinary paragraph

    \n
  8. \n
  9. \n

    AA

    \n
  10. \n
  11. \n

    BB

    \n
  12. \n
", "marked_expected_output": "
    \n
  1. A

    \n
  2. \n
  3. B

    \n
  4. \n
  5. C

    \n
  6. \n
  7. D
    \nordinary paragraph

    \n
  8. \n
  9. AA

    \n
  10. \n
  11. BB

    \n
  12. \n
", "text_content": "1. A\n2. B\n3. C\n4. D\nordinary paragraph\n5. AA\n6. BB" }, { "name": "spoilers_fenced_spoiler", "input": "```spoiler header\ncontent\n```\noutside spoiler\n", "expected_output": "
\n

header

\n
\n

content

\n
\n

outside spoiler

", "text_content": "header (…)\noutside spoiler" }, { "name": "spoilers_empty_header", "input": "```spoiler\ncontent\n```\noutside spoiler\n", "expected_output": "
\n
\n

content

\n
\n

outside spoiler

", "text_content": "(…)\noutside spoiler" }, { "name": "spoilers_script_tags", "input": "```spoiler \n\n```", "expected_output": "
\n

<script>alert(1)</script>

\n
\n

<script>alert(1)</script>

\n
", "marked_expected_output": "
\n

<script>alert(1)</script>\n\n

\n
\n

<script>alert(1)</script>\n\n

\n
", "text_content": " (…)\n" }, { "name": "spoilers_block_quote", "input": "~~~quote\n```spoiler header\ncontent\n```\noutside spoiler\n~~~\noutside quote", "expected_output": "
\n
\n

header

\n
\n

content

\n
\n

outside spoiler

\n
\n

outside quote

", "text_content": "> header (…)\n> outside spoiler\n\noutside quote" }, { "name": "spoilers_with_header_markdown", "input": "```spoiler [Header](https://example.com) :smile:\ncontent\n```", "expected_output": "
\n

Header :smile:

\n
\n

content

\n
", "text_content": "Header 🙂 (…)\n" }, { "name": "spoiler_with_inline_image", "input": "```spoiler header\nContent http://example.com/image.png\n```", "expected_output": "
\n

header

\n
", "marked_expected_output": "
\n

header

\n
", "text_content": "header (…)\n" }, { "name": "embedded_link_inside_Bold", "input": "**[Static types in Python](https://blog.zulip.com/2016/10/13/static-types-in-python-oh-mypy)**", "expected_output": "

Static types in Python

" }, { "name": "embedded_link_inside_Italic", "input": "*[Static types in Python](https://blog.zulip.com/2016/10/13/static-types-in-python-oh-mypy)*", "expected_output": "

Static types in Python

" }, { "name": "edge_case_embedded_link_inside_Bold", "input": "

**

[

Static types in Python

](https://blog.zulip.com/2016/10/13/static-types-in-python-oh-mypy)**", "expected_output": "

<h1><h1><h2>Static types in Python</h2></h1></h1>

", "marked_expected_output": "

<h1><h1><h2>Static types in Python</h2></h1></h1>\n\n

" }, { "name": "edge_case_embedded_link_inside_Italic", "input": "

*

[

Static types in Python

](https://blog.zulip.com/2016/10/13/static-types-in-python-oh-mypy)*", "expected_output": "

<h1><h1><h2>Static types in Python</h2></h1></h1>

", "marked_expected_output": "

<h1><h1><h2>Static types in Python</h2></h1></h1>\n\n

" }, { "name": "telephone_sms_link", "input": "[call me](tel:+14155551234) [or maybe not](sms:+14155551234)", "expected_output": "

call me or maybe not

" }, { "name": "codeblock_hilite_shebang_feature_no_path_1", "input": "```\n#!python\nprint(\"Hello World\")\n```", "expected_output": "
#!python\nprint("Hello World")\n
", "marked_expected_output": "
#!python\nprint("Hello World")\n
" }, { "name": "codeblock_hilite_shebang_feature_no_path_2", "input": "```\n:::python\nprint(\"Hello World\")\n```", "expected_output": "
:::python\nprint("Hello World")\n
", "marked_expected_output": "
:::python\nprint("Hello World")\n
" }, { "name": "codeblock_hilite_shebang_feature_with_path", "input": "```\n#!/usr/bin/python\nprint(\"Hello World\")\n```", "expected_output": "
#!/usr/bin/python\nprint("Hello World")\n
", "marked_expected_output": "
#!/usr/bin/python\nprint("Hello World")\n
" } ], "linkify_tests": [ [ "http://www.google.com", "

%s

", "http://www.google.com" ], [ "https://www.google.com", "

%s

", "https://www.google.com" ], [ "http://www.theregister.co.uk/foo/bar", "

%s

", "http://www.theregister.co.uk/foo/bar" ], [ " some text https://www.google.com/", "

some text %s

", "https://www.google.com/" ], [ "with short example.com url", "

with short %s url

", "example.com" ], [ "t.co", "

%s

", "t.co" ], [ "readme.md", "

readme.md

", "readme.md" ], [ "go to views.org please", "

go to %s please

", "views.org" ], [ "http://foo.com/blah_blah/", "

%s

", "http://foo.com/blah_blah/" ], [ "python class views.py is", "

python class views.py is

", "" ], [ "with www www.zulip.com/foo ok?", "

with www %s ok?

", "www.zulip.com/foo" ], [ "allow questions like foo.com?", "

allow questions like %s?

", "foo.com" ], [ "\"is.gd/foo/ \"", "

\"%s \"

", "is.gd/foo/" ], [ "end of sentence https://t.co.", "

end of sentence %s.

", "https://t.co" ], [ "(Something like http://foo.com/blah_blah)", "

(Something like %s)

", "http://foo.com/blah_blah" ], [ "\"is.gd/foo/\"", "

\"%s\"

", "is.gd/foo/" ], [ "end with a quote www.google.com\"", "

end with a quote %s\"

", "www.google.com" ], [ "end with an exclamation www.google.com!", "

end with an exclamation %s!

", "www.google.com" ], [ "http://www.guardian.co.uk/foo/bar", "

%s

", "http://www.guardian.co.uk/foo/bar" ], [ "from http://supervisord.org/running.html:", "

from %s:

", "http://supervisord.org/running.html" ], [ "http://raven.io", "

%s

", "http://raven.io" ], [ "at https://zulip.com/api. Check it!", "

at %s. Check it!

", "https://zulip.com/api" ], [ "goo.gl/abc", "

%s

", "goo.gl/abc" ], [ "I spent a year at ucl.ac.uk", "

I spent a year at %s

", "ucl.ac.uk" ], [ "http://a.cc/i/FMXO", "

%s

", "http://a.cc/i/FMXO" ], [ "http://fmota.eu/blog/test.html", "

%s

", "http://fmota.eu/blog/test.html" ], [ "http://j.mp/14Hwm3X", "

%s

", "http://j.mp/14Hwm3X" ], [ "http://localhost:9991/?show_debug=1", "

%s

", "http://localhost:9991/?show_debug=1" ], [ "anyone before? (http://a.cc/i/FMXO)", "

anyone before? (%s)

", "http://a.cc/i/FMXO" ], [ "(http://en.wikipedia.org/wiki/Each-way_(bet))", "

(%s)

", "http://en.wikipedia.org/wiki/Each-way_(bet)" ], [ "(http://en.wikipedia.org/wiki/Each-way_(bet)_(more_parens))", "

(%s)

", "http://en.wikipedia.org/wiki/Each-way_(bet)_(more_parens)" ], [ "http://en.wikipedia.org/wiki/Qt_(framework)", "

%s

", "http://en.wikipedia.org/wiki/Qt_(framework)" ], [ "http://fr.wikipedia.org/wiki/Fichier:SMirC-facepalm.svg", "

%s

", "http://fr.wikipedia.org/wiki/Fichier:SMirC-facepalm.svg" ], [ "https://en.wikipedia.org/wiki/File:Methamphetamine_from_ephedrine_with_HI_en.mov", "

%s

", "https://en.wikipedia.org/wiki/File:Methamphetamine_from_ephedrine_with_HI_en.mov" ], [ "https://jira.atlassian.com/browse/JRA-31953?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel", "

%s

", "https://jira.atlassian.com/browse/JRA-31953?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel" ], [ "http://web.archive.org/web/20120630032016/http://web.mit.edu/mitcard/idpolicies.html", "

%s

", "http://web.archive.org/web/20120630032016/http://web.mit.edu/mitcard/idpolicies.html" ], [ "http://www.postgresql.org/message-id/14040.1364490185@sss.pgh.pa.us", "

%s

", "http://www.postgresql.org/message-id/14040.1364490185@sss.pgh.pa.us" ], [ "javascript:alert(\"hi\");.com", "

javascript:alert(\"hi\");.com

", "" ], [ "javascript:foo.com", "

javascript:%s

", "foo.com" ], [ "javascript://foo.com", "

javascript://foo.com

", "" ], [ "foobarscript://foo.com", "

foobarscript://foo.com

", "" ], [ "about:blank.com", "

about:%s

", "blank.com" ], [ "[foo](javascript:foo.com)", "

[foo](javascript:%s)

", "foo.com" ], [ "[foo](javascript://foo.com)", "

[foo](javascript://foo.com)

", "" ], [ "aim:addbuddy?screenname=foo", "

aim:addbuddy?screenname=foo

", "" ], [ "itms://itunes.com/apps/appname", "

itms://itunes.com/apps/appname

", "" ], [ "[foo](itms://itunes.com/apps/appname)", "

[foo](itms://itunes.com/apps/appname)

", "" ], [ "1 [](foo://) 3 [](foo://) 5", "

1 [](foo://) 3 [](foo://) 5

", "" ], [ "javascript:\"foo&bar\"", "

javascript:<i>\"foo&bar\"</i>

", "" ], [ "[foo](javascript:\"foo&bar\")", "

[foo](javascript:<i>\"foo&bar\"</i>)

", "" ], [ "http://zulip.testserver/#narrow/stream/1-Denmark", "

http://zulip.testserver/#narrow/stream/1-Denmark

", "" ], [ "http://zulip.testserver/https://example.com", "

%s

", "http://zulip.testserver/https://example.com" ], [ "a@b.com", "

%s

", "a@b.com" ], [ "", "

<%s>

", "a@b.com" ], [ "a@b.com/foo", "

a@b.com/foo

", "" ], [ "http://leo@foo.com/my/file", "

%s

", "http://leo@foo.com/my/file" ], [ "http://example.com/something?with,commas,in,url, but not at end", "

%s, but not at end

", "http://example.com/something?with,commas,in,url" ], [ "http://www.yelp.com/biz/taim-mobile-falafel-and-smoothie-truck-new-york#query", "

%s

", "http://www.yelp.com/biz/taim-mobile-falafel-and-smoothie-truck-new-york#query" ], [ " some text https://www.google.com/baz_(match)?with=foo&bar=baz with extras", "

some text %s with extras

", "https://www.google.com/baz_(match)?with=foo&bar=baz" ], [ "hash it http://foo.com/blah_(wikipedia)_blah#cite-1", "

hash it %s

", "http://foo.com/blah_(wikipedia)_blah#cite-1" ], [ "http://technet.microsoft.com/en-us/library/Cc751099.rk20_25_big(l=en-us).mov", "

%s

", "http://technet.microsoft.com/en-us/library/Cc751099.rk20_25_big(l=en-us).mov" ], [ "https://metacpan.org/module/Image::Resize::OpenCV", "

%s

", "https://metacpan.org/module/Image::Resize::OpenCV" ], [ "foo.com/a::trollface::b", "

%s

", "foo.com/a::trollface::b" ], [ "a.commandstuff()", "

a.commandstuff()

", "" ], [ "love...it", "

love...it

", "" ], [ "sorry,http://example.com/", "

sorry,%s

", "http://example.com/" ], [ "two nested parens https://zulip.com/(we_like_(to_nest_)_nest)_nest", "

two nested parens %s

", "https://zulip.com/(we_like_(to_nest_)_nest)_nest" ], [ "three nested parens https://zulip.com/(we_like_(to_(and_)nest_)_nest)_nest", "

three nested parens %s

", "https://zulip.com/(we_like_(to_(and_)nest_)_nest)_nest" ], [ "four nested parens https://zulip.com/(we_like_(to_n(e)st_)_n(es)t)_nest", "

four nested parens %s

", "https://zulip.com/(we_like_(to_n(e)st_)_n(es)t)_nest" ], [ "six nested parens https://zulip.com/(we_like_((t(d(o(___)o)o))o_nest_)_nest)_nest", "

six nested parens %s

", "https://zulip.com/(we_like_((t(d(o(___)o)o))o_nest_)_nest)_nest" ], [ "eight is too many https://zulip.com/(we_like_((t(d(o(_(1(2)1)__)o)o))o_nest_)_nest)_nest", "

eight is too many https://zulip.com/(we_like_((t(d(o(_(1(2)1)__)o)o))o_nest_)_nest)_nest

", "" ], [ "nested with autodetection zulip.us/(we_like_(to_n(e)st_)_n(es)t)_nest", "

nested with autodetection %s

", "zulip.us/(we_like_(to_n(e)st_)_n(es)t)_nest" ], [ "quora http://generate.quora.net/render?width=700&from=-4hours&until=now&height=400&bgcolor=black&lineMode=connected&title=arb%20hint%20status&target=alias(ans.hintland.hand.arb.enhint_rate%2C%22enhint%20rate%22)&target=alias(ans.hintland.hand.arb.unhint_rate%2C%22unhint%20rate%22)&target=alias(ans.hintland.hand.arb.size%2C%22hint%20size%22)&target=alias(scale(ans.vagabond.dingarb_cube_count%2C10000)%2C%22cube%20count%20x%2010K%22)&target=alias(scale(hnumbers.time.ding.gegevens.query.count%2C10)%2C%22ding%20gegevens%20query%20count%20x%2010%22)&fgcolor=white&uniq=0.44046106841415167", "

quora %s

", "http://generate.quora.net/render?width=700&from=-4hours&until=now&height=400&bgcolor=black&lineMode=connected&title=arb%20hint%20status&target=alias(ans.hintland.hand.arb.enhint_rate%2C%22enhint%20rate%22)&target=alias(ans.hintland.hand.arb.unhint_rate%2C%22unhint%20rate%22)&target=alias(ans.hintland.hand.arb.size%2C%22hint%20size%22)&target=alias(scale(ans.vagabond.dingarb_cube_count%2C10000)%2C%22cube%20count%20x%2010K%22)&target=alias(scale(hnumbers.time.ding.gegevens.query.count%2C10)%2C%22ding%20gegevens%20query%20count%20x%2010%22)&fgcolor=white&uniq=0.44046106841415167" ] ] }