123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862 |
- // CodeMirror, copyright (c) by Marijn Haverbeke and others
- // Distributed under an MIT license: https://codemirror.net/LICENSE
- ;(function () {
- var config = { tabSize: 4, indentUnit: 2 }
- var mode = CodeMirror.getMode(config, 'markdown')
- function MT(name) {
- test.mode(name, mode, Array.prototype.slice.call(arguments, 1))
- }
- var modeHighlightFormatting = CodeMirror.getMode(config, { name: 'markdown', highlightFormatting: true })
- function FT(name) {
- test.mode(name, modeHighlightFormatting, Array.prototype.slice.call(arguments, 1))
- }
- var modeMT_noXml = CodeMirror.getMode(config, { name: 'markdown', xml: false })
- function MT_noXml(name) {
- test.mode(name, modeMT_noXml, Array.prototype.slice.call(arguments, 1))
- }
- var modeMT_noFencedHighlight = CodeMirror.getMode(config, { name: 'markdown', fencedCodeBlockHighlighting: false })
- function MT_noFencedHighlight(name) {
- test.mode(name, modeMT_noFencedHighlight, Array.prototype.slice.call(arguments, 1))
- }
- var modeAtxNoSpace = CodeMirror.getMode(config, { name: 'markdown', allowAtxHeaderWithoutSpace: true })
- function AtxNoSpaceTest(name) {
- test.mode(name, modeAtxNoSpace, Array.prototype.slice.call(arguments, 1))
- }
- var modeOverrideClasses = CodeMirror.getMode(config, {
- name: 'markdown',
- strikethrough: true,
- emoji: true,
- tokenTypeOverrides: {
- header: 'override-header',
- code: 'override-code',
- quote: 'override-quote',
- list1: 'override-list1',
- list2: 'override-list2',
- list3: 'override-list3',
- hr: 'override-hr',
- image: 'override-image',
- imageAltText: 'override-image-alt-text',
- imageMarker: 'override-image-marker',
- linkInline: 'override-link-inline',
- linkEmail: 'override-link-email',
- linkText: 'override-link-text',
- linkHref: 'override-link-href',
- em: 'override-em',
- strong: 'override-strong',
- strikethrough: 'override-strikethrough',
- emoji: 'override-emoji',
- },
- })
- function TokenTypeOverrideTest(name) {
- test.mode(name, modeOverrideClasses, Array.prototype.slice.call(arguments, 1))
- }
- var modeFormattingOverride = CodeMirror.getMode(config, {
- name: 'markdown',
- highlightFormatting: true,
- tokenTypeOverrides: {
- formatting: 'override-formatting',
- },
- })
- function FormatTokenTypeOverrideTest(name) {
- test.mode(name, modeFormattingOverride, Array.prototype.slice.call(arguments, 1))
- }
- var modeET = CodeMirror.getMode(config, { name: 'markdown', emoji: true })
- function ET(name) {
- test.mode(name, modeET, Array.prototype.slice.call(arguments, 1))
- }
- FT('formatting_emAsterisk', '[em&formatting&formatting-em *][em foo][em&formatting&formatting-em *]')
- FT('formatting_emUnderscore', '[em&formatting&formatting-em _][em foo][em&formatting&formatting-em _]')
- FT('formatting_strongAsterisk', '[strong&formatting&formatting-strong **][strong foo][strong&formatting&formatting-strong **]')
- FT('formatting_strongUnderscore', '[strong&formatting&formatting-strong __][strong foo][strong&formatting&formatting-strong __]')
- FT('formatting_codeBackticks', '[comment&formatting&formatting-code `][comment foo][comment&formatting&formatting-code `]')
- FT('formatting_doubleBackticks', '[comment&formatting&formatting-code ``][comment foo ` bar][comment&formatting&formatting-code ``]')
- FT('formatting_atxHeader', '[header&header-1&formatting&formatting-header&formatting-header-1 # ][header&header-1 foo # bar ][header&header-1&formatting&formatting-header&formatting-header-1 #]')
- FT('formatting_setextHeader', '[header&header-1 foo]', '[header&header-1&formatting&formatting-header&formatting-header-1 =]')
- FT('formatting_blockquote', '[quote"e-1&formatting&formatting-quote&formatting-quote-1 > ][quote"e-1 foo]')
- FT('formatting_list', '[variable-2&formatting&formatting-list&formatting-list-ul - ][variable-2 foo]')
- FT('formatting_list', '[variable-2&formatting&formatting-list&formatting-list-ol 1. ][variable-2 foo]')
- FT(
- 'formatting_link',
- '[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string&url (][string&url http://example.com/][string&formatting&formatting-link-string&url )]'
- )
- FT(
- 'formatting_linkReference',
- '[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string&url [][string&url bar][string&formatting&formatting-link-string&url ]]]',
- '[link&formatting&formatting-link [][link bar][link&formatting&formatting-link ]]:] [string&url http://example.com/]'
- )
- FT('formatting_linkWeb', '[link&formatting&formatting-link <][link http://example.com/][link&formatting&formatting-link >]')
- FT('formatting_linkEmail', '[link&formatting&formatting-link <][link user@example.com][link&formatting&formatting-link >]')
- FT('formatting_escape', '[formatting-escape \\*]')
- FT(
- 'formatting_image',
- '[formatting&formatting-image&image&image-marker !][formatting&formatting-image&image&image-alt-text&link [[][image&image-alt-text&link alt text][formatting&formatting-image&image&image-alt-text&link ]]][formatting&formatting-link-string&string&url (][url&string http://link.to/image.jpg][formatting&formatting-link-string&string&url )]'
- )
- FT('codeBlock', '[comment&formatting&formatting-code-block ```css]', '[tag foo]', '[comment&formatting&formatting-code-block ```]')
- MT('plainText', 'foo')
- // Don't style single trailing space
- MT('trailingSpace1', 'foo ')
- // Two or more trailing spaces should be styled with line break character
- MT('trailingSpace2', 'foo[trailing-space-a ][trailing-space-new-line ]')
- MT('trailingSpace3', 'foo[trailing-space-a ][trailing-space-b ][trailing-space-new-line ]')
- MT('trailingSpace4', 'foo[trailing-space-a ][trailing-space-b ][trailing-space-a ][trailing-space-new-line ]')
- // Code blocks using 4 spaces (regardless of CodeMirror.tabSize value)
- MT('codeBlocksUsing4Spaces', ' [comment foo]')
- // Code blocks using 4 spaces with internal indentation
- MT('codeBlocksUsing4SpacesIndentation', ' [comment bar]', ' [comment hello]', ' [comment world]', ' [comment foo]', 'bar')
- // Code blocks should end even after extra indented lines
- MT('codeBlocksWithTrailingIndentedLine', ' [comment foo]', ' [comment bar]', ' [comment baz]', ' ', 'hello')
- // Code blocks using 1 tab (regardless of CodeMirror.indentWithTabs value)
- MT('codeBlocksUsing1Tab', '\t[comment foo]')
- // No code blocks directly after paragraph
- // http://spec.commonmark.org/0.19/#example-65
- MT('noCodeBlocksAfterParagraph', 'Foo', ' Bar')
- MT('codeBlocksAfterATX', '[header&header-1 # foo]', ' [comment code]')
- MT('codeBlocksAfterSetext', '[header&header-2 foo]', '[header&header-2 ---]', ' [comment code]')
- MT('codeBlocksAfterFencedCode', '[comment ```]', '[comment foo]', '[comment ```]', ' [comment code]')
- // Inline code using backticks
- MT('inlineCodeUsingBackticks', 'foo [comment `bar`]')
- // Block code using single backtick (shouldn't work)
- MT('blockCodeSingleBacktick', '[comment `]', '[comment foo]', '[comment `]')
- // Unclosed backticks
- // Instead of simply marking as CODE, it would be nice to have an
- // incomplete flag for CODE, that is styled slightly different.
- MT('unclosedBackticks', 'foo [comment `bar]')
- // Per documentation: "To include a literal backtick character within a
- // code span, you can use multiple backticks as the opening and closing
- // delimiters"
- MT('doubleBackticks', '[comment ``foo ` bar``]')
- // Tests based on Dingus
- // http://daringfireball.net/projects/markdown/dingus
- //
- // Multiple backticks within an inline code block
- MT('consecutiveBackticks', '[comment `foo```bar`]')
- // Multiple backticks within an inline code block with a second code block
- MT('consecutiveBackticks', '[comment `foo```bar`] hello [comment `world`]')
- // Unclosed with several different groups of backticks
- MT('unclosedBackticks', '[comment ``foo ``` bar` hello]')
- // Closed with several different groups of backticks
- MT('closedBackticks', '[comment ``foo ``` bar` hello``] world')
- // info string cannot contain backtick, thus should result in inline code
- MT('closingFencedMarksOnSameLine', '[comment ``` code ```] foo')
- // atx headers
- // http://daringfireball.net/projects/markdown/syntax#header
- MT('atxH1', '[header&header-1 # foo]')
- MT('atxH2', '[header&header-2 ## foo]')
- MT('atxH3', '[header&header-3 ### foo]')
- MT('atxH4', '[header&header-4 #### foo]')
- MT('atxH5', '[header&header-5 ##### foo]')
- MT('atxH6', '[header&header-6 ###### foo]')
- // http://spec.commonmark.org/0.19/#example-24
- MT('noAtxH7', '####### foo')
- // http://spec.commonmark.org/0.19/#example-25
- MT('noAtxH1WithoutSpace', '#5 bolt')
- // CommonMark requires a space after # but most parsers don't
- AtxNoSpaceTest('atxNoSpaceAllowed_H1NoSpace', '[header&header-1 #foo]')
- AtxNoSpaceTest('atxNoSpaceAllowed_H4NoSpace', '[header&header-4 ####foo]')
- AtxNoSpaceTest('atxNoSpaceAllowed_H1Space', '[header&header-1 # foo]')
- // Inline styles should be parsed inside headers
- MT('atxH1inline', '[header&header-1 # foo ][header&header-1&em *bar*]')
- MT('atxIndentedTooMuch', '[header&header-1 # foo]', ' [comment # bar]')
- // disable atx inside blockquote until we implement proper blockquote inner mode
- // TODO: fix to be CommonMark-compliant
- MT('atxNestedInsideBlockquote', '[quote"e-1 > # foo]')
- MT('atxAfterBlockquote', '[quote"e-1 > foo]', '[header&header-1 # bar]')
- // Setext headers - H1, H2
- // Per documentation, "Any number of underlining =’s or -’s will work."
- // http://daringfireball.net/projects/markdown/syntax#header
- // Ideally, the text would be marked as `header` as well, but this is
- // not really feasible at the moment. So, instead, we're testing against
- // what works today, to avoid any regressions.
- //
- // Check if single underlining = works
- MT('setextH1', '[header&header-1 foo]', '[header&header-1 =]')
- // Check if 3+ ='s work
- MT('setextH1', '[header&header-1 foo]', '[header&header-1 ===]')
- // Check if single underlining - should not be interpreted
- // as it might lead to an empty list:
- // https://spec.commonmark.org/0.28/#setext-heading-underline
- MT('setextH2Single', 'foo', '-')
- // Check if 3+ -'s work
- MT('setextH2', '[header&header-2 foo]', '[header&header-2 ---]')
- // http://spec.commonmark.org/0.19/#example-45
- MT('setextH2AllowSpaces', '[header&header-2 foo]', ' [header&header-2 ---- ]')
- // http://spec.commonmark.org/0.19/#example-44
- MT('noSetextAfterIndentedCodeBlock', ' [comment foo]', '[hr ---]')
- MT('setextAfterFencedCode', '[comment ```]', '[comment foo]', '[comment ```]', '[header&header-2 bar]', '[header&header-2 ---]')
- MT('setextAfterATX', '[header&header-1 # foo]', '[header&header-2 bar]', '[header&header-2 ---]')
- // http://spec.commonmark.org/0.19/#example-51
- MT('noSetextAfterQuote', '[quote"e-1 > foo]', '[hr ---]', '', '[quote"e-1 > foo]', '[quote"e-1 bar]', '[hr ---]')
- MT('noSetextAfterList', '[variable-2 - foo]', '[hr ---]')
- MT('noSetextAfterList_listContinuation', '[variable-2 - foo]', 'bar', '[hr ---]')
- MT('setextAfterList_afterIndentedCode', '[variable-2 - foo]', '', ' [comment bar]', '[header&header-2 baz]', '[header&header-2 ---]')
- MT('setextAfterList_afterFencedCodeBlocks', '[variable-2 - foo]', '', ' [comment ```]', ' [comment bar]', ' [comment ```]', '[header&header-2 baz]', '[header&header-2 ---]')
- MT('setextAfterList_afterHeader', '[variable-2 - foo]', ' [variable-2&header&header-1 # bar]', '[header&header-2 baz]', '[header&header-2 ---]')
- MT('setextAfterList_afterHr', '[variable-2 - foo]', '', ' [hr ---]', '[header&header-2 bar]', '[header&header-2 ---]')
- MT('setext_nestedInlineMarkup', '[header&header-1 foo ][em&header&header-1 *bar*]', '[header&header-1 =]')
- MT('setext_linkDef', "[link [[aaa]]:] [string&url http://google.com 'title']", '[hr ---]')
- // currently, looks max one line ahead, thus won't catch valid CommonMark
- // markup
- MT('setext_oneLineLookahead', 'foo', '[header&header-1 bar]', '[header&header-1 =]')
- // ensure we regard space after a single dash as a list
- MT('setext_emptyList', 'foo', '[variable-2 - ]', 'foo')
- // Single-line blockquote with trailing space
- MT('blockquoteSpace', '[quote"e-1 > foo]')
- // Single-line blockquote
- MT('blockquoteNoSpace', '[quote"e-1 >foo]')
- // No blank line before blockquote
- MT('blockquoteNoBlankLine', 'foo', '[quote"e-1 > bar]')
- MT('blockquoteNested', '[quote"e-1 > foo]', '[quote"e-1 >][quote"e-2 > foo]', '[quote"e-1 >][quote"e-2 >][quote"e-3 > foo]')
- // ensure quote-level is inferred correctly even if indented
- MT('blockquoteNestedIndented', ' [quote"e-1 > foo]', ' [quote"e-1 >][quote"e-2 > foo]', ' [quote"e-1 >][quote"e-2 >][quote"e-3 > foo]')
- // ensure quote-level is inferred correctly even if indented
- MT('blockquoteIndentedTooMuch', 'foo', ' > bar')
- // Single-line blockquote followed by normal paragraph
- MT('blockquoteThenParagraph', '[quote"e-1 >foo]', '', 'bar')
- // Multi-line blockquote (lazy mode)
- MT('multiBlockquoteLazy', '[quote"e-1 >foo]', '[quote"e-1 bar]')
- // Multi-line blockquote followed by normal paragraph (lazy mode)
- MT('multiBlockquoteLazyThenParagraph', '[quote"e-1 >foo]', '[quote"e-1 bar]', '', 'hello')
- // Multi-line blockquote (non-lazy mode)
- MT('multiBlockquote', '[quote"e-1 >foo]', '[quote"e-1 >bar]')
- // Multi-line blockquote followed by normal paragraph (non-lazy mode)
- MT('multiBlockquoteThenParagraph', '[quote"e-1 >foo]', '[quote"e-1 >bar]', '', 'hello')
- // disallow lists inside blockquote for now because it causes problems outside blockquote
- // TODO: fix to be CommonMark-compliant
- MT('listNestedInBlockquote', '[quote"e-1 > - foo]')
- // disallow fenced blocks inside blockquote because it causes problems outside blockquote
- // TODO: fix to be CommonMark-compliant
- MT(
- 'fencedBlockNestedInBlockquote',
- '[quote"e-1 > ```]',
- '[quote"e-1 > code]',
- '[quote"e-1 > ```]',
- // ensure we still allow inline code
- '[quote"e-1 > ][quote"e-1&comment `code`]'
- )
- // Header with leading space after continued blockquote (#3287, negative indentation)
- MT('headerAfterContinuedBlockquote', '[quote"e-1 > foo]', '[quote"e-1 bar]', '', ' [header&header-1 # hello]')
- // Check list types
- MT('listAsterisk', 'foo', 'bar', '', '[variable-2 * foo]', '[variable-2 * bar]')
- MT('listPlus', 'foo', 'bar', '', '[variable-2 + foo]', '[variable-2 + bar]')
- MT('listDash', 'foo', 'bar', '', '[variable-2 - foo]', '[variable-2 - bar]')
- MT('listNumber', 'foo', 'bar', '', '[variable-2 1. foo]', '[variable-2 2. bar]')
- MT('listFromParagraph', 'foo', '[variable-2 1. bar]', '[variable-2 2. hello]')
- // List after hr
- MT('listAfterHr', '[hr ---]', '[variable-2 - bar]')
- // List after header
- MT('listAfterHeader', '[header&header-1 # foo]', '[variable-2 - bar]')
- // hr after list
- MT('hrAfterList', '[variable-2 - foo]', '[hr -----]')
- MT('hrAfterFencedCode', '[comment ```]', '[comment code]', '[comment ```]', '[hr ---]')
- // allow hr inside lists
- // (require prev line to be empty or hr, TODO: non-CommonMark-compliant)
- MT('hrInsideList', '[variable-2 - foo]', '', ' [hr ---]', ' [hr ---]', '', ' [comment ---]')
- MT('consecutiveHr', '[hr ---]', '[hr ---]', '[hr ---]')
- // Formatting in lists (*)
- MT(
- 'listAsteriskFormatting',
- '[variable-2 * ][variable-2&em *foo*][variable-2 bar]',
- '[variable-2 * ][variable-2&strong **foo**][variable-2 bar]',
- '[variable-2 * ][variable-2&em&strong ***foo***][variable-2 bar]',
- '[variable-2 * ][variable-2&comment `foo`][variable-2 bar]'
- )
- // Formatting in lists (+)
- MT(
- 'listPlusFormatting',
- '[variable-2 + ][variable-2&em *foo*][variable-2 bar]',
- '[variable-2 + ][variable-2&strong **foo**][variable-2 bar]',
- '[variable-2 + ][variable-2&em&strong ***foo***][variable-2 bar]',
- '[variable-2 + ][variable-2&comment `foo`][variable-2 bar]'
- )
- // Formatting in lists (-)
- MT(
- 'listDashFormatting',
- '[variable-2 - ][variable-2&em *foo*][variable-2 bar]',
- '[variable-2 - ][variable-2&strong **foo**][variable-2 bar]',
- '[variable-2 - ][variable-2&em&strong ***foo***][variable-2 bar]',
- '[variable-2 - ][variable-2&comment `foo`][variable-2 bar]'
- )
- // Formatting in lists (1.)
- MT(
- 'listNumberFormatting',
- '[variable-2 1. ][variable-2&em *foo*][variable-2 bar]',
- '[variable-2 2. ][variable-2&strong **foo**][variable-2 bar]',
- '[variable-2 3. ][variable-2&em&strong ***foo***][variable-2 bar]',
- '[variable-2 4. ][variable-2&comment `foo`][variable-2 bar]'
- )
- // Paragraph lists
- MT('listParagraph', '[variable-2 * foo]', '', '[variable-2 * bar]')
- // Multi-paragraph lists
- //
- // 4 spaces
- MT('listMultiParagraph', '[variable-2 * foo]', '', '[variable-2 * bar]', '', ' [variable-2 hello]')
- // 4 spaces, extra blank lines (should still be list, per Dingus)
- MT('listMultiParagraphExtra', '[variable-2 * foo]', '', '[variable-2 * bar]', '', '', ' [variable-2 hello]')
- // 4 spaces, plus 1 space (should still be list, per Dingus)
- MT('listMultiParagraphExtraSpace', '[variable-2 * foo]', '', '[variable-2 * bar]', '', ' [variable-2 hello]', '', ' [variable-2 world]')
- // 1 tab
- MT('listTab', '[variable-2 * foo]', '', '[variable-2 * bar]', '', '\t[variable-2 hello]')
- // No indent
- MT('listNoIndent', '[variable-2 * foo]', '', '[variable-2 * bar]', '', 'hello')
- MT(
- 'listCommonMarkIndentationCode',
- '[variable-2 * Code blocks also affect]',
- ' [variable-3 * The next level starts where the contents start.]',
- ' [variable-3 * Anything less than that will keep the item on the same level.]',
- ' [variable-3 * Each list item can indent the first level further and further.]',
- ' [variable-3 * For the most part, this makes sense while writing a list.]',
- ' [keyword * This means two items with same indentation can be different levels.]',
- ' [keyword * Each level has an indent requirement that can change between items.]',
- ' [keyword * A list item that meets this will be part of the next level.]',
- ' [variable-3 * Otherwise, it will be part of the level where it does meet this.]',
- ' [variable-2 * World]'
- )
- // should handle nested and un-nested lists
- MT(
- 'listCommonMark_MixedIndents',
- '[variable-2 * list1]',
- ' [variable-2 list1]',
- ' [variable-2&header&header-1 # heading still part of list1]',
- ' [variable-2 text after heading still part of list1]',
- '',
- ' [comment indented codeblock]',
- ' [variable-2 list1 after code block]',
- ' [variable-3 * list2]',
- // amount of spaces on empty lines between lists doesn't matter
- ' ',
- // extra empty lines irrelevant
- '',
- '',
- ' [variable-3 indented text part of list2]',
- ' [keyword * list3]',
- '',
- ' [variable-3 text at level of list2]',
- '',
- ' [variable-2 de-indented text part of list1 again]',
- '',
- ' [variable-2&comment ```]',
- ' [comment code]',
- ' [variable-2&comment ```]',
- '',
- ' [variable-2 text after fenced code]'
- )
- // should correctly parse numbered list content indentation
- MT(
- 'listCommonMark_NumberedListIndent',
- '[variable-2 1000. list with base indent of 6]',
- '',
- ' [variable-2 text must be indented 6 spaces at minimum]',
- '',
- ' [variable-2 9-spaces indented text still part of list]',
- '',
- ' [comment indented codeblock starts at 10 spaces]',
- '',
- ' [comment text indented by 5 spaces no longer belong to list]'
- )
- // should consider tab as 4 spaces
- MT('listCommonMark_TabIndented', '[variable-2 * list]', '\t[variable-3 * list2]', '', '\t\t[variable-3 part of list2]')
- MT('listAfterBlockquote', '[quote"e-1 > foo]', '[variable-2 - bar]')
- // shouldn't create sublist if it's indented more than allowed
- MT('nestedListIndentedTooMuch', '[variable-2 - foo]', ' [variable-2 - bar]')
- MT('listIndentedTooMuchAfterParagraph', 'foo', ' - bar')
- // Blockquote
- MT('blockquote', '[variable-2 * foo]', '', '[variable-2 * bar]', '', ' [variable-2"e"e-1 > hello]')
- // Code block
- MT('blockquoteCode', '[variable-2 * foo]', '', '[variable-2 * bar]', '', ' [comment > hello]', '', ' [variable-2 world]')
- // Code block followed by text
- MT('blockquoteCodeText', '[variable-2 * foo]', '', ' [variable-2 bar]', '', ' [comment hello]', '', ' [variable-2 world]')
- // Nested list
- MT('listAsteriskNested', '[variable-2 * foo]', '', ' [variable-3 * bar]')
- MT('listPlusNested', '[variable-2 + foo]', '', ' [variable-3 + bar]')
- MT('listDashNested', '[variable-2 - foo]', '', ' [variable-3 - bar]')
- MT('listNumberNested', '[variable-2 1. foo]', '', ' [variable-3 2. bar]')
- MT('listMixed', '[variable-2 * foo]', '', ' [variable-3 + bar]', '', ' [keyword - hello]', '', ' [variable-2 1. world]')
- MT('listBlockquote', '[variable-2 * foo]', '', ' [variable-3 + bar]', '', ' [quote"e-1&variable-3 > hello]')
- MT('listCode', '[variable-2 * foo]', '', ' [variable-3 + bar]', '', ' [comment hello]')
- // Code with internal indentation
- MT('listCodeIndentation', '[variable-2 * foo]', '', ' [comment bar]', ' [comment hello]', ' [comment world]', ' [comment foo]', ' [variable-2 bar]')
- // List nesting edge cases
- MT('listNested', '[variable-2 * foo]', '', ' [variable-3 * bar]', '', ' [variable-3 hello]')
- MT('listNested', '[variable-2 * foo]', '', ' [variable-3 * bar]', '', ' [keyword * foo]')
- // Code followed by text
- MT('listCodeText', '[variable-2 * foo]', '', ' [comment bar]', '', 'hello')
- // Following tests directly from official Markdown documentation
- // http://daringfireball.net/projects/markdown/syntax#hr
- MT('hrSpace', '[hr * * *]')
- MT('hr', '[hr ***]')
- MT('hrLong', '[hr *****]')
- MT('hrSpaceDash', '[hr - - -]')
- MT('hrDashLong', '[hr ---------------------------------------]')
- //Images
- MT('Images', '[image&image-marker !][image&image-alt-text&link [[alt text]]][string&url (http://link.to/image.jpg)]')
- //Images with highlight alt text
- MT('imageEm', '[image&image-marker !][image&image-alt-text&link [[][image-alt-text&em&image&link *alt text*][image&image-alt-text&link ]]][string&url (http://link.to/image.jpg)]')
- MT('imageStrong', '[image&image-marker !][image&image-alt-text&link [[][image-alt-text&strong&image&link **alt text**][image&image-alt-text&link ]]][string&url (http://link.to/image.jpg)]')
- MT('imageEmStrong', '[image&image-marker !][image&image-alt-text&link [[][image&image-alt-text&em&strong&link ***alt text***][image&image-alt-text&link ]]][string&url (http://link.to/image.jpg)]')
- // Inline link with title
- MT('linkTitle', '[link [[foo]]][string&url (http://example.com/ "bar")] hello')
- // Inline link without title
- MT('linkNoTitle', '[link [[foo]]][string&url (http://example.com/)] bar')
- // Inline link with image
- MT('linkImage', '[link [[][link&image&image-marker !][link&image&image-alt-text&link [[alt text]]][string&url (http://link.to/image.jpg)][link ]]][string&url (http://example.com/)] bar')
- // Inline link with Em
- MT('linkEm', '[link [[][link&em *foo*][link ]]][string&url (http://example.com/)] bar')
- // Inline link with Strong
- MT('linkStrong', '[link [[][link&strong **foo**][link ]]][string&url (http://example.com/)] bar')
- // Inline link with EmStrong
- MT('linkEmStrong', '[link [[][link&em&strong ***foo***][link ]]][string&url (http://example.com/)] bar')
- MT('multilineLink', '[link [[foo]', '[link bar]]][string&url (https://foo#_a)]', 'should not be italics')
- // Image with title
- MT('imageTitle', '[image&image-marker !][image&image-alt-text&link [[alt text]]][string&url (http://example.com/ "bar")] hello')
- // Image without title
- MT('imageNoTitle', '[image&image-marker !][image&image-alt-text&link [[alt text]]][string&url (http://example.com/)] bar')
- // Image with asterisks
- MT('imageAsterisks', '[image&image-marker !][image&image-alt-text&link [[ ][image&image-alt-text&em&link *alt text*][image&image-alt-text&link ]]][string&url (http://link.to/image.jpg)] bar')
- // Not a link. Should be normal text due to square brackets being used
- // regularly in text, especially in quoted material, and no space is allowed
- // between square brackets and parentheses (per Dingus).
- MT('notALink', '[link [[foo]]] (bar)')
- // Reference-style links
- MT('linkReference', '[link [[foo]]][string&url [[bar]]] hello')
- // Reference-style links with Em
- MT('linkReferenceEm', '[link [[][link&em *foo*][link ]]][string&url [[bar]]] hello')
- // Reference-style links with Strong
- MT('linkReferenceStrong', '[link [[][link&strong **foo**][link ]]][string&url [[bar]]] hello')
- // Reference-style links with EmStrong
- MT('linkReferenceEmStrong', '[link [[][link&em&strong ***foo***][link ]]][string&url [[bar]]] hello')
- // Reference-style links with optional space separator (per documentation)
- // "You can optionally use a space to separate the sets of brackets"
- MT('linkReferenceSpace', '[link [[foo]]] [string&url [[bar]]] hello')
- // Should only allow a single space ("...use *a* space...")
- MT('linkReferenceDoubleSpace', '[link [[foo]]] [link [[bar]]] hello')
- // Reference-style links with implicit link name
- MT('linkImplicit', '[link [[foo]]][string&url [[]]] hello')
- // @todo It would be nice if, at some point, the document was actually
- // checked to see if the referenced link exists
- // Link label, for reference-style links (taken from documentation)
- MT('labelNoTitle', '[link [[foo]]:] [string&url http://example.com/]')
- MT('labelIndented', ' [link [[foo]]:] [string&url http://example.com/]')
- MT('labelSpaceTitle', '[link [[foo bar]]:] [string&url http://example.com/ "hello"]')
- MT('labelDoubleTitle', '[link [[foo bar]]:] [string&url http://example.com/ "hello"] "world"')
- MT('labelTitleDoubleQuotes', '[link [[foo]]:] [string&url http://example.com/ "bar"]')
- MT('labelTitleSingleQuotes', "[link [[foo]]:] [string&url http://example.com/ 'bar']")
- MT('labelTitleParentheses', '[link [[foo]]:] [string&url http://example.com/ (bar)]')
- MT('labelTitleInvalid', '[link [[foo]]:] [string&url http://example.com/] bar')
- MT('labelLinkAngleBrackets', '[link [[foo]]:] [string&url <http://example.com/> "bar"]')
- MT('labelTitleNextDoubleQuotes', '[link [[foo]]:] [string&url http://example.com/]', '[string "bar"] hello')
- MT('labelTitleNextSingleQuotes', '[link [[foo]]:] [string&url http://example.com/]', "[string 'bar'] hello")
- MT('labelTitleNextParentheses', '[link [[foo]]:] [string&url http://example.com/]', '[string (bar)] hello')
- MT('labelTitleNextMixed', '[link [[foo]]:] [string&url http://example.com/]', '(bar" hello')
- MT('labelEscape', '[link [[foo \\]] ]]:] [string&url http://example.com/]')
- MT('labelEscapeColon', '[link [[foo \\]]: bar]]:] [string&url http://example.com/]')
- MT('labelEscapeEnd', '\\[[foo\\]]: http://example.com/')
- MT('linkWeb', '[link <http://example.com/>] foo')
- MT('linkWebDouble', '[link <http://example.com/>] foo [link <http://example.com/>]')
- MT('linkEmail', '[link <user@example.com>] foo')
- MT('linkEmailDouble', '[link <user@example.com>] foo [link <user@example.com>]')
- MT('emAsterisk', '[em *foo*] bar')
- MT('emUnderscore', '[em _foo_] bar')
- MT('emInWordAsterisk', 'foo[em *bar*]hello')
- MT('emInWordUnderscore', 'foo_bar_hello')
- // Per documentation: "...surround an * or _ with spaces, it’ll be
- // treated as a literal asterisk or underscore."
- MT('emEscapedBySpaceIn', 'foo [em _bar _ hello_] world')
- MT('emEscapedBySpaceOut', 'foo _ bar [em _hello_] world')
- MT('emEscapedByNewline', 'foo', '_ bar [em _hello_] world')
- // Unclosed emphasis characters
- // Instead of simply marking as EM / STRONG, it would be nice to have an
- // incomplete flag for EM and STRONG, that is styled slightly different.
- MT('emIncompleteAsterisk', 'foo [em *bar]')
- MT('emIncompleteUnderscore', 'foo [em _bar]')
- MT('strongAsterisk', '[strong **foo**] bar')
- MT('strongUnderscore', '[strong __foo__] bar')
- MT('emStrongAsterisk', '[em *foo][em&strong **bar*][strong hello**] world')
- MT('emStrongUnderscore', '[em _foo ][em&strong __bar_][strong hello__] world')
- // "...same character must be used to open and close an emphasis span.""
- MT('emStrongMixed', '[em _foo][em&strong **bar*hello__ world]')
- MT('emStrongMixed', '[em *foo ][em&strong __bar_hello** world]')
- MT('linkWithNestedParens', '[link [[foo]]][string&url (bar(baz))]')
- // These characters should be escaped:
- // \ backslash
- // ` backtick
- // * asterisk
- // _ underscore
- // {} curly braces
- // [] square brackets
- // () parentheses
- // # hash mark
- // + plus sign
- // - minus sign (hyphen)
- // . dot
- // ! exclamation mark
- MT('escapeBacktick', 'foo \\`bar\\`')
- MT('doubleEscapeBacktick', 'foo \\\\[comment `bar\\\\`]')
- MT('escapeAsterisk', 'foo \\*bar\\*')
- MT('doubleEscapeAsterisk', 'foo \\\\[em *bar\\\\*]')
- MT('escapeUnderscore', 'foo \\_bar\\_')
- MT('doubleEscapeUnderscore', 'foo \\\\[em _bar\\\\_]')
- MT('escapeHash', '\\# foo')
- MT('doubleEscapeHash', '\\\\# foo')
- MT('escapeNewline', '\\', '[em *foo*]')
- // Class override tests
- TokenTypeOverrideTest('overrideHeader1', '[override-header&override-header-1 # Foo]')
- TokenTypeOverrideTest('overrideHeader2', '[override-header&override-header-2 ## Foo]')
- TokenTypeOverrideTest('overrideHeader3', '[override-header&override-header-3 ### Foo]')
- TokenTypeOverrideTest('overrideHeader4', '[override-header&override-header-4 #### Foo]')
- TokenTypeOverrideTest('overrideHeader5', '[override-header&override-header-5 ##### Foo]')
- TokenTypeOverrideTest('overrideHeader6', '[override-header&override-header-6 ###### Foo]')
- TokenTypeOverrideTest('overrideCode', '[override-code `foo`]')
- TokenTypeOverrideTest('overrideCodeBlock', '[override-code ```]', '[override-code foo]', '[override-code ```]')
- TokenTypeOverrideTest('overrideQuote', '[override-quote&override-quote-1 > foo]', '[override-quote&override-quote-1 > bar]')
- TokenTypeOverrideTest(
- 'overrideQuoteNested',
- '[override-quote&override-quote-1 > foo]',
- '[override-quote&override-quote-1 >][override-quote&override-quote-2 > bar]',
- '[override-quote&override-quote-1 >][override-quote&override-quote-2 >][override-quote&override-quote-3 > baz]'
- )
- TokenTypeOverrideTest(
- 'overrideLists',
- '[override-list1 - foo]',
- '',
- ' [override-list2 + bar]',
- '',
- ' [override-list3 * baz]',
- '',
- ' [override-list1 1. qux]',
- '',
- ' [override-list2 - quux]'
- )
- TokenTypeOverrideTest('overrideHr', '[override-hr * * *]')
- TokenTypeOverrideTest('overrideImage', '[override-image&override-image-marker !][override-image&override-image-alt-text&link [[alt text]]][override-link-href&url (http://link.to/image.jpg)]')
- TokenTypeOverrideTest('overrideLinkText', '[override-link-text [[foo]]][override-link-href&url (http://example.com)]')
- TokenTypeOverrideTest('overrideLinkEmailAndInline', '[override-link-email <][override-link-inline foo@example.com>]')
- TokenTypeOverrideTest('overrideEm', '[override-em *foo*]')
- TokenTypeOverrideTest('overrideStrong', '[override-strong **foo**]')
- TokenTypeOverrideTest('overrideStrikethrough', '[override-strikethrough ~~foo~~]')
- TokenTypeOverrideTest('overrideEmoji', '[override-emoji :foo:]')
- FormatTokenTypeOverrideTest('overrideFormatting', '[override-formatting-escape \\*]')
- // Tests to make sure GFM-specific things aren't getting through
- MT('taskList', '[variable-2 * ][link&variable-2 [[ ]]][variable-2 bar]')
- MT('fencedCodeBlocks', '[comment ```]', '[comment foo]', '', '[comment bar]', '[comment ```]', 'baz')
- MT('fencedCodeBlocks_invalidClosingFence_trailingText', '[comment ```]', '[comment foo]', '[comment ``` must not have trailing text]', '[comment baz]')
- MT('fencedCodeBlocks_invalidClosingFence_trailingTabs', '[comment ```]', '[comment foo]', '[comment ```\t]', '[comment baz]')
- MT(
- 'fencedCodeBlocks_validClosingFence',
- '[comment ```]',
- '[comment foo]',
- // may have trailing spaces
- '[comment ``` ]',
- 'baz'
- )
- MT('fencedCodeBlocksInList_closingFenceIndented', '[variable-2 - list]', ' [variable-2&comment ```]', ' [comment foo]', ' [variable-2&comment ```]', ' [variable-2 baz]')
- MT('fencedCodeBlocksInList_closingFenceIndentedTooMuch', '[variable-2 - list]', ' [variable-2&comment ```]', ' [comment foo]', ' [comment ```]', ' [comment baz]')
- MT('fencedCodeBlockModeSwitching', '[comment ```javascript]', '[variable foo]', '', '[comment ```]', 'bar')
- MT_noFencedHighlight('fencedCodeBlock_noHighlight', '[comment ```javascript]', '[comment foo]', '[comment ```]')
- MT('fencedCodeBlockModeSwitchingObjc', '[comment ```objective-c]', '[keyword @property] [variable NSString] [operator *] [variable foo];', '[comment ```]', 'bar')
- MT('fencedCodeBlocksMultipleChars', '[comment `````]', '[comment foo]', '[comment ```]', '[comment foo]', '[comment `````]', 'bar')
- MT('fencedCodeBlocksTildes', '[comment ~~~]', '[comment foo]', '[comment ~~~]', 'bar')
- MT('fencedCodeBlocksTildesMultipleChars', '[comment ~~~~~]', '[comment ~~~]', '[comment foo]', '[comment ~~~~~]', 'bar')
- MT('fencedCodeBlocksMultipleChars', '[comment `````]', '[comment foo]', '[comment ```]', '[comment foo]', '[comment `````]', 'bar')
- MT('fencedCodeBlocksMixed', '[comment ~~~]', '[comment ```]', '[comment foo]', '[comment ~~~]', 'bar')
- MT('fencedCodeBlocksAfterBlockquote', '[quote"e-1 > foo]', '[comment ```]', '[comment bar]', '[comment ```]')
- // fencedCode indented too much should act as simple indentedCode
- // (hence has no highlight formatting)
- FT('tooMuchIndentedFencedCode', ' [comment ```]', ' [comment code]', ' [comment ```]')
- MT(
- 'autoTerminateFencedCodeWhenLeavingList',
- '[variable-2 - list1]',
- ' [variable-3 - list2]',
- ' [variable-3&comment ```]',
- ' [comment code]',
- ' [variable-3 - list2]',
- ' [variable-2&comment ```]',
- ' [comment code]',
- '[quote"e-1 > foo]'
- )
- // Tests that require XML mode
- MT(
- 'xmlMode',
- '[tag&bracket <][tag div][tag&bracket >]',
- ' *foo*',
- ' [tag&bracket <][tag http://github.com][tag&bracket />]',
- '[tag&bracket </][tag div][tag&bracket >]',
- '[link <http://github.com/>]'
- )
- MT(
- 'xmlModeWithMarkdownInside',
- '[tag&bracket <][tag div] [attribute markdown]=[string 1][tag&bracket >]',
- '[em *foo*]',
- '[link <http://github.com/>]',
- '[tag </div>]',
- '[link <http://github.com/>]',
- '[tag&bracket <][tag div][tag&bracket >]',
- '[tag&bracket </][tag div][tag&bracket >]'
- )
- MT('xmlModeLineBreakInTags', '[tag&bracket <][tag div] [attribute id]=[string "1"]', ' [attribute class]=[string "sth"][tag&bracket >]xxx', '[tag&bracket </][tag div][tag&bracket >]')
- MT('xmlModeCommentWithBlankLine', '[comment <!-- Hello]', '', '[comment World -->]')
- MT('xmlModeCDATA', '[atom <![CDATA[ Hello]', '', '[atom FooBar]', '[atom Test ]]]]>]')
- MT('xmlModePreprocessor', "[meta <?php] [meta echo '1234'; ?>]")
- MT_noXml('xmlHighlightDisabled', '<div>foo</div>')
- // Tests Emojis
- ET('emojiDefault', '[builtin :foobar:]')
- ET('emojiTable', ' :--:')
- })()
|