diff --git a/AUTHORS b/AUTHORS index 280dea2f5f..f800b86b7d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -48,6 +48,7 @@ Andreas Reischuck Andres Taylor Andre von Houck Andrew Cheng +Andrew Dassonville Andrey Fedorov Andrey Klyuchnikov Andrey Lushnikov @@ -68,6 +69,7 @@ Anthony Grimes Anton Kovalyov Apollo Zhu AQNOUCH Mohammed +Aram Shatakhtsyan areos Arnab Bose Arsène von Wyss @@ -155,6 +157,7 @@ Daniel Kesler Daniel KJ Daniel Neel Daniel Parnell +Daniel Thwaites Danila Malyutin Danny Yoo darealshinji @@ -213,7 +216,9 @@ ForbesLindesay Forbes Lindesay Ford_Lawnmower Forrest Oliphant +Franco Catena Frank Wiegand +Fredrik Borg Gabriel Gheorghian Gabriel Horner Gabriel Nahmias @@ -238,6 +243,7 @@ Grant Skinner greengiant Gregory Koberger Grzegorz Mazur +Guan Gui Guillaume Massé Guillaume Massé guraga @@ -249,12 +255,14 @@ Harshvardhan Gupta Hasan Karahan Hector Oswaldo Caballero Hendrik Wallbaum +Henrik Haugbølle Herculano Campos Hiroyuki Makino hitsthings Hocdoc Hugues Malphettes Ian Beck +Ian Davies Ian Dickinson Ian Wehrman Ian Wetherbee @@ -303,6 +311,7 @@ jem (graphite) Jeremy Parmenter Jim Jim Avery +jkaplon JobJob jochenberger Jochen Berger @@ -336,6 +345,7 @@ ju1ius Juan Benavides Romero Jucovschi Constantin Juho Vuori +Julien CROUZET Julien Rebetez Justin Andresen Justin Hileman @@ -376,6 +386,7 @@ LloydMilligan LM lochel Lorenzo Stoakes +Louis Mauchet Luca Fabbri Luciano Longo Lu Fangjian @@ -405,6 +416,7 @@ Mark Lentczner Marko Bonaci Mark Peace Markus Bordihn +Markus Olsson Martin Balek Martín Gaitán Martin Hasoň @@ -522,8 +534,8 @@ peterkroon Peter Kroon Philipp A Philip Stadermann +Pi Delport Pierre Gerold -Piët Delport Pieter Ouwerkerk Pontus Melke prasanthj @@ -627,6 +639,7 @@ thanasis TheHowl themrmax think +Thomas Brouard Thomas Dvornik Thomas Kluyver Thomas Schmid @@ -656,10 +669,12 @@ vf Victor Bocharsky Vincent Woo Volker Mische +vtripolitakis Weiyan Shao wenli Wes Cossick Wesley Wiser +Weston Ruter Will Binns-Smith Will Dean William Jamieson diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cc7ed75fd..409c7234bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,45 @@ +## 5.31.0 (2017-10-20) + +### Bug fixes + +Further improve selection drawing and cursor motion in right-to-left documents. + +[vim bindings](http://codemirror.net/demo/vim.html): Fix ctrl-w behavior, support quote-dot and backtick-dot marks, make the wide cursor visible in contentEditable [input mode](http://codemirror.net/doc/manual.html#option_contentEditable). + +[continuecomment addon](http://codemirror.net/doc/manual.html#addon_continuecomment): Fix bug when pressing enter after a single-line block comment. + +[markdown mode](http://codemirror.net/mode/markdown/): Fix issue with leaving indented fenced code blocks. + +[javascript mode](http://codemirror.net/mode/javascript/): Fix bad parsing of operators without spaces between them. Fix some corner cases around semicolon insertion and regexps. + +### New features + +Modes added with [`addOverlay`](http://codemirror.net/doc/manual.html#addOverlay) now have access to a [`baseToken`](http://codemirror.net/doc/manual.html#baseToken) method on their input stream, giving access to the tokens of the underlying mode. + +## 5.30.0 (2017-09-20) + +### Bug fixes + +Fixed a number of issues with drawing right-to-left selections and mouse selection in bidirectional text. + +[search addon](http://codemirror.net/demo/search/): Fix crash when restarting search after doing empty search. + +[mark-selection addon](http://cm/doc/manual.html#addon_mark-selection): Fix off-by-one bug. + +[tern addon](http://codemirror.net/demo/tern.html): Fix bad request made when editing at the bottom of a large document. + +[javascript mode](http://codemirror.net/mode/javascript/): Improve parsing in a number of corner cases. + +[markdown mode](http://codemirror.net/mode/markdown/): Fix crash when a sub-mode doesn't support indentation, allow uppercase X in task lists. + +[gfm mode](http://codemirror.net/mode/gfm/): Don't highlight SHA1 'hashes' without numbers to avoid false positives. + +[soy mode](http://codemirror.net/mode/soy/): Support injected data and `@param` in comments. + +### New features + +[simple mode addon](http://codemirror.net/demo/simplemode.html): Allow groups in regexps when `token` isn't an array. + ## 5.29.0 (2017-08-24) ### Bug fixes @@ -54,7 +96,7 @@ Fix crash when using mode lookahead. ### Bug fixes -Fix crash in the [simple mode](http://codemirror.net/demo/simplemode.html) addon. +Fix crash in the [simple mode](http://codemirror.net/demo/simplemode.html)< addon. ## 5.27.0 (2017-06-22) diff --git a/README.md b/README.md index 3328e3bdfb..a3a351be4d 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,8 @@ CodeMirror is a versatile text editor implemented in JavaScript for the browser. It is specialized for editing code, and comes with over 100 language modes and various addons that implement more advanced -editing functionality. +editing functionality. Every language comes with fully-featured code +and syntax highlighting to help with reading and editing complex code. A rich programming API and a CSS theming system are available for customizing CodeMirror to fit your application, and extending it with diff --git a/addon/comment/continuecomment.js b/addon/comment/continuecomment.js index d7385ef223..d92318b345 100644 --- a/addon/comment/continuecomment.js +++ b/addon/comment/continuecomment.js @@ -9,11 +9,6 @@ else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { - var modes = ["clike", "css", "javascript"]; - - for (var i = 0; i < modes.length; ++i) - CodeMirror.extendMode(modes[i], {blockCommentContinue: " * "}); - function continueComment(cm) { if (cm.getOption("disableInput")) return CodeMirror.Pass; var ranges = cm.listSelections(), mode, inserts = []; @@ -27,10 +22,10 @@ var insert = null; if (mode.blockCommentStart && mode.blockCommentContinue) { var line = cm.getLine(pos.line).slice(0, pos.ch) - var end = line.indexOf(mode.blockCommentEnd), found + var end = line.lastIndexOf(mode.blockCommentEnd), found if (end != -1 && end == pos.ch - mode.blockCommentEnd.length) { // Comment ended, don't continue it - } else if ((found = line.indexOf(mode.blockCommentStart)) > -1) { + } else if ((found = line.lastIndexOf(mode.blockCommentStart)) > -1 && found > end) { insert = line.slice(0, found) if (/\S/.test(insert)) { insert = "" diff --git a/addon/edit/closebrackets.js b/addon/edit/closebrackets.js index 01fdd96ce1..7b07f7fd8a 100644 --- a/addon/edit/closebrackets.js +++ b/addon/edit/closebrackets.js @@ -23,6 +23,7 @@ cm.state.closeBrackets = null; } if (val) { + ensureBound(getOption(val, "pairs")) cm.state.closeBrackets = val; cm.addKeyMap(keyMap); } @@ -34,10 +35,14 @@ return defaults[name]; } - var bind = defaults.pairs + "`"; var keyMap = {Backspace: handleBackspace, Enter: handleEnter}; - for (var i = 0; i < bind.length; i++) - keyMap["'" + bind.charAt(i) + "'"] = handler(bind.charAt(i)); + function ensureBound(chars) { + for (var i = 0; i < chars.length; i++) { + var ch = chars.charAt(i), key = "'" + ch + "'" + if (!keyMap[key]) keyMap[key] = handler(ch) + } + } + ensureBound(defaults.pairs + "`") function handler(ch) { return function(cm) { return handleChar(cm, ch); }; @@ -79,7 +84,8 @@ if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass; } cm.operation(function() { - cm.replaceSelection("\n\n", null); + var linesep = cm.lineSeparator() || "\n"; + cm.replaceSelection(linesep + linesep, null); cm.execCommand("goCharLeft"); ranges = cm.listSelections(); for (var i = 0; i < ranges.length; i++) { diff --git a/addon/edit/continuelist.js b/addon/edit/continuelist.js index 8cda0eaaad..fe950211b5 100644 --- a/addon/edit/continuelist.js +++ b/addon/edit/continuelist.js @@ -25,7 +25,8 @@ var inQuote = eolState.quote !== 0; var line = cm.getLine(pos.line), match = listRE.exec(line); - if (!ranges[i].empty() || (!inList && !inQuote) || !match) { + var cursorBeforeBullet = /^\s*$/.test(line.slice(0, pos.ch)); + if (!ranges[i].empty() || (!inList && !inQuote) || !match || cursorBeforeBullet) { cm.execCommand("newlineAndIndent"); return; } diff --git a/addon/hint/show-hint.js b/addon/hint/show-hint.js index 604bd3b715..f72a0a9c69 100644 --- a/addon/hint/show-hint.js +++ b/addon/hint/show-hint.js @@ -302,7 +302,7 @@ setTimeout(function(){cm.focus();}, 20); }); - CodeMirror.signal(data, "select", completions[0], hints.firstChild); + CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]); return true; } diff --git a/addon/lint/css-lint.js b/addon/lint/css-lint.js index b7e1a4fe5d..135d031a35 100644 --- a/addon/lint/css-lint.js +++ b/addon/lint/css-lint.js @@ -15,7 +15,7 @@ })(function(CodeMirror) { "use strict"; -CodeMirror.registerHelper("lint", "css", function(text) { +CodeMirror.registerHelper("lint", "css", function(text, options) { var found = []; if (!window.CSSLint) { if (window.console) { @@ -23,7 +23,7 @@ CodeMirror.registerHelper("lint", "css", function(text) { } return found; } - var results = CSSLint.verify(text), messages = results.messages, message = null; + var results = CSSLint.verify(text, options), messages = results.messages, message = null; for ( var i = 0; i < messages.length; i++) { message = messages[i]; var startLine = message.line -1, endLine = message.line -1, startCol = message.col -1, endCol = message.col; diff --git a/addon/lint/lint.js b/addon/lint/lint.js index 825065ed2a..a9eb8fa66b 100644 --- a/addon/lint/lint.js +++ b/addon/lint/lint.js @@ -138,7 +138,11 @@ function startLinting(cm) { var state = cm.state.lint, options = state.options; - var passOptions = options.options || options; // Support deprecated passing of `options` property in options + /* + * Passing rules in `options` property prevents JSHint (and other linters) from complaining + * about unrecognized rules like `onUpdateLinting`, `delay`, `lintOnChange`, etc. + */ + var passOptions = options.options || options; var getAnnotations = options.getAnnotations || cm.getHelper(CodeMirror.Pos(0, 0), "lint"); if (!getAnnotations) return; if (options.async || getAnnotations.async) { diff --git a/addon/mode/simple.js b/addon/mode/simple.js index 15cc215825..c0f801088c 100644 --- a/addon/mode/simple.js +++ b/addon/mode/simple.js @@ -136,7 +136,7 @@ state.indent.pop(); var token = rule.token if (token && token.apply) token = token(matches) - if (matches.length > 2) { + if (matches.length > 2 && rule.token && typeof rule.token != "string") { state.pending = []; for (var j = 2; j < matches.length; j++) if (matches[j]) diff --git a/addon/runmode/runmode.node.js b/addon/runmode/runmode.node.js index 093cb30876..21c72696c8 100644 --- a/addon/runmode/runmode.node.js +++ b/addon/runmode/runmode.node.js @@ -163,6 +163,18 @@ exports.getMode = function(options, spec) { return modeObj; }; + +exports.innerMode = function(mode, state) { + var info; + while (mode.innerMode) { + info = mode.innerMode(state); + if (!info || info.mode == mode) break; + state = info.state; + mode = info.mode; + } + return info || {mode: mode, state: state}; +} + exports.registerHelper = exports.registerGlobalHelper = Math.min; exports.runMode = function(string, modespec, callback, options) { diff --git a/addon/search/search.js b/addon/search/search.js index 82938b9a56..4059ccdd0e 100644 --- a/addon/search/search.js +++ b/addon/search/search.js @@ -117,6 +117,7 @@ var state = getSearchState(cm); if (state.query) return findNext(cm, rev); var q = cm.getSelection() || state.lastQuery; + if (q instanceof RegExp && q.source == "x^") q = null if (persistent && cm.openDialog) { var hiding = null var searchNext = function(query, event) { diff --git a/addon/selection/mark-selection.js b/addon/selection/mark-selection.js index 6cceeae6c7..1602acc3de 100644 --- a/addon/selection/mark-selection.js +++ b/addon/selection/mark-selection.js @@ -86,7 +86,7 @@ if (!array.length) return coverRange(cm, from, to); var coverStart = array[0].find(), coverEnd = array[array.length - 1].find(); - if (!coverStart || !coverEnd || to.line - from.line < CHUNK_SIZE || + if (!coverStart || !coverEnd || to.line - from.line <= CHUNK_SIZE || cmp(from, coverEnd.to) >= 0 || cmp(to, coverStart.from) <= 0) return reset(cm); diff --git a/addon/tern/tern.js b/addon/tern/tern.js index 644e495f65..a80dc7e4b8 100644 --- a/addon/tern/tern.js +++ b/addon/tern/tern.js @@ -571,7 +571,7 @@ return {type: "part", name: data.name, offsetLines: from.line, - text: doc.getRange(from, Pos(endLine, 0))}; + text: doc.getRange(from, Pos(endLine, end.line == endLine ? null : 0))}; } // Generic utilities diff --git a/bin/authors.sh b/bin/authors.sh index b3ee99c6dd..3f228c1fb0 100755 --- a/bin/authors.sh +++ b/bin/authors.sh @@ -1,6 +1,6 @@ # Combine existing list of authors with everyone known in git, sort, add header. tail --lines=+3 AUTHORS > AUTHORS.tmp -git log --format='%aN' >> AUTHORS.tmp +git log --format='%aN' | grep -v "Piët Delport" >> AUTHORS.tmp echo -e "List of CodeMirror contributors. Updated before every release.\n" > AUTHORS sort -u AUTHORS.tmp >> AUTHORS rm -f AUTHORS.tmp diff --git a/demo/simplemode.html b/demo/simplemode.html index d719b63d18..04c194a4ba 100644 --- a/demo/simplemode.html +++ b/demo/simplemode.html @@ -65,15 +65,14 @@
ignoreCase
flag
will be taken into account when matching the token. This regex
- should only capture groups when the token
property is
- an array.token
: string | nulltoken
property is
+ an array. If it captures groups, it must capture all of the string
+ (since JS provides no way to find out where a group matched).
+ token
: string | array<string> | nullregex
for
- this rule captures groups, it must capture all of the
- string (since JS provides no way to find out where a group matched),
- and this property must hold an array of token styles that has one
- style for each matched group.regex
for this rule must capture a group for each array item.
+
sol
: boolean^
regexp marker doesn't work as you'd expect in
diff --git a/demo/vim.html b/demo/vim.html
index f27b8b8e2b..bd704f7583 100644
--- a/demo/vim.html
+++ b/demo/vim.html
@@ -95,7 +95,8 @@ CodeMirror is a code-editor component that can be embedded in @@ -3261,6 +3261,12 @@
baseToken() → ?{type: ?string, size: number}
addOverlay
+ (and only such modes) can use this method to inspect
+ the current token produced by the underlying mode.By default, blank lines are simply skipped when diff --git a/doc/realworld.html b/doc/realworld.html index 7c5231ba81..f0a75abf72 100644 --- a/doc/realworld.html +++ b/doc/realworld.html @@ -45,6 +45,7 @@
20-10-2017: Version 5.31.0:
+ +addOverlay
now have access to a baseToken
method on their input stream, giving access to the tokens of the underlying mode.20-09-2017: Version 5.30.0:
+ +@param
in comments.token
isn't an array.24-08-2017: Version 5.29.0:
var myModeSpec = { name: "htmlmixed", tags: { - style: [["type", /^text/(x-)?scss$/, "text/x-scss"], + style: [["type", /^text\/(x-)?scss$/, "text/x-scss"], [null, null, "css"]], custom: [[null, null, "customMode"]] } diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index 267717f8be..ca9fe8ba86 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -23,13 +23,13 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { var keywords = function(){ function kw(type) {return {type: type, style: "keyword"};} - var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); + var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"), D = kw("keyword d"); var operator = kw("operator"), atom = {type: "atom", style: "atom"}; var jsKeywords = { "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, - "return": C, "break": C, "continue": C, "new": kw("new"), "delete": C, "throw": C, "debugger": C, - "var": kw("var"), "const": kw("var"), "let": kw("var"), + "return": D, "break": D, "continue": D, "new": kw("new"), "delete": C, "void": C, "throw": C, + "debugger": kw("debugger"), "var": kw("var"), "const": kw("var"), "let": kw("var"), "function": kw("function"), "catch": kw("catch"), "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), "in": operator, "typeof": operator, "instanceof": operator, @@ -128,7 +128,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/); return ret("regexp", "string-2"); } else { - stream.eatWhile(isOperatorChar); + stream.eat("="); return ret("operator", "operator", stream.current()); } } else if (ch == "`") { @@ -138,8 +138,14 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { stream.skipToEnd(); return ret("error", "error"); } else if (isOperatorChar.test(ch)) { - if (ch != ">" || !state.lexical || state.lexical.type != ">") - stream.eatWhile(isOperatorChar); + if (ch != ">" || !state.lexical || state.lexical.type != ">") { + if (stream.eat("=")) { + if (ch == "!" || ch == "=") stream.eat("=") + } else if (/[<>*+\-]/.test(ch)) { + stream.eat(ch) + if (ch == ">") stream.eat(ch) + } + } return ret("operator", "operator", stream.current()); } else if (wordRE.test(ch)) { stream.eatWhile(wordRE); @@ -351,6 +357,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex); if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex); if (type == "keyword b") return cont(pushlex("form"), statement, poplex); + if (type == "keyword d") return cx.stream.match(/^\s*$/, false) ? cont() : cont(pushlex("stat"), maybeexpression, expect(";"), poplex); + if (type == "debugger") return cont(expect(";")); if (type == "{") return cont(pushlex("}"), block, poplex); if (type == ";") return cont(); if (type == "if") { @@ -406,7 +414,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); if (type == "function") return cont(functiondef, maybeop); if (type == "class") return cont(pushlex("form"), classExpression, poplex); - if (type == "keyword c" || type == "async") return cont(noComma ? maybeexpressionNoComma : maybeexpression); + if (type == "keyword c" || type == "async") return cont(noComma ? expressionNoComma : expression); if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop); if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression); if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop); @@ -419,10 +427,6 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type.match(/[;\}\)\],]/)) return pass(); return pass(expression); } - function maybeexpressionNoComma(type) { - if (type.match(/[;\}\)\],]/)) return pass(); - return pass(expressionNoComma); - } function maybeoperatorComma(type, value) { if (type == ",") return cont(expression); @@ -443,6 +447,11 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == ".") return cont(property, me); if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); if (isTS && value == "as") { cx.marked = "keyword"; return cont(typeexpr, me) } + if (type == "regexp") { + cx.state.lastType = cx.marked = "operator" + cx.stream.backUp(cx.stream.pos - cx.stream.start - 1) + return cont(expr) + } } function quasi(type, value) { if (type != "quasi") return pass(); @@ -491,6 +500,9 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } else if (type == "variable" || cx.style == "keyword") { cx.marked = "property"; if (value == "get" || value == "set") return cont(getterSetter); + var m // Work around fat-arrow-detection complication for detecting typescript typed arrow params + if (isTS && cx.state.fatArrowAt == cx.stream.start && (m = cx.stream.match(/^\s*:\s*/, false))) + cx.state.fatArrowAt = cx.stream.pos + m[0].length return cont(afterprop); } else if (type == "number" || type == "string") { cx.marked = jsonldMode ? "property" : (cx.style + " property"); @@ -502,7 +514,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } else if (type == "[") { return cont(expression, expect("]"), afterprop); } else if (type == "spread") { - return cont(expression, afterprop); + return cont(expressionNoComma, afterprop); + } else if (value == "*") { + cx.marked = "keyword"; + return cont(objprop); } else if (type == ":") { return pass(afterprop) } @@ -550,7 +565,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } } function typeexpr(type, value) { - if (type == "variable") { + if (type == "variable" || value == "void") { if (value == "keyof") { cx.marked = "keyword" return cont(typeexpr) @@ -648,7 +663,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, maybetype, statement, popcontext); if (isTS && value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, functiondef) } - function funarg(type) { + function funarg(type, value) { + if (value == "@") cont(expression, funarg) if (type == "spread" || type == "modifier") return cont(funarg); return pass(pattern, maybetype, maybeAssign); } @@ -674,7 +690,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { cx.marked = "keyword"; return cont(classBody); } - if (type == "variable") { + if (type == "variable" || cx.style == "keyword") { cx.marked = "property"; return cont(isTS ? classfield : functiondef, classBody); } @@ -736,7 +752,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { function expressionAllowed(stream, state, backUp) { return state.tokenize == tokenBase && - /^(?:operator|sof|keyword c|case|new|export|default|[\[{}\(,;:]|=>)$/.test(state.lastType) || + /^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(state.lastType) || (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0)))) } @@ -805,6 +821,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { electricInput: /^\s*(?:case .*?:|default:|\{|\})$/, blockCommentStart: jsonMode ? null : "/*", blockCommentEnd: jsonMode ? null : "*/", + blockCommentContinue: jsonMode ? null : " * ", lineComment: jsonMode ? null : "//", fold: "brace", closeBrackets: "()[]{}''\"\"``", diff --git a/mode/javascript/test.js b/mode/javascript/test.js index f110b5c263..213bab06a8 100644 --- a/mode/javascript/test.js +++ b/mode/javascript/test.js @@ -236,6 +236,19 @@ " [keyword return] [number 2]", "}") + MT("regexp_corner_case", + "[operator +]{} [operator /] [atom undefined];", + "[[[meta ...][string-2 /\\//] ]];", + "[keyword void] [string-2 /\\//];", + "[keyword do] [string-2 /\\//]; [keyword while] ([number 0]);", + "[keyword if] ([number 0]) {} [keyword else] [string-2 /\\//];", + "[string-2 `${][variable async][operator ++][string-2 }//`];", + "[string-2 `${]{} [operator /] [string-2 /\\//}`];") + + MT("return_eol", + "[keyword return]", + "{} [string-2 /5/]") + var ts_mode = CodeMirror.getMode({indentUnit: 2}, "application/typescript") function TS(name) { test.mode(name, ts_mode, Array.prototype.slice.call(arguments, 1)) @@ -352,6 +365,9 @@ " [property constructor]([keyword readonly] [keyword private] [def x]) {}", "}") + TS("arrow prop", + "({[property a]: [def p] [operator =>] [variable-2 p]})") + var jsonld_mode = CodeMirror.getMode( {indentUnit: 2}, {name: "javascript", jsonld: true} diff --git a/mode/markdown/index.html b/mode/markdown/index.html index abb379f61a..f17ecdc9ac 100644 --- a/mode/markdown/index.html +++ b/mode/markdown/index.html @@ -396,6 +396,12 @@Markdown mode
{code: "code"}
).allowAtxHeaderWithoutSpace: boolean
false
).MIME types defined: text/x-markdown
.
MIME types defined: text/x-protobuf
.
MIME types defined: +
MIME types defined:
text/x-sql
,
text/x-mysql
,
text/x-mariadb
,
@@ -60,6 +60,7 @@
text/x-pgsql
,
text/x-gql
,
text/x-gpsql
.
+ text/x-esper
.