| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990 | // CodeMirror, copyright (c) by Marijn Haverbeke and others// Distributed under an MIT license: http://codemirror.net/LICENSE(function() {  var mode = CodeMirror.getMode({tabSize: 4}, "markdown");  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }  var modeHighlightFormatting = CodeMirror.getMode({tabSize: 4}, {name: "markdown", highlightFormatting: true});  function FT(name) { test.mode(name, modeHighlightFormatting, Array.prototype.slice.call(arguments, 1)); }  var modeAtxNoSpace = CodeMirror.getMode({tabSize: 4}, {name: "markdown", allowAtxHeaderWithoutSpace: true});  function AtxNoSpaceTest(name) { test.mode(name, modeAtxNoSpace, Array.prototype.slice.call(arguments, 1)); }  var modeFenced = CodeMirror.getMode({tabSize: 4}, {name: "markdown", fencedCodeBlocks: true});  function FencedTest(name) { test.mode(name, modeFenced, Array.prototype.slice.call(arguments, 1)); }  var modeOverrideClasses = CodeMirror.getMode({tabsize: 4}, {    name: "markdown",    strikethrough: true,    tokenTypeOverrides: {      "header" : "override-header",      "code" : "override-code",      "quote" : "override-quote",      "list1" : "override-list1",      "list2" : "override-list2",      "list3" : "override-list3",      "hr" : "override-hr",      "image" : "override-image",      "imageAltText": "override-image-alt-text",      "imageMarker": "override-image-marker",      "linkInline" : "override-link-inline",      "linkEmail" : "override-link-email",      "linkText" : "override-link-text",      "linkHref" : "override-link-href",      "em" : "override-em",      "strong" : "override-strong",      "strikethrough" : "override-strikethrough"  }});  function TokenTypeOverrideTest(name) { test.mode(name, modeOverrideClasses, Array.prototype.slice.call(arguments, 1)); }  var modeFormattingOverride = CodeMirror.getMode({tabsize: 4}, {    name: "markdown",    highlightFormatting: true,    tokenTypeOverrides: {      "formatting" : "override-formatting"  }});  function FormatTokenTypeOverrideTest(name) { test.mode(name, modeFormattingOverride, Array.prototype.slice.call(arguments, 1)); }  FT("formatting_emAsterisk",     "[em&formatting&formatting-em *][em foo][em&formatting&formatting-em *]");  FT("formatting_emUnderscore",     "[em&formatting&formatting-em _][em foo][em&formatting&formatting-em _]");  FT("formatting_strongAsterisk",     "[strong&formatting&formatting-strong **][strong foo][strong&formatting&formatting-strong **]");  FT("formatting_strongUnderscore",     "[strong&formatting&formatting-strong __][strong foo][strong&formatting&formatting-strong __]");  FT("formatting_codeBackticks",     "[comment&formatting&formatting-code `][comment foo][comment&formatting&formatting-code `]");  FT("formatting_doubleBackticks",     "[comment&formatting&formatting-code ``][comment foo ` bar][comment&formatting&formatting-code ``]");  FT("formatting_atxHeader",     "[header&header-1&formatting&formatting-header&formatting-header-1 # ][header&header-1 foo # bar ][header&header-1&formatting&formatting-header&formatting-header-1 #]");  FT("formatting_setextHeader",     "foo",     "[header&header-1&formatting&formatting-header&formatting-header-1 =]");  FT("formatting_blockquote",     "[quote"e-1&formatting&formatting-quote&formatting-quote-1 > ][quote"e-1 foo]");  FT("formatting_list",     "[variable-2&formatting&formatting-list&formatting-list-ul - ][variable-2 foo]");  FT("formatting_list",     "[variable-2&formatting&formatting-list&formatting-list-ol 1. ][variable-2 foo]");  FT("formatting_link",     "[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string&url (][string&url http://example.com/][string&formatting&formatting-link-string&url )]");  FT("formatting_linkReference",     "[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string&url [][string&url bar][string&formatting&formatting-link-string&url ]]]",     "[link&formatting&formatting-link [][link bar][link&formatting&formatting-link ]]:] [string&url http://example.com/]");  FT("formatting_linkWeb",     "[link&formatting&formatting-link <][link http://example.com/][link&formatting&formatting-link >]");  FT("formatting_linkEmail",     "[link&formatting&formatting-link <][link user@example.com][link&formatting&formatting-link >]");  FT("formatting_escape",     "[formatting-escape \\*]");  FT("formatting_image",     "[formatting&formatting-image&image&image-marker !][formatting&formatting-image&image&image-alt-text&link [[][image&image-alt-text&link alt text][formatting&formatting-image&image&image-alt-text&link ]]][formatting&formatting-link-string&string&url (][url&string http://link.to/image.jpg][formatting&formatting-link-string&string&url )]");  MT("plainText",     "foo");  // Don't style single trailing space  MT("trailingSpace1",     "foo ");  // Two or more trailing spaces should be styled with line break character  MT("trailingSpace2",     "foo[trailing-space-a  ][trailing-space-new-line  ]");  MT("trailingSpace3",     "foo[trailing-space-a  ][trailing-space-b  ][trailing-space-new-line  ]");  MT("trailingSpace4",     "foo[trailing-space-a  ][trailing-space-b  ][trailing-space-a  ][trailing-space-new-line  ]");  // Code blocks using 4 spaces (regardless of CodeMirror.tabSize value)  MT("codeBlocksUsing4Spaces",     "    [comment foo]");  // Code blocks using 4 spaces with internal indentation  MT("codeBlocksUsing4SpacesIndentation",     "    [comment bar]",     "        [comment hello]",     "            [comment world]",     "    [comment foo]",     "bar");  // Code blocks should end even after extra indented lines  MT("codeBlocksWithTrailingIndentedLine",     "    [comment foo]",     "        [comment bar]",     "    [comment baz]",     "    ",     "hello");  // Code blocks using 1 tab (regardless of CodeMirror.indentWithTabs value)  MT("codeBlocksUsing1Tab",     "\t[comment foo]");  // No code blocks directly after paragraph  // http://spec.commonmark.org/0.19/#example-65  MT("noCodeBlocksAfterParagraph",     "Foo",     "    Bar");  // Inline code using backticks  MT("inlineCodeUsingBackticks",     "foo [comment `bar`]");  // Block code using single backtick (shouldn't work)  MT("blockCodeSingleBacktick",     "[comment `]",     "[comment foo]",     "[comment `]");  // Unclosed backticks  // Instead of simply marking as CODE, it would be nice to have an  // incomplete flag for CODE, that is styled slightly different.  MT("unclosedBackticks",     "foo [comment `bar]");  // Per documentation: "To include a literal backtick character within a  // code span, you can use multiple backticks as the opening and closing  // delimiters"  MT("doubleBackticks",     "[comment ``foo ` bar``]");  // Tests based on Dingus  // http://daringfireball.net/projects/markdown/dingus  //  // Multiple backticks within an inline code block  MT("consecutiveBackticks",     "[comment `foo```bar`]");  // Multiple backticks within an inline code block with a second code block  MT("consecutiveBackticks",     "[comment `foo```bar`] hello [comment `world`]");  // Unclosed with several different groups of backticks  MT("unclosedBackticks",     "[comment ``foo ``` bar` hello]");  // Closed with several different groups of backticks  MT("closedBackticks",     "[comment ``foo ``` bar` hello``] world");  // atx headers  // http://daringfireball.net/projects/markdown/syntax#header  MT("atxH1",     "[header&header-1 # foo]");  MT("atxH2",     "[header&header-2 ## foo]");  MT("atxH3",     "[header&header-3 ### foo]");  MT("atxH4",     "[header&header-4 #### foo]");  MT("atxH5",     "[header&header-5 ##### foo]");  MT("atxH6",     "[header&header-6 ###### foo]");  // http://spec.commonmark.org/0.19/#example-24  MT("noAtxH7",     "####### foo");  // http://spec.commonmark.org/0.19/#example-25  MT("noAtxH1WithoutSpace",     "#5 bolt");  // CommonMark requires a space after # but most parsers don't  AtxNoSpaceTest("atxNoSpaceAllowed_H1NoSpace",     "[header&header-1 #foo]");  AtxNoSpaceTest("atxNoSpaceAllowed_H4NoSpace",     "[header&header-4 ####foo]");  AtxNoSpaceTest("atxNoSpaceAllowed_H1Space",     "[header&header-1 # foo]");  // Inline styles should be parsed inside headers  MT("atxH1inline",     "[header&header-1 # foo ][header&header-1&em *bar*]");  // Setext headers - H1, H2  // Per documentation, "Any number of underlining =’s or -’s will work."  // http://daringfireball.net/projects/markdown/syntax#header  // Ideally, the text would be marked as `header` as well, but this is  // not really feasible at the moment. So, instead, we're testing against  // what works today, to avoid any regressions.  //  // Check if single underlining = works  MT("setextH1",     "foo",     "[header&header-1 =]");  // Check if 3+ ='s work  MT("setextH1",     "foo",     "[header&header-1 ===]");  // Check if single underlining - works  MT("setextH2",     "foo",     "[header&header-2 -]");  // Check if 3+ -'s work  MT("setextH2",     "foo",     "[header&header-2 ---]");  // http://spec.commonmark.org/0.19/#example-45  MT("setextH2AllowSpaces",     "foo",     "   [header&header-2 ----      ]");  // http://spec.commonmark.org/0.19/#example-44  MT("noSetextAfterIndentedCodeBlock",     "     [comment foo]",     "[hr ---]");  // http://spec.commonmark.org/0.19/#example-51  MT("noSetextAfterQuote",     "[quote"e-1 > foo]",     "[hr ---]");  MT("noSetextAfterList",     "[variable-2 - foo]",     "[hr ---]");  // Single-line blockquote with trailing space  MT("blockquoteSpace",     "[quote"e-1 > foo]");  // Single-line blockquote  MT("blockquoteNoSpace",     "[quote"e-1 >foo]");  // No blank line before blockquote  MT("blockquoteNoBlankLine",     "foo",     "[quote"e-1 > bar]");  // Nested blockquote  MT("blockquoteSpace",     "[quote"e-1 > foo]",     "[quote"e-1 >][quote"e-2 > foo]",     "[quote"e-1 >][quote"e-2 >][quote"e-3 > foo]");  // Single-line blockquote followed by normal paragraph  MT("blockquoteThenParagraph",     "[quote"e-1 >foo]",     "",     "bar");  // Multi-line blockquote (lazy mode)  MT("multiBlockquoteLazy",     "[quote"e-1 >foo]",     "[quote"e-1 bar]");  // Multi-line blockquote followed by normal paragraph (lazy mode)  MT("multiBlockquoteLazyThenParagraph",     "[quote"e-1 >foo]",     "[quote"e-1 bar]",     "",     "hello");  // Multi-line blockquote (non-lazy mode)  MT("multiBlockquote",     "[quote"e-1 >foo]",     "[quote"e-1 >bar]");  // Multi-line blockquote followed by normal paragraph (non-lazy mode)  MT("multiBlockquoteThenParagraph",     "[quote"e-1 >foo]",     "[quote"e-1 >bar]",     "",     "hello");  // Header with leading space after continued blockquote (#3287, negative indentation)  MT("headerAfterContinuedBlockquote",     "[quote"e-1 > foo]",     "[quote"e-1 bar]",     "",     " [header&header-1 # hello]");  // Check list types  MT("listAsterisk",     "foo",     "bar",     "",     "[variable-2 * foo]",     "[variable-2 * bar]");  MT("listPlus",     "foo",     "bar",     "",     "[variable-2 + foo]",     "[variable-2 + bar]");  MT("listDash",     "foo",     "bar",     "",     "[variable-2 - foo]",     "[variable-2 - bar]");  MT("listNumber",     "foo",     "bar",     "",     "[variable-2 1. foo]",     "[variable-2 2. bar]");  // Lists require a preceding blank line (per Dingus)  MT("listBogus",     "foo",     "1. bar",     "2. hello");  // List after hr  MT("listAfterHr",     "[hr ---]",     "[variable-2 - bar]");  // List after header  MT("listAfterHeader",     "[header&header-1 # foo]",     "[variable-2 - bar]");  // hr after list  MT("hrAfterList",     "[variable-2 - foo]",     "[hr -----]");  // Formatting in lists (*)  MT("listAsteriskFormatting",     "[variable-2 * ][variable-2&em *foo*][variable-2  bar]",     "[variable-2 * ][variable-2&strong **foo**][variable-2  bar]",     "[variable-2 * ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2  bar]",     "[variable-2 * ][variable-2&comment `foo`][variable-2  bar]");  // Formatting in lists (+)  MT("listPlusFormatting",     "[variable-2 + ][variable-2&em *foo*][variable-2  bar]",     "[variable-2 + ][variable-2&strong **foo**][variable-2  bar]",     "[variable-2 + ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2  bar]",     "[variable-2 + ][variable-2&comment `foo`][variable-2  bar]");  // Formatting in lists (-)  MT("listDashFormatting",     "[variable-2 - ][variable-2&em *foo*][variable-2  bar]",     "[variable-2 - ][variable-2&strong **foo**][variable-2  bar]",     "[variable-2 - ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2  bar]",     "[variable-2 - ][variable-2&comment `foo`][variable-2  bar]");  // Formatting in lists (1.)  MT("listNumberFormatting",     "[variable-2 1. ][variable-2&em *foo*][variable-2  bar]",     "[variable-2 2. ][variable-2&strong **foo**][variable-2  bar]",     "[variable-2 3. ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2  bar]",     "[variable-2 4. ][variable-2&comment `foo`][variable-2  bar]");  // Paragraph lists  MT("listParagraph",     "[variable-2 * foo]",     "",     "[variable-2 * bar]");  // Multi-paragraph lists  //  // 4 spaces  MT("listMultiParagraph",     "[variable-2 * foo]",     "",     "[variable-2 * bar]",     "",     "    [variable-2 hello]");  // 4 spaces, extra blank lines (should still be list, per Dingus)  MT("listMultiParagraphExtra",     "[variable-2 * foo]",     "",     "[variable-2 * bar]",     "",     "",     "    [variable-2 hello]");  // 4 spaces, plus 1 space (should still be list, per Dingus)  MT("listMultiParagraphExtraSpace",     "[variable-2 * foo]",     "",     "[variable-2 * bar]",     "",     "     [variable-2 hello]",     "",     "    [variable-2 world]");  // 1 tab  MT("listTab",     "[variable-2 * foo]",     "",     "[variable-2 * bar]",     "",     "\t[variable-2 hello]");  // No indent  MT("listNoIndent",     "[variable-2 * foo]",     "",     "[variable-2 * bar]",     "",     "hello");  MT("listCommonMarkIndentationCode",     "[variable-2 * Code blocks also affect]",     "  [variable-3 * The next level starts where the contents start.]",     "   [variable-3 *    Anything less than that will keep the item on the same level.]",     "       [variable-3 * Each list item can indent the first level further and further.]",     "  [variable-3 * For the most part, this makes sense while writing a list.]",     "    [keyword * This means two items with same indentation can be different levels.]",     "     [keyword *  Each level has an indent requirement that can change between items.]",     "       [keyword * A list item that meets this will be part of the next level.]",     "   [variable-3 * Otherwise, it will be part of the level where it does meet this.]",     " [variable-2 * World]");  // Blockquote  MT("blockquote",     "[variable-2 * foo]",     "",     "[variable-2 * bar]",     "",     "    [variable-2"e"e-1 > hello]");  // Code block  MT("blockquoteCode",     "[variable-2 * foo]",     "",     "[variable-2 * bar]",     "",     "        [comment > hello]",     "",     "    [variable-2 world]");  // Code block followed by text  MT("blockquoteCodeText",     "[variable-2 * foo]",     "",     "    [variable-2 bar]",     "",     "        [comment hello]",     "",     "    [variable-2 world]");  // Nested list  MT("listAsteriskNested",     "[variable-2 * foo]",     "",     "    [variable-3 * bar]");  MT("listPlusNested",     "[variable-2 + foo]",     "",     "    [variable-3 + bar]");  MT("listDashNested",     "[variable-2 - foo]",     "",     "    [variable-3 - bar]");  MT("listNumberNested",     "[variable-2 1. foo]",     "",     "    [variable-3 2. bar]");  MT("listMixed",     "[variable-2 * foo]",     "",     "    [variable-3 + bar]",     "",     "        [keyword - hello]",     "",     "            [variable-2 1. world]");  MT("listBlockquote",     "[variable-2 * foo]",     "",     "    [variable-3 + bar]",     "",     "        [quote"e-1&variable-3 > hello]");  MT("listCode",     "[variable-2 * foo]",     "",     "    [variable-3 + bar]",     "",     "            [comment hello]");  // Code with internal indentation  MT("listCodeIndentation",     "[variable-2 * foo]",     "",     "        [comment bar]",     "            [comment hello]",     "                [comment world]",     "        [comment foo]",     "    [variable-2 bar]");  // List nesting edge cases  MT("listNested",    "[variable-2 * foo]",    "",    "    [variable-3 * bar]",    "",    "       [variable-3 hello]"  );  MT("listNested",    "[variable-2 * foo]",    "",    "    [variable-3 * bar]",    "",    "      [keyword * foo]"  );  // Code followed by text  MT("listCodeText",     "[variable-2 * foo]",     "",     "        [comment bar]",     "",     "hello");  // Following tests directly from official Markdown documentation  // http://daringfireball.net/projects/markdown/syntax#hr  MT("hrSpace",     "[hr * * *]");  MT("hr",     "[hr ***]");  MT("hrLong",     "[hr *****]");  MT("hrSpaceDash",     "[hr - - -]");  MT("hrDashLong",     "[hr ---------------------------------------]");  //Images  MT("Images",     "[image&image-marker !][image&image-alt-text&link [[alt text]]][string&url (http://link.to/image.jpg)]")  //Images with highlight alt text  MT("imageEm",     "[image&image-marker !][image&image-alt-text&link [[][image-alt-text&em&image&link *alt text*][image&image-alt-text&link ]]][string&url (http://link.to/image.jpg)]");  MT("imageStrong",     "[image&image-marker !][image&image-alt-text&link [[][image-alt-text&strong&image&link **alt text**][image&image-alt-text&link ]]][string&url (http://link.to/image.jpg)]");  MT("imageEmStrong",     "[image&image-marker !][image&image-alt-text&link [[][image-alt-text&image&strong&link **][image&image-alt-text&em&strong&link *alt text**][image&image-alt-text&em&link *][image&image-alt-text&link ]]][string&url (http://link.to/image.jpg)]");  // Inline link with title  MT("linkTitle",     "[link [[foo]]][string&url (http://example.com/ \"bar\")] hello");  // Inline link without title  MT("linkNoTitle",     "[link [[foo]]][string&url (http://example.com/)] bar");  // Inline link with image  MT("linkImage",     "[link [[][link&image&image-marker !][link&image&image-alt-text&link [[alt text]]][string&url (http://link.to/image.jpg)][link ]]][string&url (http://example.com/)] bar");  // Inline link with Em  MT("linkEm",     "[link [[][link&em *foo*][link ]]][string&url (http://example.com/)] bar");  // Inline link with Strong  MT("linkStrong",     "[link [[][link&strong **foo**][link ]]][string&url (http://example.com/)] bar");  // Inline link with EmStrong  MT("linkEmStrong",     "[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string&url (http://example.com/)] bar");  // Image with title  MT("imageTitle",     "[image&image-marker !][image&image-alt-text&link [[alt text]]][string&url (http://example.com/ \"bar\")] hello");  // Image without title  MT("imageNoTitle",     "[image&image-marker !][image&image-alt-text&link [[alt text]]][string&url (http://example.com/)] bar");  // Image with asterisks  MT("imageAsterisks",     "[image&image-marker !][image&image-alt-text&link [[ ][image&image-alt-text&em&link *alt text*][image&image-alt-text&link ]]][string&url (http://link.to/image.jpg)] bar");  // Not a link. Should be normal text due to square brackets being used  // regularly in text, especially in quoted material, and no space is allowed  // between square brackets and parentheses (per Dingus).  MT("notALink",     "[[foo]] (bar)");  // Reference-style links  MT("linkReference",     "[link [[foo]]][string&url [[bar]]] hello");  // Reference-style links with Em  MT("linkReferenceEm",     "[link [[][link&em *foo*][link ]]][string&url [[bar]]] hello");  // Reference-style links with Strong  MT("linkReferenceStrong",     "[link [[][link&strong **foo**][link ]]][string&url [[bar]]] hello");  // Reference-style links with EmStrong  MT("linkReferenceEmStrong",     "[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string&url [[bar]]] hello");  // Reference-style links with optional space separator (per documentation)  // "You can optionally use a space to separate the sets of brackets"  MT("linkReferenceSpace",     "[link [[foo]]] [string&url [[bar]]] hello");  // Should only allow a single space ("...use *a* space...")  MT("linkReferenceDoubleSpace",     "[[foo]]  [[bar]] hello");  // Reference-style links with implicit link name  MT("linkImplicit",     "[link [[foo]]][string&url [[]]] hello");  // @todo It would be nice if, at some point, the document was actually  // checked to see if the referenced link exists  // Link label, for reference-style links (taken from documentation)  MT("labelNoTitle",     "[link [[foo]]:] [string&url http://example.com/]");  MT("labelIndented",     "   [link [[foo]]:] [string&url http://example.com/]");  MT("labelSpaceTitle",     "[link [[foo bar]]:] [string&url http://example.com/ \"hello\"]");  MT("labelDoubleTitle",     "[link [[foo bar]]:] [string&url http://example.com/ \"hello\"] \"world\"");  MT("labelTitleDoubleQuotes",     "[link [[foo]]:] [string&url http://example.com/  \"bar\"]");  MT("labelTitleSingleQuotes",     "[link [[foo]]:] [string&url http://example.com/  'bar']");  MT("labelTitleParentheses",     "[link [[foo]]:] [string&url http://example.com/  (bar)]");  MT("labelTitleInvalid",     "[link [[foo]]:] [string&url http://example.com/] bar");  MT("labelLinkAngleBrackets",     "[link [[foo]]:] [string&url <http://example.com/>  \"bar\"]");  MT("labelTitleNextDoubleQuotes",     "[link [[foo]]:] [string&url http://example.com/]",     "[string \"bar\"] hello");  MT("labelTitleNextSingleQuotes",     "[link [[foo]]:] [string&url http://example.com/]",     "[string 'bar'] hello");  MT("labelTitleNextParentheses",     "[link [[foo]]:] [string&url http://example.com/]",     "[string (bar)] hello");  MT("labelTitleNextMixed",     "[link [[foo]]:] [string&url http://example.com/]",     "(bar\" hello");  MT("labelEscape",     "[link [[foo \\]] ]]:] [string&url http://example.com/]");  MT("labelEscapeColon",     "[link [[foo \\]]: bar]]:] [string&url http://example.com/]");  MT("labelEscapeEnd",     "[[foo\\]]: http://example.com/");  MT("linkWeb",     "[link <http://example.com/>] foo");  MT("linkWebDouble",     "[link <http://example.com/>] foo [link <http://example.com/>]");  MT("linkEmail",     "[link <user@example.com>] foo");  MT("linkEmailDouble",     "[link <user@example.com>] foo [link <user@example.com>]");  MT("emAsterisk",     "[em *foo*] bar");  MT("emUnderscore",     "[em _foo_] bar");  MT("emInWordAsterisk",     "foo[em *bar*]hello");  MT("emInWordUnderscore",     "foo[em _bar_]hello");  // Per documentation: "...surround an * or _ with spaces, it’ll be  // treated as a literal asterisk or underscore."  MT("emEscapedBySpaceIn",     "foo [em _bar _ hello_] world");  MT("emEscapedBySpaceOut",     "foo _ bar[em _hello_]world");  MT("emEscapedByNewline",     "foo",     "_ bar[em _hello_]world");  // Unclosed emphasis characters  // Instead of simply marking as EM / STRONG, it would be nice to have an  // incomplete flag for EM and STRONG, that is styled slightly different.  MT("emIncompleteAsterisk",     "foo [em *bar]");  MT("emIncompleteUnderscore",     "foo [em _bar]");  MT("strongAsterisk",     "[strong **foo**] bar");  MT("strongUnderscore",     "[strong __foo__] bar");  MT("emStrongAsterisk",     "[em *foo][em&strong **bar*][strong hello**] world");  MT("emStrongUnderscore",     "[em _foo][em&strong __bar_][strong hello__] world");  // "...same character must be used to open and close an emphasis span.""  MT("emStrongMixed",     "[em _foo][em&strong **bar*hello__ world]");  MT("emStrongMixed",     "[em *foo][em&strong __bar_hello** world]");  MT("linkWithNestedParens",     "[link [[foo]]][string&url (bar(baz))]")  // These characters should be escaped:  // \   backslash  // `   backtick  // *   asterisk  // _   underscore  // {}  curly braces  // []  square brackets  // ()  parentheses  // #   hash mark  // +   plus sign  // -   minus sign (hyphen)  // .   dot  // !   exclamation mark  MT("escapeBacktick",     "foo \\`bar\\`");  MT("doubleEscapeBacktick",     "foo \\\\[comment `bar\\\\`]");  MT("escapeAsterisk",     "foo \\*bar\\*");  MT("doubleEscapeAsterisk",     "foo \\\\[em *bar\\\\*]");  MT("escapeUnderscore",     "foo \\_bar\\_");  MT("doubleEscapeUnderscore",     "foo \\\\[em _bar\\\\_]");  MT("escapeHash",     "\\# foo");  MT("doubleEscapeHash",     "\\\\# foo");  MT("escapeNewline",     "\\",     "[em *foo*]");  // Class override tests  TokenTypeOverrideTest("overrideHeader1",    "[override-header&override-header-1 # Foo]");  TokenTypeOverrideTest("overrideHeader2",    "[override-header&override-header-2 ## Foo]");  TokenTypeOverrideTest("overrideHeader3",    "[override-header&override-header-3 ### Foo]");  TokenTypeOverrideTest("overrideHeader4",    "[override-header&override-header-4 #### Foo]");  TokenTypeOverrideTest("overrideHeader5",    "[override-header&override-header-5 ##### Foo]");  TokenTypeOverrideTest("overrideHeader6",    "[override-header&override-header-6 ###### Foo]");  TokenTypeOverrideTest("overrideCode",    "[override-code `foo`]");  TokenTypeOverrideTest("overrideCodeBlock",    "[override-code ```]",    "[override-code foo]",    "[override-code ```]");  TokenTypeOverrideTest("overrideQuote",    "[override-quote&override-quote-1 > foo]",    "[override-quote&override-quote-1 > bar]");  TokenTypeOverrideTest("overrideQuoteNested",    "[override-quote&override-quote-1 > foo]",    "[override-quote&override-quote-1 >][override-quote&override-quote-2 > bar]",    "[override-quote&override-quote-1 >][override-quote&override-quote-2 >][override-quote&override-quote-3 > baz]");  TokenTypeOverrideTest("overrideLists",    "[override-list1 - foo]",    "",    "    [override-list2 + bar]",    "",    "        [override-list3 * baz]",    "",    "            [override-list1 1. qux]",    "",    "                [override-list2 - quux]");  TokenTypeOverrideTest("overrideHr",    "[override-hr * * *]");  TokenTypeOverrideTest("overrideImage",    "[override-image&override-image-marker !][override-image&override-image-alt-text&link [[alt text]]][override-link-href&url (http://link.to/image.jpg)]");  TokenTypeOverrideTest("overrideLinkText",    "[override-link-text [[foo]]][override-link-href&url (http://example.com)]");  TokenTypeOverrideTest("overrideLinkEmailAndInline",    "[override-link-email <][override-link-inline foo@example.com>]");  TokenTypeOverrideTest("overrideEm",    "[override-em *foo*]");  TokenTypeOverrideTest("overrideStrong",    "[override-strong **foo**]");  TokenTypeOverrideTest("overrideStrikethrough",    "[override-strikethrough ~~foo~~]");  FormatTokenTypeOverrideTest("overrideFormatting",    "[override-formatting-escape \\*]");  // Tests to make sure GFM-specific things aren't getting through  MT("taskList",     "[variable-2 * [ ]] bar]");  MT("noFencedCodeBlocks",     "~~~",     "foo",     "~~~");  FencedTest("fencedCodeBlocks",     "[comment ```]",     "[comment foo]",     "[comment ```]",     "bar");  FencedTest("fencedCodeBlocksMultipleChars",     "[comment `````]",     "[comment foo]",     "[comment ```]",     "[comment foo]",     "[comment `````]",     "bar");  FencedTest("fencedCodeBlocksTildes",     "[comment ~~~]",     "[comment foo]",     "[comment ~~~]",     "bar");  FencedTest("fencedCodeBlocksTildesMultipleChars",     "[comment ~~~~~]",     "[comment ~~~]",     "[comment foo]",     "[comment ~~~~~]",     "bar");  FencedTest("fencedCodeBlocksMultipleChars",     "[comment `````]",     "[comment foo]",     "[comment ```]",     "[comment foo]",     "[comment `````]",     "bar");  FencedTest("fencedCodeBlocksMixed",     "[comment ~~~]",     "[comment ```]",     "[comment foo]",     "[comment ~~~]",     "bar");  // Tests that require XML mode  MT("xmlMode",     "[tag&bracket <][tag div][tag&bracket >]",     "*foo*",     "[tag&bracket <][tag http://github.com][tag&bracket />]",     "[tag&bracket </][tag div][tag&bracket >]",     "[link <http://github.com/>]");  MT("xmlModeWithMarkdownInside",     "[tag&bracket <][tag div] [attribute markdown]=[string 1][tag&bracket >]",     "[em *foo*]",     "[link <http://github.com/>]",     "[tag </div>]",     "[link <http://github.com/>]",     "[tag&bracket <][tag div][tag&bracket >]",     "[tag&bracket </][tag div][tag&bracket >]");})();
 |