Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/phpmyadmin/phpmyadmin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMadhura Jayaratne <madhura.cj@gmail.com>2015-05-20 13:19:40 +0300
committerMadhura Jayaratne <madhura.cj@gmail.com>2015-05-20 13:19:40 +0300
commitf0838d4080e6cfbb3a90b682802119bdd7347bb6 (patch)
tree07d8d2dba4c6cd2db3dab9d7ef25ab998d911ca6 /js/codemirror
parentf2720fa1fc7dc5c0698f2207fbe9f64f7ed95fb6 (diff)
Upgrade CodeMirror to version 5.3.0
Signed-off-by: Madhura Jayaratne <madhura.cj@gmail.com>
Diffstat (limited to 'js/codemirror')
-rw-r--r--js/codemirror/LICENSE2
-rw-r--r--js/codemirror/addon/hint/show-hint.css38
-rw-r--r--js/codemirror/addon/hint/show-hint.js133
-rw-r--r--js/codemirror/addon/hint/sql-hint.js28
-rw-r--r--js/codemirror/lib/codemirror.css325
-rw-r--r--js/codemirror/lib/codemirror.js334
-rw-r--r--js/codemirror/mode/javascript/javascript.js11
-rw-r--r--js/codemirror/mode/sql/sql.js12
8 files changed, 675 insertions, 208 deletions
diff --git a/js/codemirror/LICENSE b/js/codemirror/LICENSE
index d21bbea5a6..f4a5a4a25f 100644
--- a/js/codemirror/LICENSE
+++ b/js/codemirror/LICENSE
@@ -1,4 +1,4 @@
-Copyright (C) 2014 by Marijn Haverbeke <marijnh@gmail.com> and others
+Copyright (C) 2015 by Marijn Haverbeke <marijnh@gmail.com> and others
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/js/codemirror/addon/hint/show-hint.css b/js/codemirror/addon/hint/show-hint.css
new file mode 100644
index 0000000000..924e638f7f
--- /dev/null
+++ b/js/codemirror/addon/hint/show-hint.css
@@ -0,0 +1,38 @@
+.CodeMirror-hints {
+ position: absolute;
+ z-index: 10;
+ overflow: hidden;
+ list-style: none;
+
+ margin: 0;
+ padding: 2px;
+
+ -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+ -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+ box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+ border-radius: 3px;
+ border: 1px solid silver;
+
+ background: white;
+ font-size: 90%;
+ font-family: monospace;
+
+ max-height: 20em;
+ overflow-y: auto;
+}
+
+.CodeMirror-hint {
+ margin: 0;
+ padding: 0 4px;
+ border-radius: 2px;
+ max-width: 19em;
+ overflow: hidden;
+ white-space: pre;
+ color: black;
+ cursor: pointer;
+}
+
+li.CodeMirror-hint-active {
+ background: #08f;
+ color: white;
+}
diff --git a/js/codemirror/addon/hint/show-hint.js b/js/codemirror/addon/hint/show-hint.js
index f544619428..d228fc8890 100644
--- a/js/codemirror/addon/hint/show-hint.js
+++ b/js/codemirror/addon/hint/show-hint.js
@@ -24,44 +24,45 @@
return cm.showHint(newOpts);
};
- var asyncRunID = 0;
- function retrieveHints(getter, cm, options, then) {
- if (getter.async) {
- var id = ++asyncRunID;
- getter(cm, function(hints) {
- if (asyncRunID == id) then(hints);
- }, options);
- } else {
- then(getter(cm, options));
- }
- }
-
CodeMirror.defineExtension("showHint", function(options) {
// We want a single cursor position.
if (this.listSelections().length > 1 || this.somethingSelected()) return;
if (this.state.completionActive) this.state.completionActive.close();
var completion = this.state.completionActive = new Completion(this, options);
- var getHints = completion.options.hint;
- if (!getHints) return;
+ if (!completion.options.hint) return;
CodeMirror.signal(this, "startCompletion", this);
- return retrieveHints(getHints, this, completion.options, function(hints) { completion.showHints(hints); });
+ completion.update(true);
});
function Completion(cm, options) {
this.cm = cm;
this.options = this.buildOptions(options);
- this.widget = this.onClose = null;
+ this.widget = null;
+ this.debounce = 0;
+ this.tick = 0;
+ this.startPos = this.cm.getCursor();
+ this.startLen = this.cm.getLine(this.startPos.line).length;
+
+ var self = this;
+ cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
}
+ var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
+ return setTimeout(fn, 1000/60);
+ };
+ var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
+
Completion.prototype = {
close: function() {
if (!this.active()) return;
this.cm.state.completionActive = null;
+ this.tick = null;
+ this.cm.off("cursorActivity", this.activityFunc);
+ if (this.widget && this.data) CodeMirror.signal(this.data, "close");
if (this.widget) this.widget.close();
- if (this.onClose) this.onClose();
CodeMirror.signal(this.cm, "endCompletion", this.cm);
},
@@ -78,70 +79,50 @@
this.close();
},
- showHints: function(data) {
- if (!data || !data.list.length || !this.active()) return this.close();
-
- if (this.options.completeSingle && data.list.length == 1)
- this.pick(data, 0);
- else
- this.showWidget(data);
- },
-
- showWidget: function(data) {
- this.widget = new Widget(this, data);
- CodeMirror.signal(data, "shown");
-
- var debounce = 0, completion = this, finished;
- var closeOn = this.options.closeCharacters;
- var startPos = this.cm.getCursor(), startLen = this.cm.getLine(startPos.line).length;
-
- var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
- return setTimeout(fn, 1000/60);
- };
- var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
-
- function done() {
- if (finished) return;
- finished = true;
- completion.close();
- completion.cm.off("cursorActivity", activity);
- if (data) CodeMirror.signal(data, "close");
+ cursorActivity: function() {
+ if (this.debounce) {
+ cancelAnimationFrame(this.debounce);
+ this.debounce = 0;
}
- function update() {
- if (finished) return;
- CodeMirror.signal(data, "update");
- retrieveHints(completion.options.hint, completion.cm, completion.options, finishUpdate);
- }
- function finishUpdate(data_) {
- data = data_;
- if (finished) return;
- if (!data || !data.list.length) return done();
- if (completion.widget) completion.widget.close();
- completion.widget = new Widget(completion, data);
+ var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
+ if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
+ pos.ch < this.startPos.ch || this.cm.somethingSelected() ||
+ (pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
+ this.close();
+ } else {
+ var self = this;
+ this.debounce = requestAnimationFrame(function() {self.update();});
+ if (this.widget) this.widget.disable();
}
+ },
- function clearDebounce() {
- if (debounce) {
- cancelAnimationFrame(debounce);
- debounce = 0;
- }
+ update: function(first) {
+ if (this.tick == null) return;
+ if (this.data) CodeMirror.signal(this.data, "update");
+ if (!this.options.hint.async) {
+ this.finishUpdate(this.options.hint(this.cm, this.options), first);
+ } else {
+ var myTick = ++this.tick, self = this;
+ this.options.hint(this.cm, function(data) {
+ if (self.tick == myTick) self.finishUpdate(data, first);
+ }, this.options);
}
+ },
+
+ finishUpdate: function(data, first) {
+ this.data = data;
- function activity() {
- clearDebounce();
- var pos = completion.cm.getCursor(), line = completion.cm.getLine(pos.line);
- if (pos.line != startPos.line || line.length - pos.ch != startLen - startPos.ch ||
- pos.ch < startPos.ch || completion.cm.somethingSelected() ||
- (pos.ch && closeOn.test(line.charAt(pos.ch - 1)))) {
- completion.close();
+ var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
+ if (this.widget) this.widget.close();
+ if (data && data.list.length) {
+ if (picked && data.list.length == 1) {
+ this.pick(data, 0);
} else {
- debounce = requestAnimationFrame(update);
- if (completion.widget) completion.widget.close();
+ this.widget = new Widget(this, data);
+ CodeMirror.signal(data, "shown");
}
}
- this.cm.on("cursorActivity", activity);
- this.onClose = done;
},
buildOptions: function(options) {
@@ -206,6 +187,7 @@
function Widget(completion, data) {
this.completion = completion;
this.data = data;
+ this.picked = false;
var widget = this, cm = completion.cm;
var hints = this.hints = document.createElement("ul");
@@ -320,6 +302,13 @@
cm.off("scroll", this.onScroll);
},
+ disable: function() {
+ this.completion.cm.removeKeyMap(this.keyMap);
+ var widget = this;
+ this.keyMap = {Enter: function() { widget.picked = true; }};
+ this.completion.cm.addKeyMap(this.keyMap);
+ },
+
pick: function() {
this.completion.pick(this.data, this.selectedHint);
},
diff --git a/js/codemirror/addon/hint/sql-hint.js b/js/codemirror/addon/hint/sql-hint.js
index 37937ca9a2..08051ce74f 100644
--- a/js/codemirror/addon/hint/sql-hint.js
+++ b/js/codemirror/addon/hint/sql-hint.js
@@ -52,12 +52,9 @@
function addMatches(result, search, wordlist, formatter) {
for (var word in wordlist) {
if (!wordlist.hasOwnProperty(word)) continue;
- if (Array.isArray(wordlist)) {
- word = wordlist[word];
- }
- if (match(search, word)) {
- result.push(formatter(word));
- }
+ if (wordlist.slice) word = wordlist[word];
+
+ if (match(search, word)) result.push(formatter(word));
}
}
@@ -115,18 +112,25 @@
string = nameParts.pop();
var table = nameParts.join(".");
+ var alias = false;
+ var aliasTable = table;
// Check if table is available. If not, find table by Alias
- if (!getItem(tables, table))
+ if (!getItem(tables, table)) {
+ var oldTable = table;
table = findTableByAlias(table, editor);
+ if (table !== oldTable) alias = true;
+ }
var columns = getItem(tables, table);
- if (columns && Array.isArray(tables) && columns.columns)
+ if (columns && columns.columns)
columns = columns.columns;
if (columns) {
addMatches(result, string, columns, function(w) {
if (typeof w == "string") {
- w = table + "." + w;
+ var tableInsert = table;
+ if (alias == true) tableInsert = aliasTable;
+ w = tableInsert + "." + w;
} else {
w = shallowClone(w);
w.text = table + "." + w.text;
@@ -208,6 +212,7 @@
CodeMirror.registerHelper("hint", "sql", function(editor, options) {
tables = (options && options.tables) || {};
var defaultTableName = options && options.defaultTable;
+ var disableKeywords = options && options.disableKeywords;
defaultTable = defaultTableName && getItem(tables, defaultTableName);
keywords = keywords || getKeywords(editor);
@@ -216,7 +221,7 @@
defaultTable = defaultTable || [];
- if (Array.isArray(tables) && defaultTable.columns)
+ if (defaultTable.columns)
defaultTable = defaultTable.columns;
var cur = editor.getCursor();
@@ -240,7 +245,8 @@
} 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();});
+ if (!disableKeywords)
+ addMatches(result, search, keywords, function(w) {return w.toUpperCase();});
}
return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};
diff --git a/js/codemirror/lib/codemirror.css b/js/codemirror/lib/codemirror.css
new file mode 100644
index 0000000000..ceacd13047
--- /dev/null
+++ b/js/codemirror/lib/codemirror.css
@@ -0,0 +1,325 @@
+/* BASICS */
+
+.CodeMirror {
+ /* Set height, width, borders, and global font properties here */
+ font-family: monospace;
+ height: 300px;
+ color: black;
+}
+
+/* PADDING */
+
+.CodeMirror-lines {
+ padding: 4px 0; /* Vertical padding around content */
+}
+.CodeMirror pre {
+ padding: 0 4px; /* Horizontal padding of content */
+}
+
+.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
+ background-color: white; /* The little square between H and V scrollbars */
+}
+
+/* GUTTER */
+
+.CodeMirror-gutters {
+ border-right: 1px solid #ddd;
+ background-color: #f7f7f7;
+ white-space: nowrap;
+}
+.CodeMirror-linenumbers {}
+.CodeMirror-linenumber {
+ padding: 0 3px 0 5px;
+ min-width: 20px;
+ text-align: right;
+ color: #999;
+ white-space: nowrap;
+}
+
+.CodeMirror-guttermarker { color: black; }
+.CodeMirror-guttermarker-subtle { color: #999; }
+
+/* CURSOR */
+
+.CodeMirror div.CodeMirror-cursor {
+ border-left: 1px solid black;
+}
+/* Shown when moving in bi-directional text */
+.CodeMirror div.CodeMirror-secondarycursor {
+ border-left: 1px solid silver;
+}
+.CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
+ width: auto;
+ border: 0;
+ background: #7e7;
+}
+.CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
+ z-index: 1;
+}
+
+.cm-animate-fat-cursor {
+ width: auto;
+ border: 0;
+ -webkit-animation: blink 1.06s steps(1) infinite;
+ -moz-animation: blink 1.06s steps(1) infinite;
+ animation: blink 1.06s steps(1) infinite;
+}
+@-moz-keyframes blink {
+ 0% { background: #7e7; }
+ 50% { background: none; }
+ 100% { background: #7e7; }
+}
+@-webkit-keyframes blink {
+ 0% { background: #7e7; }
+ 50% { background: none; }
+ 100% { background: #7e7; }
+}
+@keyframes blink {
+ 0% { background: #7e7; }
+ 50% { background: none; }
+ 100% { background: #7e7; }
+}
+
+/* Can style cursor different in overwrite (non-insert) mode */
+div.CodeMirror-overwrite div.CodeMirror-cursor {}
+
+.cm-tab { display: inline-block; text-decoration: inherit; }
+
+.CodeMirror-ruler {
+ border-left: 1px solid #ccc;
+ position: absolute;
+}
+
+/* DEFAULT THEME */
+
+.cm-s-default .cm-keyword {color: #708;}
+.cm-s-default .cm-atom {color: #219;}
+.cm-s-default .cm-number {color: #164;}
+.cm-s-default .cm-def {color: #00f;}
+.cm-s-default .cm-variable,
+.cm-s-default .cm-punctuation,
+.cm-s-default .cm-property,
+.cm-s-default .cm-operator {}
+.cm-s-default .cm-variable-2 {color: #05a;}
+.cm-s-default .cm-variable-3 {color: #085;}
+.cm-s-default .cm-comment {color: #a50;}
+.cm-s-default .cm-string {color: #a11;}
+.cm-s-default .cm-string-2 {color: #f50;}
+.cm-s-default .cm-meta {color: #555;}
+.cm-s-default .cm-qualifier {color: #555;}
+.cm-s-default .cm-builtin {color: #30a;}
+.cm-s-default .cm-bracket {color: #997;}
+.cm-s-default .cm-tag {color: #170;}
+.cm-s-default .cm-attribute {color: #00c;}
+.cm-s-default .cm-header {color: blue;}
+.cm-s-default .cm-quote {color: #090;}
+.cm-s-default .cm-hr {color: #999;}
+.cm-s-default .cm-link {color: #00c;}
+
+.cm-negative {color: #d44;}
+.cm-positive {color: #292;}
+.cm-header, .cm-strong {font-weight: bold;}
+.cm-em {font-style: italic;}
+.cm-link {text-decoration: underline;}
+.cm-strikethrough {text-decoration: line-through;}
+
+.cm-s-default .cm-error {color: #f00;}
+.cm-invalidchar {color: #f00;}
+
+.CodeMirror-composing { border-bottom: 2px solid; }
+
+/* Default styles for common addons */
+
+div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
+div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
+.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
+.CodeMirror-activeline-background {background: #e8f2ff;}
+
+/* STOP */
+
+/* The rest of this file contains styles related to the mechanics of
+ the editor. You probably shouldn't touch them. */
+
+.CodeMirror {
+ position: relative;
+ overflow: hidden;
+ background: white;
+}
+
+.CodeMirror-scroll {
+ overflow: scroll !important; /* Things will break if this is overridden */
+ /* 30px is the magic margin used to hide the element's real scrollbars */
+ /* See overflow: hidden in .CodeMirror */
+ margin-bottom: -30px; margin-right: -30px;
+ padding-bottom: 30px;
+ height: 100%;
+ outline: none; /* Prevent dragging from highlighting the element */
+ position: relative;
+}
+.CodeMirror-sizer {
+ position: relative;
+ border-right: 30px solid transparent;
+}
+
+/* The fake, visible scrollbars. Used to force redraw during scrolling
+ before actuall scrolling happens, thus preventing shaking and
+ flickering artifacts. */
+.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
+ position: absolute;
+ z-index: 6;
+ display: none;
+}
+.CodeMirror-vscrollbar {
+ right: 0; top: 0;
+ overflow-x: hidden;
+ overflow-y: scroll;
+}
+.CodeMirror-hscrollbar {
+ bottom: 0; left: 0;
+ overflow-y: hidden;
+ overflow-x: scroll;
+}
+.CodeMirror-scrollbar-filler {
+ right: 0; bottom: 0;
+}
+.CodeMirror-gutter-filler {
+ left: 0; bottom: 0;
+}
+
+.CodeMirror-gutters {
+ position: absolute; left: 0; top: 0;
+ z-index: 3;
+}
+.CodeMirror-gutter {
+ white-space: normal;
+ height: 100%;
+ display: inline-block;
+ margin-bottom: -30px;
+ /* Hack to make IE7 behave */
+ *zoom:1;
+ *display:inline;
+}
+.CodeMirror-gutter-wrapper {
+ position: absolute;
+ z-index: 4;
+ height: 100%;
+}
+.CodeMirror-gutter-elt {
+ position: absolute;
+ cursor: default;
+ z-index: 4;
+}
+.CodeMirror-gutter-wrapper {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ user-select: none;
+}
+
+.CodeMirror-lines {
+ cursor: text;
+ min-height: 1px; /* prevents collapsing before first draw */
+}
+.CodeMirror pre {
+ /* Reset some styles that the rest of the page might have set */
+ -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
+ border-width: 0;
+ background: transparent;
+ font-family: inherit;
+ font-size: inherit;
+ margin: 0;
+ white-space: pre;
+ word-wrap: normal;
+ line-height: inherit;
+ color: inherit;
+ z-index: 2;
+ position: relative;
+ overflow: visible;
+ -webkit-tap-highlight-color: transparent;
+}
+.CodeMirror-wrap pre {
+ word-wrap: break-word;
+ white-space: pre-wrap;
+ word-break: normal;
+}
+
+.CodeMirror-linebackground {
+ position: absolute;
+ left: 0; right: 0; top: 0; bottom: 0;
+ z-index: 0;
+}
+
+.CodeMirror-linewidget {
+ position: relative;
+ z-index: 2;
+ overflow: auto;
+}
+
+.CodeMirror-widget {}
+
+.CodeMirror-code {
+ outline: none;
+}
+
+/* Force content-box sizing for the elements where we expect it */
+.CodeMirror-scroll,
+.CodeMirror-sizer,
+.CodeMirror-gutter,
+.CodeMirror-gutters,
+.CodeMirror-linenumber {
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+}
+
+.CodeMirror-measure {
+ position: absolute;
+ width: 100%;
+ height: 0;
+ overflow: hidden;
+ visibility: hidden;
+}
+.CodeMirror-measure pre { position: static; }
+
+.CodeMirror div.CodeMirror-cursor {
+ position: absolute;
+ border-right: none;
+ width: 0;
+}
+
+div.CodeMirror-cursors {
+ visibility: hidden;
+ position: relative;
+ z-index: 3;
+}
+.CodeMirror-focused div.CodeMirror-cursors {
+ visibility: visible;
+}
+
+.CodeMirror-selected { background: #d9d9d9; }
+.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
+.CodeMirror-crosshair { cursor: crosshair; }
+.CodeMirror ::selection { background: #d7d4f0; }
+.CodeMirror ::-moz-selection { background: #d7d4f0; }
+
+.cm-searching {
+ background: #ffa;
+ background: rgba(255, 255, 0, .4);
+}
+
+/* IE7 hack to prevent it from returning funny offsetTops on the spans */
+.CodeMirror span { *vertical-align: text-bottom; }
+
+/* Used to force a border model for a node */
+.cm-force-border { padding-right: .1px; }
+
+@media print {
+ /* Hide the cursor when printing */
+ .CodeMirror div.CodeMirror-cursors {
+ visibility: hidden;
+ }
+}
+
+/* See issue #2901 */
+.cm-tab-wrap-hack:after { content: ''; }
+
+/* Help users use markselection to safely style text background */
+span.CodeMirror-selectedtext { background: none; }
diff --git a/js/codemirror/lib/codemirror.js b/js/codemirror/lib/codemirror.js
index 98a45c60ba..a1dfd0fc3d 100644
--- a/js/codemirror/lib/codemirror.js
+++ b/js/codemirror/lib/codemirror.js
@@ -82,12 +82,15 @@
keyMaps: [], // stores maps added by addKeyMap
overlays: [], // highlighting overlays, as added by addOverlay
modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info
- overwrite: false, focused: false,
+ overwrite: false,
+ delayingBlurEvent: false,
+ focused: false,
suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll
draggingText: false,
highlight: new Delayed(), // stores highlight worker timeout
- keySeq: null // Unfinished key sequence
+ keySeq: null, // Unfinished key sequence
+ specialChars: null
};
var cm = this;
@@ -591,7 +594,7 @@
"CodeMirror-linenumber CodeMirror-gutter-elt"));
var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
display.lineGutter.style.width = "";
- display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding);
+ display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1;
display.lineNumWidth = display.lineNumInnerWidth + padding;
display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
display.lineGutter.style.width = display.lineNumWidth + "px";
@@ -725,12 +728,9 @@
}
function postUpdateDisplay(cm, update) {
- var force = update.force, viewport = update.viewport;
+ var viewport = update.viewport;
for (var first = true;; first = false) {
- if (first && cm.options.lineWrapping && update.oldDisplayWidth != displayWidth(cm)) {
- force = true;
- } else {
- force = false;
+ if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) {
// Clip forced viewport to actual scrollable area.
if (viewport && viewport.top != null)
viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)};
@@ -1076,7 +1076,7 @@
// was made out of.
var lastCopied = null;
- function applyTextInput(cm, inserted, deleted, sel) {
+ function applyTextInput(cm, inserted, deleted, sel, origin) {
var doc = cm.doc;
cm.display.shift = false;
if (!sel) sel = doc.sel;
@@ -1102,33 +1102,43 @@
}
var updateInput = cm.curOp.updateInput;
var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines,
- origin: cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input"};
+ origin: origin || (cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input")};
makeChange(cm.doc, changeEvent);
signalLater(cm, "inputRead", cm, changeEvent);
- // When an 'electric' character is inserted, immediately trigger a reindent
- if (inserted && !cm.state.pasteIncoming && cm.options.electricChars &&
- cm.options.smartIndent && range.head.ch < 100 &&
- (!i || sel.ranges[i - 1].head.line != range.head.line)) {
- var mode = cm.getModeAt(range.head);
- var end = changeEnd(changeEvent);
- if (mode.electricChars) {
- for (var j = 0; j < mode.electricChars.length; j++)
- if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
- indentLine(cm, end.line, "smart");
- break;
- }
- } else if (mode.electricInput) {
- if (mode.electricInput.test(getLine(doc, end.line).text.slice(0, end.ch)))
- indentLine(cm, end.line, "smart");
- }
- }
}
+ if (inserted && !cm.state.pasteIncoming)
+ triggerElectric(cm, inserted);
+
ensureCursorVisible(cm);
cm.curOp.updateInput = updateInput;
cm.curOp.typing = true;
cm.state.pasteIncoming = cm.state.cutIncoming = false;
}
+ function triggerElectric(cm, inserted) {
+ // When an 'electric' character is inserted, immediately trigger a reindent
+ if (!cm.options.electricChars || !cm.options.smartIndent) return;
+ var sel = cm.doc.sel;
+
+ for (var i = sel.ranges.length - 1; i >= 0; i--) {
+ var range = sel.ranges[i];
+ if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) continue;
+ var mode = cm.getModeAt(range.head);
+ var indented = false;
+ if (mode.electricChars) {
+ for (var j = 0; j < mode.electricChars.length; j++)
+ if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
+ indented = indentLine(cm, range.head.line, "smart");
+ break;
+ }
+ } else if (mode.electricInput) {
+ if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch)))
+ indented = indentLine(cm, range.head.line, "smart");
+ }
+ if (indented) signalLater(cm, "electricInput", cm, range.head.line);
+ }
+ }
+
function copyableRanges(cm) {
var text = [], ranges = [];
for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
@@ -1164,6 +1174,7 @@
this.inaccurateSelection = false;
// Used to work around IE issue with selection being forgotten when focus moves away from textarea
this.hasSelection = false;
+ this.composing = null;
};
function hiddenTextarea() {
@@ -1228,6 +1239,8 @@
te.value = lastCopied.join("\n");
selectInput(te);
}
+ } else if (!cm.options.lineWiseCopyCut) {
+ return;
} else {
var ranges = copyableRanges(cm);
lastCopied = ranges.text;
@@ -1254,6 +1267,21 @@
on(display.lineSpace, "selectstart", function(e) {
if (!eventInWidget(display, e)) e_preventDefault(e);
});
+
+ on(te, "compositionstart", function() {
+ var start = cm.getCursor("from");
+ input.composing = {
+ start: start,
+ range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"})
+ };
+ });
+ on(te, "compositionend", function() {
+ if (input.composing) {
+ input.poll();
+ input.composing.range.clear();
+ input.composing = null;
+ }
+ });
},
prepareSelection: function() {
@@ -1381,19 +1409,29 @@
return false;
}
- if (text.charCodeAt(0) == 0x200b && cm.doc.sel == cm.display.selForContextMenu && !prevInput)
- prevInput = "\u200b";
+ if (cm.doc.sel == cm.display.selForContextMenu) {
+ var first = text.charCodeAt(0);
+ if (first == 0x200b && !prevInput) prevInput = "\u200b";
+ if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo"); }
+ }
// Find the part of the input that is actually new
var same = 0, l = Math.min(prevInput.length, text.length);
while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
var self = this;
runInOp(cm, function() {
- applyTextInput(cm, text.slice(same), prevInput.length - same);
+ applyTextInput(cm, text.slice(same), prevInput.length - same,
+ null, self.composing ? "*compose" : null);
// Don't leave long text in the textarea, since it makes further polling slow
if (text.length > 1000 || text.indexOf("\n") > -1) input.value = self.prevInput = "";
else self.prevInput = text;
+
+ if (self.composing) {
+ self.composing.range.clear();
+ self.composing.range = cm.markText(self.composing.start, cm.getCursor("to"),
+ {className: "CodeMirror-composing"});
+ }
});
return true;
},
@@ -1440,7 +1478,9 @@
function prepareSelectAllHack() {
if (te.selectionStart != null) {
var selected = cm.somethingSelected();
- var extval = te.value = "\u200b" + (selected ? te.value : "");
+ var extval = "\u200b" + (selected ? te.value : "");
+ te.value = "\u21da"; // Used to catch context-menu undo
+ te.value = extval;
input.prevInput = selected ? "" : "\u200b";
te.selectionStart = 1; te.selectionEnd = extval.length;
// Re-set this, in case some other handler touched the
@@ -1458,7 +1498,8 @@
if (te.selectionStart != null) {
if (!ie || (ie && ie_version < 9)) prepareSelectAllHack();
var i = 0, poll = function() {
- if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0)
+ if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 &&
+ te.selectionEnd > 0 && input.prevInput == "\u200b")
operation(cm, commands.selectAll)(cm);
else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500);
else display.input.reset();
@@ -1491,6 +1532,7 @@
this.cm = cm;
this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null;
this.polling = new Delayed();
+ this.gracePeriod = false;
}
ContentEditableInput.prototype = copyObj({
@@ -1552,6 +1594,8 @@
if (cm.somethingSelected()) {
lastCopied = cm.getSelections();
if (e.type == "cut") cm.replaceSelection("", null, "cut");
+ } else if (!cm.options.lineWiseCopyCut) {
+ return;
} else {
var ranges = copyableRanges(cm);
lastCopied = ranges.text;
@@ -1625,10 +1669,21 @@
sel.removeAllRanges();
sel.addRange(rng);
if (old && sel.anchorNode == null) sel.addRange(old);
+ else if (gecko) this.startGracePeriod();
}
this.rememberSelection();
},
+ startGracePeriod: function() {
+ var input = this;
+ clearTimeout(this.gracePeriod);
+ this.gracePeriod = setTimeout(function() {
+ input.gracePeriod = false;
+ if (input.selectionChanged())
+ input.cm.operation(function() { input.cm.curOp.selectionChanged = true; });
+ }, 20);
+ },
+
showMultipleSelections: function(info) {
removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors);
removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection);
@@ -1671,12 +1726,15 @@
this.polling.set(this.cm.options.pollInterval, poll);
},
- pollSelection: function() {
- if (this.composing) return;
+ selectionChanged: function() {
+ var sel = window.getSelection();
+ return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
+ sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset;
+ },
- var sel = window.getSelection(), cm = this.cm;
- if (sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
- sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset) {
+ pollSelection: function() {
+ if (!this.composing && !this.gracePeriod && this.selectionChanged()) {
+ var sel = window.getSelection(), cm = this.cm;
this.rememberSelection();
var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);
var head = domToPos(cm, sel.focusNode, sel.focusOffset);
@@ -1783,7 +1841,7 @@
var partPos = getBidiPartAt(order, pos.ch);
side = partPos % 2 ? "right" : "left";
}
- var result = nodeAndOffsetInLineMap(info.map, pos.ch, "left");
+ var result = nodeAndOffsetInLineMap(info.map, pos.ch, side);
result.offset = result.collapse == "right" ? result.end : result.start;
return result;
}
@@ -2895,6 +2953,7 @@
updateMaxLine: false, // Set when the widest line needs to be determined anew
scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
scrollToPos: null, // Used to scroll to a specific position
+ focus: false,
id: ++nextOpId // Unique ID
};
if (operationGroup) {
@@ -3012,6 +3071,7 @@
if (cm.state.focused && op.updateInput)
cm.display.input.reset(op.typing);
+ if (op.focus && op.focus == activeElt()) ensureFocus(op.cm);
}
function endOperation_finish(op) {
@@ -3376,15 +3436,11 @@
// Prevent wrapper from ever scrolling
on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
- function drag_(e) {
- if (!signalDOMEvent(cm, e)) e_stop(e);
- }
- if (cm.options.dragDrop) {
- on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});
- on(d.scroller, "dragenter", drag_);
- on(d.scroller, "dragover", drag_);
- on(d.scroller, "drop", operation(cm, onDrop));
- }
+ d.dragFunctions = {
+ simple: function(e) {if (!signalDOMEvent(cm, e)) e_stop(e);},
+ start: function(e){onDragStart(cm, e);},
+ drop: operation(cm, onDrop)
+ };
var inp = d.input.getField();
on(inp, "keyup", function(e) { onKeyUp.call(cm, e); });
@@ -3394,6 +3450,18 @@
on(inp, "blur", bind(onBlur, cm));
}
+ function dragDropChanged(cm, value, old) {
+ var wasOn = old && old != CodeMirror.Init;
+ if (!value != !wasOn) {
+ var funcs = cm.display.dragFunctions;
+ var toggle = value ? on : off;
+ toggle(cm.display.scroller, "dragstart", funcs.start);
+ toggle(cm.display.scroller, "dragenter", funcs.simple);
+ toggle(cm.display.scroller, "dragover", funcs.simple);
+ toggle(cm.display.scroller, "drop", funcs.drop);
+ }
+ }
+
// Called when the window resizes
function onResize(cm) {
var d = cm.display;
@@ -3475,6 +3543,7 @@
break;
case 3:
if (captureRightClick) onContextMenu(cm, e);
+ else delayBlurEvent(cm);
break;
}
}
@@ -3482,7 +3551,7 @@
var lastClick, lastDoubleClick;
function leftButtonDown(cm, e, start) {
if (ie) setTimeout(bind(ensureFocus, cm), 0);
- else ensureFocus(cm);
+ else cm.curOp.focus = activeElt();
var now = +new Date, type;
if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) {
@@ -3507,7 +3576,7 @@
// Start a text drag. When it ends, see if any dragging actually
// happen, and treat as a click if it didn't.
function leftButtonStartDrag(cm, e, start, modifier) {
- var display = cm.display;
+ var display = cm.display, startTime = +new Date;
var dragEnd = operation(cm, function(e2) {
if (webkit) display.scroller.draggable = false;
cm.state.draggingText = false;
@@ -3515,12 +3584,13 @@
off(display.scroller, "drop", dragEnd);
if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
e_preventDefault(e2);
- if (!modifier)
+ if (!modifier && +new Date - 200 < startTime)
extendSelection(cm.doc, start);
- display.input.focus();
- // Work around unexplainable focus problem in IE9 (#2127)
- if (ie && ie_version == 9)
+ // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
+ if (webkit || ie && ie_version == 9)
setTimeout(function() {document.body.focus(); display.input.focus();}, 20);
+ else
+ display.input.focus();
}
});
// Let the drag handler handle this.
@@ -3546,6 +3616,7 @@
ourRange = new Range(start, start);
} else {
ourRange = doc.sel.primary();
+ ourIndex = doc.sel.primIndex;
}
if (e.altKey) {
@@ -3577,7 +3648,7 @@
ourIndex = ranges.length;
setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex),
{scroll: false, origin: "*mouse"});
- } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single") {
+ } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single" && !e.shiftKey) {
setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0));
startSel = doc.sel;
} else {
@@ -3640,7 +3711,7 @@
var cur = posFromMouse(cm, e, true, type == "rect");
if (!cur) return;
if (cmp(cur, lastPos) != 0) {
- ensureFocus(cm);
+ cm.curOp.focus = activeElt();
extendTo(cur);
var visible = visibleLines(display, doc);
if (cur.line >= visible.to || cur.line < visible.from)
@@ -3743,7 +3814,7 @@
try {
var text = e.dataTransfer.getData("Text");
if (text) {
- if (cm.state.draggingText && !(mac ? e.metaKey : e.ctrlKey))
+ if (cm.state.draggingText && !(mac ? e.altKey : e.ctrlKey))
var selected = cm.listSelections();
setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));
if (selected) for (var i = 0; i < selected.length; ++i)
@@ -3998,7 +4069,7 @@
var lastStoppedKey = null;
function onKeyDown(e) {
var cm = this;
- ensureFocus(cm);
+ cm.curOp.focus = activeElt();
if (signalDOMEvent(cm, e)) return;
// IE does strange things with escape.
if (ie && ie_version < 11 && e.keyCode == 27) e.returnValue = false;
@@ -4050,7 +4121,19 @@
// FOCUS/BLUR EVENTS
+ function delayBlurEvent(cm) {
+ cm.state.delayingBlurEvent = true;
+ setTimeout(function() {
+ if (cm.state.delayingBlurEvent) {
+ cm.state.delayingBlurEvent = false;
+ onBlur(cm);
+ }
+ }, 100);
+ }
+
function onFocus(cm) {
+ if (cm.state.delayingBlurEvent) cm.state.delayingBlurEvent = false;
+
if (cm.options.readOnly == "nocursor") return;
if (!cm.state.focused) {
signal(cm, "focus", cm);
@@ -4068,6 +4151,8 @@
restartBlink(cm);
}
function onBlur(cm) {
+ if (cm.state.delayingBlurEvent) return;
+
if (cm.state.focused) {
signal(cm, "blur", cm);
cm.state.focused = false;
@@ -4572,6 +4657,8 @@
if (indentString != curSpaceString) {
replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
+ line.stateAfter = null;
+ return true;
} else {
// Ensure that, if the cursor was in the whitespace at the start
// of the line, it is moved to the end of that space.
@@ -4584,7 +4671,6 @@
}
}
}
- line.stateAfter = null;
}
// Utility for applying a change to a line by handle or number,
@@ -4824,7 +4910,7 @@
getHelpers: function(pos, type) {
var found = [];
- if (!helpers.hasOwnProperty(type)) return helpers;
+ if (!helpers.hasOwnProperty(type)) return found;
var help = helpers[type], mode = this.getModeAt(pos);
if (typeof mode[type] == "string") {
if (help[mode[type]]) found.push(help[mode[type]]);
@@ -4874,10 +4960,15 @@
return lineAtHeight(this.doc, height + this.display.viewOffset);
},
heightAtLine: function(line, mode) {
- var end = false, last = this.doc.first + this.doc.size - 1;
- if (line < this.doc.first) line = this.doc.first;
- else if (line > last) { line = last; end = true; }
- var lineObj = getLine(this.doc, line);
+ var end = false, lineObj;
+ if (typeof line == "number") {
+ var last = this.doc.first + this.doc.size - 1;
+ if (line < this.doc.first) line = this.doc.first;
+ else if (line > last) { line = last; end = true; }
+ lineObj = getLine(this.doc, line);
+ } else {
+ lineObj = line;
+ }
return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page").top +
(end ? this.doc.height - heightAtLine(lineObj) : 0);
},
@@ -4906,12 +4997,6 @@
});
}),
- addLineWidget: methodOp(function(handle, node, options) {
- return addLineWidget(this, handle, node, options);
- }),
-
- removeLineWidget: function(widget) { widget.clear(); },
-
lineInfo: function(line) {
if (typeof line == "number") {
if (!isLine(this.doc, line)) return null;
@@ -4973,6 +5058,8 @@
return commands[cmd](this);
},
+ triggerElectric: methodOp(function(text) { triggerElectric(this, text); }),
+
findPosH: function(from, amount, unit, visually) {
var dir = 1;
if (amount < 0) { dir = -1; amount = -amount; }
@@ -5186,10 +5273,10 @@
clearCaches(cm);
regChange(cm);
}, true);
- option("specialChars", /[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val) {
- cm.options.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
- cm.refresh();
- }, true);
+ option("specialChars", /[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val, old) {
+ cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
+ if (old != CodeMirror.Init) cm.refresh();
+ });
option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true);
option("electricChars", true);
option("inputStyle", mobile ? "contenteditable" : "textarea", function() {
@@ -5235,6 +5322,7 @@
option("showCursorWhenSelecting", false, updateSelection, true);
option("resetSelectionOnContextMenu", true);
+ option("lineWiseCopyCut", true);
option("readOnly", false, function(cm, val) {
if (val == "nocursor") {
@@ -5247,7 +5335,7 @@
}
});
option("disableInput", false, function(cm, val) {if (!val) cm.display.input.reset();}, true);
- option("dragDrop", true);
+ option("dragDrop", true, dragDropChanged);
option("cursorBlinkRate", 530);
option("cursorScrollMargin", 0);
@@ -5639,7 +5727,7 @@
for (var i = 0; i < keys.length; i++) {
var val, name;
if (i == keys.length - 1) {
- name = keyname;
+ name = keys.join(" ");
val = value;
} else {
name = keys.slice(0, i + 1).join(" ");
@@ -6431,10 +6519,10 @@
// Line widgets are block elements displayed above or below a line.
- var LineWidget = CodeMirror.LineWidget = function(cm, node, options) {
+ var LineWidget = CodeMirror.LineWidget = function(doc, node, options) {
if (options) for (var opt in options) if (options.hasOwnProperty(opt))
this[opt] = options[opt];
- this.cm = cm;
+ this.doc = doc;
this.node = node;
};
eventMixin(LineWidget);
@@ -6445,52 +6533,55 @@
}
LineWidget.prototype.clear = function() {
- var cm = this.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);
+ var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);
if (no == null || !ws) return;
for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
if (!ws.length) line.widgets = null;
var height = widgetHeight(this);
- runInOp(cm, function() {
+ updateLineHeight(line, Math.max(0, line.height - height));
+ if (cm) runInOp(cm, function() {
adjustScrollWhenAboveVisible(cm, line, -height);
regLineChange(cm, no, "widget");
- updateLineHeight(line, Math.max(0, line.height - height));
});
};
LineWidget.prototype.changed = function() {
- var oldH = this.height, cm = this.cm, line = this.line;
+ var oldH = this.height, cm = this.doc.cm, line = this.line;
this.height = null;
var diff = widgetHeight(this) - oldH;
if (!diff) return;
- runInOp(cm, function() {
+ updateLineHeight(line, line.height + diff);
+ if (cm) runInOp(cm, function() {
cm.curOp.forceUpdate = true;
adjustScrollWhenAboveVisible(cm, line, diff);
- updateLineHeight(line, line.height + diff);
});
};
function widgetHeight(widget) {
if (widget.height != null) return widget.height;
+ var cm = widget.doc.cm;
+ if (!cm) return 0;
if (!contains(document.body, widget.node)) {
var parentStyle = "position: relative;";
if (widget.coverGutter)
- parentStyle += "margin-left: -" + widget.cm.display.gutters.offsetWidth + "px;";
+ parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;";
if (widget.noHScroll)
- parentStyle += "width: " + widget.cm.display.wrapper.clientWidth + "px;";
- removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, parentStyle));
+ parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;";
+ removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle));
}
return widget.height = widget.node.offsetHeight;
}
- function addLineWidget(cm, handle, node, options) {
- var widget = new LineWidget(cm, node, options);
- if (widget.noHScroll) cm.display.alignWidgets = true;
- changeLine(cm.doc, handle, "widget", function(line) {
+ function addLineWidget(doc, handle, node, options) {
+ var widget = new LineWidget(doc, node, options);
+ var cm = doc.cm;
+ if (cm && widget.noHScroll) cm.display.alignWidgets = true;
+ changeLine(doc, handle, "widget", function(line) {
var widgets = line.widgets || (line.widgets = []);
if (widget.insertAt == null) widgets.push(widget);
else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);
widget.line = line;
- if (!lineIsHidden(cm.doc, line)) {
- var aboveVisible = heightAtLine(line) < cm.doc.scrollTop;
+ if (cm && !lineIsHidden(doc, line)) {
+ var aboveVisible = heightAtLine(line) < doc.scrollTop;
updateLineHeight(line, line.height + widgetHeight(widget));
if (aboveVisible) addToScrollPos(cm, null, widget.height);
cm.curOp.forceUpdate = true;
@@ -6710,7 +6801,9 @@
// is needed on Webkit to be able to get line-level bounding
// rectangles for it (in measureChar).
var content = elt("span", null, null, webkit ? "padding-right: .1px" : null);
- var builder = {pre: elt("pre", [content]), content: content, col: 0, pos: 0, cm: cm};
+ var builder = {pre: elt("pre", [content]), content: content,
+ col: 0, pos: 0, cm: cm,
+ splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")};
lineView.measure = {};
// Iterate over the logical lines that make up this visual line.
@@ -6720,8 +6813,6 @@
builder.addToken = buildToken;
// Optionally wire in some hacks into the token-rendering
// algorithm, to deal with browser quirks.
- if ((ie || webkit) && cm.getOption("lineWrapping"))
- builder.addToken = buildTokenSplitSpaces(builder.addToken);
if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))
builder.addToken = buildTokenBadBidi(builder.addToken, order);
builder.map = [];
@@ -6770,10 +6861,11 @@
// the line map. Takes care to render special characters separately.
function buildToken(builder, text, style, startStyle, endStyle, title, css) {
if (!text) return;
- var special = builder.cm.options.specialChars, mustWrap = false;
+ var displayText = builder.splitSpaces ? text.replace(/ {3,}/g, splitSpaces) : text;
+ var special = builder.cm.state.specialChars, mustWrap = false;
if (!special.test(text)) {
builder.col += text.length;
- var content = document.createTextNode(text);
+ var content = document.createTextNode(displayText);
builder.map.push(builder.pos, builder.pos + text.length, content);
if (ie && ie_version < 9) mustWrap = true;
builder.pos += text.length;
@@ -6784,7 +6876,7 @@
var m = special.exec(text);
var skipped = m ? m.index - pos : text.length - pos;
if (skipped) {
- var txt = document.createTextNode(text.slice(pos, pos + skipped));
+ var txt = document.createTextNode(displayText.slice(pos, pos + skipped));
if (ie && ie_version < 9) content.appendChild(elt("span", [txt]));
else content.appendChild(txt);
builder.map.push(builder.pos, builder.pos + skipped, txt);
@@ -6821,22 +6913,17 @@
builder.content.appendChild(content);
}
- function buildTokenSplitSpaces(inner) {
- function split(old) {
- var out = " ";
- for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
- out += " ";
- return out;
- }
- return function(builder, text, style, startStyle, endStyle, title) {
- inner(builder, text.replace(/ {3,}/g, split), style, startStyle, endStyle, title);
- };
+ function splitSpaces(old) {
+ var out = " ";
+ for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
+ out += " ";
+ return out;
}
// Work around nonsense dimensions being reported for stretches of
// right-to-left text.
function buildTokenBadBidi(inner, order) {
- return function(builder, text, style, startStyle, endStyle, title) {
+ return function(builder, text, style, startStyle, endStyle, title, css) {
style = style ? style + " cm-force-border" : "cm-force-border";
var start = builder.pos, end = start + text.length;
for (;;) {
@@ -6845,8 +6932,8 @@
var part = order[i];
if (part.to > start && part.from <= start) break;
}
- if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title);
- inner(builder, text.slice(0, part.to - start), style, startStyle, null, title);
+ if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title, css);
+ inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css);
startStyle = null;
text = text.slice(part.to - start);
start = part.to;
@@ -6888,8 +6975,13 @@
var foundBookmarks = [];
for (var j = 0; j < spans.length; ++j) {
var sp = spans[j], m = sp.marker;
- if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
- if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
+ if (m.type == "bookmark" && sp.from == pos && m.widgetNode) {
+ foundBookmarks.push(m);
+ } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) {
+ if (sp.to != null && sp.to != pos && nextChange > sp.to) {
+ nextChange = sp.to;
+ spanEndStyle = "";
+ }
if (m.className) spanStyle += " " + m.className;
if (m.css) css = m.css;
if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
@@ -6900,12 +6992,12 @@
} else if (sp.from > pos && nextChange > sp.from) {
nextChange = sp.from;
}
- if (m.type == "bookmark" && sp.from == pos && m.widgetNode) foundBookmarks.push(m);
}
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]);
@@ -7368,13 +7460,19 @@
});
}),
+ addLineWidget: docMethodOp(function(handle, node, options) {
+ return addLineWidget(this, handle, node, options);
+ }),
+ removeLineWidget: function(widget) { widget.clear(); },
+
markText: function(from, to, options) {
return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
},
setBookmark: function(pos, options) {
var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
insertLeft: options && options.insertLeft,
- clearWhenEmpty: false, shared: options && options.shared};
+ clearWhenEmpty: false, shared: options && options.shared,
+ handleMouseEvents: options && options.handleMouseEvents};
pos = clipPos(this, pos);
return markText(this, pos, pos, realOpts, "bookmark");
},
@@ -8108,7 +8206,7 @@
return function(){return f.apply(null, args);};
}
- var nonASCIISingleCaseWordChar = /[\u00df\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
+ var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
var isWordCharBasic = CodeMirror.isWordChar = function(ch) {
return /\w/.test(ch) || ch > "\x80" &&
(ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
@@ -8630,6 +8728,8 @@
lst(order).to -= m[0].length;
order.push(new BidiSpan(0, len - m[0].length, len));
}
+ if (order[0].level == 2)
+ order.unshift(new BidiSpan(1, order[0].to, order[0].to));
if (order[0].level != lst(order).level)
order.push(new BidiSpan(order[0].level, len, len));
@@ -8639,7 +8739,7 @@
// THE END
- CodeMirror.version = "5.0.1";
+ CodeMirror.version = "5.3.0";
return CodeMirror;
});
diff --git a/js/codemirror/mode/javascript/javascript.js b/js/codemirror/mode/javascript/javascript.js
index 3f05ac46c3..ef0184789a 100644
--- a/js/codemirror/mode/javascript/javascript.js
+++ b/js/codemirror/mode/javascript/javascript.js
@@ -549,6 +549,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}
function classBody(type, value) {
if (type == "variable" || cx.style == "keyword") {
+ if (value == "static") {
+ cx.marked = "keyword";
+ return cont(classBody);
+ }
cx.marked = "property";
if (value == "get" || value == "set") return cont(classGetterSetter, functiondef, classBody);
return cont(functiondef, classBody);
@@ -581,7 +585,11 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function importSpec(type, value) {
if (type == "{") return contCommasep(importSpec, "}");
if (type == "variable") register(value);
- return cont();
+ if (value == "*") cx.marked = "keyword";
+ return cont(maybeAs);
+ }
+ function maybeAs(_type, value) {
+ if (value == "as") { cx.marked = "keyword"; return cont(importSpec); }
}
function maybeFrom(_type, value) {
if (value == "from") { cx.marked = "keyword"; return cont(expression); }
@@ -669,6 +677,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
blockCommentEnd: jsonMode ? null : "*/",
lineComment: jsonMode ? null : "//",
fold: "brace",
+ closeBrackets: "()[]{}''\"\"``",
helperType: jsonMode ? "json" : "javascript",
jsonldMode: jsonldMode,
diff --git a/js/codemirror/mode/sql/sql.js b/js/codemirror/mode/sql/sql.js
index ee6c194b0e..a908277151 100644
--- a/js/codemirror/mode/sql/sql.js
+++ b/js/codemirror/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 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 ";
// turn a space-separated list into an array
function set(str) {
@@ -280,7 +280,7 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {
CodeMirror.defineMIME("text/x-mssql", {
name: "sql",
client: set("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"),
- keywords: set(sqlKeywords + "begin trigger proc view index for add constraint key primary foreign collate clustered nonclustered"),
+ keywords: set(sqlKeywords + "begin trigger proc view index for add constraint key primary foreign collate clustered nonclustered declare"),
builtin: set("bigint numeric bit smallint decimal smallmoney int tinyint money float real char varchar text nchar nvarchar ntext binary varbinary image cursor timestamp hierarchyid uniqueidentifier sql_variant xml table "),
atoms: set("false true null unknown"),
operatorChars: /^[*+\-%<>!=]/,
@@ -293,7 +293,7 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {
CodeMirror.defineMIME("text/x-mysql", {
name: "sql",
client: set("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"),
- keywords: set(sqlKeywords + "accessible action add after algorithm all analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general get global grant grants group groupby_concat handler hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show signal slave slow smallint snapshot soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views warnings when while with work write xa xor year_month zerofill begin do then else loop repeat"),
+ keywords: set(sqlKeywords + "accessible action add after algorithm all analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general get global grant grants group group_concat handler hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show signal slave slow smallint snapshot soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views warnings when while with work write xa xor year_month zerofill begin do then else loop repeat"),
builtin: set("bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric"),
atoms: set("false true null unknown"),
operatorChars: /^[*+\-%<>!=&|^]/,
@@ -327,9 +327,9 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {
CodeMirror.defineMIME("text/x-cassandra", {
name: "sql",
client: { },
- keywords: set("use select from using consistency where limit first reversed first and in insert into values using consistency ttl update set delete truncate begin batch apply create keyspace with columnfamily primary key index on drop alter type add any one quorum all local_quorum each_quorum"),
- builtin: set("ascii bigint blob boolean counter decimal double float int text timestamp uuid varchar varint"),
- atoms: set("false true"),
+ keywords: set("add all allow alter and any apply as asc authorize batch begin by clustering columnfamily compact consistency count create custom delete desc distinct drop each_quorum exists filtering from grant if in index insert into key keyspace keyspaces level limit local_one local_quorum modify nan norecursive nosuperuser not of on one order password permission permissions primary quorum rename revoke schema select set storage superuser table three to token truncate ttl two type unlogged update use user users using values where with writetime"),
+ builtin: set("ascii bigint blob boolean counter decimal double float frozen inet int list map static text timestamp timeuuid tuple uuid varchar varint"),
+ atoms: set("false true infinity NaN"),
operatorChars: /^[<>=]/,
dateSQL: { },
support: set("commentSlashSlash decimallessFloat"),