diff --git a/lively.ide/editor-modes.js b/lively.ide/editor-modes.js index 1c3745f4eb..43544ff5d9 100644 --- a/lively.ide/editor-modes.js +++ b/lively.ide/editor-modes.js @@ -183,13 +183,16 @@ function tokenizeLines (mode, lines, _startState, newLineFn, recordFn) { function tokenizeLine (mode, line, state, recordFn) { let { text } = line; - if (!text) return state; let stream = new StringStream(text, 2/* indent...FIXME */); state = line.modeState = typeof mode.copyState === 'function' ? mode.copyState(state) : copyState(mode, state); let tokens = []; let prevLine = line.prevLine(); state._string = text; + if (text === '' && mode.blankLine){ + mode.blankLine(state); + return state; + } while (!stream.eol()) { let name = mode.token(stream, state); recordFn(name, state, stream.start, stream.pos, stream, line, mode); diff --git a/lively.ide/md/editor-plugin.js b/lively.ide/md/editor-plugin.js index d8eca2fd31..18a74fa51a 100644 --- a/lively.ide/md/editor-plugin.js +++ b/lively.ide/md/editor-plugin.js @@ -193,7 +193,9 @@ export default class MarkdownEditorPlugin extends CodeMirrorEnabledEditorPlugin for (let i = 0; i < lineTokens.length; i = i + 5) { let startColumn = lineTokens[i]; let endColumn = lineTokens[i + 1]; - let tokens = (lineTokens[i + 2] || '').split(' '); + let tokens = lineTokens[i + 2]; + tokens = tokens?.split ? tokens : ''; + tokens = tokens.split(' '); // style = theme[tokens[0]] || theme.default; let style; diff --git a/lively.ide/md/mode.js b/lively.ide/md/mode.js index 5b6e8cdcf4..3ae880a784 100644 --- a/lively.ide/md/mode.js +++ b/lively.ide/md/mode.js @@ -1,4 +1,3 @@ -/* eslint-disable no-use-before-define */ // Copyright (C) 2017 by Marijn Haverbeke and others // https://codemirror.net/LICENSE @@ -6,9 +5,9 @@ import '../xml/mode.js'; import '../html/mode.js'; import { - passIndent, - innerMode, + passIndent, innerMode, getMode, + findModeByName, defineMode, defineMIME, copyState, @@ -17,8 +16,17 @@ import { defineMode('markdown', function (cmCfg, modeCfg) { let htmlMode = getMode(cmCfg, 'text/html'); - - let htmlModeMissing = htmlMode.name === 'null'; + // var htmlMode = findModeByName("html") || getMode(cmCfg, "text/html"); + let htmlModeMissing = htmlMode.name == 'null'; + + // function _getMode(name) { + // if (findModeByName) { + // var found = findModeByName(name); + // if (found) name = found.mime || found.mimes[0]; + // } + // var mode = getMode(cmCfg, name); + // return mode.name == "null" ? null : mode; + // } // Should characters that affect highlighting be highlighted separate? // Does not include characters that will be output (such as `1.` and `-` for lists) @@ -28,20 +36,17 @@ defineMode('markdown', function (cmCfg, modeCfg) { // Excess `>` will emit `error` token. if (modeCfg.maxBlockquoteDepth === undefined) { modeCfg.maxBlockquoteDepth = 0; } + // Use `fencedCodeBlocks` to configure fenced code blocks. false to + // disable, string to specify a precise regexp that the fence should + // match, and true to allow three or more backticks or tildes (as + // per CommonMark). + // Turn on task lists? ("- [ ] " and "- [x] ") if (modeCfg.taskLists === undefined) modeCfg.taskLists = false; // Turn on strikethrough syntax if (modeCfg.strikethrough === undefined) { modeCfg.strikethrough = false; } - if (modeCfg.emoji === undefined) { modeCfg.emoji = false; } - - if (modeCfg.fencedCodeBlockHighlighting === undefined) { modeCfg.fencedCodeBlockHighlighting = true; } - - if (modeCfg.fencedCodeBlockDefaultMode === undefined) { modeCfg.fencedCodeBlockDefaultMode = 'text/plain'; } - - if (modeCfg.xml === undefined) { modeCfg.xml = true; } - // Allow token types to be overridden by user-provided token types. if (modeCfg.tokenTypeOverrides === undefined) { modeCfg.tokenTypeOverrides = {}; } @@ -63,8 +68,7 @@ defineMode('markdown', function (cmCfg, modeCfg) { linkHref: 'string', em: 'em', strong: 'strong', - strikethrough: 'strikethrough', - emoji: 'builtin' + strikethrough: 'strikethrough' }; for (let tokenType in tokenTypes) { @@ -75,13 +79,13 @@ defineMode('markdown', function (cmCfg, modeCfg) { let hrRE = /^([*\-_])(?:\s*\1){2,}\s*$/; let listRE = /^(?:[*\-+]|^[0-9]+([.)]))\s+/; - let taskListRE = /^\[(x| )\](?=\s)/i; // Must follow listRE + let taskListRE = /^\[(x| )\](?=\s)/; // Must follow listRE let atxHeaderRE = modeCfg.allowAtxHeaderWithoutSpace ? /^(#+)/ : /^(#+)(?: |$)/; - let setextHeaderRE = /^ {0,3}(?:\={1,}|-{2,})\s*$/; - let textRE = /^[^#!\[\]*_\\<>` "'(~:]+/; - let fencedCodeRE = /^(~~~+|```+)[ \t]*([\w\/+#-]*)[^\n`]*$/; - let linkDefRE = /^\s*\[[^\]]+?\]:.*$/; // naive link-definition - let punctuation = /[!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E42\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC9\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDF3C-\uDF3E]|\uD809[\uDC70-\uDC74]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]/; + let setextHeaderRE = /^ *(?:\={1,}|-{1,})\s*$/; + let textRE = /^[^#!\[\]*_\\<>` "'(~]+/; + let fencedCodeRE = new RegExp('^(' + (modeCfg.fencedCodeBlocks === true ? '~~~+|```+' : modeCfg.fencedCodeBlocks) + + ')[ \\t]*([\\w+#\-]*)'); + let punctuation = /[!\"#$%&\'()*+,\-\.\/:;<=>?@\[\\\]^_`{|}~—]/; let expandedTab = ' '; // CommonMark specifies tab as 4 spaces function switchInline (stream, state, f) { @@ -103,8 +107,6 @@ defineMode('markdown', function (cmCfg, modeCfg) { function blankLine (state) { // Reset linkTitle state state.linkTitle = false; - state.linkHref = false; - state.linkText = false; // Reset EM state state.em = false; // Reset STRONG state @@ -115,41 +117,31 @@ defineMode('markdown', function (cmCfg, modeCfg) { state.quote = 0; // Reset state.indentedCode state.indentedCode = false; - if (state.f === htmlBlock) { - let exit = htmlModeMissing; - if (!exit) { - let inner = innerMode(htmlMode, state.htmlState); - exit = inner.mode.name === 'xml' && inner.state.tagStart === null && - (!inner.state.context && inner.state.tokenize.isInText); - } - if (exit) { - state.f = inlineNormal; - state.block = blockNormal; - state.htmlState = null; - } + if (state.f == htmlBlock) { + state.f = inlineNormal; + state.block = blockNormal; } // Reset state.trailingSpace state.trailingSpace = 0; state.trailingSpaceNewLine = false; // Mark this line as blank state.prevLine = state.thisLine; - state.thisLine = { stream: null }; + state.thisLine = null; return null; } function blockNormal (stream, state) { - let firstTokenOnLine = stream.column() === state.indentation; - let prevLineLineIsEmpty = lineIsEmpty(state.prevLine.stream); - let prevLineIsIndentedCode = state.indentedCode; - let prevLineIsHr = state.prevLine.hr; + let sol = stream.sol(); + let prevLineIsList = state.list !== false; - let maxNonCodeIndentation = (state.listStack[state.listStack.length - 1] || 0) + 3; + let prevLineIsIndentedCode = state.indentedCode; state.indentedCode = false; - let lineIndentation = state.indentation; + let lineIndentation; // compute once per line (on first token) if (state.indentationDiff === null) { + lineIndentation = state.indentation; state.indentationDiff = state.indentation; if (prevLineIsList) { state.list = null; @@ -171,50 +163,42 @@ defineMode('markdown', function (cmCfg, modeCfg) { } } - // not comprehensive (currently only for setext detection purposes) - let allowsInlineContinuation = ( - !prevLineLineIsEmpty && !prevLineIsHr && !state.prevLine.header && - (!prevLineIsList || !prevLineIsIndentedCode) && - !state.prevLine.fencedCodeEnd - ); - - let isHr = (state.list === false || prevLineIsHr || prevLineLineIsEmpty) && - state.indentation <= maxNonCodeIndentation && stream.match(hrRE); - let match = null; - if (state.indentationDiff >= 4 && (prevLineIsIndentedCode || state.prevLine.fencedCodeEnd || - state.prevLine.header || prevLineLineIsEmpty)) { + if (state.indentationDiff >= 4 && (prevLineIsIndentedCode || lineIsEmpty(state.prevLine))) { stream.skipToEnd(); state.indentedCode = true; return tokenTypes.code; } else if (stream.eatSpace()) { return null; - } else if (firstTokenOnLine && state.indentation <= maxNonCodeIndentation && (match = stream.match(atxHeaderRE)) && match[1].length <= 6) { - state.quote = 0; + } else if ((match = stream.match(atxHeaderRE)) && match[1].length <= 6) { state.header = match[1].length; - state.thisLine.header = true; if (modeCfg.highlightFormatting) state.formatting = 'header'; state.f = state.inline; return getType(state); - } else if (state.indentation <= maxNonCodeIndentation && stream.eat('>')) { - state.quote = firstTokenOnLine ? 1 : state.quote + 1; + } else if (!lineIsEmpty(state.prevLine) && !state.quote && !prevLineIsList && + !prevLineIsIndentedCode && (match = stream.match(setextHeaderRE))) { + state.header = match[0].charAt(0) == '=' ? 1 : 2; + if (modeCfg.highlightFormatting) state.formatting = 'header'; + state.f = state.inline; + return getType(state); + } else if (stream.eat('>')) { + state.quote = sol ? 1 : state.quote + 1; if (modeCfg.highlightFormatting) state.formatting = 'quote'; stream.eatSpace(); return getType(state); - } else if (!isHr && !state.setext && firstTokenOnLine && state.indentation <= maxNonCodeIndentation && (match = stream.match(listRE))) { + } else if (stream.peek() === '[') { + return switchInline(stream, state, footnoteLink); + } else if (stream.match(hrRE, true)) { + state.hr = true; + return tokenTypes.hr; + } else if (match = stream.match(listRE)) { let listType = match[1] ? 'ol' : 'ul'; state.indentation = lineIndentation + stream.current().length; state.list = true; - state.quote = 0; // Add this list item's content's indentation to the stack state.listStack.push(state.indentation); - // Reset inline styles which shouldn't propagate across list items - state.em = false; - state.strong = false; - state.code = false; - state.strikethrough = false; if (modeCfg.taskLists && stream.match(taskListRE, false)) { state.taskList = true; @@ -222,47 +206,15 @@ defineMode('markdown', function (cmCfg, modeCfg) { state.f = state.inline; if (modeCfg.highlightFormatting) state.formatting = ['list', 'list-' + listType]; return getType(state); - } else if (firstTokenOnLine && state.indentation <= maxNonCodeIndentation && (match = stream.match(fencedCodeRE, true))) { - state.quote = 0; - state.fencedEndRE = new RegExp(match[1] + '+ *$'); + } else if (modeCfg.fencedCodeBlocks && (match = stream.match(fencedCodeRE, true))) { + state.fencedChars = match[1]; // try switching mode - state.localMode = modeCfg.fencedCodeBlockHighlighting && getMode(match[2] || modeCfg.fencedCodeBlockDefaultMode); + state.localMode = getMode(match[2]); if (state.localMode) state.localState = startState(state.localMode); state.f = state.block = local; if (modeCfg.highlightFormatting) state.formatting = 'code-block'; state.code = -1; return getType(state); - // SETEXT has lowest block-scope precedence after HR, so check it after - // the others (code, blockquote, list...) - } else if ( - // if setext set, indicates line after ---/=== - state.setext || ( - // line before ---/=== - (!allowsInlineContinuation || !prevLineIsList) && !state.quote && state.list === false && - !state.code && !isHr && !linkDefRE.test(stream.string) && - (match = stream.lookAhead(1)) && (match = match.match(setextHeaderRE)) - ) - ) { - if (!state.setext) { - state.header = match[0].charAt(0) === '=' ? 1 : 2; - state.setext = state.header; - } else { - state.header = state.setext; - // has no effect on type so we can reset it now - state.setext = 0; - stream.skipToEnd(); - if (modeCfg.highlightFormatting) state.formatting = 'header'; - } - state.thisLine.header = true; - state.f = state.inline; - return getType(state); - } else if (isHr) { - stream.skipToEnd(); - state.hr = true; - state.thisLine.hr = true; - return tokenTypes.hr; - } else if (stream.peek() === '[') { - return switchInline(stream, state, footnoteLink); } return switchInline(stream, state, state.inline); @@ -272,7 +224,7 @@ defineMode('markdown', function (cmCfg, modeCfg) { let style = htmlMode.token(stream, state.htmlState); if (!htmlModeMissing) { let inner = innerMode(htmlMode, state.htmlState); - if ((inner.mode.name === 'xml' && inner.state.tagStart === null && + if ((inner.mode.name == 'xml' && inner.state.tagStart === null && (!inner.state.context && inner.state.tokenize.isInText)) || (state.md_inside && stream.current().indexOf('>') > -1)) { state.f = inlineNormal; @@ -284,21 +236,17 @@ defineMode('markdown', function (cmCfg, modeCfg) { } function local (stream, state) { - let currListInd = state.listStack[state.listStack.length - 1] || 0; - let hasExitedList = state.indentation < currListInd; - let maxFencedEndInd = currListInd + 3; - if (state.fencedEndRE && state.indentation <= maxFencedEndInd && (hasExitedList || stream.match(state.fencedEndRE))) { + if (state.fencedChars && stream.match(state.fencedChars)) { if (modeCfg.highlightFormatting) state.formatting = 'code-block'; - let returnType; - if (!hasExitedList) returnType = getType(state); + let returnType = getType(state); state.localMode = state.localState = null; state.block = blockNormal; state.f = inlineNormal; - state.fencedEndRE = null; + state.fencedChars = null; state.code = 0; - state.thisLine.fencedCodeEnd = true; - if (hasExitedList) return switchBlock(stream, state, state.block); return returnType; + } else if (state.fencedChars && stream.skipTo(state.fencedChars)) { + return 'comment'; } else if (state.localMode) { return state.localMode.token(stream, state.localState); } else { @@ -350,7 +298,6 @@ defineMode('markdown', function (cmCfg, modeCfg) { if (state.strong) { styles.push(tokenTypes.strong); } if (state.em) { styles.push(tokenTypes.em); } if (state.strikethrough) { styles.push(tokenTypes.strikethrough); } - if (state.emoji) { styles.push(tokenTypes.emoji); } if (state.linkText) { styles.push(tokenTypes.linkText); } if (state.code) { styles.push(tokenTypes.code); } if (state.image) { styles.push(tokenTypes.image); } @@ -408,7 +355,7 @@ defineMode('markdown', function (cmCfg, modeCfg) { } if (state.taskList) { - let taskOpen = stream.match(taskListRE, true)[1] === ' '; + let taskOpen = stream.match(taskListRE, true)[1] !== 'x'; if (taskOpen) state.taskOpen = true; else state.taskClosed = true; if (modeCfg.highlightFormatting) state.formatting = 'task'; @@ -446,11 +393,11 @@ defineMode('markdown', function (cmCfg, modeCfg) { if (modeCfg.highlightFormatting) state.formatting = 'code'; stream.eatWhile('`'); let count = stream.current().length; - if (state.code === 0 && (!state.quote || count === 1)) { + if (state.code == 0) { state.code = count; return getType(state); - } else if (count === state.code) { // Must be exact - const t = getType(state); + } else if (count == state.code) { // Must be exact + var t = getType(state); state.code = 0; return t; } else { @@ -464,7 +411,7 @@ defineMode('markdown', function (cmCfg, modeCfg) { if (ch === '\\') { stream.next(); if (modeCfg.highlightFormatting) { - let type = getType(state); + var type = getType(state); let formattingEscape = tokenTypes.formatting + '-escape'; return type ? type + ' ' + formattingEscape : formattingEscape; } @@ -486,7 +433,7 @@ defineMode('markdown', function (cmCfg, modeCfg) { if (ch === ']' && state.imageAltText) { if (modeCfg.highlightFormatting) state.formatting = 'image'; - let type = getType(state); + var type = getType(state); state.imageAltText = false; state.image = false; state.inline = state.f = linkHref; @@ -494,7 +441,6 @@ defineMode('markdown', function (cmCfg, modeCfg) { } if (ch === '[' && !state.image) { - if (state.linkText && stream.match(/^.*?\]/)) return getType(state); state.linkText = true; if (modeCfg.highlightFormatting) state.formatting = 'link'; return getType(state); @@ -502,7 +448,7 @@ defineMode('markdown', function (cmCfg, modeCfg) { if (ch === ']' && state.linkText) { if (modeCfg.highlightFormatting) state.formatting = 'link'; - let type = getType(state); + var type = getType(state); state.linkText = false; state.inline = state.f = stream.match(/\(.*?\)| ?\[.*?\]/, false) ? linkHref : inlineNormal; return type; @@ -511,7 +457,7 @@ defineMode('markdown', function (cmCfg, modeCfg) { if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) { state.f = state.inline = linkInline; if (modeCfg.highlightFormatting) state.formatting = 'link'; - let type = getType(state); + var type = getType(state); if (type) { type += ' '; } else { @@ -523,7 +469,7 @@ defineMode('markdown', function (cmCfg, modeCfg) { if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) { state.f = state.inline = linkInline; if (modeCfg.highlightFormatting) state.formatting = 'link'; - let type = getType(state); + var type = getType(state); if (type) { type += ' '; } else { @@ -532,9 +478,9 @@ defineMode('markdown', function (cmCfg, modeCfg) { return type + tokenTypes.linkEmail; } - if (modeCfg.xml && ch === '<' && stream.match(/^(!--|\?|!\[CDATA\[|[a-z][a-z0-9-]*(?:\s+[a-z_:.\-]+(?:\s*=\s*[^>]+)?)*\s*(?:>|$))/i, false)) { + if (ch === '<' && stream.match(/^(!--|[a-z]+(?:\s+[a-z_:.\-]+(?:\s*=\s*[^ >]+)?)*\s*>)/i, false)) { let end = stream.string.indexOf('>', stream.pos); - if (end !== -1) { + if (end != -1) { let atts = stream.string.substring(stream.start, end); if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) state.md_inside = true; } @@ -543,11 +489,11 @@ defineMode('markdown', function (cmCfg, modeCfg) { return switchBlock(stream, state, htmlBlock); } - if (modeCfg.xml && ch === '<' && stream.match(/^\/\w*?>/)) { + if (ch === '<' && stream.match(/^\/\w*?>/)) { state.md_inside = false; return 'tag'; } else if (ch === '*' || ch === '_') { - let len = 1; let before = stream.pos === 1 ? ' ' : stream.string.charAt(stream.pos - 2); + let len = 1; let before = stream.pos == 1 ? ' ' : stream.string.charAt(stream.pos - 2); while (len < 3 && stream.eat(ch)) len++; let after = stream.peek() || ' '; // See http://spec.commonmark.org/0.27/#emphasis-and-strong-emphasis @@ -555,16 +501,16 @@ defineMode('markdown', function (cmCfg, modeCfg) { let rightFlanking = !/\s/.test(before) && (!punctuation.test(before) || /\s/.test(after) || punctuation.test(after)); let setEm = null; let setStrong = null; if (len % 2) { // Em - if (!state.em && leftFlanking && (ch === '*' || !rightFlanking || punctuation.test(before))) { setEm = true; } else if (state.em === ch && rightFlanking && (ch === '*' || !leftFlanking || punctuation.test(after))) { setEm = false; } + if (!state.em && leftFlanking && (ch === '*' || !rightFlanking || punctuation.test(before))) { setEm = true; } else if (state.em == ch && rightFlanking && (ch === '*' || !leftFlanking || punctuation.test(after))) { setEm = false; } } if (len > 1) { // Strong - if (!state.strong && leftFlanking && (ch === '*' || !rightFlanking || punctuation.test(before))) { setStrong = true; } else if (state.strong === ch && rightFlanking && (ch === '*' || !leftFlanking || punctuation.test(after))) { setStrong = false; } + if (!state.strong && leftFlanking && (ch === '*' || !rightFlanking || punctuation.test(before))) { setStrong = true; } else if (state.strong == ch && rightFlanking && (ch === '*' || !leftFlanking || punctuation.test(after))) { setStrong = false; } } - if (setStrong !== null || setEm !== null) { - if (modeCfg.highlightFormatting) state.formatting = setEm === null ? 'strong' : setStrong === null ? 'em' : 'strong em'; + if (setStrong != null || setEm != null) { + if (modeCfg.highlightFormatting) state.formatting = setEm == null ? 'strong' : setStrong == null ? 'em' : 'strong em'; if (setEm === true) state.em = ch; if (setStrong === true) state.strong = ch; - const t = getType(state); + var t = getType(state); if (setEm === false) state.em = false; if (setStrong === false) state.strong = false; return t; @@ -583,7 +529,7 @@ defineMode('markdown', function (cmCfg, modeCfg) { if (ch === '~' && stream.eatWhile(ch)) { if (state.strikethrough) { // Remove strikethrough if (modeCfg.highlightFormatting) state.formatting = 'strikethrough'; - const t = getType(state); + var t = getType(state); state.strikethrough = false; return t; } else if (stream.match(/^[^\s]/, false)) { // Add strikethrough @@ -592,7 +538,7 @@ defineMode('markdown', function (cmCfg, modeCfg) { return getType(state); } } else if (ch === ' ') { - if (stream.match('~~', true)) { // Probably surrounded by space + if (stream.match(/^~~/, true)) { // Probably surrounded by space if (stream.peek() === ' ') { // Surrounded by spaces, ignore return getType(state); } else { // Not surrounded by spaces, back up pointer @@ -602,16 +548,8 @@ defineMode('markdown', function (cmCfg, modeCfg) { } } - if (modeCfg.emoji && ch === ':' && stream.match(/^(?:[a-z_\d+][a-z_\d+-]*|\-[a-z_\d+][a-z_\d+-]*):/)) { - state.emoji = true; - if (modeCfg.highlightFormatting) state.formatting = 'emoji'; - let retType = getType(state); - state.emoji = false; - return retType; - } - if (ch === ' ') { - if (stream.match(/^ +$/, false)) { + if (stream.match(/ +$/, false)) { state.trailingSpace++; } else if (state.trailingSpace) { state.trailingSpaceNewLine = true; @@ -691,7 +629,7 @@ defineMode('markdown', function (cmCfg, modeCfg) { } function footnoteLinkInside (stream, state) { - if (stream.match(']:', true)) { + if (stream.match(/^\]:/, true)) { state.f = state.inline = footnoteUrl; if (modeCfg.highlightFormatting) state.formatting = 'link'; let returnType = getType(state); @@ -715,19 +653,19 @@ defineMode('markdown', function (cmCfg, modeCfg) { if (stream.peek() === undefined) { // End of line, set flag to check next line state.linkTitle = true; } else { // More content on line, check if link title - stream.match(/^(?:\s+(?:"(?:[^"\\]|\\.)+"|'(?:[^'\\]|\\.)+'|\((?:[^)\\]|\\.)+\)))?/, true); + stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true); } state.f = state.inline = inlineNormal; return tokenTypes.linkHref + ' url'; } - const mode = { + var mode = { startState: function () { return { f: blockNormal, - prevLine: { stream: null }, - thisLine: { stream: null }, + prevLine: null, + thisLine: null, block: blockNormal, htmlState: null, @@ -744,7 +682,6 @@ defineMode('markdown', function (cmCfg, modeCfg) { em: false, strong: false, header: 0, - setext: 0, hr: false, taskList: false, list: false, @@ -753,8 +690,7 @@ defineMode('markdown', function (cmCfg, modeCfg) { trailingSpace: 0, trailingSpaceNewLine: false, strikethrough: false, - emoji: false, - fencedEndRE: null + fencedChars: null }; }, @@ -777,14 +713,11 @@ defineMode('markdown', function (cmCfg, modeCfg) { formatting: false, linkText: s.linkText, linkTitle: s.linkTitle, - linkHref: s.linkHref, code: s.code, em: s.em, strong: s.strong, strikethrough: s.strikethrough, - emoji: s.emoji, header: s.header, - setext: s.setext, hr: s.hr, taskList: s.taskList, list: s.list, @@ -794,7 +727,7 @@ defineMode('markdown', function (cmCfg, modeCfg) { trailingSpace: s.trailingSpace, trailingSpaceNewLine: s.trailingSpaceNewLine, md_inside: s.md_inside, - fencedEndRE: s.fencedEndRE + fencedChars: s.fencedChars }; }, @@ -802,17 +735,18 @@ defineMode('markdown', function (cmCfg, modeCfg) { // Reset state.formatting state.formatting = false; - if (stream !== state.thisLine.stream) { + if (stream != state.thisLine) { + // Reset state.header and state.hr state.header = 0; state.hr = false; if (stream.match(/^\s*$/, true)) { blankLine(state); - return null; + return state; } state.prevLine = state.thisLine; - state.thisLine = { stream: stream }; + state.thisLine = stream; // Reset state.taskList state.taskList = false; @@ -821,28 +755,26 @@ defineMode('markdown', function (cmCfg, modeCfg) { state.trailingSpace = 0; state.trailingSpaceNewLine = false; - if (!state.localState) { - state.f = state.block; - if (state.f !== htmlBlock) { - let indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, expandedTab).length; - state.indentation = indentation; - state.indentationDiff = null; - if (indentation > 0) return null; - } + state.f = state.block; + if (state.f != htmlBlock) { + let indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, expandedTab).length; + state.indentation = indentation; + state.indentationDiff = null; + if (indentation > 0) return null; } } return state.f(stream, state); }, innerMode: function (state) { - if (state.block === htmlBlock) return { state: state.htmlState, mode: htmlMode }; + if (state.block == htmlBlock) return { state: state.htmlState, mode: htmlMode }; if (state.localState) return { state: state.localState, mode: state.localMode }; return { state: state, mode: mode }; }, indent: function (state, textAfter, line) { - if (state.block === htmlBlock && htmlMode.indent) return htmlMode.indent(state.htmlState, textAfter, line); - if (state.localState && state.localMode.indent) return state.localMode.indent(state.localState, textAfter, line); + if (state.block == htmlBlock) return htmlMode.indent(state.htmlState, textAfter, line); + if (state.localState) return state.localMode.indent(state.localState, textAfter, line); return passIndent; }, @@ -850,10 +782,11 @@ defineMode('markdown', function (cmCfg, modeCfg) { getType: getType, - blockCommentStart: '', closeBrackets: "()[]{}''\"\"``", - fold: 'markdown' + fold: 'markdown', + + blockCommentStart: '' }; return mode; }, 'xml');