From 5a6f158eedf354acd88f66f1d09c9b221fc636d8 Mon Sep 17 00:00:00 2001 From: Stu Kennedy Date: Wed, 11 Nov 2015 23:42:25 +0000 Subject: [PATCH 001/161] [show-hint addon] Change selected item in hint options on mousmove Moving the mouse will change the selected hint option --- addon/hint/show-hint.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/addon/hint/show-hint.js b/addon/hint/show-hint.js index a1e56c38..b359208d 100644 --- a/addon/hint/show-hint.js +++ b/addon/hint/show-hint.js @@ -295,6 +295,12 @@ setTimeout(function(){cm.focus();}, 20); }); + CodeMirror.on(hints, "mousemove", function(e) { + var elt = getHintElement(hints, e.target || e.srcElement); + if (elt && elt.hintId != null) + widget.changeActive(elt.hintId); + }); + CodeMirror.signal(data, "select", completions[0], hints.firstChild); return true; } From 1de8132e2cefbe34043508dea747fffdfb90a2bc Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 12 Nov 2015 11:35:18 +0100 Subject: [PATCH 002/161] [show-hint addon] Only follow mouse with focus when completeOnSingleClick is on Make this the default Issue #3636 --- addon/hint/show-hint.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/addon/hint/show-hint.js b/addon/hint/show-hint.js index b359208d..7eefad8b 100644 --- a/addon/hint/show-hint.js +++ b/addon/hint/show-hint.js @@ -295,11 +295,12 @@ setTimeout(function(){cm.focus();}, 20); }); - CodeMirror.on(hints, "mousemove", function(e) { - var elt = getHintElement(hints, e.target || e.srcElement); - if (elt && elt.hintId != null) - widget.changeActive(elt.hintId); - }); + if (completion.options.completeOnSingleClick) + CodeMirror.on(hints, "mousemove", function(e) { + var elt = getHintElement(hints, e.target || e.srcElement); + if (elt && elt.hintId != null) + widget.changeActive(elt.hintId); + }); CodeMirror.signal(data, "select", completions[0], hints.firstChild); return true; @@ -436,7 +437,7 @@ alignWithWord: true, closeCharacters: /[\s()\[\]{};:>,]/, closeOnUnfocus: true, - completeOnSingleClick: false, + completeOnSingleClick: true, container: null, customKeys: null, extraKeys: null From 7530191700a67477d5866e1d606a4d4b8d4072b6 Mon Sep 17 00:00:00 2001 From: mihailik Date: Thu, 12 Nov 2015 15:59:28 +0000 Subject: [PATCH 003/161] [markdown mode] Fix typo --- mode/markdown/markdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/markdown/markdown.js b/mode/markdown/markdown.js index 2349ddf2..97dfb746 100644 --- a/mode/markdown/markdown.js +++ b/mode/markdown/markdown.js @@ -712,7 +712,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { f: s.f, prevLine: s.prevLine, - thisLine: s.this, + thisLine: s.thisLine, block: s.block, htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState), From 8e0660682d4171fc203867f7acdcb94ea77c80c5 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 17 Nov 2015 05:16:48 +0100 Subject: [PATCH 004/161] [javascript mode] Recognize regexp after case and new keywords Closes ##3648 --- mode/javascript/javascript.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index b961b890..0cbc36d7 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -121,8 +121,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } else if (stream.eat("/")) { stream.skipToEnd(); return ret("comment", "comment"); - } else if (state.lastType == "operator" || state.lastType == "keyword c" || - state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) { + } else if (/^(?:operator|sof|keyword c|case|new|[\[{}\(,;:])$/.test(state.lastType)) { readRegexp(stream); stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/); return ret("regexp", "string-2"); From cedae180f76cec84dbed6ab530f80ec136054b99 Mon Sep 17 00:00:00 2001 From: satamas Date: Mon, 16 Nov 2015 20:25:41 +0300 Subject: [PATCH 005/161] [kotlin mode] Improve string tokenizing, add keywords --- mode/clike/clike.js | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/mode/clike/clike.js b/mode/clike/clike.js index 566aa048..0cbe2fae 100644 --- a/mode/clike/clike.js +++ b/mode/clike/clike.js @@ -535,19 +535,36 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { modeProps: {closeBrackets: {triples: '"'}} }); + function tokenKotlinString(tripleString){ + return function (stream, state) { + var escaped = false, next, end = false; + while (!stream.eol()) { + if (!tripleString && !escaped && stream.match('"') ) {end = true; break;} + if (tripleString && stream.match('"""')) {end = true; break;} + next = stream.next(); + if(!escaped && next == "$" && stream.match('{')) + stream.skipTo("}"); + escaped = !escaped && next == "\\" && !tripleString; + } + if (end || !tripleString) + state.tokenize = null; + return "string"; + } + } + def("text/x-kotlin", { name: "clike", keywords: words( /*keywords*/ "package as typealias class interface this super val " + "var fun for is in This throw return " + - "break continue object if else while do try when !in !is as?" + + "break continue object if else while do try when !in !is as? " + /*soft keywords*/ "file import where by get set abstract enum open inner override private public internal " + "protected catch finally out final vararg reified dynamic companion constructor init " + "sealed field property receiver param sparam lateinit data inline noinline tailrec " + - "external annotation crossinline" + "external annotation crossinline const operator infix" ), types: words( /* package java.lang */ @@ -556,10 +573,18 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " + "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void" ), + intendSwitch: false, + indentStatements: false, multiLineStrings: true, blockKeywords: words("catch class do else finally for if where try while enum"), defKeywords: words("class val var object package interface fun"), atoms: words("true false null this"), + hooks: { + '"': function(stream, state) { + state.tokenize = tokenKotlinString(stream.match('""')); + return state.tokenize(stream, state); + } + }, modeProps: {closeBrackets: {triples: '"'}} }); From e477745492b75e1851689cd4832f7e16f7a94335 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Sat, 14 Nov 2015 02:58:07 -0500 Subject: [PATCH 006/161] [dart mode] add "as" to keywords `import "package:foo/foo.dart" as bar;` should highlight "as" as a keyword. --- mode/dart/dart.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/dart/dart.js b/mode/dart/dart.js index b1ee3776..88bb2779 100644 --- a/mode/dart/dart.js +++ b/mode/dart/dart.js @@ -15,7 +15,7 @@ "implements get native operator set typedef with enum throw rethrow " + "assert break case continue default in return new deferred async await " + "try catch finally do else for if switch while import library export " + - "part of show hide is").split(" "); + "part of show hide is as").split(" "); var blockKeywords = "try catch finally do else for if switch while".split(" "); var atoms = "true false null".split(" "); var builtins = "void bool num int double dynamic var String".split(" "); From a1e780ba7a6dce48781c93f998e6544fae657280 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Sat, 14 Nov 2015 03:12:06 -0500 Subject: [PATCH 007/161] [dart mode] in annotations "." is legal `@ng1.Injectable` is a legal annotation --- mode/dart/dart.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/dart/dart.js b/mode/dart/dart.js index 88bb2779..d92eb519 100644 --- a/mode/dart/dart.js +++ b/mode/dart/dart.js @@ -46,7 +46,7 @@ atoms: set(atoms), hooks: { "@": function(stream) { - stream.eatWhile(/[\w\$_]/); + stream.eatWhile(/[\w\$_\.]/); return "meta"; }, From 0216c3a753ec7dc8b594bb9bf155ea28bb422575 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 18 Nov 2015 16:13:07 +0100 Subject: [PATCH 008/161] [javascript mode] Allow spread in object literals Closes #3650 --- mode/javascript/javascript.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index 0cbc36d7..26e1693c 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -464,6 +464,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { return cont(afterprop); } else if (type == "[") { return cont(expression, expect("]"), afterprop); + } else if (type == "spread") { + return cont(expression); } } function getterSetter(type) { From 5bf7669e2fe96ffd46ebf46584c3a25d1e4d5ef8 Mon Sep 17 00:00:00 2001 From: Kayur Patel Date: Wed, 18 Nov 2015 00:46:30 -0800 Subject: [PATCH 009/161] [vim keymap] Fix JSDoc comment According to http://usejsdoc.org/about-getting-started.html, jsdoc comments must start with /** --- keymap/vim.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keymap/vim.js b/keymap/vim.js index 14897a84..02ed53af 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -3208,7 +3208,7 @@ return cur; } - /* + /** * Returns the boundaries of the next word. If the cursor in the middle of * the word, then returns the boundaries of the current word, starting at * the cursor. If the cursor is at the start/end of a word, and we are going From 160d3f64d4998b5677c7c79e7f333c8ad4caf479 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 19 Nov 2015 00:21:36 +0100 Subject: [PATCH 010/161] Initialize Doc.extend property in constructor Closes #3652 --- lib/codemirror.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/codemirror.js b/lib/codemirror.js index ff2f1a54..f97998ed 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -7358,6 +7358,7 @@ this.id = ++nextDocId; this.modeOption = mode; this.lineSep = lineSep; + this.extend = false; if (typeof text == "string") text = this.splitLines(text); updateDoc(this, {from: start, to: start, text: text}); From be4c5f3cb32757f47c402d3cfa85faf14e184dae Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 20 Nov 2015 21:32:44 +0100 Subject: [PATCH 011/161] [python mode] Fix parsing of properties Clean up weirdly specified regexps Closes #3641 --- mode/python/python.js | 45 ++++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/mode/python/python.js b/mode/python/python.js index e5a09719..553f2d6f 100644 --- a/mode/python/python.js +++ b/mode/python/python.js @@ -48,18 +48,18 @@ CodeMirror.defineMode("python", function(conf, parserConf) { var ERRORCLASS = "error"; - var singleDelimiters = parserConf.singleDelimiters || new RegExp("^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]"); - var doubleOperators = parserConf.doubleOperators || new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))"); - var doubleDelimiters = parserConf.doubleDelimiters || new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))"); - var tripleDelimiters = parserConf.tripleDelimiters || new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))"); + var singleDelimiters = parserConf.singleDelimiters || /^[\(\)\[\]\{\}@,:`=;\.]/; + var doubleOperators = parserConf.doubleOperators || /^([!<>]==|<>|<<|>>|\/\/|\*\*)/; + var doubleDelimiters = parserConf.doubleDelimiters || /^(\+=|\-=|\*=|%=|\/=|&=|\|=|\^=)/; + var tripleDelimiters = parserConf.tripleDelimiters || /^(\/\/=|>>=|<<=|\*\*=)/; if (parserConf.version && parseInt(parserConf.version, 10) == 3){ // since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator - var singleOperators = parserConf.singleOperators || new RegExp("^[\\+\\-\\*/%&|\\^~<>!@]"); - var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*"); + var singleOperators = parserConf.singleOperators || /^[\+\-\*\/%&|\^~<>!@]/; + var identifiers = parserConf.identifiers|| /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*/; } else { - var singleOperators = parserConf.singleOperators || new RegExp("^[\\+\\-\\*/%&|\\^~<>!]"); - var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z][_A-Za-z0-9]*"); + var singleOperators = parserConf.singleOperators || /^[\+\-\*\/%&|\^~<>!]/; + var identifiers = parserConf.identifiers|| /^[_A-Za-z][_A-Za-z0-9]*/; } var hangingIndent = parserConf.hangingIndent || conf.indentUnit; @@ -160,13 +160,16 @@ // Handle operators and Delimiters if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) - return null; + return "punctuation"; if (stream.match(doubleOperators) || stream.match(singleOperators)) return "operator"; if (stream.match(singleDelimiters)) - return null; + return "punctuation"; + + if (state.lastToken == "." && stream.match(identifiers)) + return "property"; if (stream.match(keywords) || stream.match(wordOperators)) return "keyword"; @@ -246,17 +249,6 @@ var style = state.tokenize(stream, state); var current = stream.current(); - // Handle '.' connected identifiers - if (current == ".") { - style = stream.match(identifiers, false) ? null : ERRORCLASS; - if (style == null && state.lastStyle == "meta") { - // Apply 'meta' style to '.' connected identifiers when - // appropriate. - style = "meta"; - } - return style; - } - // Handle decorators if (current == "@"){ if(parserConf.version && parseInt(parserConf.version, 10) == 3){ @@ -267,7 +259,7 @@ } if ((style == "variable" || style == "builtin") - && state.lastStyle == "meta") + && state.lastToken == "meta") style = "meta"; // Handle scope changes. @@ -300,7 +292,6 @@ return { tokenize: tokenBase, scopes: [{offset: basecolumn || 0, type: "py", align: null}], - lastStyle: null, lastToken: null, lambda: false, dedent: 0 @@ -312,11 +303,9 @@ if (addErr) state.errorToken = false; var style = tokenLexer(stream, state); - state.lastStyle = style; - - var current = stream.current(); - if (current && style) - state.lastToken = current; + if (style && style != "comment") + state.lastToken = (style == "keyword" || style == "punctuation") ? stream.current() : style; + if (style == "punctuation") style = null; if (stream.eol() && state.lambda) state.lambda = false; From 2a84b591b06470ad2063e2f2f03516eca2e4b42c Mon Sep 17 00:00:00 2001 From: Josh Cohen Date: Sun, 15 Nov 2015 23:57:24 -0500 Subject: [PATCH 012/161] [haml mode] Ignore {% liquid tags The old behavior sees the closing %} as a haml tag begin. The result is that the rest of the file after the %} doesnt highlight correctly. Dont go into quote mode when stream is '{%'. --- mode/haml/haml.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mode/haml/haml.js b/mode/haml/haml.js index 8fe63b02..03ce8335 100644 --- a/mode/haml/haml.js +++ b/mode/haml/haml.js @@ -85,8 +85,10 @@ state.tokenize = rubyInQuote(")"); return state.tokenize(stream, state); } else if (ch == "{") { - state.tokenize = rubyInQuote("}"); - return state.tokenize(stream, state); + if (!stream.match(/^\{%.*/)) { + state.tokenize = rubyInQuote("}"); + return state.tokenize(stream, state); + } } } From 88071b32ffd90b7ea50df965e7f511850ba4c8b1 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sat, 21 Nov 2015 12:43:29 +0100 Subject: [PATCH 013/161] [comment-fold addon] Ignore block comment start strings inside comments Closes #3651 --- addon/fold/comment-fold.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/addon/fold/comment-fold.js b/addon/fold/comment-fold.js index b75db7ea..60fa3e43 100644 --- a/addon/fold/comment-fold.js +++ b/addon/fold/comment-fold.js @@ -28,7 +28,9 @@ CodeMirror.registerGlobalHelper("fold", "comment", function(mode) { continue; } if (pass == 1 && found < start.ch) return; - if (/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1)))) { + if (/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1))) && + (lineText.slice(found - endToken.length, found) == endToken || + !/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found))))) { startCh = found + startToken.length; break; } From 9024f7cc61fcfd6b1490b9ee52045a2c7d0e7b99 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sat, 21 Nov 2015 12:59:44 +0100 Subject: [PATCH 014/161] [javascript mode] Revert "attempt to fix parsing when async/await are present" This reverts commit 94fc3b71e8e9f52b9239276a34658023933aac68. --- mode/javascript/javascript.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index 26e1693c..993d3eaf 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -32,12 +32,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { "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"), - "async": kw("async"), "function": kw("function"), "catch": kw("catch"), + "function": kw("function"), "catch": kw("catch"), "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), "in": operator, "typeof": operator, "instanceof": operator, "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, "this": kw("this"), "class": kw("class"), "super": kw("atom"), - "await": C, "yield": C, "export": kw("export"), "import": kw("import"), "extends": C + "yield": C, "export": kw("export"), "import": kw("import"), "extends": C }; // Extend the 'normal' keywords with the TypeScript language extensions @@ -372,7 +372,6 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); - if (type == "async") return cont(expression); if (type == "function") return cont(functiondef, maybeop); if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression); if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop); @@ -451,9 +450,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == "variable") {cx.marked = "property"; return cont();} } function objprop(type, value) { - if (type == "async") { - return cont(objprop); - } else if (type == "variable" || cx.style == "keyword") { + if (type == "variable" || cx.style == "keyword") { cx.marked = "property"; if (value == "get" || value == "set") return cont(getterSetter); return cont(afterprop); From 446d89def9aabe93f4030ab446546598b7ea2df6 Mon Sep 17 00:00:00 2001 From: Sergey Goder Date: Fri, 20 Nov 2015 19:02:33 -0800 Subject: [PATCH 015/161] [sql mode] Add `limit` to default SQL keyords --- mode/sql/sql.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/sql/sql.js b/mode/sql/sql.js index a9082771..86c68f72 100644 --- a/mode/sql/sql.js +++ b/mode/sql/sql.js @@ -257,7 +257,7 @@ CodeMirror.defineMode("sql", function(config, parserConfig) { } // these keywords are used by all SQL dialects (however, a mode can still overwrite it) - var sqlKeywords = "alter and as asc between by count create delete desc distinct drop from group having in insert into is join like not on or order select set table union update values where "; + var sqlKeywords = "alter and as asc between by count create delete desc distinct drop from group having in insert into is join like not on or order select set table union update values where limit"; // turn a space-separated list into an array function set(str) { From daad4a601ad1ffb35f4607bd49cdc3249cb5dda1 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 23 Nov 2015 10:53:41 +0100 Subject: [PATCH 016/161] [rust mode] Support multiline strings Issue #3660 --- mode/rust/rust.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/mode/rust/rust.js b/mode/rust/rust.js index 1ce0c01e..8558b53f 100644 --- a/mode/rust/rust.js +++ b/mode/rust/rust.js @@ -12,11 +12,12 @@ "use strict"; CodeMirror.defineSimpleMode("rust",{ - start:[ + start: [ // string and byte string - {regex: /b?"(?:[^\\]|\\.)*?"/, token: "string"}, + {regex: /b?"/, token: "string", next: "string"}, // raw string and raw byte string - {regex: /(b?r)(#*)(".*?)("\2)/, token: ["string", "string", "string", "string"]}, + {regex: /b?r"/, token: "string", next: "string_raw"}, + {regex: /b?r#+"/, token: "string", next: "string_raw_hash"}, // character {regex: /'(?:[^'\\]|\\(?:[nrt0'"]|x[\da-fA-F]{2}|u\{[\da-fA-F]{6}\}))'/, token: "string-2"}, // byte @@ -39,6 +40,18 @@ CodeMirror.defineSimpleMode("rust",{ {regex: /[\{\[\(]/, indent: true}, {regex: /[\}\]\)]/, dedent: true} ], + string: [ + {regex: /"/, token: "string", next: "start"}, + {regex: /(?:[^\\"]|\\(?:.|$))*/, token: "string"} + ], + string_raw: [ + {regex: /"/, token: "string", next: "start"}, + {regex: /[^"]*/, token: "string"} + ], + string_raw_hash: [ + {regex: /"#+/, token: "string", next: "start"}, + {regex: /(?:[^"]|"(?!#))*/, token: "string"} + ], comment: [ {regex: /.*?\*\//, token: "comment", next: "start"}, {regex: /.*/, token: "comment"} From a29e51697083c3cd6678f5bdda459a447321f3aa Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 23 Nov 2015 10:57:41 +0100 Subject: [PATCH 017/161] [handlebars and nsis modes] Do tokenize mismatched quotes as strings So that autoclosing works. Issue #3660 --- mode/handlebars/handlebars.js | 4 ++-- mode/nsis/nsis.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mode/handlebars/handlebars.js b/mode/handlebars/handlebars.js index 40dfea42..d6d9f5b0 100644 --- a/mode/handlebars/handlebars.js +++ b/mode/handlebars/handlebars.js @@ -21,8 +21,8 @@ { regex: /\}\}/, pop: true, token: "tag" }, // Double and single quotes - { regex: /"(?:[^\\]|\\.)*?"/, token: "string" }, - { regex: /'(?:[^\\]|\\.)*?'/, token: "string" }, + { regex: /"(?:[^\\"]|\\.)*"?/, token: "string" }, + { regex: /'(?:[^\\']|\\.)*'?/, token: "string" }, // Handlebars keywords { regex: />|[#\/]([A-Za-z_]\w*)/, token: "keyword" }, diff --git a/mode/nsis/nsis.js b/mode/nsis/nsis.js index 4c73fb73..172207c5 100644 --- a/mode/nsis/nsis.js +++ b/mode/nsis/nsis.js @@ -19,9 +19,9 @@ CodeMirror.defineSimpleMode("nsis",{ {regex: /(?:[+-]?)(?:0x[\d,a-f]+)|(?:0o[0-7]+)|(?:0b[0,1]+)|(?:\d+.?\d*)/, token: "number"}, // Strings - { regex: /"(?:[^\\]|\\.)*?"/, token: "string" }, - { regex: /'(?:[^\\]|\\.)*?'/, token: "string" }, - { regex: /`(?:[^\\]|\\.)*?`/, token: "string" }, + { regex: /"(?:[^\\"]|\\.)*"?/, token: "string" }, + { regex: /'(?:[^\\']|\\.)*'?/, token: "string" }, + { regex: /`(?:[^\\`]|\\.)*`?/, token: "string" }, // Compile Time Commands {regex: /(?:\!(include|addincludedir|addplugindir|appendfile|cd|delfile|echo|error|execute|packhdr|finalize|getdllversion|system|tempfile|warning|verbose|define|undef|insertmacro|makensis|searchparse|searchreplace))\b/, token: "keyword"}, From 2e3a2a1134cd4c5f92f21fb762c80c9a3e8f332d Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 23 Nov 2015 11:12:10 +0100 Subject: [PATCH 018/161] [rust mode] Adjust tests to new handling of strings --- mode/rust/test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/mode/rust/test.js b/mode/rust/test.js index 1a3c6e72..eb256c47 100644 --- a/mode/rust/test.js +++ b/mode/rust/test.js @@ -26,7 +26,6 @@ '[string "\\"foo\\""]', '[string r#""foo""#]', '[string "foo #\\"# bar"]', - '[string r##"foo #"# bar"##]', '[string b"foo"]', '[string br"foo"]', From 10b0c73e45a2f23f2b34871e5b8b00bcc2fe54c1 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 23 Nov 2015 11:47:09 +0100 Subject: [PATCH 019/161] Support adding multiple css strings to a token using markText --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index f97998ed..249f40ee 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -7089,7 +7089,7 @@ spanEndStyle = ""; } if (m.className) spanStyle += " " + m.className; - if (m.css) css = m.css; + if (m.css) css = (css ? css + ";" : "") + m.css; if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle; if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle; if (m.title && !title) title = m.title; From ec73f71ee6d04cc5c257f098bfcf693460be1866 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 23 Nov 2015 12:22:30 +0100 Subject: [PATCH 020/161] Mark release 5.9.0 --- AUTHORS | 7 +++++++ doc/compress.html | 1 + doc/manual.html | 2 +- doc/releases.html | 11 +++++++++++ index.html | 2 +- lib/codemirror.js | 2 +- package.json | 2 +- 7 files changed, 23 insertions(+), 4 deletions(-) diff --git a/AUTHORS b/AUTHORS index 1e3ece23..4f060641 100644 --- a/AUTHORS +++ b/AUTHORS @@ -91,6 +91,7 @@ Brian Sletten Bruce Mitchener Caitlin Potter Calin Barbat +Chad Jolly Chandra Sekhar Pydi Charles Skelton Cheah Chu Yeow @@ -233,6 +234,7 @@ jeffkenton Jeff Pickhardt jem (graphite) Jeremy Parmenter +JobJob Jochen Berger Johan Ask John Connor @@ -247,6 +249,7 @@ Jon Malmaud Jon Sangster Joost-Wim Boekesteijn Joseph Pecoraro +Josh Cohen Joshua Newman Josh Watzman jots @@ -259,6 +262,7 @@ Justin Hileman jwallers@gmail.com kaniga karevn +Kayur Patel Ken Newman Ken Rockot Kevin Earls @@ -437,6 +441,7 @@ SCLINIC\jdecker Scott Aikin Scott Goodhew Sebastian Zaha +Sergey Goder Se-Won Kim shaund shaun gilchrist @@ -459,12 +464,14 @@ Steffen Beyer Stephen Lavelle Steve O'Hara stoskov +Stu Kennedy Sungho Kim sverweij Taha Jahangir Tako Schotanus Takuji Shimokawa Tarmil +TDaglis tel tfjgeorge Thaddee Tyl diff --git a/doc/compress.html b/doc/compress.html index 6a183ca5..7712274c 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -36,6 +36,7 @@

Script compression helper

Version: (Use line:column or scroll% syntax)'; + + function jumpToLine(cm) { + var cur = cm.getCursor(); + dialog(cm, jumpDialog, 'Jump to line:', (cur.line+1)+':'+(cur.ch+1), function(posStr) { + if (!posStr) return; + + var clnMatch = /^\s*([\+\-]?\d+)\s*\:\s*(\d+)\s*$/.exec(posStr); + var prcMatch = /^\s*([\+\-]?\d+(\.\d+)?)\%\s*/.exec(posStr); + var lnMatch = /^\s*\:?\s*([\+\-]?\d+)\s*/.exec(posStr); + if (clnMatch) { + try { + var line = parseInt(clnMatch[1]); + var ch = parseInt(clnMatch[2]); + if ('+-'.indexOf(clnMatch[1].charAt(0))>=0) + line = cur.line+line+1; + } + catch (error) { return; } + cm.setCursor(line-1, ch-1); + } + else if (prcMatch) { + try { + var prc = parseFloat(prcMatch[1]); + var line = Math.round(cm.lineCount()*prc/100); + if ('+-'.indexOf(prcMatch[1].charAt(0))>=0) + line = cur.line+line+1; + } + catch (error) { return; } + cm.setCursor(line-1, cur.ch); + } + else if (lnMatch) { + try { + var line = parseInt(lnMatch[1]); + if ('+-'.indexOf(lnMatch[1].charAt(0))>=0) + line = cur.line+line+1; + } + catch (error) { return; } + cm.setCursor(line-1, cur.ch); + } + }) + } + + CodeMirror.commands.jumpToLine = jumpToLine; + CodeMirror.keyMap.default["Alt-G"] = "jumpToLine"; +}); diff --git a/demo/search.html b/demo/search.html index 21c34251..fd445db2 100644 --- a/demo/search.html +++ b/demo/search.html @@ -14,6 +14,7 @@ + - - -

CodeMirror: msgenny mode

- -
- - - -

MIME types defined: text/x-msgenny

- - diff --git a/mode/mscgen/index_xu.html b/mode/mscgen/index_xu.html deleted file mode 100644 index 2f7bf9ec..00000000 --- a/mode/mscgen/index_xu.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - - CodeMirror: xu mode - - - - - - -

CodeMirror: xù mode

- -
- - - -

MIME types defined: text/x-xu

- - From 382f51d257112027d147f583d14d6880618fd3da Mon Sep 17 00:00:00 2001 From: sverweij Date: Sat, 5 Dec 2015 19:55:08 +0100 Subject: [PATCH 042/161] [mscgen mode] simplifies the regexps to recognize keywords for our purposes (=>|<=|...) works just as well as ((<=)|(=>)|...) --- mode/mscgen/mscgen.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mode/mscgen/mscgen.js b/mode/mscgen/mscgen.js index 3cf4eb08..d61b4706 100644 --- a/mode/mscgen/mscgen.js +++ b/mode/mscgen/mscgen.js @@ -69,11 +69,11 @@ CodeMirror.defineMIME("text/x-msgenny", {name: "mscgen", language: "msgenny"}); function wordRegexpBoundary(pWords) { - return new RegExp("\\b((" + pWords.join(")|(") + "))\\b", "i"); + return new RegExp("\\b(" + pWords.join("|") + ")\\b", "i"); } function wordRegexp(pWords) { - return new RegExp("((" + pWords.join(")|(") + "))", "i"); + return new RegExp("(" + pWords.join("|") + ")", "i"); } function startStateFn() { From 764022a60ee7c092e18c9a45f3678d6b52852a00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Sat, 5 Dec 2015 22:05:27 +0100 Subject: [PATCH 043/161] [javascript mode] Recognize regex inside template literal Closes gh-3687 --- mode/javascript/javascript.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index e97593a2..d4ae6687 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -126,7 +126,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } else if (stream.eat("/")) { stream.skipToEnd(); return ret("comment", "comment"); - } else if (/^(?:operator|sof|keyword c|case|new|[\[{}\(,;:])$/.test(state.lastType)) { + } else if (/^(?:operator|sof|keyword c|case|new|[\[{}\(,;:])$/.test(state.lastType) || + (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - 1)))) { readRegexp(stream); stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/); return ret("regexp", "string-2"); From 9399b1cdee43d648fd8649c15220afdc33fc3ec0 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 7 Dec 2015 15:43:13 +0100 Subject: [PATCH 044/161] [vim bindings] Use a simpler way to handle splitting on dashes --- keymap/vim.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index 02ed53af..c1532a17 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -292,12 +292,7 @@ // Keypress character binding of format "'a'" return key.charAt(1); } - var pieces = key.split('-'); - if (/-$/.test(key)) { - // If the - key was typed, split will result in 2 extra empty strings - // in the array. Replace them with 1 '-'. - pieces.splice(-2, 2, '-'); - } + var pieces = key.split(/-(?!$)/); var lastPiece = pieces[pieces.length - 1]; if (pieces.length == 1 && pieces[0].length == 1) { // No-modifier bindings use literal character bindings above. Skip. From 4bdf6440429bc455f4ce39486d424fba0be7fa14 Mon Sep 17 00:00:00 2001 From: mihailik Date: Sat, 28 Nov 2015 15:55:34 +0000 Subject: [PATCH 045/161] Fixing hidding keyboard on arrow keys on mobile Makes sure the selection is not entirely cleared, which causs the on-screen keyboard to get hidden. Disabled for Firefox, where this causes other problems. Issue #3653 --- lib/codemirror.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 88c47bba..5bfa91d6 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1688,8 +1688,13 @@ try { var rng = range(start.node, start.offset, end.offset, end.node); } catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible if (rng) { - sel.removeAllRanges(); - sel.addRange(rng); + if (!gecko && this.cm.state.focused) { + sel.collapse(start.node, start.offset); + if (!rng.collapsed) sel.addRange(rng); + } else { + sel.removeAllRanges(); + sel.addRange(rng); + } if (old && sel.anchorNode == null) sel.addRange(old); else if (gecko) this.startGracePeriod(); } From b3010eddf829821ef279ce80a73047b6e6db6011 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sun, 13 Dec 2015 00:07:29 +0100 Subject: [PATCH 046/161] [css mode] Clean up handling of inline option --- mode/css/css.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mode/css/css.js b/mode/css/css.js index b20b4907..2673074a 100644 --- a/mode/css/css.js +++ b/mode/css/css.js @@ -12,9 +12,8 @@ "use strict"; CodeMirror.defineMode("css", function(config, parserConfig) { - var provided = parserConfig; + var inline = parserConfig.inline if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css"); - parserConfig.inline = provided.inline; var indentUnit = config.indentUnit, tokenHooks = parserConfig.tokenHooks, @@ -368,9 +367,9 @@ CodeMirror.defineMode("css", function(config, parserConfig) { return { startState: function(base) { return {tokenize: null, - state: parserConfig.inline ? "block" : "top", + state: inline ? "block" : "top", stateArg: null, - context: new Context(parserConfig.inline ? "block" : "top", base || 0, null)}; + context: new Context(inline ? "block" : "top", base || 0, null)}; }, token: function(stream, state) { From 0dbe0ef55d50734818325bbbc211f47c21c3c0ed Mon Sep 17 00:00:00 2001 From: TDaglis Date: Tue, 15 Dec 2015 11:39:14 +0000 Subject: [PATCH 047/161] [django mode] better highlighting of in/and/or/not Currently operators in most themes look like normal text because cm-operator doesn't usually get special styling. This patch highlights word operators (in/and/or/not) to make them stand out better. --- mode/django/django.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/mode/django/django.js b/mode/django/django.js index 7fae876c..eb8d6591 100644 --- a/mode/django/django.js +++ b/mode/django/django.js @@ -35,11 +35,13 @@ "truncatechars_html", "truncatewords", "truncatewords_html", "unordered_list", "upper", "urlencode", "urlize", "urlizetrunc", "wordcount", "wordwrap", "yesno"], - operators = ["==", "!=", "<", ">", "<=", ">=", "in", "not", "or", "and"]; + operators = ["==", "!=", "<", ">", "<=", ">="], + wordOperators = ["in", "not", "or", "and"]; keywords = new RegExp("^\\b(" + keywords.join("|") + ")\\b"); filters = new RegExp("^\\b(" + filters.join("|") + ")\\b"); operators = new RegExp("^\\b(" + operators.join("|") + ")\\b"); + wordOperators = new RegExp("^\\b(" + wordOperators.join("|") + ")\\b"); // We have to return "null" instead of null, in order to avoid string // styling as the default, when using Django templates inside HTML @@ -270,6 +272,11 @@ return "operator"; } + // Attempt to match a word operator + if (stream.match(wordOperators)) { + return "keyword"; + } + // Attempt to match a keyword var keywordMatch = stream.match(keywords); if (keywordMatch) { From 07207dd57c351b7ce9861960c1fba03caf301a99 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 15 Dec 2015 22:13:51 +0100 Subject: [PATCH 048/161] [show-hint addon] Use mouseover rather than mousemove to change selection So that tiny mouse motions don't keep resetting the selected item Closes #3698 --- addon/hint/show-hint.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addon/hint/show-hint.js b/addon/hint/show-hint.js index 7eefad8b..204e136f 100644 --- a/addon/hint/show-hint.js +++ b/addon/hint/show-hint.js @@ -296,10 +296,10 @@ }); if (completion.options.completeOnSingleClick) - CodeMirror.on(hints, "mousemove", function(e) { - var elt = getHintElement(hints, e.target || e.srcElement); - if (elt && elt.hintId != null) - widget.changeActive(elt.hintId); + CodeMirror.on(hints, "mouseover", function(e) { + var target = e.target || e.srcElement + if (target.hintId != null && !target.contains(e.relatedTarget || e.fromElement)) + widget.changeActive(target.hintId); }); CodeMirror.signal(data, "select", completions[0], hints.firstChild); From 9951761dc3e690cb958b4f11f7a84092466c9c56 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 15 Dec 2015 22:36:46 +0100 Subject: [PATCH 049/161] Fall back to putting CodeMirror in window if this is undefined Issue #3708 --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 5bfa91d6..07a23f1b 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -13,7 +13,7 @@ else if (typeof define == "function" && define.amd) // AMD return define([], mod); else // Plain browser env - this.CodeMirror = mod(); + (this || window).CodeMirror = mod(); })(function() { "use strict"; From b7f07850a9339b85a97fe0c261b5d3929c31d835 Mon Sep 17 00:00:00 2001 From: Cole R Lawrence Date: Mon, 14 Dec 2015 11:59:30 -0600 Subject: [PATCH 050/161] Link text runmode script in the correct location --- demo/runmode.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/runmode.html b/demo/runmode.html index 257f03d6..ab8938d8 100644 --- a/demo/runmode.html +++ b/demo/runmode.html @@ -43,7 +43,7 @@

Mode Runner Demo

Running a CodeMirror mode outside of the editor. The CodeMirror.runMode function, defined - in lib/runmode.js takes the following arguments:

+ in addon/runmode/runmode.js takes the following arguments:

text (string)
From 4c66400caefe1dbaf959b30ed835feec6942aa86 Mon Sep 17 00:00:00 2001 From: Jim Date: Mon, 14 Dec 2015 11:47:37 -0800 Subject: [PATCH 051/161] Correct typo in codemirror.css (`actuall` vs `actual`) There was a typo in one of the comments (`actuall` vs `actual`). --- lib/codemirror.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.css b/lib/codemirror.css index 3543523e..1067b3ee 100644 --- a/lib/codemirror.css +++ b/lib/codemirror.css @@ -165,7 +165,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} } /* The fake, visible scrollbars. Used to force redraw during scrolling - before actuall scrolling happens, thus preventing shaking and + before actual scrolling happens, thus preventing shaking and flickering artifacts. */ .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { position: absolute; From 188ae75e0154ba68d918ab21939163d8bf2d9f87 Mon Sep 17 00:00:00 2001 From: McBrainy Date: Mon, 14 Dec 2015 17:49:23 -0600 Subject: [PATCH 052/161] Fix typo in manual It took me forever to figure out why vim mode wasn't working, and all because the manual said to set the "keymap" option and not the "keyMap" option. I also added quotes to make it clear that "vim" is a string. --- doc/manual.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/manual.html b/doc/manual.html index 22d32df0..8812a171 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -3251,8 +3251,8 @@

VIM Mode API

CodeMirror has a robust VIM mode that attempts to faithfully emulate VIM's most useful features. It can be enabled by including keymap/vim.js - and setting the keymap option to - vim.

+ and setting the keyMap option to + "vim".

Configuration

From 7e35f03ad1639d92735c8dee1e1b5c86a727c873 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 15 Dec 2015 22:48:56 +0100 Subject: [PATCH 053/161] [runmode addon] Treat everything with an appendChild property as a DOM output node Closes #3703 --- addon/runmode/runmode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/runmode/runmode.js b/addon/runmode/runmode.js index 07d2279f..a51c6d0d 100644 --- a/addon/runmode/runmode.js +++ b/addon/runmode/runmode.js @@ -16,7 +16,7 @@ CodeMirror.runMode = function(string, modespec, callback, options) { var ie = /MSIE \d/.test(navigator.userAgent); var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9); - if (callback.nodeType == 1) { + if (callback.appendChild) { var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize; var node = callback, col = 0; node.innerHTML = ""; From bae907609a698e0da4579f69d13f84eccc252833 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 16 Dec 2015 09:09:22 +0100 Subject: [PATCH 054/161] [sublime bindings] Give ctrl-/ command a name Closes #3689 --- keymap/sublime.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keymap/sublime.js b/keymap/sublime.js index e0640b76..e0d0e92b 100644 --- a/keymap/sublime.js +++ b/keymap/sublime.js @@ -243,7 +243,7 @@ }); }; - map[ctrl + "/"] = function(cm) { + cmds[map[ctrl + "/"] = "toggleCommentIndented"] = function(cm) { cm.toggleComment({ indent: true }); } From 06e83fd66ebe639038eb64013891a1535ed07f25 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 16 Dec 2015 09:15:52 +0100 Subject: [PATCH 055/161] [show-hint addon] Revert select-on-mouse behavior Issue #3636 Issue #3698 --- addon/hint/show-hint.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/addon/hint/show-hint.js b/addon/hint/show-hint.js index 204e136f..cbe3b39a 100644 --- a/addon/hint/show-hint.js +++ b/addon/hint/show-hint.js @@ -295,13 +295,6 @@ setTimeout(function(){cm.focus();}, 20); }); - if (completion.options.completeOnSingleClick) - CodeMirror.on(hints, "mouseover", function(e) { - var target = e.target || e.srcElement - if (target.hintId != null && !target.contains(e.relatedTarget || e.fromElement)) - widget.changeActive(target.hintId); - }); - CodeMirror.signal(data, "select", completions[0], hints.firstChild); return true; } From 463797fb5ed003bacd64b69fc0910fbdb2cd0ca5 Mon Sep 17 00:00:00 2001 From: mihailik Date: Wed, 16 Dec 2015 09:55:27 +0000 Subject: [PATCH 056/161] [jump-to-line addon] Quote `default` property To avoid IE8 parser issue. --- addon/search/jump-to-line.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon/search/jump-to-line.js b/addon/search/jump-to-line.js index 49f3df4e..8b599cbc 100644 --- a/addon/search/jump-to-line.js +++ b/addon/search/jump-to-line.js @@ -45,5 +45,5 @@ }); }; - CodeMirror.keyMap.default["Alt-G"] = "jumpToLine"; + CodeMirror.keyMap["default"]["Alt-G"] = "jumpToLine"; }); From ab78fe07c459a56d92c6c4c9b50b3be86c314534 Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 11 Dec 2015 00:49:09 +0400 Subject: [PATCH 057/161] [vim] fix autoindent of S command --- keymap/vim.js | 20 ++++++++++++++------ test/vim_test.js | 15 ++++++++++++--- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index c1532a17..59815957 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -1954,13 +1954,21 @@ text = text.slice(0, - match[0].length); } } - var wasLastLine = head.line - 1 == cm.lastLine(); - cm.replaceRange('', anchor, head); - if (args.linewise && !wasLastLine) { + var prevLineEnd = new Pos(anchor.line - 1, Number.MAX_VALUE); + var wasLastLine = cm.firstLine() == cm.lastLine(); + if (head.line > cm.lastLine() && args.linewise && !wasLastLine) { + cm.replaceRange('', prevLineEnd, head); + } else { + cm.replaceRange('', anchor, head); + } + if (args.linewise) { // Push the next line back down, if there is a next line. - CodeMirror.commands.newlineAndIndent(cm); - // null ch so setCursor moves to end of line. - anchor.ch = null; + if (!wasLastLine) { + cm.setCursor(prevLineEnd); + CodeMirror.commands.newlineAndIndent(cm); + } + // make sure cursor ends up at the end of the line. + anchor.ch = Number.MAX_VALUE; } finalHead = anchor; } else { diff --git a/test/vim_test.js b/test/vim_test.js index 855cb882..74c6a950 100644 --- a/test/vim_test.js +++ b/test/vim_test.js @@ -2148,9 +2148,18 @@ testVim('S_normal', function(cm, vim, helpers) { cm.setCursor(0, 1); helpers.doKeys('j', 'S'); helpers.doKeys(''); - helpers.assertCursorAt(1, 0); - eq('aa\n\ncc', cm.getValue()); -}, { value: 'aa\nbb\ncc'}); + helpers.assertCursorAt(1, 1); + eq('aa{\n \ncc', cm.getValue()); + helpers.doKeys('j', 'S'); + eq('aa{\n \n ', cm.getValue()); + helpers.assertCursorAt(2, 2); + helpers.doKeys(''); + helpers.doKeys('d', 'd', 'd', 'd'); + helpers.assertCursorAt(0, 0); + helpers.doKeys('S'); + is(vim.insertMode); + eq('', cm.getValue()); +}, { value: 'aa{\nbb\ncc'}); testVim('blockwise_paste', function(cm, vim, helpers) { cm.setCursor(0, 0); helpers.doKeys('', '3', 'j', 'l', 'y'); From 78e3ac3520aec44b19a47d7c43232813a0e28f39 Mon Sep 17 00:00:00 2001 From: Justin Andresen Date: Thu, 17 Dec 2015 19:58:16 +0100 Subject: [PATCH 058/161] Update manual entry of extendSelectionsBy. --- doc/manual.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual.html b/doc/manual.html index 8812a171..2d8d618a 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -1350,7 +1350,7 @@

Cursor and selection methods

An equivalent of extendSelection that acts on all selections at once.
-
doc.extendSelectionsBy(f: function(range: {anchor, head}) → {anchor, head}), ?options: object)
+
doc.extendSelectionsBy(f: function(range: {anchor, head}) → {line, ch}), ?options: object)
Applies the given function to all existing selections, and calls extendSelections on the result.
From 3e88446bb59cacf133e7db1ae2221a85728b5bcc Mon Sep 17 00:00:00 2001 From: Drini Cami Date: Sat, 19 Dec 2015 02:50:21 -0500 Subject: [PATCH 059/161] [sparql mode] Add lineComment property --- mode/sparql/sparql.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mode/sparql/sparql.js b/mode/sparql/sparql.js index bbf8a76a..0cf40f58 100644 --- a/mode/sparql/sparql.js +++ b/mode/sparql/sparql.js @@ -165,7 +165,9 @@ CodeMirror.defineMode("sparql", function(config) { return context.col + (closing ? 0 : 1); else return context.indent + (closing ? 0 : indentUnit); - } + }, + + lineComment: "#" }; }); From d9042e78013f3377580966bf5a3092ccfa7848c0 Mon Sep 17 00:00:00 2001 From: Justin Andresen Date: Thu, 17 Dec 2015 18:58:45 +0100 Subject: [PATCH 060/161] Fix options of extendSelections. --- lib/codemirror.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 07a23f1b..c7c507d9 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -7454,7 +7454,7 @@ extendSelection(this, clipPos(this, head), other && clipPos(this, other), options); }), extendSelections: docMethodOp(function(heads, options) { - extendSelections(this, clipPosArray(this, heads, options)); + extendSelections(this, clipPosArray(this, heads), options); }), extendSelectionsBy: docMethodOp(function(f, options) { extendSelections(this, map(this.sel.ranges, f), options); From c39008a728e3172b196546eb7c22bb3d8a7d50f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Sch=C3=A4r?= Date: Wed, 16 Dec 2015 21:10:11 +0100 Subject: [PATCH 061/161] [markdown mode] fix escaped brackets in link def Example: `[foo\[bar\]foo]: https://example.com` --- mode/markdown/markdown.js | 4 ++-- mode/markdown/test.js | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/mode/markdown/markdown.js b/mode/markdown/markdown.js index 97dfb746..70889205 100644 --- a/mode/markdown/markdown.js +++ b/mode/markdown/markdown.js @@ -620,7 +620,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { } function footnoteLink(stream, state) { - if (stream.match(/^[^\]]*\]:/, false)) { + if (stream.match(/^([^\]\\]|\\.)*\]:/, false)) { state.f = footnoteLinkInside; stream.next(); // Consume [ if (modeCfg.highlightFormatting) state.formatting = "link"; @@ -639,7 +639,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { return returnType; } - stream.match(/^[^\]]+/, true); + stream.match(/^([^\]\\]|\\.)+/, true); return tokenTypes.linkText; } diff --git a/mode/markdown/test.js b/mode/markdown/test.js index f9cc27c3..6d7829fa 100644 --- a/mode/markdown/test.js +++ b/mode/markdown/test.js @@ -696,6 +696,15 @@ "[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 ] foo"); From 420cefd50bb4f62db4217c709064b39f55976650 Mon Sep 17 00:00:00 2001 From: Justin Andresen Date: Thu, 17 Dec 2015 19:02:41 +0100 Subject: [PATCH 062/161] Clip extended ranges. --- lib/codemirror.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index c7c507d9..dde88b4f 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -7457,7 +7457,8 @@ extendSelections(this, clipPosArray(this, heads), options); }), extendSelectionsBy: docMethodOp(function(f, options) { - extendSelections(this, map(this.sel.ranges, f), options); + var heads = map(this.sel.ranges, f); + extendSelections(this, clipPosArray(this, heads), options); }), setSelections: docMethodOp(function(ranges, primary, options) { if (!ranges.length) return; From fec88d280e1c0bf0f09b6b1db50318f39a74f172 Mon Sep 17 00:00:00 2001 From: Justin Andresen Date: Thu, 17 Dec 2015 19:02:41 +0100 Subject: [PATCH 063/161] Add an origin field to beforeSelectionChange event objects Issue #3723 --- doc/manual.html | 8 +++++--- lib/codemirror.js | 7 ++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/doc/manual.html b/doc/manual.html index 2d8d618a..bda852a7 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -582,15 +582,17 @@

Events

mode's electric patterns, and this caused the line's indentation to change. -
"beforeSelectionChange" (instance: CodeMirror, obj: {ranges, update})
+
"beforeSelectionChange" (instance: CodeMirror, obj: {ranges, origin, update})
This event is fired before the selection is moved. Its handler may inspect the set of selection ranges, present as an array of {anchor, head} objects in the ranges property of the obj argument, and optionally change them by calling the update method on this object, passing an array - of ranges in the same format. Handlers for this event have the - same restriction + of ranges in the same format. The object also contains + an origin property holding the origin string passed + to the selection-changing method, if any. Handlers for this + event have the same restriction as "beforeChange" handlers — they should not do anything to directly update the state of the editor.
diff --git a/lib/codemirror.js b/lib/codemirror.js index dde88b4f..2141cda1 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -2155,7 +2155,7 @@ // Give beforeSelectionChange handlers a change to influence a // selection update. - function filterSelectionChange(doc, sel) { + function filterSelectionChange(doc, sel, options) { var obj = { ranges: sel.ranges, update: function(ranges) { @@ -2163,7 +2163,8 @@ for (var i = 0; i < ranges.length; i++) this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor), clipPos(doc, ranges[i].head)); - } + }, + origin: options && options.origin }; signal(doc, "beforeSelectionChange", doc, obj); if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj); @@ -2189,7 +2190,7 @@ function setSelectionNoUndo(doc, sel, options) { if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) - sel = filterSelectionChange(doc, sel); + sel = filterSelectionChange(doc, sel, options); var bias = options && options.bias || (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1); From ca8fb83d48ebb9fe2d24b8f08abfe204f706dcad Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sun, 20 Dec 2015 21:50:47 +0100 Subject: [PATCH 064/161] Fire DOM events for paste --- doc/manual.html | 2 +- lib/codemirror.js | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/manual.html b/doc/manual.html index bda852a7..695a7ed2 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -654,7 +654,7 @@

Events

"mousedown", "dblclick", "contextmenu", "keydown", "keypress", - "keyup", "dragstart", "dragenter", + "keyup", "paste", "dragstart", "dragenter", "dragover", "drop" (instance: CodeMirror, event: Event)
Fired when CodeMirror is handling a DOM event of this type. diff --git a/lib/codemirror.js b/lib/codemirror.js index 2141cda1..6305cafd 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -1251,7 +1251,7 @@ }); on(te, "paste", function(e) { - if (handlePaste(e, cm)) return true; + if (signalDOMEvent(cm, e) || handlePaste(e, cm)) return cm.state.pasteIncoming = true; input.fastPoll(); @@ -1285,7 +1285,7 @@ on(te, "copy", prepareCopyCut); on(display.scroller, "paste", function(e) { - if (eventInWidget(display, e)) return; + if (eventInWidget(display, e) || signalDOMEvent(cm, e)) return; cm.state.pasteIncoming = true; input.focus(); }); @@ -1570,7 +1570,9 @@ var div = input.div = display.lineDiv; disableBrowserMagic(div); - on(div, "paste", function(e) { handlePaste(e, cm); }) + on(div, "paste", function(e) { + if (!signalDOMEvent(cm, e)) handlePaste(e, cm); + }) on(div, "compositionstart", function(e) { var data = e.data; From a4e987079517e1ff23d73c5a572f69d15ec4ff55 Mon Sep 17 00:00:00 2001 From: Chunliang Lyu Date: Sat, 19 Dec 2015 22:39:10 +0800 Subject: [PATCH 065/161] Add mode for GitHub Flavored Markdown with YAML front matter --- mode/yaml-markdown/index.html | 114 ++++++++++++++++++++++++++++ mode/yaml-markdown/yaml-markdown.js | 64 ++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 mode/yaml-markdown/index.html create mode 100644 mode/yaml-markdown/yaml-markdown.js diff --git a/mode/yaml-markdown/index.html b/mode/yaml-markdown/index.html new file mode 100644 index 00000000..ad610da8 --- /dev/null +++ b/mode/yaml-markdown/index.html @@ -0,0 +1,114 @@ + + +CodeMirror: GitHub Flavored Markdown with YAML front matter mode + + + + + + + + + + + + + +
+

GitHub Flavored Markdown with YAML front matter mode

+
+ + +
diff --git a/mode/yaml-markdown/yaml-markdown.js b/mode/yaml-markdown/yaml-markdown.js new file mode 100644 index 00000000..a1af80f3 --- /dev/null +++ b/mode/yaml-markdown/yaml-markdown.js @@ -0,0 +1,64 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +(function (mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../gfm/gfm"), require("../yaml/yaml")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../gfm/gfm", "../yaml/yaml"], mod); + else // Plain browser env + mod(CodeMirror); +})(function (CodeMirror) { + + // a mixed mode for Markdown text with an optional YAML front matter + CodeMirror.defineMode("yaml-markdown", function (config) { + var gfmMode = CodeMirror.getMode(config, {name: "gfm"}); + var yamlMode = CodeMirror.getMode(config, {name: "yaml"}); + + return { + startState: function () { + var gfmState = gfmMode.startState(); + var yamlState = yamlMode.startState(); + return { + firstLine: true, + mode: gfmMode, + gfmState: gfmState, + yamlState: yamlState + }; + }, + copyState: function (state) { + return { + mode: state.mode, + gfmState: gfmMode.copyState(state.gfmState), + yamlState: state.yamlState + }; + }, + token: function (stream, state) { + if (state.firstLine && stream.match(/---/, false)) { + state.firstLine = false; + state.mode = yamlMode; + return yamlMode.token(stream, state.yamlState); + } else if (state.mode == yamlMode && stream.match(/---/, false)) { + state.mode = gfmMode; + return yamlMode.token(stream, state.yamlState); + } else if (state.mode == yamlMode) { + return state.mode.token(stream, state.yamlState); + } else { + return state.mode.token(stream, state.gfmState); + } + }, + innerMode: function (state) { + if (state.mode == gfmMode) { + return gfmMode.innerMode(state.gfmState); + } else { + return {mode: yamlMode, state: state}; + } + }, + blankLine: function (state) { + if (state.mode == gfmMode) { + return gfmMode.blankLine(state.gfmState) + } + } + }; + }); +}); From d6212b9216e4a3add9df636726d0c59dfd62ca74 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sun, 20 Dec 2015 22:15:16 +0100 Subject: [PATCH 066/161] [yaml-frontmatter mode] Repurpose yaml-markdown mode to a general yaml-frontmatter mode Issue #3722 --- doc/compress.html | 1 + mode/index.html | 1 + .../index.html | 17 +++-- mode/yaml-frontmatter/yaml-frontmatter.js | 68 +++++++++++++++++++ mode/yaml-markdown/yaml-markdown.js | 64 ----------------- 5 files changed, 82 insertions(+), 69 deletions(-) rename mode/{yaml-markdown => yaml-frontmatter}/index.html (83%) create mode 100644 mode/yaml-frontmatter/yaml-frontmatter.js delete mode 100644 mode/yaml-markdown/yaml-markdown.js diff --git a/doc/compress.html b/doc/compress.html index f7c511c7..fe8260ad 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -219,6 +219,7 @@

Script compression helper

+ diff --git a/mode/index.html b/mode/index.html index 477ca2c1..72419241 100644 --- a/mode/index.html +++ b/mode/index.html @@ -148,6 +148,7 @@

Language modes

  • XML/HTML
  • XQuery
  • YAML
  • +
  • YAML frontmatter
  • Z80
  • diff --git a/mode/yaml-markdown/index.html b/mode/yaml-frontmatter/index.html similarity index 83% rename from mode/yaml-markdown/index.html rename to mode/yaml-frontmatter/index.html index ad610da8..30bed2f8 100644 --- a/mode/yaml-markdown/index.html +++ b/mode/yaml-frontmatter/index.html @@ -1,6 +1,6 @@ -CodeMirror: GitHub Flavored Markdown with YAML front matter mode +CodeMirror: YAML front matter mode @@ -10,7 +10,7 @@ - +
    -

    GitHub Flavored Markdown with YAML front matter mode

    +

    YAML front matter mode

    + +

    Defines a mode that parses +a YAML frontmatter +at the start of a file, switching to a base mode at the end of that. +Takes a mode configuration option base to configure the +base mode, which defaults to "gfm".

    +
    diff --git a/mode/yaml-frontmatter/yaml-frontmatter.js b/mode/yaml-frontmatter/yaml-frontmatter.js new file mode 100644 index 00000000..5b65dffb --- /dev/null +++ b/mode/yaml-frontmatter/yaml-frontmatter.js @@ -0,0 +1,68 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +(function (mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../yaml/yaml")) + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../yaml/yaml"], mod) + else // Plain browser env + mod(CodeMirror) +})(function (CodeMirror) { + + var START = 0, FRONTMATTER = 1, BODY = 2 + + // a mixed mode for Markdown text with an optional YAML front matter + CodeMirror.defineMode("yaml-frontmatter", function (config, parserConfig) { + var yamlMode = CodeMirror.getMode(config, "yaml") + var innerMode = CodeMirror.getMode(config, parserConfig && parserConfig.base || "gfm") + + function curMode(state) { + return state.state == BODY ? innerMode : yamlMode + } + + return { + startState: function () { + return { + state: START, + inner: CodeMirror.startState(yamlMode) + } + }, + copyState: function (state) { + return { + state: state.state, + inner: CodeMirror.copyState(curMode(state), state.inner) + } + }, + token: function (stream, state) { + if (state.state == START) { + if (stream.match(/---/, false)) { + state.state = FRONTMATTER + return yamlMode.token(stream, state.inner) + } else { + stream.state = BODY + state.inner = CodeMirror.startState(innerMode) + return innerMode.token(stream, state.inner) + } + } else if (state.state == FRONTMATTER) { + var end = stream.sol() && stream.match(/---/, false) + var style = yamlMode.token(stream, state.inner) + if (end) { + state.state = BODY + state.inner = CodeMirror.startState(innerMode) + } + return style + } else { + return innerMode.token(stream, state.inner) + } + }, + innerMode: function (state) { + return {mode: curMode(state), state: state.inner} + }, + blankLine: function (state) { + var mode = curMode(state) + if (mode.blankLine) return mode.blankLine(state.inner) + } + } + }) +}) diff --git a/mode/yaml-markdown/yaml-markdown.js b/mode/yaml-markdown/yaml-markdown.js deleted file mode 100644 index a1af80f3..00000000 --- a/mode/yaml-markdown/yaml-markdown.js +++ /dev/null @@ -1,64 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function (mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../gfm/gfm"), require("../yaml/yaml")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../gfm/gfm", "../yaml/yaml"], mod); - else // Plain browser env - mod(CodeMirror); -})(function (CodeMirror) { - - // a mixed mode for Markdown text with an optional YAML front matter - CodeMirror.defineMode("yaml-markdown", function (config) { - var gfmMode = CodeMirror.getMode(config, {name: "gfm"}); - var yamlMode = CodeMirror.getMode(config, {name: "yaml"}); - - return { - startState: function () { - var gfmState = gfmMode.startState(); - var yamlState = yamlMode.startState(); - return { - firstLine: true, - mode: gfmMode, - gfmState: gfmState, - yamlState: yamlState - }; - }, - copyState: function (state) { - return { - mode: state.mode, - gfmState: gfmMode.copyState(state.gfmState), - yamlState: state.yamlState - }; - }, - token: function (stream, state) { - if (state.firstLine && stream.match(/---/, false)) { - state.firstLine = false; - state.mode = yamlMode; - return yamlMode.token(stream, state.yamlState); - } else if (state.mode == yamlMode && stream.match(/---/, false)) { - state.mode = gfmMode; - return yamlMode.token(stream, state.yamlState); - } else if (state.mode == yamlMode) { - return state.mode.token(stream, state.yamlState); - } else { - return state.mode.token(stream, state.gfmState); - } - }, - innerMode: function (state) { - if (state.mode == gfmMode) { - return gfmMode.innerMode(state.gfmState); - } else { - return {mode: yamlMode, state: state}; - } - }, - blankLine: function (state) { - if (state.mode == gfmMode) { - return gfmMode.blankLine(state.gfmState) - } - } - }; - }); -}); From 237a6b69baab3c5d0c4dedc00ad70ceb436d6d13 Mon Sep 17 00:00:00 2001 From: Erik Welander Date: Sat, 12 Dec 2015 01:56:34 -0800 Subject: [PATCH 067/161] [vim] Correct the scroll position for zt & zb. zt was placing 40% of the line above the visible area, and zb was placing it too high. --- keymap/vim.js | 4 +--- test/vim_test.js | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/keymap/vim.js b/keymap/vim.js index 59815957..0548b75b 100644 --- a/keymap/vim.js +++ b/keymap/vim.js @@ -2147,9 +2147,7 @@ switch (actionArgs.position) { case 'center': y = y - (height / 2) + lineHeight; break; - case 'bottom': y = y - height + lineHeight*1.4; - break; - case 'top': y = y + lineHeight*0.4; + case 'bottom': y = y - height + lineHeight; break; } cm.scrollTo(null, y); diff --git a/test/vim_test.js b/test/vim_test.js index 74c6a950..25f7e75e 100644 --- a/test/vim_test.js +++ b/test/vim_test.js @@ -3119,6 +3119,25 @@ forEach(['zb','zz','zt','z-','z.','z'], function(e, idx){ return new Array(500).join('\n'); })()}); }); +testVim('zb_to_bottom', function(cm, vim, helpers){ + var lineNum = 250; + cm.setSize(600, 35*cm.defaultTextHeight()); + cm.setCursor(lineNum, 0); + helpers.doKeys('z', 'b'); + var scrollInfo = cm.getScrollInfo(); + eq(scrollInfo.top + scrollInfo.clientHeight, cm.charCoords(Pos(lineNum, 0), 'local').bottom); +}, { value: (function(){ + return new Array(500).join('\n'); +})()}); +testVim('zt_to_top', function(cm, vim, helpers){ + var lineNum = 250; + cm.setSize(600, 35*cm.defaultTextHeight()); + cm.setCursor(lineNum, 0); + helpers.doKeys('z', 't'); + eq(cm.getScrollInfo().top, cm.charCoords(Pos(lineNum, 0), 'local').top); +}, { value: (function(){ + return new Array(500).join('\n'); +})()}); testVim('zb Date: Mon, 21 Dec 2015 10:05:31 +0100 Subject: [PATCH 068/161] [clike mode] Highlight comments in preprocessor lines Closes #3709 --- mode/clike/clike.js | 25 ++++++++++++------------- mode/clike/test.js | 9 +++++++++ 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/mode/clike/clike.js b/mode/clike/clike.js index 0cbe2fae..3766209c 100644 --- a/mode/clike/clike.js +++ b/mode/clike/clike.js @@ -262,21 +262,20 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { var cTypes = "int long char short double float unsigned signed void size_t ptrdiff_t"; function cppHook(stream, state) { - if (!state.startOfLine) return false; - for (;;) { - if (stream.skipTo("\\")) { - stream.next(); - if (stream.eol()) { - state.tokenize = cppHook; - break; - } - } else { - stream.skipToEnd(); - state.tokenize = null; - break; + if (!state.startOfLine) return false + for (var ch, next = null; ch = stream.peek();) { + if (!ch) { + break + } else if (ch == "\\" && stream.match(/^.$/)) { + next = cppHook + break + } else if (ch == "/" && stream.match(/^\/[\/\*]/, false)) { + break } + stream.next() } - return "meta"; + state.tokenize = next + return "meta" } function pointerHook(_stream, state) { diff --git a/mode/clike/test.js b/mode/clike/test.js index c84d22e1..c2600326 100644 --- a/mode/clike/test.js +++ b/mode/clike/test.js @@ -31,6 +31,15 @@ " [variable x][operator ++];", "[keyword return];"); + MT("preprocessor", + "[meta #define FOO 3]", + "[variable-3 int] [variable foo];", + "[meta #define BAR\\]", + "[meta 4]", + "[variable-3 unsigned] [variable-3 int] [variable bar] [operator =] [number 8];", + "[meta #include ][comment // comment]") + + var mode_cpp = CodeMirror.getMode({indentUnit: 2}, "text/x-c++src"); function MTCPP(name) { test.mode(name, mode_cpp, Array.prototype.slice.call(arguments, 1)); } From c7b64ca080df3657f5094a51a976a167176a4178 Mon Sep 17 00:00:00 2001 From: TSUYUSATO Kitsune Date: Thu, 17 Dec 2015 00:12:45 +0900 Subject: [PATCH 069/161] [crystal mode] Add --- mode/crystal/crystal.js | 391 ++++++++++++++++++++++++++++++++++++++++ mode/crystal/index.html | 119 ++++++++++++ mode/index.html | 1 + mode/meta.js | 1 + 4 files changed, 512 insertions(+) create mode 100644 mode/crystal/crystal.js create mode 100644 mode/crystal/index.html diff --git a/mode/crystal/crystal.js b/mode/crystal/crystal.js new file mode 100644 index 00000000..8fd65a5f --- /dev/null +++ b/mode/crystal/crystal.js @@ -0,0 +1,391 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + "use strict"; + + CodeMirror.defineMode("crystal", function(config) { + function wordRegExp(words, end) { + return new RegExp((end ? "" : "^") + "(?:" + words.join("|") + ")" + (end ? "$" : "\\b")); + } + + function chain(tokenize, stream, state) { + state.tokenize.push(tokenize); + return tokenize(stream, state); + } + + var operators = /^(?:[-+/%|&^]|\*\*?|[<>]{2})/; + var conditionalOperators = /^(?:[=!]~|===|<=>|[<>=!]=?|[|&]{2}|~)/; + var indexingOperators = /^(?:\[\][?=]?)/; + var anotherOperators = /^(?:\.(?:\.{2})?|->|[?:])/; + var idents = /^[a-z_\u009F-\uFFFF][a-zA-Z0-9_\u009F-\uFFFF]*/; + var types = /^[A-Z_\u009F-\uFFFF][a-zA-Z0-9_\u009F-\uFFFF]*/; + var keywords = wordRegExp([ + "abstract", "alias", "as", "asm", "begin", "break", "case", "class", "def", "do", + "else", "elsif", "end", "ensure", "enum", "extend", "for", "fun", "if", "ifdef", + "include", "instance_sizeof", "lib", "macro", "module", "next", "of", "out", "pointerof", + "private", "protected", "rescue", "return", "require", "sizeof", "struct", + "super", "then", "type", "typeof", "union", "unless", "until", "when", "while", "with", + "yield", "__DIR__", "__FILE__", "__LINE__" + ]); + var atomWords = wordRegExp(["true", "false", "nil", "self"]); + var indentKeywordsArray = [ + "def", "fun", "macro", + "class", "module", "struct", "lib", "enum", "union", + "if", "unless", "case", "while", "until", "begin", "then", + "do", + "for", "ifdef" + ]; + var indentKeywords = wordRegExp(indentKeywordsArray); + var dedentKeywordsArray = [ + "end", + "else", "elsif", + "rescue", "ensure" + ]; + var dedentKeywords = wordRegExp(dedentKeywordsArray); + var dedentPunctualsArray = ["\\)", "\\}", "\\]"]; + var dedentPunctuals = new RegExp("^(?:" + dedentPunctualsArray.join("|") + ")$"); + var nextTokenizer = { + "def": tokenFollowIdent, "fun": tokenFollowIdent, "macro": tokenMacroDef, + "class": tokenFollowType, "module": tokenFollowType, "struct": tokenFollowType, + "lib": tokenFollowType, "enum": tokenFollowType, "union": tokenFollowType + }; + var matching = {"[": "]", "{": "}", "(": ")", "<": ">"}; + + function tokenBase(stream, state) { + if (stream.eatSpace()) { + return null; + } + + // Macros + if (state.lastToken != "\\" && stream.match("{%", false)) { + return chain(tokenMacro("%", "%"), stream, state); + } + + if (state.lastToken != "\\" && stream.match("{{", false)) { + return chain(tokenMacro("{", "}"), stream, state); + } + + // Comments + if (stream.peek() == "#") { + stream.skipToEnd(); + return "comment"; + } + + // Variables and keywords + var matched; + if (matched = stream.match(idents)) { + stream.eat(/[?!]/); + + matched = stream.current(); + if (stream.eat(":")) { + return "atom"; + } else if (state.lastToken == ".") { + return "property"; + } else if (keywords.test(matched)) { + if (state.lastToken != "abstract" && indentKeywords.test(matched)) { + if (!(matched == "fun" && state.blocks.indexOf("lib") >= 0)) { + state.blocks.push(matched); + state.currentIndent += 1; + } + } else if (dedentKeywords.test(matched)) { + state.blocks.pop(); + state.currentIndent -= 1; + } + + if (nextTokenizer.hasOwnProperty(matched)) { + state.tokenize.push(nextTokenizer[matched]); + } + + return "keyword"; + } else if (atomWords.test(matched)) { + return "atom"; + } + + return "variable"; + } + + // Class variables and instance variables + // or attributes + if (stream.eat("@")) { + if (stream.peek() == "[") { + return chain(tokenNest("[", "]", "meta"), stream, state); + } + + stream.eat("@"); + stream.match(idents) || stream.match(types); + return "variable-2"; + } + + // Global variables + if (stream.eat("$")) { + stream.eat(/[0-9]+|\?/) || stream.match(idents) || stream.match(types); + return "variable-3"; + } + + // Constants and types + if (stream.match(types)) { + return "tag"; + } + + // Symbols or ':' operator + if (stream.eat(":")) { + if (stream.eat("\"")) { + return chain(tokenQuote("\"", "atom", false), stream, state); + } else if (stream.match(idents) || stream.match(types) || + stream.match(operators) || stream.match(conditionalOperators) || stream.match(indexingOperators)) { + return "atom"; + } + stream.eat(":"); + return "operator"; + } + + // Strings + if (stream.eat("\"")) { + return chain(tokenQuote("\"", "string", true), stream, state); + } + + // Strings or regexps or macro variables or '%' operator + if (stream.peek() == "%") { + var style = "string"; + var embed = true; + var delim; + + if (stream.match("%r")) { + // Regexps + style = "string-2"; + delim = stream.next(); + } else if (stream.match("%w")) { + embed = false; + delim = stream.next(); + } else { + if(delim = stream.match(/^%([^\w\s=])/)) { + delim = delim[1]; + } else if (stream.match(/^%[a-zA-Z0-9_\u009F-\uFFFF]*/)) { + // Macro variables + return "meta"; + } else { + // '%' operator + return "operator"; + } + } + + if (matching.hasOwnProperty(delim)) { + delim = matching[delim]; + } + return chain(tokenQuote(delim, style, embed), stream, state); + } + + // Characters + if (stream.eat("'")) { + stream.match(/^(?:[^']|\\(?:[befnrtv0'"]|[0-7]{3}|u(?:[0-9a-fA-F]{4}|\{[0-9a-fA-F]{1,6}\})))/); + stream.eat("'"); + return "atom"; + } + + // Numbers + if (stream.eat("0")) { + if (stream.eat("x")) { + stream.match(/^[0-9a-fA-F]+/); + } else if (stream.eat("o")) { + stream.match(/^[0-7]+/); + } else if (stream.eat("b")) { + stream.match(/^[01]+/); + } + return "number"; + } + + if (stream.eat(/\d/)) { + stream.match(/^\d*(?:\.\d+)?(?:[eE][+-]?\d+)?/); + return "number"; + } + + // Operators + if (stream.match(operators)) { + stream.eat("="); // Operators can follow assigin symbol. + return "operator"; + } + + if (stream.match(conditionalOperators) || stream.match(anotherOperators)) { + return "operator"; + } + + // Parens and braces + if (matched = stream.match(/[({[]/, false)) { + matched = matched[0]; + return chain(tokenNest(matched, matching[matched], null), stream, state); + } + + // Escapes + if (stream.eat("\\")) { + stream.next(); + return "meta"; + } + + stream.next(); + return null; + } + + function tokenNest(begin, end, style, started) { + return function (stream, state) { + if (!started && stream.match(begin)) { + state.tokenize[state.tokenize.length - 1] = tokenNest(begin, end, style, true); + state.currentIndent += 1; + return style; + } + + var nextStyle = tokenBase(stream, state); + if (stream.current() === end) { + state.tokenize.pop(); + state.currentIndent -= 1; + nextStyle = style; + } + + return nextStyle; + }; + } + + function tokenMacro(begin, end, started) { + return function (stream, state) { + if (!started && stream.match("{" + begin)) { + state.currentIndent += 1; + state.tokenize[state.tokenize.length - 1] = tokenMacro(begin, end, true); + return "meta"; + } + + if (stream.match(end + "}")) { + state.currentIndent -= 1; + state.tokenize.pop(); + return "meta"; + } + + return tokenBase(stream, state); + }; + } + + function tokenMacroDef(stream, state) { + if (stream.eatSpace()) { + return null; + } + + var matched; + if (matched = stream.match(idents)) { + if (matched == "def") { + return "keyword"; + } + stream.eat(/[?!]/); + } + + state.tokenize.pop(); + return "def"; + } + + function tokenFollowIdent(stream, state) { + if (stream.eatSpace()) { + return null; + } + + if (stream.match(idents)) { + stream.eat(/[!?]/); + } else { + stream.match(operators) || stream.match(conditionalOperators) || stream.match(indexingOperators); + } + state.tokenize.pop(); + return "def"; + } + + function tokenFollowType(stream, state) { + if (stream.eatSpace()) { + return null; + } + + stream.match(types); + state.tokenize.pop(); + return "def"; + } + + function tokenQuote(end, style, embed) { + return function (stream, state) { + var escaped = false; + + while (stream.peek()) { + if (!escaped) { + if (stream.match("{%", false)) { + state.tokenize.push(tokenMacro("%", "%")); + return style; + } + + if (stream.match("{{", false)) { + state.tokenize.push(tokenMacro("{", "}")); + return style; + } + + if (embed && stream.match("#{", false)) { + state.tokenize.push(tokenNest("#{", "}", "meta")); + return style; + } + + var ch = stream.next(); + + if (ch == end) { + state.tokenize.pop(); + return style; + } + + escaped = ch == "\\"; + } else { + stream.next(); + escaped = false; + } + } + + return style; + }; + } + + return { + startState: function () { + return { + tokenize: [tokenBase], + currentIndent: 0, + lastToken: null, + blocks: [] + }; + }, + + token: function (stream, state) { + var style = state.tokenize[state.tokenize.length - 1](stream, state); + var token = stream.current(); + + if (style && style != "comment") { + state.lastToken = token; + } + + return style; + }, + + indent: function (state, textAfter) { + textAfter = textAfter.replace(/^\s*(?:\{%)?\s*|\s*(?:%\})?\s*$/g, ""); + + if (dedentKeywords.test(textAfter) || dedentPunctuals.test(textAfter)) { + return config.indentUnit * (state.currentIndent - 1); + } + + return config.indentUnit * state.currentIndent; + }, + + fold: "indent", + electricInput: wordRegExp(dedentPunctualsArray.concat(dedentKeywordsArray), true), + lineComment: '#' + }; + }); + + CodeMirror.defineMIME("text/x-crystal", "crystal"); +}); diff --git a/mode/crystal/index.html b/mode/crystal/index.html new file mode 100644 index 00000000..4bd0399f --- /dev/null +++ b/mode/crystal/index.html @@ -0,0 +1,119 @@ + + +CodeMirror: Ruby mode + + + + + + + + + + + +
    +

    Crystal mode

    +
    + + +

    MIME types defined: text/x-crystal.

    +
    diff --git a/mode/index.html b/mode/index.html index 72419241..072b89bd 100644 --- a/mode/index.html +++ b/mode/index.html @@ -42,6 +42,7 @@

    Language modes

  • COBOL
  • CoffeeScript
  • Common Lisp
  • +
  • Crystal
  • CSS
  • Cypher
  • Cython
  • diff --git a/mode/meta.js b/mode/meta.js index 7af51c1e..69e2a3ef 100644 --- a/mode/meta.js +++ b/mode/meta.js @@ -28,6 +28,7 @@ {name: "Common Lisp", mime: "text/x-common-lisp", mode: "commonlisp", ext: ["cl", "lisp", "el"], alias: ["lisp"]}, {name: "Cypher", mime: "application/x-cypher-query", mode: "cypher", ext: ["cyp", "cypher"]}, {name: "Cython", mime: "text/x-cython", mode: "python", ext: ["pyx", "pxd", "pxi"]}, + {name: "Crystal", mime: "text/x-crystal", mode: "crystal", ext: ["cr"]}, {name: "CSS", mime: "text/css", mode: "css", ext: ["css"]}, {name: "CQL", mime: "text/x-cassandra", mode: "sql", ext: ["cql"]}, {name: "D", mime: "text/x-d", mode: "d", ext: ["d"]}, From 09e20bce214c2bd849667783365a7283b803d8eb Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 21 Dec 2015 10:42:29 +0100 Subject: [PATCH 070/161] [crystal mode] Integrate --- doc/compress.html | 1 + mode/crystal/crystal.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/compress.html b/doc/compress.html index fe8260ad..74c68347 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -122,6 +122,7 @@

    Script compression helper

    + diff --git a/mode/crystal/crystal.js b/mode/crystal/crystal.js index 8fd65a5f..2e74bee4 100644 --- a/mode/crystal/crystal.js +++ b/mode/crystal/crystal.js @@ -81,7 +81,7 @@ // Variables and keywords var matched; - if (matched = stream.match(idents)) { + if (stream.match(idents)) { stream.eat(/[?!]/); matched = stream.current(); From 6bc4c5a082be035ecf1c2bc66c0237df7c94850f Mon Sep 17 00:00:00 2001 From: TSUYUSATO Kitsune Date: Mon, 21 Dec 2015 18:55:12 +0900 Subject: [PATCH 071/161] [crystal mode] Crystal looks like Ruby but not Ruby --- mode/crystal/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mode/crystal/index.html b/mode/crystal/index.html index 4bd0399f..ec03e250 100644 --- a/mode/crystal/index.html +++ b/mode/crystal/index.html @@ -1,6 +1,6 @@ -CodeMirror: Ruby mode +CodeMirror: Crystal mode @@ -23,7 +23,7 @@ From fcfe83818aaee069c932be21cffeb855d7ac6cb0 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 21 Dec 2015 11:16:41 +0100 Subject: [PATCH 072/161] Fix assignment of end styles when there are multiple active marks We can't check for nextChange until all marks have been looked at See https://discuss.codemirror.net/t/marktext-endstyle-appearing-multiple-times/568/5 --- lib/codemirror.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 6305cafd..a90b9b59 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -7089,7 +7089,7 @@ if (nextChange == pos) { // Update current marker set spanStyle = spanEndStyle = spanStartStyle = title = css = ""; collapsed = null; nextChange = Infinity; - var foundBookmarks = []; + var foundBookmarks = [], endStyles for (var j = 0; j < spans.length; ++j) { var sp = spans[j], m = sp.marker; if (m.type == "bookmark" && sp.from == pos && m.widgetNode) { @@ -7102,7 +7102,7 @@ if (m.className) spanStyle += " " + m.className; if (m.css) css = (css ? css + ";" : "") + m.css; if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle; - if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle; + if (m.endStyle && sp.to == nextChange) (endStyles || (endStyles = [])).push(m.endStyle, sp.to) if (m.title && !title) title = m.title; if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0)) collapsed = sp; @@ -7110,6 +7110,9 @@ nextChange = sp.from; } } + if (endStyles) for (var j = 0; j < endStyles.length; j += 2) + if (endStyles[j + 1] == nextChange) spanEndStyle += " " + endStyles[j] + if (collapsed && (collapsed.from || 0) == pos) { buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos, collapsed.marker, collapsed.from == null); From 8a3e59cb49b05da385639c350858c2a2a07e60c1 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 21 Dec 2015 11:30:25 +0100 Subject: [PATCH 073/161] Mark release 5.10.0 --- AUTHORS | 11 +++++++++++ doc/compress.html | 1 + doc/manual.html | 2 +- doc/releases.html | 19 ++++++++++++++++--- index.html | 2 +- lib/codemirror.js | 2 +- package.json | 2 +- 7 files changed, 32 insertions(+), 7 deletions(-) diff --git a/AUTHORS b/AUTHORS index 4f060641..830a968c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -105,9 +105,11 @@ Christian Petrov Christopher Brown Christopher Mitchell Christopher Pfohl +Chunliang Lyu ciaranj CodeAnimal coderaiser +Cole R Lawrence ComFreek Curtis Gagliardi dagsta @@ -144,6 +146,7 @@ Doug Wikle Drew Bratcher Drew Hintz Drew Khoury +Drini Cami Dror BG duralog eborden @@ -152,6 +155,7 @@ ekhaled Elisée Enam Mijbah Noor Eric Allam +Erik Welander eustas Fabien O'Carroll Fabio Zendhi Nagao @@ -219,6 +223,7 @@ Jan Jongboom jankeromnes Jan Keromnes Jan Odvarko +Jan Schär Jan T. Sott Jared Forsyth Jason @@ -234,7 +239,9 @@ jeffkenton Jeff Pickhardt jem (graphite) Jeremy Parmenter +Jim JobJob +jochenberger Jochen Berger Johan Ask John Connor @@ -258,6 +265,7 @@ ju1ius Juan Benavides Romero Jucovschi Constantin Juho Vuori +Justin Andresen Justin Hileman jwallers@gmail.com kaniga @@ -337,6 +345,7 @@ Max Kirsch Max Schaefer Max Xiantu mbarkhau +McBrainy melpon Metatheos Micah Dubinko @@ -376,6 +385,7 @@ Nicholas Bollweg Nicholas Bollweg (Nick) Nick Kreeger Nick Small +Nicolò Ribaudo Niels van Groningen nightwing Nikita Beloglazov @@ -492,6 +502,7 @@ Tom MacWright Tony Jian Travis Heppe Triangle717 +TSUYUSATO Kitsune twifkak Vestimir Markov vf diff --git a/doc/compress.html b/doc/compress.html index 74c68347..1f1d0f07 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -36,6 +36,7 @@

    Script compression helper

    Version: + + + + + From 07bcf88d8606b6aa75951862abe504fcf83f64b0 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 29 Dec 2015 09:32:54 +0100 Subject: [PATCH 086/161] [haskell-literate mode] Integrate Issue #3730 --- doc/compress.html | 1 + mode/haskell-literate/haskell-literate.js | 27 ++++++++++++++--------- mode/haskell-literate/index.html | 6 +++++ mode/index.html | 2 +- mode/meta.js | 1 + 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/doc/compress.html b/doc/compress.html index 1f1d0f07..25379782 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -149,6 +149,7 @@

    Script compression helper

    + diff --git a/mode/haskell-literate/haskell-literate.js b/mode/haskell-literate/haskell-literate.js index f50d2fb1..f51e96b6 100644 --- a/mode/haskell-literate/haskell-literate.js +++ b/mode/haskell-literate/haskell-literate.js @@ -9,30 +9,35 @@ else // Plain browser env mod(CodeMirror) })(function (CodeMirror) { - CodeMirror.defineMode("haskell-literate", function (config) { - var haskellMode = CodeMirror.getMode(config, "haskell") + "use strict" + + CodeMirror.defineMode("haskell-literate", function (config, parserConfig) { + var baseMode = CodeMirror.getMode(config, (parserConfig && parserConfig.base) || "haskell") + return { startState: function () { return { - haskellCode: false, - haskellState: CodeMirror.startState(haskellMode) + inCode: false, + baseState: CodeMirror.startState(baseMode) } }, token: function (stream, state) { - if ((stream.sol() && stream.next() == '>') || state.haskellCode) { - state.haskellCode = true - return haskellMode.token(stream, state.haskellState) + if (stream.sol()) { + if (state.inCode = stream.eat(">")) + return "meta" + } + if (state.inCode) { + return baseMode.token(stream, state.baseState) } else { stream.skipToEnd() return "comment" } }, - blankLine: function (state) { - state.haskellCode = false - }, innerMode: function (state) { - return {state: state.haskellState, mode: haskellMode}; + return state.inCode ? {state: state.baseState, mode: baseMode} : null } } }) + + CodeMirror.defineMIME("text/x-literate-haskell", "haskell-literate") }) diff --git a/mode/haskell-literate/index.html b/mode/haskell-literate/index.html index 05172477..8c9bc60d 100644 --- a/mode/haskell-literate/index.html +++ b/mode/haskell-literate/index.html @@ -269,6 +269,12 @@

    Haskell literate mode

    +

    MIME types + defined: text/x-literate-haskell.

    + +

    Parser configuration parameters recognized: base to + set the base mode (defaults to "haskell").

    + diff --git a/mode/index.html b/mode/index.html index 072b89bd..2a159ec5 100644 --- a/mode/index.html +++ b/mode/index.html @@ -68,7 +68,7 @@

    Language modes

  • Groovy
  • HAML
  • Handlebars
  • -
  • Haskell
  • +
  • Haskell (Literate)
  • Haxe
  • HTML embedded (JSP, ASP.NET)
  • HTML mixed-mode
  • diff --git a/mode/meta.js b/mode/meta.js index 69e2a3ef..e4b97360 100644 --- a/mode/meta.js +++ b/mode/meta.js @@ -56,6 +56,7 @@ {name: "Groovy", mime: "text/x-groovy", mode: "groovy", ext: ["groovy"]}, {name: "HAML", mime: "text/x-haml", mode: "haml", ext: ["haml"]}, {name: "Haskell", mime: "text/x-haskell", mode: "haskell", ext: ["hs"]}, + {name: "Haskell (Literate)", mime: "text/x-literate-haskell", mode: "haskell-literate", ext: ["lhs"]}, {name: "Haxe", mime: "text/x-haxe", mode: "haxe", ext: ["hx"]}, {name: "HXML", mime: "text/x-hxml", mode: "haxe", ext: ["hxml"]}, {name: "ASP.NET", mime: "application/x-aspx", mode: "htmlembedded", ext: ["aspx"], alias: ["asp", "aspx"]}, From b3f9487046e37facd64196380ebdd8639efc57b5 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 29 Dec 2015 13:33:29 +0100 Subject: [PATCH 087/161] [jsx mode] Add Closes #3742 Closes #3744 --- doc/compress.html | 2 +- mode/index.html | 2 +- mode/javascript/javascript.js | 16 +++++-- mode/jsx/index.html | 89 +++++++++++++++++++++++++++++++++++ mode/jsx/jsx.js | 85 +++++++++++++++++++++++++++++++++ mode/jsx/test.js | 35 ++++++++++++++ mode/meta.js | 1 + mode/xml/xml.js | 25 ++++++---- test/index.html | 2 + 9 files changed, 243 insertions(+), 14 deletions(-) create mode 100644 mode/jsx/index.html create mode 100644 mode/jsx/jsx.js create mode 100644 mode/jsx/test.js diff --git a/doc/compress.html b/doc/compress.html index 25379782..a79b3097 100644 --- a/doc/compress.html +++ b/doc/compress.html @@ -159,7 +159,7 @@

    Script compression helper

    - + diff --git a/mode/index.html b/mode/index.html index 2a159ec5..a6c293ec 100644 --- a/mode/index.html +++ b/mode/index.html @@ -76,7 +76,7 @@

    Language modes

  • IDL
  • Java
  • Jade
  • -
  • JavaScript
  • +
  • JavaScript (JSX)
  • Jinja2
  • Julia
  • Kotlin
  • diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index d4ae6687..c8515477 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -13,6 +13,11 @@ })(function(CodeMirror) { "use strict"; +function expressionAllowed(stream, state, backUp) { + return /^(?:operator|sof|keyword c|case|new|[\[{}\(,;:])$/.test(state.lastType) || + (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0)))) +} + CodeMirror.defineMode("javascript", function(config, parserConfig) { var indentUnit = config.indentUnit; var statementIndent = parserConfig.statementIndent; @@ -126,8 +131,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } else if (stream.eat("/")) { stream.skipToEnd(); return ret("comment", "comment"); - } else if (/^(?:operator|sof|keyword c|case|new|[\[{}\(,;:])$/.test(state.lastType) || - (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - 1)))) { + } else if (expressionAllowed(stream, state, 1)) { readRegexp(stream); stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/); return ret("regexp", "string-2"); @@ -711,7 +715,13 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { helperType: jsonMode ? "json" : "javascript", jsonldMode: jsonldMode, - jsonMode: jsonMode + jsonMode: jsonMode, + + expressionAllowed: expressionAllowed, + skipExpression: function(state) { + var top = state.cc[state.cc.length - 1] + if (top == expression || top == expressionNoComma) state.cc.pop() + } }; }); diff --git a/mode/jsx/index.html b/mode/jsx/index.html new file mode 100644 index 00000000..cb51edb3 --- /dev/null +++ b/mode/jsx/index.html @@ -0,0 +1,89 @@ + + +CodeMirror: JSX mode + + + + + + + + + + + +
    +

    JSX mode

    + +
    + + + +

    JSX Mode for React's +JavaScript syntax extension.

    + +

    MIME types defined: text/jsx.

    + +
    diff --git a/mode/jsx/jsx.js b/mode/jsx/jsx.js new file mode 100644 index 00000000..c3d227a8 --- /dev/null +++ b/mode/jsx/jsx.js @@ -0,0 +1,85 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript")) + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript"], mod) + else // Plain browser env + mod(CodeMirror) +})(function(CodeMirror) { + "use strict" + + function copyContext(context) { + return {state: CodeMirror.copyState(context.mode, context.state), + mode: context.mode, + depth: context.depth, + prev: context.prev && copyContext(context.prev)} + } + + CodeMirror.defineMode("jsx", function(config) { + var xmlMode = CodeMirror.getMode(config, "xml") + var jsMode = CodeMirror.getMode(config, "javascript") + + return { + startState: function() { + return {context: {state: CodeMirror.startState(jsMode), mode: jsMode}} + }, + + copyState: function(state) { + return {context: copyContext(state.context)} + }, + + token: function(stream, state) { + var cx = state.context + if (cx.mode == xmlMode) { + if (stream.peek() == "{") { + xmlMode.skipAttribute(cx.state) + state.context = {state: CodeMirror.startState(jsMode, xmlMode.indent(cx.state, "")), + mode: jsMode, + depth: 1, + prev: state.context} + return jsMode.token(stream, state.context.state) + } else { // FIXME skip attribute + var style = xmlMode.token(stream, cx.state), cur, brace + if (/\btag\b/.test(style) && !cx.state.context && /^\/?>$/.test(stream.current())) + state.context = state.context.prev + else if (!style && (brace = (cur = stream.current()).indexOf("{")) > -1) + stream.backUp(cur.length - brace) + return style + } + } else { // jsMode + if (stream.peek() == "<" && jsMode.expressionAllowed(stream, cx.state)) { + jsMode.skipExpression(cx.state) + state.context = {state: CodeMirror.startState(xmlMode, jsMode.indent(cx.state, "")), + mode: xmlMode, + prev: state.context} + return xmlMode.token(stream, state.context.state) + } else { + var style = jsMode.token(stream, cx.state) + if (!style && cx.depth != null) { + var cur = stream.current() + if (cur == "{") { + cx.depth++ + } else if (cur == "}") { + if (--cx.depth == 0) state.context = state.context.prev + } + } + return style + } + } + }, + + indent: function(state, textAfter, fullLine) { + return state.context.mode.indent(state.context.state, textAfter, fullLine) + }, + + innerMode: function(state) { + return state.context[state.context.length - 1] + } + } + }, "xml", "javascript") + + CodeMirror.defineMIME("text/jsx", "jsx") +}) diff --git a/mode/jsx/test.js b/mode/jsx/test.js new file mode 100644 index 00000000..63fafb27 --- /dev/null +++ b/mode/jsx/test.js @@ -0,0 +1,35 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +(function() { + var mode = CodeMirror.getMode({indentUnit: 2}, "jsx") + function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)) } + + MT("selfclose", + "[keyword var] [def x] [operator =] [bracket&tag <] [tag foo] [bracket&tag />] [operator +] [number 1];") + + MT("openclose", + "([bracket&tag <][tag foo][bracket&tag >]hello [atom &][bracket&tag ][operator ++])") + + MT("attr", + "([bracket&tag <][tag foo] [attribute abc]=[string 'value'][bracket&tag >]hello [atom &][bracket&tag ][operator ++])") + + MT("braced_attr", + "([bracket&tag <][tag foo] [attribute abc]={[number 10]}[bracket&tag >]hello [atom &][bracket&tag ][operator ++])") + + MT("braced_text", + "([bracket&tag <][tag foo][bracket&tag >]hello {[number 10]} [atom &][bracket&tag ][operator ++])") + + MT("nested_tag", + "([bracket&tag <][tag foo][bracket&tag ><][tag bar][bracket&tag >][operator ++])") + + MT("nested_jsx", + "[keyword return] (", + " [bracket&tag <][tag foo][bracket&tag >]", + " say {[number 1] [operator +] [bracket&tag <][tag bar] [attribute attr]={[number 10]}[bracket&tag />]}!", + " [bracket&tag ][operator ++]", + ")") + + MT("preserve_js_context", + "[variable x] [operator =] [string-2 `quasi${][bracket&tag <][tag foo][bracket&tag />][string-2 }quoted`]") +})() diff --git a/mode/meta.js b/mode/meta.js index e4b97360..49520717 100644 --- a/mode/meta.js +++ b/mode/meta.js @@ -70,6 +70,7 @@ mode: "javascript", ext: ["js"], alias: ["ecmascript", "js", "node"]}, {name: "JSON", mimes: ["application/json", "application/x-json"], mode: "javascript", ext: ["json", "map"], alias: ["json5"]}, {name: "JSON-LD", mime: "application/ld+json", mode: "javascript", ext: ["jsonld"], alias: ["jsonld"]}, + {name: "JSX", mime: "text/jsx", mode: "jsx", ext: ["jsx"]}, {name: "Jinja2", mime: "null", mode: "jinja2"}, {name: "Julia", mime: "text/x-julia", mode: "julia", ext: ["jl"]}, {name: "Kotlin", mime: "text/x-kotlin", mode: "clike", ext: ["kt"]}, diff --git a/mode/xml/xml.js b/mode/xml/xml.js index 5ad21720..92808e14 100644 --- a/mode/xml/xml.js +++ b/mode/xml/xml.js @@ -297,12 +297,14 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { } return { - startState: function() { - return {tokenize: inText, - state: baseState, - indented: 0, - tagName: null, tagStart: null, - context: null}; + startState: function(baseIndent) { + var state = {tokenize: inText, + state: baseState, + indented: baseIndent || 0, + tagName: null, tagStart: null, + context: null} + if (baseIndent != null) state.baseIndent = baseIndent + return state }, token: function(stream, state) { @@ -362,10 +364,10 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { break; } } - while (context && !context.startOfLine) + while (context && context.prev && !context.startOfLine) context = context.prev; if (context) return context.indent + indentUnit; - else return 0; + else return state.baseIndent || 0; }, electricInput: /<\/[\s\w:]+>$/, @@ -373,7 +375,12 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { blockCommentEnd: "-->", configuration: parserConfig.htmlMode ? "html" : "xml", - helperType: parserConfig.htmlMode ? "html" : "xml" + helperType: parserConfig.htmlMode ? "html" : "xml", + + skipAttribute: function(state) { + if (state.state == attrValueState) + state.state = attrState + } }; }); diff --git a/test/index.html b/test/index.html index b0b1fa97..3e227a06 100644 --- a/test/index.html +++ b/test/index.html @@ -23,6 +23,7 @@ + @@ -107,6 +108,7 @@

    Test Suite

    + From b42563cadcfb6a490732090757dae38569ba6068 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 29 Dec 2015 22:16:37 +0100 Subject: [PATCH 088/161] [jsx mode] Support JS comments Issue #3745 --- mode/jsx/jsx.js | 43 +++++++++++++++++++++++++++---------------- mode/jsx/test.js | 9 +++++++++ 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/mode/jsx/jsx.js b/mode/jsx/jsx.js index c3d227a8..ebae7844 100644 --- a/mode/jsx/jsx.js +++ b/mode/jsx/jsx.js @@ -11,11 +11,15 @@ })(function(CodeMirror) { "use strict" + function Context(state, mode, depth, prev) { + this.state = state; this.mode = mode; this.depth = depth; this.prev = prev + } + function copyContext(context) { - return {state: CodeMirror.copyState(context.mode, context.state), - mode: context.mode, - depth: context.depth, - prev: context.prev && copyContext(context.prev)} + return new Context(CodeMirror.copyState(context.mode, context.state), + context.mode, + context.depth, + context.prev && copyContext(context.prev)) } CodeMirror.defineMode("jsx", function(config) { @@ -24,7 +28,7 @@ return { startState: function() { - return {context: {state: CodeMirror.startState(jsMode), mode: jsMode}} + return {context: new Context(CodeMirror.startState(jsMode), jsMode)} }, copyState: function(state) { @@ -34,27 +38,34 @@ token: function(stream, state) { var cx = state.context if (cx.mode == xmlMode) { - if (stream.peek() == "{") { + if (cx.depth) { // Inside a JS /* */ comment + if (stream.match(/^.*?\*\//)) cx.depth = 0 + else stream.skipToEnd() + return "comment" + } else if (stream.peek() == "{") { xmlMode.skipAttribute(cx.state) - state.context = {state: CodeMirror.startState(jsMode, xmlMode.indent(cx.state, "")), - mode: jsMode, - depth: 1, - prev: state.context} + state.context = new Context(CodeMirror.startState(jsMode, xmlMode.indent(cx.state, "")), + jsMode, 1, state.context) return jsMode.token(stream, state.context.state) + } else if (stream.match("//")) { + stream.skipToEnd() + return "comment" + } else if (stream.match("/*")) { + cx.depth = 1 + return this.token(stream, state) } else { // FIXME skip attribute - var style = xmlMode.token(stream, cx.state), cur, brace + var style = xmlMode.token(stream, cx.state), cur, stop if (/\btag\b/.test(style) && !cx.state.context && /^\/?>$/.test(stream.current())) state.context = state.context.prev - else if (!style && (brace = (cur = stream.current()).indexOf("{")) > -1) - stream.backUp(cur.length - brace) + else if (!style && (stop = (cur = stream.current()).search(/\{|\/[*\/]/)) > -1) + stream.backUp(cur.length - stop) return style } } else { // jsMode if (stream.peek() == "<" && jsMode.expressionAllowed(stream, cx.state)) { jsMode.skipExpression(cx.state) - state.context = {state: CodeMirror.startState(xmlMode, jsMode.indent(cx.state, "")), - mode: xmlMode, - prev: state.context} + state.context = new Context(CodeMirror.startState(xmlMode, jsMode.indent(cx.state, "")), + xmlMode, 0, state.context) return xmlMode.token(stream, state.context.state) } else { var style = jsMode.token(stream, cx.state) diff --git a/mode/jsx/test.js b/mode/jsx/test.js index 63fafb27..e45f67cd 100644 --- a/mode/jsx/test.js +++ b/mode/jsx/test.js @@ -32,4 +32,13 @@ MT("preserve_js_context", "[variable x] [operator =] [string-2 `quasi${][bracket&tag <][tag foo][bracket&tag />][string-2 }quoted`]") + + MT("line_comment", + "([bracket&tag <][tag foo][bracket&tag >] [comment // hello]", + " [bracket&tag ][operator ++])") + + MT("block_comment", + "([bracket&tag <][tag foo][bracket&tag >] [comment /* hello]", + "[comment line 2]", + "[comment line 3 */] [bracket&tag ][operator ++])") })() From e8ad6773ba672017a50af029b260eafbc93c5f46 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 29 Dec 2015 22:30:28 +0100 Subject: [PATCH 089/161] [xml mode] Allow more direct access to configuration Use it to enable value-less attributes in the JSX mode Issue #3745 --- mode/jsx/jsx.js | 2 +- mode/jsx/test.js | 4 ++ mode/xml/xml.js | 124 ++++++++++++++++++++++++----------------------- 3 files changed, 68 insertions(+), 62 deletions(-) diff --git a/mode/jsx/jsx.js b/mode/jsx/jsx.js index ebae7844..d38d16c8 100644 --- a/mode/jsx/jsx.js +++ b/mode/jsx/jsx.js @@ -23,7 +23,7 @@ } CodeMirror.defineMode("jsx", function(config) { - var xmlMode = CodeMirror.getMode(config, "xml") + var xmlMode = CodeMirror.getMode(config, {name: "xml", allowMissing: true}) var jsMode = CodeMirror.getMode(config, "javascript") return { diff --git a/mode/jsx/test.js b/mode/jsx/test.js index e45f67cd..c0032a4c 100644 --- a/mode/jsx/test.js +++ b/mode/jsx/test.js @@ -41,4 +41,8 @@ "([bracket&tag <][tag foo][bracket&tag >] [comment /* hello]", "[comment line 2]", "[comment line 3 */] [bracket&tag ][operator ++])") + + MT("missing_attr", + "([bracket&tag <][tag foo] [attribute selected][bracket&tag />][operator ++])") + })() diff --git a/mode/xml/xml.js b/mode/xml/xml.js index 92808e14..014f7d84 100644 --- a/mode/xml/xml.js +++ b/mode/xml/xml.js @@ -11,54 +11,56 @@ })(function(CodeMirror) { "use strict"; -CodeMirror.defineMode("xml", function(config, parserConfig) { - var indentUnit = config.indentUnit; - var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1; - var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag; - if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true; +var htmlConfig = { + autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true, + 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true, + 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true, + 'track': true, 'wbr': true, 'menuitem': true}, + implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true, + 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true, + 'th': true, 'tr': true}, + contextGrabbers: { + 'dd': {'dd': true, 'dt': true}, + 'dt': {'dd': true, 'dt': true}, + 'li': {'li': true}, + 'option': {'option': true, 'optgroup': true}, + 'optgroup': {'optgroup': true}, + 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true, + 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true, + 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true, + 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true, + 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true}, + 'rp': {'rp': true, 'rt': true}, + 'rt': {'rp': true, 'rt': true}, + 'tbody': {'tbody': true, 'tfoot': true}, + 'td': {'td': true, 'th': true}, + 'tfoot': {'tbody': true}, + 'th': {'td': true, 'th': true}, + 'thead': {'tbody': true, 'tfoot': true}, + 'tr': {'tr': true} + }, + doNotIndent: {"pre": true}, + allowUnquoted: true, + allowMissing: true, + caseFold: true +} - var Kludges = parserConfig.htmlMode ? { - autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true, - 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true, - 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true, - 'track': true, 'wbr': true, 'menuitem': true}, - implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true, - 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true, - 'th': true, 'tr': true}, - contextGrabbers: { - 'dd': {'dd': true, 'dt': true}, - 'dt': {'dd': true, 'dt': true}, - 'li': {'li': true}, - 'option': {'option': true, 'optgroup': true}, - 'optgroup': {'optgroup': true}, - 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true, - 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true, - 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true, - 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true, - 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true}, - 'rp': {'rp': true, 'rt': true}, - 'rt': {'rp': true, 'rt': true}, - 'tbody': {'tbody': true, 'tfoot': true}, - 'td': {'td': true, 'th': true}, - 'tfoot': {'tbody': true}, - 'th': {'td': true, 'th': true}, - 'thead': {'tbody': true, 'tfoot': true}, - 'tr': {'tr': true} - }, - doNotIndent: {"pre": true}, - allowUnquoted: true, - allowMissing: true, - caseFold: true - } : { - autoSelfClosers: {}, - implicitlyClosed: {}, - contextGrabbers: {}, - doNotIndent: {}, - allowUnquoted: false, - allowMissing: false, - caseFold: false - }; - var alignCDATA = parserConfig.alignCDATA; +var xmlConfig = { + autoSelfClosers: {}, + implicitlyClosed: {}, + contextGrabbers: {}, + doNotIndent: {}, + allowUnquoted: false, + allowMissing: false, + caseFold: false +} + +CodeMirror.defineMode("xml", function(editorConf, config_) { + var indentUnit = editorConf.indentUnit + var config = {} + var defaults = config_.htmlMode ? htmlConfig : xmlConfig + for (var prop in defaults) config[prop] = defaults[prop] + for (var prop in config_) config[prop] = config_[prop] // Return variables for tokenizers var type, setStyle; @@ -188,7 +190,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { this.tagName = tagName; this.indent = state.indented; this.startOfLine = startOfLine; - if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent)) + if (config.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent)) this.noIndent = true; } function popContext(state) { @@ -201,8 +203,8 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { return; } parentTagName = state.context.tagName; - if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) || - !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) { + if (!config.contextGrabbers.hasOwnProperty(parentTagName) || + !config.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) { return; } popContext(state); @@ -233,7 +235,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { if (type == "word") { var tagName = stream.current(); if (state.context && state.context.tagName != tagName && - Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName)) + config.implicitlyClosed.hasOwnProperty(state.context.tagName)) popContext(state); if (state.context && state.context.tagName == tagName) { setStyle = "tag"; @@ -269,7 +271,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { var tagName = state.tagName, tagStart = state.tagStart; state.tagName = state.tagStart = null; if (type == "selfcloseTag" || - Kludges.autoSelfClosers.hasOwnProperty(tagName)) { + config.autoSelfClosers.hasOwnProperty(tagName)) { maybePopContext(state, tagName); } else { maybePopContext(state, tagName); @@ -282,12 +284,12 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { } function attrEqState(type, stream, state) { if (type == "equals") return attrValueState; - if (!Kludges.allowMissing) setStyle = "error"; + if (!config.allowMissing) setStyle = "error"; return attrState(type, stream, state); } function attrValueState(type, stream, state) { if (type == "string") return attrContinuedState; - if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;} + if (type == "word" && config.allowUnquoted) {setStyle = "string"; return attrState;} setStyle = "error"; return attrState(type, stream, state); } @@ -337,19 +339,19 @@ CodeMirror.defineMode("xml", function(config, parserConfig) { return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0; // Indent the starts of attribute names. if (state.tagName) { - if (multilineTagIndentPastTag) + if (config.multilineTagIndentPastTag !== false) return state.tagStart + state.tagName.length + 2; else - return state.tagStart + indentUnit * multilineTagIndentFactor; + return state.tagStart + indentUnit * (config.multilineTagIndentFactor || 1); } - if (alignCDATA && /", - configuration: parserConfig.htmlMode ? "html" : "xml", - helperType: parserConfig.htmlMode ? "html" : "xml", + configuration: config.htmlMode ? "html" : "xml", + helperType: config.htmlMode ? "html" : "xml", skipAttribute: function(state) { if (state.state == attrValueState) From e3dc9731678b2f4b33b5faf9ffb90332d3c97c96 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 29 Dec 2015 22:49:02 +0100 Subject: [PATCH 090/161] [jsx mode] Improve indentation of nested JavaScript Kludge the xml indentation to ignore inside-tag positions, and properly set start indentation state in javascript mode. Issue #3745 --- mode/javascript/javascript.js | 2 +- mode/jsx/jsx.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index c8515477..ee6e4016 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -659,7 +659,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), localVars: parserConfig.localVars, context: parserConfig.localVars && {vars: parserConfig.localVars}, - indented: 0 + indented: basecolumn || 0 }; if (parserConfig.globalVars && typeof parserConfig.globalVars == "object") state.globalVars = parserConfig.globalVars; diff --git a/mode/jsx/jsx.js b/mode/jsx/jsx.js index d38d16c8..ccf2ee74 100644 --- a/mode/jsx/jsx.js +++ b/mode/jsx/jsx.js @@ -44,8 +44,11 @@ return "comment" } else if (stream.peek() == "{") { xmlMode.skipAttribute(cx.state) + var tagName = cx.state.tagName + cx.state.tagName = null state.context = new Context(CodeMirror.startState(jsMode, xmlMode.indent(cx.state, "")), jsMode, 1, state.context) + cx.state.tagName = tagName return jsMode.token(stream, state.context.state) } else if (stream.match("//")) { stream.skipToEnd() @@ -87,7 +90,7 @@ }, innerMode: function(state) { - return state.context[state.context.length - 1] + return state.context } } }, "xml", "javascript") From d103ebfc453193406d3d01c8fbf638cadd00793d Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 29 Dec 2015 22:54:28 +0100 Subject: [PATCH 091/161] [jsx mode] Add test case for spread syntax --- mode/jsx/test.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mode/jsx/test.js b/mode/jsx/test.js index c0032a4c..1d2fe498 100644 --- a/mode/jsx/test.js +++ b/mode/jsx/test.js @@ -44,5 +44,14 @@ MT("missing_attr", "([bracket&tag <][tag foo] [attribute selected][bracket&tag />][operator ++])") - + + MT("indent_js", + "([bracket&tag <][tag foo][bracket&tag >]", + " [bracket&tag <][tag bar] [attribute baz]={[keyword function]() {", + " [keyword return] [number 10]", + " }}[bracket&tag />]", + " [bracket&tag ])") + + MT("spread", + "([bracket&tag <][tag foo] [attribute bar]={[meta ...][variable baz] [operator /][number 2]}[bracket&tag />])") })() From bec6669991a226de6c8b8f6046f2296ac346b68c Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 30 Dec 2015 11:52:33 +0100 Subject: [PATCH 092/161] [jsx mode] Only recognize comments inside of tags Issue #3745 --- mode/jsx/jsx.js | 35 ++++++++++++++++++++++------------- mode/jsx/test.js | 17 +++++++++++++---- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/mode/jsx/jsx.js b/mode/jsx/jsx.js index ccf2ee74..6b7b6c24 100644 --- a/mode/jsx/jsx.js +++ b/mode/jsx/jsx.js @@ -11,6 +11,9 @@ })(function(CodeMirror) { "use strict" + // Depth means the amount of open braces in JS context, in XML + // context 0 means not in tag, 1 means in tag, and 2 means in tag + // and js block comment. function Context(state, mode, depth, prev) { this.state = state; this.mode = mode; this.depth = depth; this.prev = prev } @@ -23,7 +26,7 @@ } CodeMirror.defineMode("jsx", function(config) { - var xmlMode = CodeMirror.getMode(config, {name: "xml", allowMissing: true}) + var xmlMode = CodeMirror.getMode(config, {name: "xml", allowMissing: true, multilineTagIndentPastTag: false}) var jsMode = CodeMirror.getMode(config, "javascript") return { @@ -38,8 +41,8 @@ token: function(stream, state) { var cx = state.context if (cx.mode == xmlMode) { - if (cx.depth) { // Inside a JS /* */ comment - if (stream.match(/^.*?\*\//)) cx.depth = 0 + if (cx.depth == 2) { // Inside a JS /* */ comment + if (stream.match(/^.*?\*\//)) cx.depth = 1 else stream.skipToEnd() return "comment" } else if (stream.peek() == "{") { @@ -47,21 +50,27 @@ var tagName = cx.state.tagName cx.state.tagName = null state.context = new Context(CodeMirror.startState(jsMode, xmlMode.indent(cx.state, "")), - jsMode, 1, state.context) + jsMode, 0, state.context) cx.state.tagName = tagName - return jsMode.token(stream, state.context.state) - } else if (stream.match("//")) { + return this.token(stream, state) + } else if (cx.depth == 1 && stream.match("//")) { stream.skipToEnd() return "comment" - } else if (stream.match("/*")) { - cx.depth = 1 + } else if (cx.depth == 1 && stream.match("/*")) { + cx.depth = 2 return this.token(stream, state) } else { // FIXME skip attribute - var style = xmlMode.token(stream, cx.state), cur, stop - if (/\btag\b/.test(style) && !cx.state.context && /^\/?>$/.test(stream.current())) - state.context = state.context.prev - else if (!style && (stop = (cur = stream.current()).search(/\{|\/[*\/]/)) > -1) + var style = xmlMode.token(stream, cx.state), cur = stream.current(), stop + if (/\btag\b/.test(style)) { + if (/>$/.test(cur)) { + if (cx.state.context) cx.depth = 0 + else state.context = state.context.prev + } else if (/^ -1) { stream.backUp(cur.length - stop) + } return style } } else { // jsMode @@ -69,7 +78,7 @@ jsMode.skipExpression(cx.state) state.context = new Context(CodeMirror.startState(xmlMode, jsMode.indent(cx.state, "")), xmlMode, 0, state.context) - return xmlMode.token(stream, state.context.state) + return this.token(stream, state) } else { var style = jsMode.token(stream, cx.state) if (!style && cx.depth != null) { diff --git a/mode/jsx/test.js b/mode/jsx/test.js index 1d2fe498..ee601651 100644 --- a/mode/jsx/test.js +++ b/mode/jsx/test.js @@ -34,13 +34,22 @@ "[variable x] [operator =] [string-2 `quasi${][bracket&tag <][tag foo][bracket&tag />][string-2 }quoted`]") MT("line_comment", - "([bracket&tag <][tag foo][bracket&tag >] [comment // hello]", + "([bracket&tag <][tag foo] [comment // hello]", + " [bracket&tag >][operator ++])") + + MT("line_comment_not_in_tag", + "([bracket&tag <][tag foo][bracket&tag >] // hello", " [bracket&tag ][operator ++])") MT("block_comment", - "([bracket&tag <][tag foo][bracket&tag >] [comment /* hello]", - "[comment line 2]", - "[comment line 3 */] [bracket&tag ][operator ++])") + "([bracket&tag <][tag foo] [comment /* hello]", + "[comment line 2]", + "[comment line 3 */] [bracket&tag >][operator ++])") + + MT("block_comment_not_in_tag", + "([bracket&tag <][tag foo][bracket&tag >]/* hello", + " line 2", + " line 3 */ [bracket&tag ][operator ++])") MT("missing_attr", "([bracket&tag <][tag foo] [attribute selected][bracket&tag />][operator ++])") From 8870302a3f2efec00e68d32f6a9d5af959210241 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 30 Dec 2015 12:02:21 +0100 Subject: [PATCH 093/161] [jsx mode] Support tag attributes Issue #3745 --- mode/jsx/jsx.js | 134 ++++++++++++++++++++++++++++------------------- mode/jsx/test.js | 3 ++ 2 files changed, 82 insertions(+), 55 deletions(-) diff --git a/mode/jsx/jsx.js b/mode/jsx/jsx.js index 6b7b6c24..5f6afc18 100644 --- a/mode/jsx/jsx.js +++ b/mode/jsx/jsx.js @@ -29,6 +29,84 @@ var xmlMode = CodeMirror.getMode(config, {name: "xml", allowMissing: true, multilineTagIndentPastTag: false}) var jsMode = CodeMirror.getMode(config, "javascript") + function flatXMLIndent(state) { + var tagName = state.tagName + state.tagName = null + var result = xmlMode.indent(state, "") + state.tagName = tagName + return result + } + + function token(stream, state) { + if (state.context.mode == xmlMode) + return xmlToken(stream, state, state.context) + else + return jsToken(stream, state, state.context) + } + + function xmlToken(stream, state, cx) { + if (cx.depth == 2) { // Inside a JS /* */ comment + if (stream.match(/^.*?\*\//)) cx.depth = 1 + else stream.skipToEnd() + return "comment" + } + + if (stream.peek() == "{") { + xmlMode.skipAttribute(cx.state) + state.context = new Context(CodeMirror.startState(jsMode, flatXMLIndent(cx.state)), + jsMode, 0, state.context) + return token(stream, state) + } + + if (cx.depth == 1) { // Inside of tag + if (stream.peek() == "<") { // Tag inside of tag + xmlMode.skipAttribute(cx.state) + state.context = new Context(CodeMirror.startState(xmlMode, flatXMLIndent(cx.state)), + xmlMode, 0, state.context) + return token(stream, state) + } else if (stream.match("//")) { + stream.skipToEnd() + return "comment" + } else if (stream.match("/*")) { + cx.depth = 2 + return token(stream, state) + } + } + + var style = xmlMode.token(stream, cx.state), cur = stream.current(), stop + if (/\btag\b/.test(style)) { + if (/>$/.test(cur)) { + if (cx.state.context) cx.depth = 0 + else state.context = state.context.prev + } else if (/^ -1) { + stream.backUp(cur.length - stop) + } + return style + } + + function jsToken(stream, state, cx) { + if (stream.peek() == "<" && jsMode.expressionAllowed(stream, cx.state)) { + jsMode.skipExpression(cx.state) + state.context = new Context(CodeMirror.startState(xmlMode, jsMode.indent(cx.state, "")), + xmlMode, 0, state.context) + return token(stream, state) + } + + var style = jsMode.token(stream, cx.state) + if (!style && cx.depth != null) { + var cur = stream.current() + if (cur == "{") { + cx.depth++ + } else if (cur == "}") { + if (--cx.depth == 0) state.context = state.context.prev + } + } + return style + } + return { startState: function() { return {context: new Context(CodeMirror.startState(jsMode), jsMode)} @@ -38,61 +116,7 @@ return {context: copyContext(state.context)} }, - token: function(stream, state) { - var cx = state.context - if (cx.mode == xmlMode) { - if (cx.depth == 2) { // Inside a JS /* */ comment - if (stream.match(/^.*?\*\//)) cx.depth = 1 - else stream.skipToEnd() - return "comment" - } else if (stream.peek() == "{") { - xmlMode.skipAttribute(cx.state) - var tagName = cx.state.tagName - cx.state.tagName = null - state.context = new Context(CodeMirror.startState(jsMode, xmlMode.indent(cx.state, "")), - jsMode, 0, state.context) - cx.state.tagName = tagName - return this.token(stream, state) - } else if (cx.depth == 1 && stream.match("//")) { - stream.skipToEnd() - return "comment" - } else if (cx.depth == 1 && stream.match("/*")) { - cx.depth = 2 - return this.token(stream, state) - } else { // FIXME skip attribute - var style = xmlMode.token(stream, cx.state), cur = stream.current(), stop - if (/\btag\b/.test(style)) { - if (/>$/.test(cur)) { - if (cx.state.context) cx.depth = 0 - else state.context = state.context.prev - } else if (/^ -1) { - stream.backUp(cur.length - stop) - } - return style - } - } else { // jsMode - if (stream.peek() == "<" && jsMode.expressionAllowed(stream, cx.state)) { - jsMode.skipExpression(cx.state) - state.context = new Context(CodeMirror.startState(xmlMode, jsMode.indent(cx.state, "")), - xmlMode, 0, state.context) - return this.token(stream, state) - } else { - var style = jsMode.token(stream, cx.state) - if (!style && cx.depth != null) { - var cur = stream.current() - if (cur == "{") { - cx.depth++ - } else if (cur == "}") { - if (--cx.depth == 0) state.context = state.context.prev - } - } - return style - } - } - }, + token: token, indent: function(state, textAfter, fullLine) { return state.context.mode.indent(state.context.state, textAfter, fullLine) diff --git a/mode/jsx/test.js b/mode/jsx/test.js index ee601651..0ea99017 100644 --- a/mode/jsx/test.js +++ b/mode/jsx/test.js @@ -63,4 +63,7 @@ MT("spread", "([bracket&tag <][tag foo] [attribute bar]={[meta ...][variable baz] [operator /][number 2]}[bracket&tag />])") + + MT("tag_attribute", + "([bracket&tag <][tag foo] [attribute bar]=[bracket&tag <][tag foo][bracket&tag />/>][operator ++])") })() From 78aba6492cb31e1b3ab680af47896e1a0b8a2156 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 30 Dec 2015 12:09:05 +0100 Subject: [PATCH 094/161] [javascript mode] Allow expressions after fat arrow Issue #3745 --- mode/javascript/javascript.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index ee6e4016..f4e7ed6d 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -14,7 +14,7 @@ "use strict"; function expressionAllowed(stream, state, backUp) { - return /^(?:operator|sof|keyword c|case|new|[\[{}\(,;:])$/.test(state.lastType) || + return /^(?:operator|sof|keyword c|case|new|[\[{}\(,;:]|=>)$/.test(state.lastType) || (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0)))) } From 5c53fe7c7f97147650bac3f20c1518a7b5cdd16e Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 30 Dec 2015 14:09:47 +0100 Subject: [PATCH 095/161] [nginx mode] Fix MIME declaration Closes #3746 --- mode/nginx/nginx.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode/nginx/nginx.js b/mode/nginx/nginx.js index 135b9cc7..00a32249 100644 --- a/mode/nginx/nginx.js +++ b/mode/nginx/nginx.js @@ -173,6 +173,6 @@ CodeMirror.defineMode("nginx", function(config) { }; }); -CodeMirror.defineMIME("text/nginx", "text/x-nginx-conf"); +CodeMirror.defineMIME("text/x-nginx-conf", "nginx"); }); From 5f228475fd7059c3d712da96c441496fccd25081 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 4 Jan 2016 10:34:49 +0100 Subject: [PATCH 096/161] Signal touchstart event, signal mousedown even during touch Issue #3736 --- doc/manual.html | 3 ++- lib/codemirror.js | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/manual.html b/doc/manual.html index a33b77ae..5087df90 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -653,7 +653,8 @@

    Events

    should not try to change the state of the editor.
    "mousedown", - "dblclick", "contextmenu", "keydown", "keypress", + "dblclick", "touchstart", "contextmenu", + "keydown", "keypress", "keyup", "cut", "copy", "paste", "dragstart", "dragenter", "dragover", "drop" diff --git a/lib/codemirror.js b/lib/codemirror.js index c4f5a000..55412ae7 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3435,7 +3435,7 @@ return dx * dx + dy * dy > 20 * 20; } on(d.scroller, "touchstart", function(e) { - if (!isMouseLikeTouchEvent(e)) { + if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e)) { clearTimeout(touchFinished); var now = +new Date; d.activeTouch = {start: now, moved: false, @@ -3564,7 +3564,7 @@ // not interfere with, such as a scrollbar or widget. function onMouseDown(e) { var cm = this, display = cm.display; - if (display.activeTouch && display.input.supportsTouch() || signalDOMEvent(cm, e)) return; + if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) return; display.shift = e.shiftKey; if (eventInWidget(display, e)) { From 0d73c4bf947efccfb43b534ca2f78c513f43cdb5 Mon Sep 17 00:00:00 2001 From: Devin Abbott Date: Wed, 30 Dec 2015 12:35:43 -0800 Subject: [PATCH 097/161] [javascript mode] Allow trailing comma in object destructure Issue #3745 --- mode/javascript/javascript.js | 1 + mode/javascript/test.js | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/mode/javascript/javascript.js b/mode/javascript/javascript.js index f4e7ed6d..fa5721d5 100644 --- a/mode/javascript/javascript.js +++ b/mode/javascript/javascript.js @@ -537,6 +537,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } if (type == "variable") cx.marked = "property"; if (type == "spread") return cont(pattern); + if (type == "}") return pass(); return cont(expect(":"), pattern, maybeAssign); } function maybeAssign(_type, value) { diff --git a/mode/javascript/test.js b/mode/javascript/test.js index 252e064d..cb43d089 100644 --- a/mode/javascript/test.js +++ b/mode/javascript/test.js @@ -17,6 +17,10 @@ " [[[variable-2 c], [variable y] ]] [operator =] [variable-2 c];", "})();"); + MT("destructure_trailing_comma", + "[keyword let] {[def a], [def b],} [operator =] [variable foo];", + "[keyword let] [def c];"); // Parser still in good state? + MT("class_body", "[keyword class] [def Foo] {", " [property constructor]() {}", From 65950ad0acb3d3014077d9bfe0defc8bd468b11c Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 4 Jan 2016 10:45:34 +0100 Subject: [PATCH 098/161] [jsx mode] Return empty token when switching inner modes So that addModeClass sees the right mode for the token Issue #3745 --- mode/jsx/jsx.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mode/jsx/jsx.js b/mode/jsx/jsx.js index 5f6afc18..af0e2633 100644 --- a/mode/jsx/jsx.js +++ b/mode/jsx/jsx.js @@ -55,7 +55,7 @@ xmlMode.skipAttribute(cx.state) state.context = new Context(CodeMirror.startState(jsMode, flatXMLIndent(cx.state)), jsMode, 0, state.context) - return token(stream, state) + return null } if (cx.depth == 1) { // Inside of tag @@ -63,7 +63,7 @@ xmlMode.skipAttribute(cx.state) state.context = new Context(CodeMirror.startState(xmlMode, flatXMLIndent(cx.state)), xmlMode, 0, state.context) - return token(stream, state) + return null } else if (stream.match("//")) { stream.skipToEnd() return "comment" @@ -92,7 +92,7 @@ jsMode.skipExpression(cx.state) state.context = new Context(CodeMirror.startState(xmlMode, jsMode.indent(cx.state, "")), xmlMode, 0, state.context) - return token(stream, state) + return null } var style = jsMode.token(stream, cx.state) From 8f2149c2d5861842883f078003d055546951aec4 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 4 Jan 2016 11:03:46 +0100 Subject: [PATCH 099/161] Draw bookmarks next to a collapsed span See https://discuss.codemirror.net/t/inserting-a-boomark-immediately-before-a-textmarker/590/1 --- lib/codemirror.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/codemirror.js b/lib/codemirror.js index 55412ae7..aa5664a1 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -7115,14 +7115,14 @@ if (endStyles) for (var j = 0; j < endStyles.length; j += 2) if (endStyles[j + 1] == nextChange) spanEndStyle += " " + endStyles[j] + if (!collapsed || collapsed.from == pos) for (var j = 0; j < foundBookmarks.length; ++j) + buildCollapsedSpan(builder, 0, foundBookmarks[j]); if (collapsed && (collapsed.from || 0) == pos) { buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos, collapsed.marker, collapsed.from == null); if (collapsed.to == null) return; if (collapsed.to == pos) collapsed = false; } - if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j) - buildCollapsedSpan(builder, 0, foundBookmarks[j]); } if (pos >= len) break; From f923adb268043880178ab17dcaeaeacaf5d5fdd5 Mon Sep 17 00:00:00 2001 From: Will Dean Date: Fri, 1 Jan 2016 11:50:16 +0000 Subject: [PATCH 100/161] Various HTML cleanups --- demo/btree.html | 4 +--- demo/tern.html | 4 ++-- demo/xmlcomplete.html | 4 ++-- doc/internals.html | 3 ++- doc/manual.html | 4 ++-- doc/releases.html | 4 ++-- mode/asn.1/index.html | 3 +-- mode/handlebars/index.html | 5 ++--- mode/mumps/index.html | 4 ++-- mode/nginx/index.html | 4 ++-- mode/pig/index.html | 4 +--- mode/tiki/tiki.css | 2 +- 12 files changed, 20 insertions(+), 25 deletions(-) diff --git a/demo/btree.html b/demo/btree.html index fc4997f4..ba07bc74 100644 --- a/demo/btree.html +++ b/demo/btree.html @@ -1,4 +1,4 @@ - + CodeMirror: B-Tree visualization @@ -26,9 +26,7 @@

    B-Tree visualization

    -
    - - - +

    Handlebars syntax highlighting for CodeMirror.

    MIME types defined: text/x-handlebars-template

    diff --git a/mode/mumps/index.html b/mode/mumps/index.html index bd1f69ae..b1f92c21 100644 --- a/mode/mumps/index.html +++ b/mode/mumps/index.html @@ -1,4 +1,4 @@ - + CodeMirror: MUMPS mode @@ -73,7 +73,7 @@

    MUMPS mode

    IF '$LENGTH($PIECE(XUSER(1),U,2)) QUIT 21 ;p419, p434 Q 0 ; - + + +