2 var mode = CodeMirror.getMode({tabSize: 4}, "markdown");
3 function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
8 // Don't style single trailing space
12 // Two or more trailing spaces should be styled with line break character
14 "foo[trailing-space-a ][trailing-space-new-line ]");
17 "foo[trailing-space-a ][trailing-space-b ][trailing-space-new-line ]");
20 "foo[trailing-space-a ][trailing-space-b ][trailing-space-a ][trailing-space-new-line ]");
22 // Code blocks using 4 spaces (regardless of CodeMirror.tabSize value)
23 MT("codeBlocksUsing4Spaces",
26 // Code blocks using 4 spaces with internal indentation
27 MT("codeBlocksUsing4SpacesIndentation",
34 // Code blocks using 4 spaces with internal indentation
35 MT("codeBlocksUsing4SpacesIndentation",
41 // Code blocks using 1 tab (regardless of CodeMirror.indentWithTabs value)
42 MT("codeBlocksUsing1Tab",
45 // Inline code using backticks
46 MT("inlineCodeUsingBackticks",
47 "foo [comment `bar`]");
49 // Block code using single backtick (shouldn't work)
50 MT("blockCodeSingleBacktick",
56 // Instead of simply marking as CODE, it would be nice to have an
57 // incomplete flag for CODE, that is styled slightly different.
58 MT("unclosedBackticks",
59 "foo [comment `bar]");
61 // Per documentation: "To include a literal backtick character within a
62 // code span, you can use multiple backticks as the opening and closing
65 "[comment ``foo ` bar``]");
67 // Tests based on Dingus
68 // http://daringfireball.net/projects/markdown/dingus
70 // Multiple backticks within an inline code block
71 MT("consecutiveBackticks",
72 "[comment `foo```bar`]");
74 // Multiple backticks within an inline code block with a second code block
75 MT("consecutiveBackticks",
76 "[comment `foo```bar`] hello [comment `world`]");
78 // Unclosed with several different groups of backticks
79 MT("unclosedBackticks",
80 "[comment ``foo ``` bar` hello]");
82 // Closed with several different groups of backticks
84 "[comment ``foo ``` bar` hello``] world");
87 // http://daringfireball.net/projects/markdown/syntax#header
102 "[header ##### foo]");
105 "[header ###### foo]");
107 // H6 - 7x '#' should still be H6, per Dingus
108 // http://daringfireball.net/projects/markdown/dingus
110 "[header ####### foo]");
112 // Setext headers - H1, H2
113 // Per documentation, "Any number of underlining =’s or -’s will work."
114 // http://daringfireball.net/projects/markdown/syntax#header
115 // Ideally, the text would be marked as `header` as well, but this is
116 // not really feasible at the moment. So, instead, we're testing against
117 // what works today, to avoid any regressions.
119 // Check if single underlining = works
124 // Check if 3+ ='s work
129 // Check if single underlining - works
134 // Check if 3+ -'s work
139 // Single-line blockquote with trailing space
140 MT("blockquoteSpace",
143 // Single-line blockquote
144 MT("blockquoteNoSpace",
147 // No blank line before blockquote
148 MT("blockquoteNoBlankLine",
153 MT("blockquoteSpace",
158 // Single-line blockquote followed by normal paragraph
159 MT("blockquoteThenParagraph",
164 // Multi-line blockquote (lazy mode)
165 MT("multiBlockquoteLazy",
169 // Multi-line blockquote followed by normal paragraph (lazy mode)
170 MT("multiBlockquoteLazyThenParagraph",
176 // Multi-line blockquote (non-lazy mode)
177 MT("multiBlockquote",
181 // Multi-line blockquote followed by normal paragraph (non-lazy mode)
182 MT("multiBlockquoteThenParagraph",
194 "[variable-2 * foo]",
195 "[variable-2 * bar]");
201 "[variable-2 + foo]",
202 "[variable-2 + bar]");
208 "[variable-2 - foo]",
209 "[variable-2 - bar]");
215 "[variable-2 1. foo]",
216 "[variable-2 2. bar]");
218 // Lists require a preceding blank line (per Dingus)
224 // Formatting in lists (*)
225 MT("listAsteriskFormatting",
226 "[variable-2 * ][variable-2&em *foo*][variable-2 bar]",
227 "[variable-2 * ][variable-2&strong **foo**][variable-2 bar]",
228 "[variable-2 * ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]",
229 "[variable-2 * ][variable-2&comment `foo`][variable-2 bar]");
231 // Formatting in lists (+)
232 MT("listPlusFormatting",
233 "[variable-2 + ][variable-2&em *foo*][variable-2 bar]",
234 "[variable-2 + ][variable-2&strong **foo**][variable-2 bar]",
235 "[variable-2 + ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]",
236 "[variable-2 + ][variable-2&comment `foo`][variable-2 bar]");
238 // Formatting in lists (-)
239 MT("listDashFormatting",
240 "[variable-2 - ][variable-2&em *foo*][variable-2 bar]",
241 "[variable-2 - ][variable-2&strong **foo**][variable-2 bar]",
242 "[variable-2 - ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]",
243 "[variable-2 - ][variable-2&comment `foo`][variable-2 bar]");
245 // Formatting in lists (1.)
246 MT("listNumberFormatting",
247 "[variable-2 1. ][variable-2&em *foo*][variable-2 bar]",
248 "[variable-2 2. ][variable-2&strong **foo**][variable-2 bar]",
249 "[variable-2 3. ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]",
250 "[variable-2 4. ][variable-2&comment `foo`][variable-2 bar]");
254 "[variable-2 * foo]",
256 "[variable-2 * bar]");
258 // Multi-paragraph lists
261 MT("listMultiParagraph",
262 "[variable-2 * foo]",
264 "[variable-2 * bar]",
266 " [variable-2 hello]");
268 // 4 spaces, extra blank lines (should still be list, per Dingus)
269 MT("listMultiParagraphExtra",
270 "[variable-2 * foo]",
272 "[variable-2 * bar]",
275 " [variable-2 hello]");
277 // 4 spaces, plus 1 space (should still be list, per Dingus)
278 MT("listMultiParagraphExtraSpace",
279 "[variable-2 * foo]",
281 "[variable-2 * bar]",
283 " [variable-2 hello]",
285 " [variable-2 world]");
289 "[variable-2 * foo]",
291 "[variable-2 * bar]",
293 "\t[variable-2 hello]");
297 "[variable-2 * foo]",
299 "[variable-2 * bar]",
305 "[variable-2 * foo]",
307 "[variable-2 * bar]",
309 " [variable-2&atom > hello]");
313 "[variable-2 * foo]",
315 "[variable-2 * bar]",
317 " [comment > hello]",
319 " [variable-2 world]");
321 // Code block followed by text
322 MT("blockquoteCodeText",
323 "[variable-2 * foo]",
329 " [variable-2 world]");
333 MT("listAsteriskNested",
334 "[variable-2 * foo]",
336 " [variable-3 * bar]");
339 "[variable-2 + foo]",
341 " [variable-3 + bar]");
344 "[variable-2 - foo]",
346 " [variable-3 - bar]");
348 MT("listNumberNested",
349 "[variable-2 1. foo]",
351 " [variable-3 2. bar]");
354 "[variable-2 * foo]",
356 " [variable-3 + bar]",
358 " [keyword - hello]",
360 " [variable-2 1. world]");
363 "[variable-2 * foo]",
365 " [variable-3 + bar]",
367 " [atom&variable-3 > hello]");
370 "[variable-2 * foo]",
372 " [variable-3 + bar]",
376 // Code with internal indentation
377 MT("listCodeIndentation",
378 "[variable-2 * foo]",
384 " [variable-2 bar]");
386 // List nesting edge cases
388 "[variable-2 * foo]",
390 " [variable-3 * bar]",
392 " [variable-2 hello]"
395 "[variable-2 * foo]",
397 " [variable-3 * bar]",
399 " [variable-3 * foo]"
402 // Code followed by text
404 "[variable-2 * foo]",
410 // Following tests directly from official Markdown documentation
411 // http://daringfireball.net/projects/markdown/syntax#hr
426 "[hr ---------------------------------------]");
428 // Inline link with title
430 "[link [[foo]]][string (http://example.com/ \"bar\")] hello");
432 // Inline link without title
434 "[link [[foo]]][string (http://example.com/)] bar");
436 // Inline link with image
438 "[link [[][tag ![[foo]]][string (http://example.com/)][link ]]][string (http://example.com/)] bar");
440 // Inline link with Em
442 "[link [[][link&em *foo*][link ]]][string (http://example.com/)] bar");
444 // Inline link with Strong
446 "[link [[][link&strong **foo**][link ]]][string (http://example.com/)] bar");
448 // Inline link with EmStrong
450 "[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string (http://example.com/)] bar");
454 "[tag ![[foo]]][string (http://example.com/ \"bar\")] hello");
456 // Image without title
458 "[tag ![[foo]]][string (http://example.com/)] bar");
460 // Image with asterisks
462 "[tag ![[*foo*]]][string (http://example.com/)] bar");
464 // Not a link. Should be normal text due to square brackets being used
465 // regularly in text, especially in quoted material, and no space is allowed
466 // between square brackets and parentheses (per Dingus).
470 // Reference-style links
472 "[link [[foo]]][string [[bar]]] hello");
474 // Reference-style links with Em
475 MT("linkReferenceEm",
476 "[link [[][link&em *foo*][link ]]][string [[bar]]] hello");
478 // Reference-style links with Strong
479 MT("linkReferenceStrong",
480 "[link [[][link&strong **foo**][link ]]][string [[bar]]] hello");
482 // Reference-style links with EmStrong
483 MT("linkReferenceEmStrong",
484 "[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string [[bar]]] hello");
486 // Reference-style links with optional space separator (per docuentation)
487 // "You can optionally use a space to separate the sets of brackets"
488 MT("linkReferenceSpace",
489 "[link [[foo]]] [string [[bar]]] hello");
491 // Should only allow a single space ("...use *a* space...")
492 MT("linkReferenceDoubleSpace",
493 "[[foo]] [[bar]] hello");
495 // Reference-style links with implicit link name
497 "[link [[foo]]][string [[]]] hello");
499 // @todo It would be nice if, at some point, the document was actually
500 // checked to see if the referenced link exists
502 // Link label, for reference-style links (taken from documentation)
505 "[link [[foo]]:] [string http://example.com/]");
508 " [link [[foo]]:] [string http://example.com/]");
510 MT("labelSpaceTitle",
511 "[link [[foo bar]]:] [string http://example.com/ \"hello\"]");
513 MT("labelDoubleTitle",
514 "[link [[foo bar]]:] [string http://example.com/ \"hello\"] \"world\"");
516 MT("labelTitleDoubleQuotes",
517 "[link [[foo]]:] [string http://example.com/ \"bar\"]");
519 MT("labelTitleSingleQuotes",
520 "[link [[foo]]:] [string http://example.com/ 'bar']");
522 MT("labelTitleParenthese",
523 "[link [[foo]]:] [string http://example.com/ (bar)]");
525 MT("labelTitleInvalid",
526 "[link [[foo]]:] [string http://example.com/] bar");
528 MT("labelLinkAngleBrackets",
529 "[link [[foo]]:] [string <http://example.com/> \"bar\"]");
531 MT("labelTitleNextDoubleQuotes",
532 "[link [[foo]]:] [string http://example.com/]",
533 "[string \"bar\"] hello");
535 MT("labelTitleNextSingleQuotes",
536 "[link [[foo]]:] [string http://example.com/]",
537 "[string 'bar'] hello");
539 MT("labelTitleNextParenthese",
540 "[link [[foo]]:] [string http://example.com/]",
541 "[string (bar)] hello");
543 MT("labelTitleNextMixed",
544 "[link [[foo]]:] [string http://example.com/]",
548 "[link <http://example.com/>] foo");
551 "[link <http://example.com/>] foo [link <http://example.com/>]");
554 "[link <user@example.com>] foo");
556 MT("linkEmailDouble",
557 "[link <user@example.com>] foo [link <user@example.com>]");
565 MT("emInWordAsterisk",
566 "foo[em *bar*]hello");
568 MT("emInWordUnderscore",
569 "foo[em _bar_]hello");
571 // Per documentation: "...surround an * or _ with spaces, it’ll be
572 // treated as a literal asterisk or underscore."
574 MT("emEscapedBySpaceIn",
575 "foo [em _bar _ hello_] world");
577 MT("emEscapedBySpaceOut",
578 "foo _ bar[em _hello_]world");
580 // Unclosed emphasis characters
581 // Instead of simply marking as EM / STRONG, it would be nice to have an
582 // incomplete flag for EM and STRONG, that is styled slightly different.
583 MT("emIncompleteAsterisk",
586 MT("emIncompleteUnderscore",
590 "[strong **foo**] bar");
592 MT("strongUnderscore",
593 "[strong __foo__] bar");
595 MT("emStrongAsterisk",
596 "[em *foo][em&strong **bar*][strong hello**] world");
598 MT("emStrongUnderscore",
599 "[em _foo][em&strong __bar_][strong hello__] world");
601 // "...same character must be used to open and close an emphasis span.""
603 "[em _foo][em&strong **bar*hello__ world]");
606 "[em *foo][em&strong __bar_hello** world]");
608 // These characters should be escaped:
614 // [] square brackets
618 // - minus sign (hyphen)
620 // ! exclamation mark
625 MT("doubleEscapeBacktick",
626 "foo \\\\[comment `bar\\\\`]");
631 MT("doubleEscapeAsterisk",
632 "foo \\\\[em *bar\\\\*]");
634 MT("escapeUnderscore",
637 MT("doubleEscapeUnderscore",
638 "foo \\\\[em _bar\\\\_]");
643 MT("doubleEscapeHash",
647 // Tests to make sure GFM-specific things aren't getting through
650 "[variable-2 * [ ]] bar]");
652 MT("fencedCodeBlocks",