Lazy Mode Loading Demo
+Current mode: text/plain
-+
Filename, mime, or mode name:
diff --git a/.gitignore b/.gitignore index b471fe6e63..b720b9be07 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ test.html .tern-* *~ *.swp +.idea +*.iml diff --git a/AUTHORS b/AUTHORS index 362fd94a7e..5d0740fe9d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -2,6 +2,7 @@ List of CodeMirror contributors. Updated before every release. 4r2r Aaron Brooks +Abdelouahab Abe Fettig Adam Ahmed Adam King @@ -61,6 +62,7 @@ Billy Moon binny B Krishna Chaitanya Blaine G +blukat29 boomyjee borawjm Brandon Frohs @@ -76,6 +78,7 @@ Chris Coyier Chris Granger Chris Houseknecht Chris Morgan +Christian Oyarzun Christopher Brown ciaranj CodeAnimal @@ -99,6 +102,7 @@ David Pathakjee deebugger Deep Thought dignifiedquire +Dimage Sapelkin domagoj412 Dominator008 Domizio Demichelis @@ -147,6 +151,7 @@ Hakan Tunc Hans Engel Hardest Hasan Karahan +Herculano Campos Hiroyuki Makino hitsthings Hocdoc @@ -190,6 +195,7 @@ John Van Der Loo Jonathan Malmaud jongalloway Jon Malmaud +Jon Sangster Joost-Wim Boekesteijn Joseph Pecoraro Joshua Newman @@ -199,6 +205,7 @@ jsoojeon Juan Benavides Romero Jucovschi Constantin Juho Vuori +Justin Hileman jwallers@gmail.com kaniga Ken Newman @@ -215,6 +222,7 @@ Lanny Laszlo Vidacs leaf corcoran Leonid Khachaturov +Leon Sorokin Leonya Khachaturov Liam Newman LM @@ -232,6 +240,7 @@ Marco Aurélio Marco Munizaga Marcus Bointon Marijn Haverbeke +Mário Gonçalves Mario Pietsch Mark Lentczner Marko Bonaci @@ -243,6 +252,7 @@ Mateusz Paprocki Mathias Bynens mats cronqvist Matthew Beale +Matthias Bussonnier Matthias BUSSONNIER Matt McDonald Matt Pass @@ -251,6 +261,7 @@ mauricio Maximilian Hils Maxim Kraev Max Kirsch +Max Xiantu mbarkhau Metatheos Micah Dubinko @@ -283,7 +294,9 @@ Nikita Beloglazov Nikita Vasilyev Nikolay Kostov nilp0inter +Nisarg Jhaveri nlwillia +Norman Rzepka pablo Page Panupong Pasupat @@ -371,6 +384,7 @@ wenli Wesley Wiser William Jamieson William Stein +Willy Wojtek Ptak Xavier Mendez YNH Webdev diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3624a39e2b..47006a17f4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,7 +12,7 @@ Community discussion, questions, and informal bug reporting is done on the ## Submitting bug reports The preferred way to report bugs is to use the -[GitHub issue tracker](http://github.com/marijnh/CodeMirror/issues). Before +[GitHub issue tracker](http://github.com/codemirror/CodeMirror/issues). Before reporting a bug, read these pointers. **Note:** The issue tracker is for *bugs*, not requests for help. Questions @@ -48,7 +48,7 @@ should be asked on the ## Contributing code - Make sure you have a [GitHub Account](https://github.com/signup/free) -- Fork [CodeMirror](https://github.com/marijnh/CodeMirror/) +- Fork [CodeMirror](https://github.com/codemirror/CodeMirror/) ([how to fork a repo](https://help.github.com/articles/fork-a-repo)) - Make your changes - If your changes are easy to test or likely to regress, add tests. diff --git a/README.md b/README.md index 6a0011b6be..42b06f7474 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # CodeMirror -[](https://travis-ci.org/marijnh/CodeMirror) +[](https://travis-ci.org/codemirror/CodeMirror) [](https://www.npmjs.org/package/codemirror) CodeMirror is a JavaScript component that provides a code editor in @@ -8,4 +8,4 @@ in, it will color your code, and optionally help with indentation. The project page is http://codemirror.net The manual is at http://codemirror.net/doc/manual.html -The contributing guidelines are in [CONTRIBUTING.md](https://github.com/marijnh/CodeMirror/blob/master/CONTRIBUTING.md) +The contributing guidelines are in [CONTRIBUTING.md](https://github.com/codemirror/CodeMirror/blob/master/CONTRIBUTING.md) diff --git a/addon/comment/comment.js b/addon/comment/comment.js index d7f569cc00..2dd114d332 100644 --- a/addon/comment/comment.js +++ b/addon/comment/comment.js @@ -109,7 +109,7 @@ CodeMirror.defineExtension("uncomment", function(from, to, options) { if (!options) options = noOptions; var self = this, mode = self.getModeAt(from); - var end = Math.min(to.line, self.lastLine()), start = Math.min(from.line, end); + var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end); // Try finding line comments var lineString = options.lineComment || mode.lineComment, lines = []; diff --git a/addon/dialog/dialog.js b/addon/dialog/dialog.js index 35a6103c2d..5a88d99e64 100644 --- a/addon/dialog/dialog.js +++ b/addon/dialog/dialog.js @@ -56,7 +56,10 @@ var inp = dialog.getElementsByTagName("input")[0], button; if (inp) { - if (options.value) inp.value = options.value; + if (options.value) { + inp.value = options.value; + inp.select(); + } if (options.onInput) CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);}); diff --git a/addon/edit/closebrackets.js b/addon/edit/closebrackets.js index 1a04f3664e..32eca014c5 100644 --- a/addon/edit/closebrackets.js +++ b/addon/edit/closebrackets.js @@ -78,24 +78,25 @@ for (var i = 0; i < ranges.length; i++) { var range = ranges[i], cur = range.head, curType; var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1)); - if (!range.empty()) + if (!range.empty()) { curType = "surround"; - else if (left == right && next == right) { + } else if (left == right && next == right) { if (cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == left + left + left) curType = "skipThree"; else curType = "skip"; } else if (left == right && cur.ch > 1 && cm.getRange(Pos(cur.line, cur.ch - 2), cur) == left + left && - (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != left)) + (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != left)) { curType = "addFour"; - else if (left == '"' || left == "'") { + } else if (left == '"' || left == "'") { if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, left)) curType = "both"; else return CodeMirror.Pass; - } else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next)) + } else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next)) { curType = "both"; - else + } else { return CodeMirror.Pass; + } if (!type) type = curType; else if (type != curType) return CodeMirror.Pass; } diff --git a/addon/edit/continuelist.js b/addon/edit/continuelist.js index 8cee761aee..9ad0a98fa0 100644 --- a/addon/edit/continuelist.js +++ b/addon/edit/continuelist.js @@ -11,7 +11,8 @@ })(function(CodeMirror) { "use strict"; - var listRE = /^(\s*)([*+-]|(\d+)\.)(\s+)/, + var listRE = /^(\s*)([> ]+|[*+-]|(\d+)\.)(\s+)/, + emptyListRE = /^(\s*)([> ]+|[*+-]|(\d+)\.)(\s*)$/, unorderedBullets = "*+-"; CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) { @@ -19,18 +20,30 @@ var ranges = cm.listSelections(), replacements = []; for (var i = 0; i < ranges.length; i++) { var pos = ranges[i].head, match; - var inList = cm.getStateAfter(pos.line).list !== false; + var eolState = cm.getStateAfter(pos.line); + var inList = eolState.list !== false; + var inQuote = eolState.quote !== false; - if (!ranges[i].empty() || !inList || !(match = cm.getLine(pos.line).match(listRE))) { + if (!ranges[i].empty() || (!inList && !inQuote) || !(match = cm.getLine(pos.line).match(listRE))) { cm.execCommand("newlineAndIndent"); return; } - var indent = match[1], after = match[4]; - var bullet = unorderedBullets.indexOf(match[2]) >= 0 - ? match[2] - : (parseInt(match[3], 10) + 1) + "."; + if (cm.getLine(pos.line).match(emptyListRE)) { + cm.replaceRange("", { + line: pos.line, ch: 0 + }, { + line: pos.line, ch: pos.ch + 1 + }); + replacements[i] = "\n"; - replacements[i] = "\n" + indent + bullet + after; + } else { + var indent = match[1], after = match[4]; + var bullet = unorderedBullets.indexOf(match[2]) >= 0 || match[2].indexOf(">") >= 0 + ? match[2] + : (parseInt(match[3], 10) + 1) + "."; + + replacements[i] = "\n" + indent + bullet + after; + } } cm.replaceSelections(replacements); diff --git a/addon/hint/sql-hint.js b/addon/hint/sql-hint.js index 20653b5318..c2b511fa2f 100644 --- a/addon/hint/sql-hint.js +++ b/addon/hint/sql-hint.js @@ -12,6 +12,7 @@ "use strict"; var tables; + var defaultTable; var keywords; var CONS = { QUERY_DIV: ";", @@ -43,18 +44,55 @@ } } - function columnCompletion(result, editor) { + function nameCompletion(result, editor) { var cur = editor.getCursor(); var token = editor.getTokenAt(cur); + var useBacktick = (token.string.charAt(0) == "`"); var string = token.string.substr(1); - var prevCur = Pos(cur.line, token.start); - var table = editor.getTokenAt(prevCur).string; - if (!tables.hasOwnProperty(table)) - table = findTableByAlias(table, editor); - var columns = tables[table]; - if (!columns) return; - - addMatches(result, string, columns, function(w) {return "." + w;}); + var prevToken = editor.getTokenAt(Pos(cur.line, token.start)); + if (token.string.charAt(0) == "." || prevToken.string == "."){ + //Suggest colunm names + if (prevToken.string == ".") { + var prevToken = editor.getTokenAt(Pos(cur.line, token.start - 1)); + } + var table = prevToken.string; + //Check if backtick is used in table name. If yes, use it for columns too. + var useBacktickTable = false; + if (table.match(/`/g)) { + useBacktickTable = true; + table = table.replace(/`/g, ""); + } + //Check if table is available. If not, find table by Alias + if (!tables.hasOwnProperty(table)) + table = findTableByAlias(table, editor); + var columns = tables[table]; + if (!columns) return; + + if (useBacktick) { + addMatches(result, string, columns, function(w) {return "`" + w + "`";}); + } + else if(useBacktickTable) { + addMatches(result, string, columns, function(w) {return ".`" + w + "`";}); + } + else { + addMatches(result, string, columns, function(w) {return "." + w;}); + } + } + else { + //Suggest table names or colums in defaultTable + while (token.start && string.charAt(0) == ".") { + token = editor.getTokenAt(Pos(cur.line, token.start - 1)); + string = token.string + string; + } + if (useBacktick) { + addMatches(result, string, tables, function(w) {return "`" + w + "`";}); + addMatches(result, string, defaultTable, function(w) {return "`" + w + "`";}); + } + else { + addMatches(result, string, tables, function(w) {return w;}); + addMatches(result, string, defaultTable, function(w) {return w;}); + } + } } function eachWord(lineText, f) { @@ -128,11 +166,14 @@ CodeMirror.registerHelper("hint", "sql", function(editor, options) { tables = (options && options.tables) || {}; + var defaultTableName = options && options.defaultTable; + defaultTable = (defaultTableName && tables[defaultTableName] || []); keywords = keywords || getKeywords(editor); + var cur = editor.getCursor(); var result = []; var token = editor.getTokenAt(cur), start, end, search; - if (token.string.match(/^[.\w@]\w*$/)) { + if (token.string.match(/^[.`\w@]\w*$/)) { search = token.string; start = token.start; end = token.end; @@ -140,18 +181,11 @@ start = end = cur.ch; search = ""; } - if (search.charAt(0) == ".") { - columnCompletion(result, editor); - if (!result.length) { - while (start && search.charAt(0) == ".") { - token = editor.getTokenAt(Pos(cur.line, token.start - 1)); - start = token.start; - search = token.string + search; - } - addMatches(result, search, tables, function(w) {return w;}); - } + if (search.charAt(0) == "." || search.charAt(0) == "`") { + nameCompletion(result, editor); } else { addMatches(result, search, tables, function(w) {return w;}); + addMatches(result, search, defaultTable, function(w) {return w;}); addMatches(result, search, keywords, function(w) {return w.toUpperCase();}); } diff --git a/addon/lint/lint.js b/addon/lint/lint.js index a87e70c09e..66f187e22e 100644 --- a/addon/lint/lint.js +++ b/addon/lint/lint.js @@ -118,10 +118,11 @@ function startLinting(cm) { var state = cm.state.lint, options = state.options; + var passOptions = options.options || options; // Support deprecated passing of `options` property in options if (options.async) - options.getAnnotations(cm, updateLinting, options); + options.getAnnotations(cm.getValue(), updateLinting, passOptions, cm); else - updateLinting(cm, options.getAnnotations(cm.getValue(), options.options)); + updateLinting(cm, options.getAnnotations(cm.getValue(), passOptions, cm)); } function updateLinting(cm, annotationsNotSorted) { @@ -170,20 +171,14 @@ showTooltipFor(e, annotationTooltip(ann), target); } - // When the mouseover fires, the cursor might not actually be over - // the character itself yet. These pairs of x,y offsets are used to - // probe a few nearby points when no suitable marked range is found. - var nearby = [0, 0, 0, 5, 0, -5, 5, 0, -5, 0]; - function onMouseOver(cm, e) { - if (!/\bCodeMirror-lint-mark-/.test((e.target || e.srcElement).className)) return; - for (var i = 0; i < nearby.length; i += 2) { - var spans = cm.findMarksAt(cm.coordsChar({left: e.clientX + nearby[i], - top: e.clientY + nearby[i + 1]}, "client")); - for (var j = 0; j < spans.length; ++j) { - var span = spans[j], ann = span.__annotation; - if (ann) return popupSpanTooltip(ann, e); - } + var target = e.target || e.srcElement; + if (!/\bCodeMirror-lint-mark-/.test(target.className)) return; + var box = target.getBoundingClientRect(), x = (box.left + box.right) / 2, y = (box.top + box.bottom) / 2; + var spans = cm.findMarksAt(cm.coordsChar({left: x, top: y}, "client")); + for (var i = 0; i < spans.length; ++i) { + var ann = spans[i].__annotation; + if (ann) return popupSpanTooltip(ann, e); } } diff --git a/addon/mode/simple.js b/addon/mode/simple.js new file mode 100644 index 0000000000..a4a86b9a65 --- /dev/null +++ b/addon/mode/simple.js @@ -0,0 +1,210 @@ +// 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.defineSimpleMode = function(name, states, props) { + CodeMirror.defineMode(name, function(config) { + return CodeMirror.simpleMode(config, states, props); + }); + }; + + CodeMirror.simpleMode = function(config, states) { + ensureState(states, "start"); + var states_ = {}, meta = states.meta || {}, hasIndentation = false; + for (var state in states) if (state != meta && states.hasOwnProperty(state)) { + var list = states_[state] = [], orig = states[state]; + for (var i = 0; i < orig.length; i++) { + var data = orig[i]; + list.push(new Rule(data, states)); + if (data.indent || data.dedent) hasIndentation = true; + } + } + var mode = { + startState: function() { + return {state: "start", pending: null, + local: null, localState: null, + indent: hasIndentation ? [] : null}; + }, + copyState: function(state) { + var s = {state: state.state, pending: state.pending, + local: state.local, localState: null, + indent: state.indent && state.indent.slice(0)}; + if (state.localState) + s.localState = CodeMirror.copyState(state.local.mode, state.localState); + if (state.stack) + s.stack = state.stack.slice(0); + for (var pers = state.persistentStates; pers; pers = pers.next) + s.persistentStates = {mode: pers.mode, + spec: pers.spec, + state: pers.state == state.localState ? s.localState : CodeMirror.copyState(pers.mode, pers.state), + next: s.persistentStates}; + return s; + }, + token: tokenFunction(states_, config), + innerMode: function(state) { return state.local && {mode: state.local.mode, state: state.localState}; }, + indent: indentFunction(states_, meta) + }; + if (meta) for (var prop in meta) if (meta.hasOwnProperty(prop)) + mode[prop] = meta[prop]; + return mode; + }; + + function ensureState(states, name) { + if (!states.hasOwnProperty(name)) + throw new Error("Undefined state " + name + "in simple mode"); + } + + function toRegex(val, caret) { + if (!val) return /(?:)/; + var flags = ""; + if (val instanceof RegExp) { + if (val.ignoreCase) flags = "i"; + val = val.source; + } else { + val = String(val); + } + return new RegExp((caret === false ? "" : "^") + "(?:" + val + ")", flags); + } + + function asToken(val) { + if (!val) return null; + if (typeof val == "string") return val.replace(/\./g, " "); + var result = []; + for (var i = 0; i < val.length; i++) + result.push(val[i] && val[i].replace(/\./g, " ")); + return result; + } + + function Rule(data, states) { + if (data.next || data.push) ensureState(states, data.next || data.push); + this.regex = toRegex(data.regex); + this.token = asToken(data.token); + this.data = data; + } + + function tokenFunction(states, config) { + return function(stream, state) { + if (state.pending) { + var pend = state.pending.shift(); + if (state.pending.length == 0) state.pending = null; + stream.pos += pend.text.length; + return pend.token; + } + + if (state.local) { + if (state.local.end && stream.match(state.local.end)) { + var tok = state.local.endToken || null; + state.local = state.localState = null; + return tok; + } else { + var tok = state.local.mode.token(stream, state.localState), m; + if (state.local.endScan && (m = state.local.endScan.exec(stream.current()))) + stream.pos = stream.start + m.index; + return tok; + } + } + + var curState = states[state.state]; + for (var i = 0; i < curState.length; i++) { + var rule = curState[i]; + var matches = stream.match(rule.regex); + if (matches) { + if (rule.data.next) { + state.state = rule.data.next; + } else if (rule.data.push) { + (state.stack || (state.stack = [])).push(state.state); + state.state = rule.data.push; + } else if (rule.data.pop && state.stack && state.stack.length) { + state.state = state.stack.pop(); + } + + if (rule.data.mode) + enterLocalMode(config, state, rule.data.mode, rule.token); + if (rule.data.indent) + state.indent.push(stream.indentation() + config.indentUnit); + if (rule.data.dedent) + state.indent.pop(); + if (matches.length > 2) { + state.pending = []; + for (var j = 2; j < matches.length; j++) + if (matches[j]) + state.pending.push({text: matches[j], token: rule.token[j - 1]}); + stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0)); + return rule.token[0]; + } else if (rule.token && rule.token.join) { + return rule.token[0]; + } else { + return rule.token; + } + } + } + stream.next(); + return null; + }; + } + + function cmp(a, b) { + if (a === b) return true; + if (!a || typeof a != "object" || !b || typeof b != "object") return false; + var props = 0; + for (var prop in a) if (a.hasOwnProperty(prop)) { + if (!b.hasOwnProperty(prop) || !cmp(a[prop], b[prop])) return false; + props++; + } + for (var prop in b) if (b.hasOwnProperty(prop)) props--; + return props == 0; + } + + function enterLocalMode(config, state, spec, token) { + var pers; + if (spec.persistent) for (var p = state.persistentStates; p && !pers; p = p.next) + if (spec.spec ? cmp(spec.spec, p.spec) : spec.mode == p.mode) pers = p; + var mode = pers ? pers.mode : spec.mode || CodeMirror.getMode(config, spec.spec); + var lState = pers ? pers.state : CodeMirror.startState(mode); + if (spec.persistent && !pers) + state.persistentStates = {mode: mode, spec: spec.spec, state: lState, next: state.persistentStates}; + + state.localState = lState; + state.local = {mode: mode, + end: spec.end && toRegex(spec.end), + endScan: spec.end && spec.forceEnd !== false && toRegex(spec.end, false), + endToken: token && token.join ? token[token.length - 1] : token}; + } + + function indexOf(val, arr) { + for (var i = 0; i < arr.length; i++) if (arr[i] === val) return true; + } + + function indentFunction(states, meta) { + return function(state, textAfter, line) { + if (state.local && state.local.mode.indent) + return state.local.mode.indent(state.localState, textAfter, line); + if (state.indent == null || state.local || meta.dontIndentStates && indexOf(state.state, meta.dontIndentStates) > -1) + return CodeMirror.Pass; + + var pos = state.indent.length - 1, rules = states[state.state]; + scan: for (;;) { + for (var i = 0; i < rules.length; i++) { + var rule = rules[i], m = rule.regex.exec(textAfter); + if (m && m[0]) { + if (rule.data.dedent && rule.data.dedentIfLineStart !== false) pos--; + if (rule.next || rule.push) rules = states[rule.next || rule.push]; + textAfter = textAfter.slice(m[0].length); + continue scan; + } + } + break; + } + return pos < 0 ? 0 : state.indent[pos]; + }; + } +}); diff --git a/addon/runmode/runmode-standalone.js b/addon/runmode/runmode-standalone.js index 0dd0c289b0..f4f352c803 100644 --- a/addon/runmode/runmode-standalone.js +++ b/addon/runmode/runmode-standalone.js @@ -74,7 +74,11 @@ CodeMirror.startState = function (mode, a1, a2) { }; var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {}; -CodeMirror.defineMode = function (name, mode) { modes[name] = mode; }; +CodeMirror.defineMode = function (name, mode) { + if (arguments.length > 2) + mode.dependencies = Array.prototype.slice.call(arguments, 2); + modes[name] = mode; +}; CodeMirror.defineMIME = function (mime, spec) { mimeModes[mime] = spec; }; CodeMirror.resolveMode = function(spec) { if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { diff --git a/addon/runmode/runmode.node.js b/addon/runmode/runmode.node.js index f64b8a152d..8b8140b4c1 100644 --- a/addon/runmode/runmode.node.js +++ b/addon/runmode/runmode.node.js @@ -74,10 +74,8 @@ exports.startState = function(mode, a1, a2) { var modes = exports.modes = {}, mimeModes = exports.mimeModes = {}; exports.defineMode = function(name, mode) { - if (arguments.length > 2) { - mode.dependencies = []; - for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]); - } + if (arguments.length > 2) + mode.dependencies = Array.prototype.slice.call(arguments, 2); modes[name] = mode; }; exports.defineMIME = function(mime, spec) { mimeModes[mime] = spec; }; diff --git a/bower.json b/bower.json index 638b9d0016..81352b6d70 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "codemirror", - "version":"4.6.0", + "version":"4.7.0", "main": ["lib/codemirror.js", "lib/codemirror.css"], "ignore": [ "**/.*", diff --git a/demo/activeline.html b/demo/activeline.html index 14851c35e4..741f6c45a4 100644 --- a/demo/activeline.html +++ b/demo/activeline.html @@ -12,12 +12,12 @@ .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}