: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
cur.changes.push(historyChangeFromChange(doc, change));
// Can not be merged, start a new event.
var before = lst(hist.done);
if (!before || !before.ranges)
pushSelectionToHistory(doc.sel, hist.done);
cur = {changes: [historyChangeFromChange(doc, change)],
generation: hist.generation};
while (hist.done.length > hist.undoDepth) {
if (!hist.done[0].ranges) hist.done.shift();
hist.done.push(selAfter);
hist.generation = ++hist.maxGeneration;
hist.lastModTime = hist.lastSelTime = time;
hist.lastOp = hist.lastSelOp = opId;
hist.lastOrigin = hist.lastSelOrigin = change.origin;
if (!last) signal(doc, "historyAdded");
function selectionEventCanBeMerged(doc, origin, prev, sel) {
var ch = origin.charAt(0);
prev.ranges.length == sel.ranges.length &&
prev.somethingSelected() == sel.somethingSelected() &&
new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500);
// Called whenever the selection changes, sets the new selection as
// the pending selection in the history, and pushes the old pending
// selection into the 'done' array when it was significantly
// different (in number of selected ranges, emptiness, or time).
function addSelectionToHistory(doc, sel, opId, options) {
var hist = doc.history, origin = options && options.origin;
// A new event is started when the previous origin does not match
// the current, or the origins don't allow matching. Origins
// starting with * are always merged, those starting with + are
// merged when similar and close together in time.
if (opId == hist.lastSelOp ||
(origin && hist.lastSelOrigin == origin &&
(hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||
selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))
hist.done[hist.done.length - 1] = sel;
pushSelectionToHistory(sel, hist.done);
hist.lastSelTime = +new Date;
hist.lastSelOrigin = origin;
if (options && options.clearRedo !== false)
clearSelectionEvents(hist.undone);
function pushSelectionToHistory(sel, dest) {
if (!(top && top.ranges && top.equals(sel)))
// Used to store marked span information in the history.
function attachLocalSpans(doc, change, from, to) {
var existing = change["spans_" + doc.id], n = 0;
doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {
(existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;
// When un/re-doing restores text containing marked spans, those
// that have been explicitly cleared should not be restored.
function removeClearedSpans(spans) {
for (var i = 0, out; i < spans.length; ++i) {
if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
else if (out) out.push(spans[i]);
return !out ? spans : out.length ? out : null;
// Retrieve and filter the old marked spans stored in a change event.
function getOldSpans(doc, change) {
var found = change["spans_" + doc.id];
for (var i = 0, nw = []; i < change.text.length; ++i)
nw.push(removeClearedSpans(found[i]));
// Used both to provide a JSON-safe object in .getHistory, and, when
// detaching a document, to split the history in two
function copyHistoryArray(events, newGroup, instantiateSel) {
for (var i = 0, copy = []; i < events.length; ++i) {
copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event);
var changes = event.changes, newChanges = [];
copy.push({changes: newChanges});
for (var j = 0; j < changes.length; ++j) {
var change = changes[j], m;
newChanges.push({from: change.from, to: change.to, text: change.text});
if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) {
if (indexOf(newGroup, Number(m[1])) > -1) {
lst(newChanges)[prop] = change[prop];
// Rebasing/resetting history to deal with externally-sourced changes
function rebaseHistSelSingle(pos, from, to, diff) {
} else if (from < pos.line) {
// Tries to rebase an array of history events given a change in the
// document. If the change touches the same lines as the event, the
// event, and everything 'behind' it, is discarded. If the change is
// before the event, the event's positions are updated. Uses a
// copy-on-write scheme for the positions, to avoid having to
// reallocate them all on every rebase, but also avoid problems with
// shared position objects being unsafely updated.
function rebaseHistArray(array, from, to, diff) {
for (var i = 0; i < array.length; ++i) {
var sub = array[i], ok = true;
if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; }
for (var j = 0; j < sub.ranges.length; j++) {
rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff);
rebaseHistSelSingle(sub.ranges[j].head, from, to, diff);
for (var j = 0; j < sub.changes.length; ++j) {
var cur = sub.changes[j];
if (to < cur.from.line) {
cur.from = Pos(cur.from.line + diff, cur.from.ch);
cur.to = Pos(cur.to.line + diff, cur.to.ch);
} else if (from <= cur.to.line) {
function rebaseHist(hist, change) {
var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
rebaseHistArray(hist.done, from, to, diff);
rebaseHistArray(hist.undone, from, to, diff);
// Due to the fact that we still support jurassic IE versions, some
// compatibility wrappers are needed.
var e_preventDefault = CodeMirror.e_preventDefault = function(e) {
if (e.preventDefault) e.preventDefault();
else e.returnValue = false;
var e_stopPropagation = CodeMirror.e_stopPropagation = function(e) {
if (e.stopPropagation) e.stopPropagation();
else e.cancelBubble = true;
function e_defaultPrevented(e) {
return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;
var e_stop = CodeMirror.e_stop = function(e) {e_preventDefault(e); e_stopPropagation(e);};
function e_target(e) {return e.target || e.srcElement;}
else if (e.button & 2) b = 3;
else if (e.button & 4) b = 2;
if (mac && e.ctrlKey && b == 1) b = 3;
// Lightweight event framework. on/off also work on DOM nodes,
// registering native DOM handlers.
var on = CodeMirror.on = function(emitter, type, f) {
if (emitter.addEventListener)
emitter.addEventListener(type, f, false);
else if (emitter.attachEvent)
emitter.attachEvent("on" + type, f);
var map = emitter._handlers || (emitter._handlers = {});
var arr = map[type] || (map[type] = []);
function getHandlers(emitter, type, copy) {
var arr = emitter._handlers && emitter._handlers[type]
if (copy) return arr && arr.length > 0 ? arr.slice() : noHandlers
else return arr || noHandlers
var off = CodeMirror.off = function(emitter, type, f) {
if (emitter.removeEventListener)
emitter.removeEventListener(type, f, false);
else if (emitter.detachEvent)
emitter.detachEvent("on" + type, f);
var handlers = getHandlers(emitter, type, false)
for (var i = 0; i < handlers.length; ++i)
if (handlers[i] == f) { handlers.splice(i, 1); break; }
var signal = CodeMirror.signal = function(emitter, type /*, values...*/) {
var handlers = getHandlers(emitter, type, true)
if (!handlers.length) return;
var args = Array.prototype.slice.call(arguments, 2);
for (var i = 0; i < handlers.length; ++i) handlers[i].apply(null, args);
var orphanDelayedCallbacks = null;
// Often, we want to signal events at a point where we are in the
// middle of some work, but don't want the handler to start calling
// other methods on the editor, which might be in an inconsistent
// state or simply not expect any other events to happen.
// signalLater looks whether there are any handlers, and schedules
// them to be executed when the last operation ends, or, if no
// operation is active, when a timeout fires.
function signalLater(emitter, type /*, values...*/) {
var arr = getHandlers(emitter, type, false)
var args = Array.prototype.slice.call(arguments, 2), list;
list = operationGroup.delayedCallbacks;
} else if (orphanDelayedCallbacks) {
list = orphanDelayedCallbacks;
list = orphanDelayedCallbacks = [];
setTimeout(fireOrphanDelayed, 0);
function bnd(f) {return function(){f.apply(null, args);};};
for (var i = 0; i < arr.length; ++i)
function fireOrphanDelayed() {
var delayed = orphanDelayedCallbacks;
orphanDelayedCallbacks = null;
for (var i = 0; i < delayed.length; ++i) delayed[i]();
// The DOM events that CodeMirror handles can be overridden by
// registering a (non-DOM) handler on the editor for the event name,
// and preventDefault-ing the event in that handler.
function signalDOMEvent(cm, e, override) {
if (typeof e == "string")
e = {type: e, preventDefault: function() { this.defaultPrevented = true; }};
signal(cm, override || e.type, cm, e);
return e_defaultPrevented(e) || e.codemirrorIgnore;
function signalCursorActivity(cm) {
var arr = cm._handlers && cm._handlers.cursorActivity;
var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []);
for (var i = 0; i < arr.length; ++i) if (indexOf(set, arr[i]) == -1)
function hasHandler(emitter, type) {
return getHandlers(emitter, type).length > 0
// Add on and off methods to a constructor's prototype, to make
// registering events on such objects more convenient.
function eventMixin(ctor) {
ctor.prototype.on = function(type, f) {on(this, type, f);};
ctor.prototype.off = function(type, f) {off(this, type, f);};
// Number of pixels added to scroller and sizer to hide scrollbar
// Returned or thrown by various protocols to signal 'I'm not
var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
// Reused option objects for setSelection & friends
var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"};
function Delayed() {this.id = null;}
Delayed.prototype.set = function(ms, f) {
this.id = setTimeout(f, ms);
// Counts the column offset in a string, taking tabs into account.
// Used mostly to find indentation.
var countColumn = CodeMirror.countColumn = function(string, end, tabSize, startIndex, startValue) {
end = string.search(/[^\s\u00a0]/);
if (end == -1) end = string.length;
for (var i = startIndex || 0, n = startValue || 0;;) {
var nextTab = string.indexOf("\t", i);
if (nextTab < 0 || nextTab >= end)
n += tabSize - (n % tabSize);
// The inverse of countColumn -- find the offset that corresponds to
var findColumn = CodeMirror.findColumn = function(string, goal, tabSize) {
for (var pos = 0, col = 0;;) {
var nextTab = string.indexOf("\t", pos);
if (nextTab == -1) nextTab = string.length;
var skipped = nextTab - pos;
if (nextTab == string.length || col + skipped >= goal)
return pos + Math.min(skipped, goal - col);
col += tabSize - (col % tabSize);
if (col >= goal) return pos;
while (spaceStrs.length <= n)
spaceStrs.push(lst(spaceStrs) + " ");
function lst(arr) { return arr[arr.length-1]; }
var selectInput = function(node) { node.select(); };
if (ios) // Mobile Safari apparently has a bug where select() is broken.
selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; };
else if (ie) // Suppress mysterious IE10 errors
selectInput = function(node) { try { node.select(); } catch(_e) {} };
function indexOf(array, elt) {
for (var i = 0; i < array.length; ++i)
if (array[i] == elt) return i;
for (var i = 0; i < array.length; i++) out[i] = f(array[i], i);
function insertSorted(array, value, score) {
var pos = 0, priority = score(value)
while (pos < array.length && score(array[pos]) <= priority) pos++
array.splice(pos, 0, value)
function createObj(base, props) {
inst = Object.create(base);
nothing.prototype = base;
if (props) copyObj(props, inst);
function copyObj(obj, target, overwrite) {
if (!target) target = {};
if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
target[prop] = obj[prop];
var args = Array.prototype.slice.call(arguments, 1);
return function(){return f.apply(null, args);};
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));
function isWordChar(ch, helper) {
if (!helper) return isWordCharBasic(ch);
if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) return true;
for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
// Extending unicode characters. A series of a non-extending char +
// any number of extending chars is treated as a single unit as far
// as editing and measuring is concerned. This is not fully correct,
// since some scripts/fonts/browsers also treat other configurations
// of code points as a group.
var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;
function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); }
function elt(tag, content, className, style) {
var e = document.createElement(tag);
if (className) e.className = className;
if (style) e.style.cssText = style;
if (typeof content == "string") e.appendChild(document.createTextNode(content));
else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
if (document.createRange) range = function(node, start, end, endNode) {
var r = document.createRange();
r.setEnd(endNode || node, end);
else range = function(node, start, end) {
var r = document.body.createTextRange();
try { r.moveToElementText(node.parentNode); }
r.moveEnd("character", end);
r.moveStart("character", start);
function removeChildren(e) {
for (var count = e.childNodes.length; count > 0; --count)
e.removeChild(e.firstChild);
function removeChildrenAndAdd(parent, e) {
return removeChildren(parent).appendChild(e);
var contains = CodeMirror.contains = function(parent, child) {
if (child.nodeType == 3) // Android browser always returns false when child is a textnode
child = child.parentNode;
return parent.contains(child);
if (child.nodeType == 11) child = child.host;
if (child == parent) return true;
} while (child = child.parentNode);
var activeElement = document.activeElement;
while (activeElement && activeElement.root && activeElement.root.activeElement)
activeElement = activeElement.root.activeElement;
// Older versions of IE throws unspecified error when touching
// document.activeElement in some cases (during loading, in iframe)
if (ie && ie_version < 11) activeElt = function() {
try { return document.activeElement; }
catch(e) { return document.body; }