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