all repos — NoPaste @ de062991ccdf763b2091f26873047685f9c0c977

Resurrected - The PussTheCat.org fork of NoPaste

scripts/CodeMirror/mode/markdown/test.js (view raw)

   1// CodeMirror, copyright (c) by Marijn Haverbeke and others
   2// Distributed under an MIT license: https://codemirror.net/LICENSE
   3
   4(function() {
   5  var config = {tabSize: 4, indentUnit: 2}
   6  var mode = CodeMirror.getMode(config, "markdown");
   7  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
   8  var modeHighlightFormatting = CodeMirror.getMode(config, {name: "markdown", highlightFormatting: true});
   9  function FT(name) { test.mode(name, modeHighlightFormatting, Array.prototype.slice.call(arguments, 1)); }
  10  var modeMT_noXml = CodeMirror.getMode(config, {name: "markdown", xml: false});
  11  function MT_noXml(name) { test.mode(name, modeMT_noXml, Array.prototype.slice.call(arguments, 1)); }
  12  var modeMT_noFencedHighlight = CodeMirror.getMode(config, {name: "markdown", fencedCodeBlockHighlighting: false});
  13  function MT_noFencedHighlight(name) { test.mode(name, modeMT_noFencedHighlight, Array.prototype.slice.call(arguments, 1)); }
  14  var modeAtxNoSpace = CodeMirror.getMode(config, {name: "markdown", allowAtxHeaderWithoutSpace: true});
  15  function AtxNoSpaceTest(name) { test.mode(name, modeAtxNoSpace, Array.prototype.slice.call(arguments, 1)); }
  16  var modeOverrideClasses = CodeMirror.getMode(config, {
  17    name: "markdown",
  18    strikethrough: true,
  19    emoji: true,
  20    tokenTypeOverrides: {
  21      "header" : "override-header",
  22      "code" : "override-code",
  23      "quote" : "override-quote",
  24      "list1" : "override-list1",
  25      "list2" : "override-list2",
  26      "list3" : "override-list3",
  27      "hr" : "override-hr",
  28      "image" : "override-image",
  29      "imageAltText": "override-image-alt-text",
  30      "imageMarker": "override-image-marker",
  31      "linkInline" : "override-link-inline",
  32      "linkEmail" : "override-link-email",
  33      "linkText" : "override-link-text",
  34      "linkHref" : "override-link-href",
  35      "em" : "override-em",
  36      "strong" : "override-strong",
  37      "strikethrough" : "override-strikethrough",
  38      "emoji" : "override-emoji"
  39  }});
  40  function TokenTypeOverrideTest(name) { test.mode(name, modeOverrideClasses, Array.prototype.slice.call(arguments, 1)); }
  41  var modeFormattingOverride = CodeMirror.getMode(config, {
  42    name: "markdown",
  43    highlightFormatting: true,
  44    tokenTypeOverrides: {
  45      "formatting" : "override-formatting"
  46  }});
  47  function FormatTokenTypeOverrideTest(name) { test.mode(name, modeFormattingOverride, Array.prototype.slice.call(arguments, 1)); }
  48  var modeET = CodeMirror.getMode(config, {name: "markdown", emoji: true});
  49  function ET(name) { test.mode(name, modeET, Array.prototype.slice.call(arguments, 1)); }
  50
  51
  52  FT("formatting_emAsterisk",
  53     "[em&formatting&formatting-em *][em foo][em&formatting&formatting-em *]");
  54
  55  FT("formatting_emUnderscore",
  56     "[em&formatting&formatting-em _][em foo][em&formatting&formatting-em _]");
  57
  58  FT("formatting_strongAsterisk",
  59     "[strong&formatting&formatting-strong **][strong foo][strong&formatting&formatting-strong **]");
  60
  61  FT("formatting_strongUnderscore",
  62     "[strong&formatting&formatting-strong __][strong foo][strong&formatting&formatting-strong __]");
  63
  64  FT("formatting_codeBackticks",
  65     "[comment&formatting&formatting-code `][comment foo][comment&formatting&formatting-code `]");
  66
  67  FT("formatting_doubleBackticks",
  68     "[comment&formatting&formatting-code ``][comment foo ` bar][comment&formatting&formatting-code ``]");
  69
  70  FT("formatting_atxHeader",
  71     "[header&header-1&formatting&formatting-header&formatting-header-1 # ][header&header-1 foo # bar ][header&header-1&formatting&formatting-header&formatting-header-1 #]");
  72
  73  FT("formatting_setextHeader",
  74     "[header&header-1 foo]",
  75     "[header&header-1&formatting&formatting-header&formatting-header-1 =]");
  76
  77  FT("formatting_blockquote",
  78     "[quote&quote-1&formatting&formatting-quote&formatting-quote-1 > ][quote&quote-1 foo]");
  79
  80  FT("formatting_list",
  81     "[variable-2&formatting&formatting-list&formatting-list-ul - ][variable-2 foo]");
  82  FT("formatting_list",
  83     "[variable-2&formatting&formatting-list&formatting-list-ol 1. ][variable-2 foo]");
  84
  85  FT("formatting_link",
  86     "[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 )]");
  87
  88  FT("formatting_linkReference",
  89     "[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 ]]]",
  90     "[link&formatting&formatting-link [][link bar][link&formatting&formatting-link ]]:] [string&url http://example.com/]");
  91
  92  FT("formatting_linkWeb",
  93     "[link&formatting&formatting-link <][link http://example.com/][link&formatting&formatting-link >]");
  94
  95  FT("formatting_linkEmail",
  96     "[link&formatting&formatting-link <][link user@example.com][link&formatting&formatting-link >]");
  97
  98  FT("formatting_escape",
  99     "[formatting-escape \\*]");
 100
 101  FT("formatting_image",
 102     "[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 )]");
 103
 104  FT("codeBlock",
 105     "[comment&formatting&formatting-code-block ```css]",
 106     "[tag foo]",
 107     "[comment&formatting&formatting-code-block ```]");
 108
 109  MT("plainText",
 110     "foo");
 111
 112  // Don't style single trailing space
 113  MT("trailingSpace1",
 114     "foo ");
 115
 116  // Two or more trailing spaces should be styled with line break character
 117  MT("trailingSpace2",
 118     "foo[trailing-space-a  ][trailing-space-new-line  ]");
 119
 120  MT("trailingSpace3",
 121     "foo[trailing-space-a  ][trailing-space-b  ][trailing-space-new-line  ]");
 122
 123  MT("trailingSpace4",
 124     "foo[trailing-space-a  ][trailing-space-b  ][trailing-space-a  ][trailing-space-new-line  ]");
 125
 126  // Code blocks using 4 spaces (regardless of CodeMirror.tabSize value)
 127  MT("codeBlocksUsing4Spaces",
 128     "    [comment foo]");
 129
 130  // Code blocks using 4 spaces with internal indentation
 131  MT("codeBlocksUsing4SpacesIndentation",
 132     "    [comment bar]",
 133     "        [comment hello]",
 134     "            [comment world]",
 135     "    [comment foo]",
 136     "bar");
 137
 138  // Code blocks should end even after extra indented lines
 139  MT("codeBlocksWithTrailingIndentedLine",
 140     "    [comment foo]",
 141     "        [comment bar]",
 142     "    [comment baz]",
 143     "    ",
 144     "hello");
 145
 146  // Code blocks using 1 tab (regardless of CodeMirror.indentWithTabs value)
 147  MT("codeBlocksUsing1Tab",
 148     "\t[comment foo]");
 149
 150  // No code blocks directly after paragraph
 151  // http://spec.commonmark.org/0.19/#example-65
 152  MT("noCodeBlocksAfterParagraph",
 153     "Foo",
 154     "    Bar");
 155
 156  MT("codeBlocksAfterATX",
 157     "[header&header-1 # foo]",
 158     "    [comment code]");
 159
 160  MT("codeBlocksAfterSetext",
 161     "[header&header-2 foo]",
 162     "[header&header-2 ---]",
 163     "    [comment code]");
 164
 165  MT("codeBlocksAfterFencedCode",
 166     "[comment ```]",
 167     "[comment foo]",
 168     "[comment ```]",
 169     "    [comment code]");
 170
 171  // Inline code using backticks
 172  MT("inlineCodeUsingBackticks",
 173     "foo [comment `bar`]");
 174
 175  // Block code using single backtick (shouldn't work)
 176  MT("blockCodeSingleBacktick",
 177     "[comment `]",
 178     "[comment foo]",
 179     "[comment `]");
 180
 181  // Unclosed backticks
 182  // Instead of simply marking as CODE, it would be nice to have an
 183  // incomplete flag for CODE, that is styled slightly different.
 184  MT("unclosedBackticks",
 185     "foo [comment `bar]");
 186
 187  // Per documentation: "To include a literal backtick character within a
 188  // code span, you can use multiple backticks as the opening and closing
 189  // delimiters"
 190  MT("doubleBackticks",
 191     "[comment ``foo ` bar``]");
 192
 193  // Tests based on Dingus
 194  // http://daringfireball.net/projects/markdown/dingus
 195  //
 196  // Multiple backticks within an inline code block
 197  MT("consecutiveBackticks",
 198     "[comment `foo```bar`]");
 199
 200  // Multiple backticks within an inline code block with a second code block
 201  MT("consecutiveBackticks",
 202     "[comment `foo```bar`] hello [comment `world`]");
 203
 204  // Unclosed with several different groups of backticks
 205  MT("unclosedBackticks",
 206     "[comment ``foo ``` bar` hello]");
 207
 208  // Closed with several different groups of backticks
 209  MT("closedBackticks",
 210     "[comment ``foo ``` bar` hello``] world");
 211
 212  // info string cannot contain backtick, thus should result in inline code
 213  MT("closingFencedMarksOnSameLine",
 214     "[comment ``` code ```] foo");
 215
 216  // atx headers
 217  // http://daringfireball.net/projects/markdown/syntax#header
 218
 219  MT("atxH1",
 220     "[header&header-1 # foo]");
 221
 222  MT("atxH2",
 223     "[header&header-2 ## foo]");
 224
 225  MT("atxH3",
 226     "[header&header-3 ### foo]");
 227
 228  MT("atxH4",
 229     "[header&header-4 #### foo]");
 230
 231  MT("atxH5",
 232     "[header&header-5 ##### foo]");
 233
 234  MT("atxH6",
 235     "[header&header-6 ###### foo]");
 236
 237  // http://spec.commonmark.org/0.19/#example-24
 238  MT("noAtxH7",
 239     "####### foo");
 240
 241  // http://spec.commonmark.org/0.19/#example-25
 242  MT("noAtxH1WithoutSpace",
 243     "#5 bolt");
 244
 245  // CommonMark requires a space after # but most parsers don't
 246  AtxNoSpaceTest("atxNoSpaceAllowed_H1NoSpace",
 247     "[header&header-1 #foo]");
 248
 249  AtxNoSpaceTest("atxNoSpaceAllowed_H4NoSpace",
 250     "[header&header-4 ####foo]");
 251
 252  AtxNoSpaceTest("atxNoSpaceAllowed_H1Space",
 253     "[header&header-1 # foo]");
 254
 255  // Inline styles should be parsed inside headers
 256  MT("atxH1inline",
 257     "[header&header-1 # foo ][header&header-1&em *bar*]");
 258
 259  MT("atxIndentedTooMuch",
 260     "[header&header-1 # foo]",
 261     "    [comment # bar]");
 262
 263  // disable atx inside blockquote until we implement proper blockquote inner mode
 264  // TODO: fix to be CommonMark-compliant
 265  MT("atxNestedInsideBlockquote",
 266     "[quote&quote-1 > # foo]");
 267
 268  MT("atxAfterBlockquote",
 269     "[quote&quote-1 > foo]",
 270     "[header&header-1 # bar]");
 271
 272  // Setext headers - H1, H2
 273  // Per documentation, "Any number of underlining =’s or -’s will work."
 274  // http://daringfireball.net/projects/markdown/syntax#header
 275  // Ideally, the text would be marked as `header` as well, but this is
 276  // not really feasible at the moment. So, instead, we're testing against
 277  // what works today, to avoid any regressions.
 278  //
 279  // Check if single underlining = works
 280  MT("setextH1",
 281     "[header&header-1 foo]",
 282     "[header&header-1 =]");
 283
 284  // Check if 3+ ='s work
 285  MT("setextH1",
 286     "[header&header-1 foo]",
 287     "[header&header-1 ===]");
 288
 289  // Check if single underlining - should not be interpreted
 290  // as it might lead to an empty list:
 291  // https://spec.commonmark.org/0.28/#setext-heading-underline
 292  MT("setextH2Single",
 293     "foo",
 294     "-");
 295
 296  // Check if 3+ -'s work
 297  MT("setextH2",
 298     "[header&header-2 foo]",
 299     "[header&header-2 ---]");
 300
 301  // http://spec.commonmark.org/0.19/#example-45
 302  MT("setextH2AllowSpaces",
 303     "[header&header-2 foo]",
 304     "   [header&header-2 ----      ]");
 305
 306  // http://spec.commonmark.org/0.19/#example-44
 307  MT("noSetextAfterIndentedCodeBlock",
 308     "     [comment foo]",
 309     "[hr ---]");
 310
 311  MT("setextAfterFencedCode",
 312     "[comment ```]",
 313     "[comment foo]",
 314     "[comment ```]",
 315     "[header&header-2 bar]",
 316     "[header&header-2 ---]");
 317
 318  MT("setextAferATX",
 319     "[header&header-1 # foo]",
 320     "[header&header-2 bar]",
 321     "[header&header-2 ---]");
 322
 323  // http://spec.commonmark.org/0.19/#example-51
 324  MT("noSetextAfterQuote",
 325     "[quote&quote-1 > foo]",
 326     "[hr ---]",
 327     "",
 328     "[quote&quote-1 > foo]",
 329     "[quote&quote-1 bar]",
 330     "[hr ---]");
 331
 332  MT("noSetextAfterList",
 333     "[variable-2 - foo]",
 334     "[hr ---]");
 335
 336  MT("noSetextAfterList_listContinuation",
 337     "[variable-2 - foo]",
 338     "bar",
 339     "[hr ---]");
 340
 341  MT("setextAfterList_afterIndentedCode",
 342     "[variable-2 - foo]",
 343     "",
 344     "      [comment bar]",
 345     "[header&header-2 baz]",
 346     "[header&header-2 ---]");
 347
 348  MT("setextAfterList_afterFencedCodeBlocks",
 349     "[variable-2 - foo]",
 350     "",
 351     "      [comment ```]",
 352     "      [comment bar]",
 353     "      [comment ```]",
 354     "[header&header-2 baz]",
 355     "[header&header-2 ---]");
 356
 357  MT("setextAfterList_afterHeader",
 358     "[variable-2 - foo]",
 359     "  [variable-2&header&header-1 # bar]",
 360     "[header&header-2 baz]",
 361     "[header&header-2 ---]");
 362
 363  MT("setextAfterList_afterHr",
 364     "[variable-2 - foo]",
 365     "",
 366     "  [hr ---]",
 367     "[header&header-2 bar]",
 368     "[header&header-2 ---]");
 369
 370  MT("setext_nestedInlineMarkup",
 371     "[header&header-1 foo ][em&header&header-1 *bar*]",
 372     "[header&header-1 =]");
 373
 374  MT("setext_linkDef",
 375     "[link [[aaa]]:] [string&url http://google.com 'title']",
 376     "[hr ---]");
 377
 378  // currently, looks max one line ahead, thus won't catch valid CommonMark
 379  //  markup
 380  MT("setext_oneLineLookahead",
 381     "foo",
 382     "[header&header-1 bar]",
 383     "[header&header-1 =]");
 384
 385  // ensure we regard space after a single dash as a list
 386  MT("setext_emptyList",
 387     "foo",
 388     "[variable-2 - ]",
 389     "foo");
 390
 391  // Single-line blockquote with trailing space
 392  MT("blockquoteSpace",
 393     "[quote&quote-1 > foo]");
 394
 395  // Single-line blockquote
 396  MT("blockquoteNoSpace",
 397     "[quote&quote-1 >foo]");
 398
 399  // No blank line before blockquote
 400  MT("blockquoteNoBlankLine",
 401     "foo",
 402     "[quote&quote-1 > bar]");
 403
 404  MT("blockquoteNested",
 405     "[quote&quote-1 > foo]",
 406     "[quote&quote-1 >][quote&quote-2 > foo]",
 407     "[quote&quote-1 >][quote&quote-2 >][quote&quote-3 > foo]");
 408
 409  // ensure quote-level is inferred correctly even if indented
 410  MT("blockquoteNestedIndented",
 411     " [quote&quote-1 > foo]",
 412     " [quote&quote-1 >][quote&quote-2 > foo]",
 413     " [quote&quote-1 >][quote&quote-2 >][quote&quote-3 > foo]");
 414
 415  // ensure quote-level is inferred correctly even if indented
 416  MT("blockquoteIndentedTooMuch",
 417     "foo",
 418     "    > bar");
 419
 420  // Single-line blockquote followed by normal paragraph
 421  MT("blockquoteThenParagraph",
 422     "[quote&quote-1 >foo]",
 423     "",
 424     "bar");
 425
 426  // Multi-line blockquote (lazy mode)
 427  MT("multiBlockquoteLazy",
 428     "[quote&quote-1 >foo]",
 429     "[quote&quote-1 bar]");
 430
 431  // Multi-line blockquote followed by normal paragraph (lazy mode)
 432  MT("multiBlockquoteLazyThenParagraph",
 433     "[quote&quote-1 >foo]",
 434     "[quote&quote-1 bar]",
 435     "",
 436     "hello");
 437
 438  // Multi-line blockquote (non-lazy mode)
 439  MT("multiBlockquote",
 440     "[quote&quote-1 >foo]",
 441     "[quote&quote-1 >bar]");
 442
 443  // Multi-line blockquote followed by normal paragraph (non-lazy mode)
 444  MT("multiBlockquoteThenParagraph",
 445     "[quote&quote-1 >foo]",
 446     "[quote&quote-1 >bar]",
 447     "",
 448     "hello");
 449
 450  // disallow lists inside blockquote for now because it causes problems outside blockquote
 451  // TODO: fix to be CommonMark-compliant
 452  MT("listNestedInBlockquote",
 453     "[quote&quote-1 > - foo]");
 454
 455  // disallow fenced blocks inside blockquote because it causes problems outside blockquote
 456  // TODO: fix to be CommonMark-compliant
 457  MT("fencedBlockNestedInBlockquote",
 458     "[quote&quote-1 > ```]",
 459     "[quote&quote-1 > code]",
 460     "[quote&quote-1 > ```]",
 461     // ensure we still allow inline code
 462     "[quote&quote-1 > ][quote&quote-1&comment `code`]");
 463
 464  // Header with leading space after continued blockquote (#3287, negative indentation)
 465  MT("headerAfterContinuedBlockquote",
 466     "[quote&quote-1 > foo]",
 467     "[quote&quote-1 bar]",
 468     "",
 469     " [header&header-1 # hello]");
 470
 471  // Check list types
 472
 473  MT("listAsterisk",
 474     "foo",
 475     "bar",
 476     "",
 477     "[variable-2 * foo]",
 478     "[variable-2 * bar]");
 479
 480  MT("listPlus",
 481     "foo",
 482     "bar",
 483     "",
 484     "[variable-2 + foo]",
 485     "[variable-2 + bar]");
 486
 487  MT("listDash",
 488     "foo",
 489     "bar",
 490     "",
 491     "[variable-2 - foo]",
 492     "[variable-2 - bar]");
 493
 494  MT("listNumber",
 495     "foo",
 496     "bar",
 497     "",
 498     "[variable-2 1. foo]",
 499     "[variable-2 2. bar]");
 500
 501  MT("listFromParagraph",
 502     "foo",
 503     "[variable-2 1. bar]",
 504     "[variable-2 2. hello]");
 505
 506  // List after hr
 507  MT("listAfterHr",
 508     "[hr ---]",
 509     "[variable-2 - bar]");
 510
 511  // List after header
 512  MT("listAfterHeader",
 513     "[header&header-1 # foo]",
 514     "[variable-2 - bar]");
 515
 516  // hr after list
 517  MT("hrAfterList",
 518     "[variable-2 - foo]",
 519     "[hr -----]");
 520
 521  MT("hrAfterFencedCode",
 522     "[comment ```]",
 523     "[comment code]",
 524     "[comment ```]",
 525     "[hr ---]");
 526
 527  // allow hr inside lists
 528  // (require prev line to be empty or hr, TODO: non-CommonMark-compliant)
 529  MT("hrInsideList",
 530     "[variable-2 - foo]",
 531     "",
 532     "  [hr ---]",
 533     "     [hr ---]",
 534     "",
 535     "      [comment ---]");
 536
 537  MT("consecutiveHr",
 538     "[hr ---]",
 539     "[hr ---]",
 540     "[hr ---]");
 541
 542  // Formatting in lists (*)
 543  MT("listAsteriskFormatting",
 544     "[variable-2 * ][variable-2&em *foo*][variable-2  bar]",
 545     "[variable-2 * ][variable-2&strong **foo**][variable-2  bar]",
 546     "[variable-2 * ][variable-2&em&strong ***foo***][variable-2  bar]",
 547     "[variable-2 * ][variable-2&comment `foo`][variable-2  bar]");
 548
 549  // Formatting in lists (+)
 550  MT("listPlusFormatting",
 551     "[variable-2 + ][variable-2&em *foo*][variable-2  bar]",
 552     "[variable-2 + ][variable-2&strong **foo**][variable-2  bar]",
 553     "[variable-2 + ][variable-2&em&strong ***foo***][variable-2  bar]",
 554     "[variable-2 + ][variable-2&comment `foo`][variable-2  bar]");
 555
 556  // Formatting in lists (-)
 557  MT("listDashFormatting",
 558     "[variable-2 - ][variable-2&em *foo*][variable-2  bar]",
 559     "[variable-2 - ][variable-2&strong **foo**][variable-2  bar]",
 560     "[variable-2 - ][variable-2&em&strong ***foo***][variable-2  bar]",
 561     "[variable-2 - ][variable-2&comment `foo`][variable-2  bar]");
 562
 563  // Formatting in lists (1.)
 564  MT("listNumberFormatting",
 565     "[variable-2 1. ][variable-2&em *foo*][variable-2  bar]",
 566     "[variable-2 2. ][variable-2&strong **foo**][variable-2  bar]",
 567     "[variable-2 3. ][variable-2&em&strong ***foo***][variable-2  bar]",
 568     "[variable-2 4. ][variable-2&comment `foo`][variable-2  bar]");
 569
 570  // Paragraph lists
 571  MT("listParagraph",
 572     "[variable-2 * foo]",
 573     "",
 574     "[variable-2 * bar]");
 575
 576  // Multi-paragraph lists
 577  //
 578  // 4 spaces
 579  MT("listMultiParagraph",
 580     "[variable-2 * foo]",
 581     "",
 582     "[variable-2 * bar]",
 583     "",
 584     "    [variable-2 hello]");
 585
 586  // 4 spaces, extra blank lines (should still be list, per Dingus)
 587  MT("listMultiParagraphExtra",
 588     "[variable-2 * foo]",
 589     "",
 590     "[variable-2 * bar]",
 591     "",
 592     "",
 593     "    [variable-2 hello]");
 594
 595  // 4 spaces, plus 1 space (should still be list, per Dingus)
 596  MT("listMultiParagraphExtraSpace",
 597     "[variable-2 * foo]",
 598     "",
 599     "[variable-2 * bar]",
 600     "",
 601     "     [variable-2 hello]",
 602     "",
 603     "    [variable-2 world]");
 604
 605  // 1 tab
 606  MT("listTab",
 607     "[variable-2 * foo]",
 608     "",
 609     "[variable-2 * bar]",
 610     "",
 611     "\t[variable-2 hello]");
 612
 613  // No indent
 614  MT("listNoIndent",
 615     "[variable-2 * foo]",
 616     "",
 617     "[variable-2 * bar]",
 618     "",
 619     "hello");
 620
 621  MT("listCommonMarkIndentationCode",
 622     "[variable-2 * Code blocks also affect]",
 623     "  [variable-3 * The next level starts where the contents start.]",
 624     "   [variable-3 *    Anything less than that will keep the item on the same level.]",
 625     "       [variable-3 * Each list item can indent the first level further and further.]",
 626     "  [variable-3 * For the most part, this makes sense while writing a list.]",
 627     "    [keyword * This means two items with same indentation can be different levels.]",
 628     "     [keyword *  Each level has an indent requirement that can change between items.]",
 629     "       [keyword * A list item that meets this will be part of the next level.]",
 630     "   [variable-3 * Otherwise, it will be part of the level where it does meet this.]",
 631     " [variable-2 * World]");
 632
 633  // should handle nested and un-nested lists
 634  MT("listCommonMark_MixedIndents",
 635     "[variable-2 * list1]",
 636     "    [variable-2 list1]",
 637     "  [variable-2&header&header-1 # heading still part of list1]",
 638     "  [variable-2 text after heading still part of list1]",
 639     "",
 640     "      [comment indented codeblock]",
 641     "  [variable-2 list1 after code block]",
 642     "  [variable-3 * list2]",
 643     // amount of spaces on empty lines between lists doesn't matter
 644     "              ",
 645     // extra empty lines irrelevant
 646     "",
 647     "",
 648     "    [variable-3 indented text part of list2]",
 649     "    [keyword * list3]",
 650     "",
 651     "    [variable-3 text at level of list2]",
 652     "",
 653     "  [variable-2 de-indented text part of list1 again]",
 654     "",
 655     "  [variable-2&comment ```]",
 656     "  [comment code]",
 657     "  [variable-2&comment ```]",
 658     "",
 659     "  [variable-2 text after fenced code]");
 660
 661  // should correctly parse numbered list content indentation
 662  MT("listCommonMark_NumeberedListIndent",
 663     "[variable-2 1000. list with base indent of 6]",
 664     "",
 665     "      [variable-2 text must be indented 6 spaces at minimum]",
 666     "",
 667     "         [variable-2 9-spaces indented text still part of list]",
 668     "",
 669     "          [comment indented codeblock starts at 10 spaces]",
 670     "",
 671     "     [comment text indented by 5 spaces no longer belong to list]");
 672
 673  // should consider tab as 4 spaces
 674  MT("listCommonMark_TabIndented",
 675     "[variable-2 * list]",
 676     "\t[variable-3 * list2]",
 677     "",
 678     "\t\t[variable-3 part of list2]");
 679
 680  MT("listAfterBlockquote",
 681     "[quote&quote-1 > foo]",
 682     "[variable-2 - bar]");
 683
 684  // shouldn't create sublist if it's indented more than allowed
 685  MT("nestedListIndentedTooMuch",
 686     "[variable-2 - foo]",
 687     "          [variable-2 - bar]");
 688
 689  MT("listIndentedTooMuchAfterParagraph",
 690     "foo",
 691     "    - bar");
 692
 693  // Blockquote
 694  MT("blockquote",
 695     "[variable-2 * foo]",
 696     "",
 697     "[variable-2 * bar]",
 698     "",
 699     "    [variable-2&quote&quote-1 > hello]");
 700
 701  // Code block
 702  MT("blockquoteCode",
 703     "[variable-2 * foo]",
 704     "",
 705     "[variable-2 * bar]",
 706     "",
 707     "        [comment > hello]",
 708     "",
 709     "    [variable-2 world]");
 710
 711  // Code block followed by text
 712  MT("blockquoteCodeText",
 713     "[variable-2 * foo]",
 714     "",
 715     "    [variable-2 bar]",
 716     "",
 717     "        [comment hello]",
 718     "",
 719     "    [variable-2 world]");
 720
 721  // Nested list
 722
 723  MT("listAsteriskNested",
 724     "[variable-2 * foo]",
 725     "",
 726     "    [variable-3 * bar]");
 727
 728  MT("listPlusNested",
 729     "[variable-2 + foo]",
 730     "",
 731     "    [variable-3 + bar]");
 732
 733  MT("listDashNested",
 734     "[variable-2 - foo]",
 735     "",
 736     "    [variable-3 - bar]");
 737
 738  MT("listNumberNested",
 739     "[variable-2 1. foo]",
 740     "",
 741     "    [variable-3 2. bar]");
 742
 743  MT("listMixed",
 744     "[variable-2 * foo]",
 745     "",
 746     "    [variable-3 + bar]",
 747     "",
 748     "        [keyword - hello]",
 749     "",
 750     "            [variable-2 1. world]");
 751
 752  MT("listBlockquote",
 753     "[variable-2 * foo]",
 754     "",
 755     "    [variable-3 + bar]",
 756     "",
 757     "        [quote&quote-1&variable-3 > hello]");
 758
 759  MT("listCode",
 760     "[variable-2 * foo]",
 761     "",
 762     "    [variable-3 + bar]",
 763     "",
 764     "            [comment hello]");
 765
 766  // Code with internal indentation
 767  MT("listCodeIndentation",
 768     "[variable-2 * foo]",
 769     "",
 770     "        [comment bar]",
 771     "            [comment hello]",
 772     "                [comment world]",
 773     "        [comment foo]",
 774     "    [variable-2 bar]");
 775
 776  // List nesting edge cases
 777  MT("listNested",
 778    "[variable-2 * foo]",
 779    "",
 780    "    [variable-3 * bar]",
 781    "",
 782    "       [variable-3 hello]"
 783  );
 784  MT("listNested",
 785    "[variable-2 * foo]",
 786    "",
 787    "    [variable-3 * bar]",
 788    "",
 789    "      [keyword * foo]"
 790  );
 791
 792  // Code followed by text
 793  MT("listCodeText",
 794     "[variable-2 * foo]",
 795     "",
 796     "        [comment bar]",
 797     "",
 798     "hello");
 799
 800  // Following tests directly from official Markdown documentation
 801  // http://daringfireball.net/projects/markdown/syntax#hr
 802
 803  MT("hrSpace",
 804     "[hr * * *]");
 805
 806  MT("hr",
 807     "[hr ***]");
 808
 809  MT("hrLong",
 810     "[hr *****]");
 811
 812  MT("hrSpaceDash",
 813     "[hr - - -]");
 814
 815  MT("hrDashLong",
 816     "[hr ---------------------------------------]");
 817
 818  //Images
 819  MT("Images",
 820     "[image&image-marker !][image&image-alt-text&link [[alt text]]][string&url (http://link.to/image.jpg)]")
 821
 822  //Images with highlight alt text
 823  MT("imageEm",
 824     "[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)]");
 825
 826  MT("imageStrong",
 827     "[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)]");
 828
 829  MT("imageEmStrong",
 830     "[image&image-marker !][image&image-alt-text&link [[][image&image-alt-text&em&strong&link ***alt text***][image&image-alt-text&link ]]][string&url (http://link.to/image.jpg)]");
 831
 832  // Inline link with title
 833  MT("linkTitle",
 834     "[link [[foo]]][string&url (http://example.com/ \"bar\")] hello");
 835
 836  // Inline link without title
 837  MT("linkNoTitle",
 838     "[link [[foo]]][string&url (http://example.com/)] bar");
 839
 840  // Inline link with image
 841  MT("linkImage",
 842     "[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");
 843
 844  // Inline link with Em
 845  MT("linkEm",
 846     "[link [[][link&em *foo*][link ]]][string&url (http://example.com/)] bar");
 847
 848  // Inline link with Strong
 849  MT("linkStrong",
 850     "[link [[][link&strong **foo**][link ]]][string&url (http://example.com/)] bar");
 851
 852  // Inline link with EmStrong
 853  MT("linkEmStrong",
 854     "[link [[][link&em&strong ***foo***][link ]]][string&url (http://example.com/)] bar");
 855
 856  MT("multilineLink",
 857     "[link [[foo]",
 858     "[link bar]]][string&url (https://foo#_a)]",
 859     "should not be italics")
 860
 861  // Image with title
 862  MT("imageTitle",
 863     "[image&image-marker !][image&image-alt-text&link [[alt text]]][string&url (http://example.com/ \"bar\")] hello");
 864
 865  // Image without title
 866  MT("imageNoTitle",
 867     "[image&image-marker !][image&image-alt-text&link [[alt text]]][string&url (http://example.com/)] bar");
 868
 869  // Image with asterisks
 870  MT("imageAsterisks",
 871     "[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");
 872
 873  // Not a link. Should be normal text due to square brackets being used
 874  // regularly in text, especially in quoted material, and no space is allowed
 875  // between square brackets and parentheses (per Dingus).
 876  MT("notALink",
 877     "[link [[foo]]] (bar)");
 878
 879  // Reference-style links
 880  MT("linkReference",
 881     "[link [[foo]]][string&url [[bar]]] hello");
 882
 883  // Reference-style links with Em
 884  MT("linkReferenceEm",
 885     "[link [[][link&em *foo*][link ]]][string&url [[bar]]] hello");
 886
 887  // Reference-style links with Strong
 888  MT("linkReferenceStrong",
 889     "[link [[][link&strong **foo**][link ]]][string&url [[bar]]] hello");
 890
 891  // Reference-style links with EmStrong
 892  MT("linkReferenceEmStrong",
 893     "[link [[][link&em&strong ***foo***][link ]]][string&url [[bar]]] hello");
 894
 895  // Reference-style links with optional space separator (per documentation)
 896  // "You can optionally use a space to separate the sets of brackets"
 897  MT("linkReferenceSpace",
 898     "[link [[foo]]] [string&url [[bar]]] hello");
 899
 900  // Should only allow a single space ("...use *a* space...")
 901  MT("linkReferenceDoubleSpace",
 902     "[link [[foo]]]  [link [[bar]]] hello");
 903
 904  // Reference-style links with implicit link name
 905  MT("linkImplicit",
 906     "[link [[foo]]][string&url [[]]] hello");
 907
 908  // @todo It would be nice if, at some point, the document was actually
 909  // checked to see if the referenced link exists
 910
 911  // Link label, for reference-style links (taken from documentation)
 912
 913  MT("labelNoTitle",
 914     "[link [[foo]]:] [string&url http://example.com/]");
 915
 916  MT("labelIndented",
 917     "   [link [[foo]]:] [string&url http://example.com/]");
 918
 919  MT("labelSpaceTitle",
 920     "[link [[foo bar]]:] [string&url http://example.com/ \"hello\"]");
 921
 922  MT("labelDoubleTitle",
 923     "[link [[foo bar]]:] [string&url http://example.com/ \"hello\"] \"world\"");
 924
 925  MT("labelTitleDoubleQuotes",
 926     "[link [[foo]]:] [string&url http://example.com/  \"bar\"]");
 927
 928  MT("labelTitleSingleQuotes",
 929     "[link [[foo]]:] [string&url http://example.com/  'bar']");
 930
 931  MT("labelTitleParentheses",
 932     "[link [[foo]]:] [string&url http://example.com/  (bar)]");
 933
 934  MT("labelTitleInvalid",
 935     "[link [[foo]]:] [string&url http://example.com/] bar");
 936
 937  MT("labelLinkAngleBrackets",
 938     "[link [[foo]]:] [string&url <http://example.com/>  \"bar\"]");
 939
 940  MT("labelTitleNextDoubleQuotes",
 941     "[link [[foo]]:] [string&url http://example.com/]",
 942     "[string \"bar\"] hello");
 943
 944  MT("labelTitleNextSingleQuotes",
 945     "[link [[foo]]:] [string&url http://example.com/]",
 946     "[string 'bar'] hello");
 947
 948  MT("labelTitleNextParentheses",
 949     "[link [[foo]]:] [string&url http://example.com/]",
 950     "[string (bar)] hello");
 951
 952  MT("labelTitleNextMixed",
 953     "[link [[foo]]:] [string&url http://example.com/]",
 954     "(bar\" hello");
 955
 956  MT("labelEscape",
 957     "[link [[foo \\]] ]]:] [string&url http://example.com/]");
 958
 959  MT("labelEscapeColon",
 960     "[link [[foo \\]]: bar]]:] [string&url http://example.com/]");
 961
 962  MT("labelEscapeEnd",
 963     "\\[[foo\\]]: http://example.com/");
 964
 965  MT("linkWeb",
 966     "[link <http://example.com/>] foo");
 967
 968  MT("linkWebDouble",
 969     "[link <http://example.com/>] foo [link <http://example.com/>]");
 970
 971  MT("linkEmail",
 972     "[link <user@example.com>] foo");
 973
 974  MT("linkEmailDouble",
 975     "[link <user@example.com>] foo [link <user@example.com>]");
 976
 977  MT("emAsterisk",
 978     "[em *foo*] bar");
 979
 980  MT("emUnderscore",
 981     "[em _foo_] bar");
 982
 983  MT("emInWordAsterisk",
 984     "foo[em *bar*]hello");
 985
 986  MT("emInWordUnderscore",
 987     "foo_bar_hello");
 988
 989  // Per documentation: "...surround an * or _ with spaces, it’ll be
 990  // treated as a literal asterisk or underscore."
 991
 992  MT("emEscapedBySpaceIn",
 993     "foo [em _bar _ hello_] world");
 994
 995  MT("emEscapedBySpaceOut",
 996     "foo _ bar [em _hello_] world");
 997
 998  MT("emEscapedByNewline",
 999     "foo",
1000     "_ bar [em _hello_] world");
1001
1002  // Unclosed emphasis characters
1003  // Instead of simply marking as EM / STRONG, it would be nice to have an
1004  // incomplete flag for EM and STRONG, that is styled slightly different.
1005  MT("emIncompleteAsterisk",
1006     "foo [em *bar]");
1007
1008  MT("emIncompleteUnderscore",
1009     "foo [em _bar]");
1010
1011  MT("strongAsterisk",
1012     "[strong **foo**] bar");
1013
1014  MT("strongUnderscore",
1015     "[strong __foo__] bar");
1016
1017  MT("emStrongAsterisk",
1018     "[em *foo][em&strong **bar*][strong hello**] world");
1019
1020  MT("emStrongUnderscore",
1021     "[em _foo ][em&strong __bar_][strong  hello__] world");
1022
1023  // "...same character must be used to open and close an emphasis span.""
1024  MT("emStrongMixed",
1025     "[em _foo][em&strong **bar*hello__ world]");
1026
1027  MT("emStrongMixed",
1028     "[em *foo ][em&strong __bar_hello** world]");
1029
1030  MT("linkWithNestedParens",
1031     "[link [[foo]]][string&url (bar(baz))]")
1032
1033  // These characters should be escaped:
1034  // \   backslash
1035  // `   backtick
1036  // *   asterisk
1037  // _   underscore
1038  // {}  curly braces
1039  // []  square brackets
1040  // ()  parentheses
1041  // #   hash mark
1042  // +   plus sign
1043  // -   minus sign (hyphen)
1044  // .   dot
1045  // !   exclamation mark
1046
1047  MT("escapeBacktick",
1048     "foo \\`bar\\`");
1049
1050  MT("doubleEscapeBacktick",
1051     "foo \\\\[comment `bar\\\\`]");
1052
1053  MT("escapeAsterisk",
1054     "foo \\*bar\\*");
1055
1056  MT("doubleEscapeAsterisk",
1057     "foo \\\\[em *bar\\\\*]");
1058
1059  MT("escapeUnderscore",
1060     "foo \\_bar\\_");
1061
1062  MT("doubleEscapeUnderscore",
1063     "foo \\\\[em _bar\\\\_]");
1064
1065  MT("escapeHash",
1066     "\\# foo");
1067
1068  MT("doubleEscapeHash",
1069     "\\\\# foo");
1070
1071  MT("escapeNewline",
1072     "\\",
1073     "[em *foo*]");
1074
1075  // Class override tests
1076  TokenTypeOverrideTest("overrideHeader1",
1077    "[override-header&override-header-1 # Foo]");
1078
1079  TokenTypeOverrideTest("overrideHeader2",
1080    "[override-header&override-header-2 ## Foo]");
1081
1082  TokenTypeOverrideTest("overrideHeader3",
1083    "[override-header&override-header-3 ### Foo]");
1084
1085  TokenTypeOverrideTest("overrideHeader4",
1086    "[override-header&override-header-4 #### Foo]");
1087
1088  TokenTypeOverrideTest("overrideHeader5",
1089    "[override-header&override-header-5 ##### Foo]");
1090
1091  TokenTypeOverrideTest("overrideHeader6",
1092    "[override-header&override-header-6 ###### Foo]");
1093
1094  TokenTypeOverrideTest("overrideCode",
1095    "[override-code `foo`]");
1096
1097  TokenTypeOverrideTest("overrideCodeBlock",
1098    "[override-code ```]",
1099    "[override-code foo]",
1100    "[override-code ```]");
1101
1102  TokenTypeOverrideTest("overrideQuote",
1103    "[override-quote&override-quote-1 > foo]",
1104    "[override-quote&override-quote-1 > bar]");
1105
1106  TokenTypeOverrideTest("overrideQuoteNested",
1107    "[override-quote&override-quote-1 > foo]",
1108    "[override-quote&override-quote-1 >][override-quote&override-quote-2 > bar]",
1109    "[override-quote&override-quote-1 >][override-quote&override-quote-2 >][override-quote&override-quote-3 > baz]");
1110
1111  TokenTypeOverrideTest("overrideLists",
1112    "[override-list1 - foo]",
1113    "",
1114    "    [override-list2 + bar]",
1115    "",
1116    "        [override-list3 * baz]",
1117    "",
1118    "            [override-list1 1. qux]",
1119    "",
1120    "                [override-list2 - quux]");
1121
1122  TokenTypeOverrideTest("overrideHr",
1123    "[override-hr * * *]");
1124
1125  TokenTypeOverrideTest("overrideImage",
1126    "[override-image&override-image-marker !][override-image&override-image-alt-text&link [[alt text]]][override-link-href&url (http://link.to/image.jpg)]");
1127
1128  TokenTypeOverrideTest("overrideLinkText",
1129    "[override-link-text [[foo]]][override-link-href&url (http://example.com)]");
1130
1131  TokenTypeOverrideTest("overrideLinkEmailAndInline",
1132    "[override-link-email <][override-link-inline foo@example.com>]");
1133
1134  TokenTypeOverrideTest("overrideEm",
1135    "[override-em *foo*]");
1136
1137  TokenTypeOverrideTest("overrideStrong",
1138    "[override-strong **foo**]");
1139
1140  TokenTypeOverrideTest("overrideStrikethrough",
1141    "[override-strikethrough ~~foo~~]");
1142
1143  TokenTypeOverrideTest("overrideEmoji",
1144    "[override-emoji :foo:]");
1145
1146  FormatTokenTypeOverrideTest("overrideFormatting",
1147    "[override-formatting-escape \\*]");
1148
1149  // Tests to make sure GFM-specific things aren't getting through
1150
1151  MT("taskList",
1152     "[variable-2 * ][link&variable-2 [[ ]]][variable-2 bar]");
1153
1154  MT("fencedCodeBlocks",
1155     "[comment ```]",
1156     "[comment foo]",
1157     "",
1158     "[comment bar]",
1159     "[comment ```]",
1160     "baz");
1161
1162  MT("fencedCodeBlocks_invalidClosingFence_trailingText",
1163     "[comment ```]",
1164     "[comment foo]",
1165     "[comment ``` must not have trailing text]",
1166     "[comment baz]");
1167
1168  MT("fencedCodeBlocks_invalidClosingFence_trailingTabs",
1169     "[comment ```]",
1170     "[comment foo]",
1171     "[comment ```\t]",
1172     "[comment baz]");
1173
1174  MT("fencedCodeBlocks_validClosingFence",
1175     "[comment ```]",
1176     "[comment foo]",
1177     // may have trailing spaces
1178     "[comment ```     ]",
1179     "baz");
1180
1181  MT("fencedCodeBlocksInList_closingFenceIndented",
1182     "[variable-2 - list]",
1183     "    [variable-2&comment ```]",
1184     "    [comment foo]",
1185     "     [variable-2&comment ```]",
1186     "    [variable-2 baz]");
1187
1188  MT("fencedCodeBlocksInList_closingFenceIndentedTooMuch",
1189     "[variable-2 - list]",
1190     "    [variable-2&comment ```]",
1191     "    [comment foo]",
1192     "      [comment ```]",
1193     "    [comment baz]");
1194
1195  MT("fencedCodeBlockModeSwitching",
1196     "[comment ```javascript]",
1197     "[variable foo]",
1198     "",
1199     "[comment ```]",
1200     "bar");
1201
1202  MT_noFencedHighlight("fencedCodeBlock_noHighlight",
1203     "[comment ```javascript]",
1204     "[comment foo]",
1205     "[comment ```]");
1206
1207  MT("fencedCodeBlockModeSwitchingObjc",
1208     "[comment ```objective-c]",
1209     "[keyword @property] [variable NSString] [operator *] [variable foo];",
1210     "[comment ```]",
1211     "bar");
1212
1213  MT("fencedCodeBlocksMultipleChars",
1214     "[comment `````]",
1215     "[comment foo]",
1216     "[comment ```]",
1217     "[comment foo]",
1218     "[comment `````]",
1219     "bar");
1220
1221  MT("fencedCodeBlocksTildes",
1222     "[comment ~~~]",
1223     "[comment foo]",
1224     "[comment ~~~]",
1225     "bar");
1226
1227  MT("fencedCodeBlocksTildesMultipleChars",
1228     "[comment ~~~~~]",
1229     "[comment ~~~]",
1230     "[comment foo]",
1231     "[comment ~~~~~]",
1232     "bar");
1233
1234  MT("fencedCodeBlocksMultipleChars",
1235     "[comment `````]",
1236     "[comment foo]",
1237     "[comment ```]",
1238     "[comment foo]",
1239     "[comment `````]",
1240     "bar");
1241
1242  MT("fencedCodeBlocksMixed",
1243     "[comment ~~~]",
1244     "[comment ```]",
1245     "[comment foo]",
1246     "[comment ~~~]",
1247     "bar");
1248
1249  MT("fencedCodeBlocksAfterBlockquote",
1250     "[quote&quote-1 > foo]",
1251     "[comment ```]",
1252     "[comment bar]",
1253     "[comment ```]");
1254
1255  // fencedCode indented too much should act as simple indentedCode
1256  //  (hence has no highlight formatting)
1257  FT("tooMuchIndentedFencedCode",
1258     "    [comment ```]",
1259     "    [comment code]",
1260     "    [comment ```]");
1261
1262  MT("autoTerminateFencedCodeWhenLeavingList",
1263     "[variable-2 - list1]",
1264     "  [variable-3 - list2]",
1265     "    [variable-3&comment ```]",
1266     "    [comment code]",
1267     "  [variable-3 - list2]",
1268     "  [variable-2&comment ```]",
1269     "  [comment code]",
1270     "[quote&quote-1 > foo]");
1271
1272  // Tests that require XML mode
1273
1274  MT("xmlMode",
1275     "[tag&bracket <][tag div][tag&bracket >]",
1276     "  *foo*",
1277     "  [tag&bracket <][tag http://github.com][tag&bracket />]",
1278     "[tag&bracket </][tag div][tag&bracket >]",
1279     "[link <http://github.com/>]");
1280
1281  MT("xmlModeWithMarkdownInside",
1282     "[tag&bracket <][tag div] [attribute markdown]=[string 1][tag&bracket >]",
1283     "[em *foo*]",
1284     "[link <http://github.com/>]",
1285     "[tag </div>]",
1286     "[link <http://github.com/>]",
1287     "[tag&bracket <][tag div][tag&bracket >]",
1288     "[tag&bracket </][tag div][tag&bracket >]");
1289
1290  MT("xmlModeLineBreakInTags",
1291     "[tag&bracket <][tag div] [attribute id]=[string \"1\"]",
1292     "     [attribute class]=[string \"sth\"][tag&bracket >]xxx",
1293     "[tag&bracket </][tag div][tag&bracket >]");
1294
1295  MT("xmlModeCommentWithBlankLine",
1296     "[comment <!-- Hello]",
1297     "",
1298     "[comment World -->]");
1299
1300  MT("xmlModeCDATA",
1301     "[atom <![CDATA[ Hello]",
1302     "",
1303     "[atom FooBar]",
1304     "[atom Test ]]]]>]");
1305
1306  MT("xmlModePreprocessor",
1307     "[meta <?php] [meta echo '1234'; ?>]");
1308
1309  MT_noXml("xmlHighlightDisabled",
1310     "<div>foo</div>");
1311
1312  // Tests Emojis
1313
1314  ET("emojiDefault",
1315    "[builtin :foobar:]");
1316
1317  ET("emojiTable",
1318    " :--:");
1319})();