+2013-08-22 Joseph Pecoraro <pecoraro@apple.com>
+
+ <https://webkit.org/b/120165> Web Inspector: Update CodeMirror to 3.16.1
+
+ Reviewed by Andy Estes.
+
+ * Tools/PrettyPrinting/codemirror.css:
+ * Tools/PrettyPrinting/codemirror.js:
+ * Tools/PrettyPrinting/css.js:
+ * Tools/PrettyPrinting/javascript.js:
+ * UserInterface/External/CodeMirror/codemirror.css:
+ * UserInterface/External/CodeMirror/codemirror.js:
+ * UserInterface/External/CodeMirror/css.js:
+ * UserInterface/External/CodeMirror/javascript.js:
+ * UserInterface/External/CodeMirror/xml.js:
+
2013-08-21 Brent Fulgham <bfulgham@apple.com>
[Windows] Clean up project file after %PlatformArchitecture% change landed.
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
+.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */
white-space: pre-wrap;
word-break: normal;
}
+.CodeMirror-code pre {
+ border-right: 30px solid transparent;
+ width: -webkit-fit-content;
+ width: -moz-fit-content;
+ width: fit-content;
+}
+.CodeMirror-wrap .CodeMirror-code pre {
+ border-right: none;
+ width: auto;
+}
.CodeMirror-linebackground {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
// This is woefully incomplete. Suggestions for alternative methods welcome.
var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
var mac = ios || /Mac/.test(navigator.platform);
- var windows = /windows/i.test(navigator.platform);
+ var windows = /win/i.test(navigator.platform);
var opera_version = opera && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
if (opera_version) opera_version = Number(opera_version[1]);
+ if (opera_version && opera_version >= 15) { opera = false; webkit = true; }
// Some browsers use the wrong event properties to signal cmd/ctrl on OS X
var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11));
var captureMiddleClick = gecko || (ie && !ie_lt9);
d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
d.scrollbarV.firstChild.style.height =
(scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px";
- } else d.scrollbarV.style.display = "";
+ } else {
+ d.scrollbarV.style.display = "";
+ d.scrollbarV.firstChild.style.height = "0";
+ }
if (needsH) {
d.scrollbarH.style.display = "block";
d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0";
d.scrollbarH.firstChild.style.width =
(d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px";
- } else d.scrollbarH.style.display = "";
+ } else {
+ d.scrollbarH.style.display = "";
+ d.scrollbarH.firstChild.style.width = "0";
+ }
if (needsH && needsV) {
d.scrollbarFiller.style.display = "block";
d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
// DISPLAY DRAWING
- function updateDisplay(cm, changes, viewPort) {
+ function updateDisplay(cm, changes, viewPort, forced) {
var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
var visible = visibleLines(cm.display, cm.doc, viewPort);
for (;;) {
- if (!updateDisplayInner(cm, changes, visible)) break;
+ if (!updateDisplayInner(cm, changes, visible, forced)) break;
+ forced = false;
updated = true;
updateSelection(cm);
updateScrollbars(cm);
// Uses a set of changes plus the current scroll position to
// determine which DOM updates have to be made, and makes the
// updates.
- function updateDisplayInner(cm, changes, visible) {
+ function updateDisplayInner(cm, changes, visible, forced) {
var display = cm.display, doc = cm.doc;
if (!display.wrapper.clientWidth) {
display.showingFrom = display.showingTo = doc.first;
}
// Bail out if the visible area is already rendered and nothing changed.
- if (changes.length == 0 &&
+ if (!forced && changes.length == 0 &&
visible.from > display.showingFrom && visible.to < display.showingTo)
return;
var positionsChangedFrom = Infinity;
if (cm.options.lineNumbers)
for (var i = 0; i < changes.length; ++i)
- if (changes[i].diff) { positionsChangedFrom = changes[i].from; break; }
+ if (changes[i].diff && changes[i].from < positionsChangedFrom) { positionsChangedFrom = changes[i].from; }
var end = doc.first + doc.size;
var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);
if (range.from >= range.to) intact.splice(i--, 1);
else intactLines += range.to - range.from;
}
- if (intactLines == to - from && from == display.showingFrom && to == display.showingTo) {
+ if (!forced && intactLines == to - from && from == display.showingFrom && to == display.showingTo) {
updateViewOffset(cm);
return;
}
}
display.showingFrom = from; display.showingTo = to;
+ updateHeightsInViewport(cm);
+ updateViewOffset(cm);
+
+ return true;
+ }
+
+ function updateHeightsInViewport(cm) {
+ var display = cm.display;
var prevBottom = display.lineDiv.offsetTop;
for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {
if (ie_lt8) {
widgets[i].height = widgets[i].node.offsetHeight;
}
}
- updateViewOffset(cm);
-
- return true;
}
function updateViewOffset(cm) {
if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();
if (lineIsHidden(cm.doc, line)) {
if (line.height != 0) updateLineHeight(line, 0);
- if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {
+ if (line.widgets && cur && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {
var w = line.widgets[i];
if (w.showIfHidden) {
var prev = cur.previousSibling;
clearInterval(display.blinker);
var on = true;
display.cursor.style.visibility = display.otherCursor.style.visibility = "";
- display.blinker = setInterval(function() {
- display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
- }, cm.options.cursorBlinkRate);
+ if (cm.options.cursorBlinkRate > 0)
+ display.blinker = setInterval(function() {
+ display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
+ }, cm.options.cursorBlinkRate);
}
// HIGHLIGHT WORKER
// smallest indentation, which tends to need the least context to
// parse correctly.
function findStartLine(cm, n, precise) {
- var minindent, minline, doc = cm.doc;
- for (var search = n, lim = n - 100; search > lim; --search) {
+ var minindent, minline, doc = cm.doc, maxScan = cm.doc.mode.innerMode ? 1000 : 100;
+ for (var search = n, lim = n - maxScan; search > lim; --search) {
if (search <= doc.first) return doc.first;
var line = getLine(doc, search - 1);
if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
function getStateBefore(cm, n, precise) {
var doc = cm.doc, display = cm.display;
- if (!doc.mode.startState) return true;
+ if (!doc.mode.startState) return true;
var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
if (!state) state = startState(doc.mode);
else state = copyState(doc.mode, state);
function measureLineInner(cm, line) {
var display = cm.display, measure = emptyArray(line.text.length);
- var pre = lineContent(cm, line, measure);
+ var pre = lineContent(cm, line, measure, true);
// IE does not cache element positions of inline elements between
// calls to getBoundingClientRect. This makes the loop below,
if (cur.measureRight) rect.right = getRect(cur.measureRight).left;
if (cur.leftSide) rect.leftSide = measureRect(getRect(cur.leftSide));
}
+ removeChildren(cm.display.measure);
for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
finishRect(cur);
if (cur.leftSide) finishRect(cur.leftSide);
var cached = !hasBadSpan && findCachedMeasurement(cm, line);
if (cached) return measureChar(cm, line, line.text.length, cached.measure, "right").right;
- var pre = lineContent(cm, line);
+ var pre = lineContent(cm, line, null, true);
var end = pre.appendChild(zeroWidthElement(cm.display.measure));
removeChildrenAndAdd(cm.display.measure, pre);
return getRect(end).right - getRect(cm.display.lineDiv).left;
// An array of ranges of lines that have to be updated. See
// updateDisplay.
changes: [],
+ forceUpdate: false,
updateInput: null,
userSelChange: null,
textChanged: null,
var coords = cursorCoords(cm, doc.sel.head);
newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
}
- if (op.changes.length || newScrollPos && newScrollPos.scrollTop != null) {
- updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop);
+ if (op.changes.length || op.forceUpdate || newScrollPos && newScrollPos.scrollTop != null) {
+ updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop, op.forceUpdate);
if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop;
}
if (!updated && op.selectionChanged) updateSelection(cm);
function readInput(cm) {
var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;
if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.state.disableInput) return false;
+ if (cm.state.pasteIncoming && cm.state.fakedLastChar) {
+ input.value = input.value.substring(0, input.value.length - 1);
+ cm.state.fakedLastChar = false;
+ }
var text = input.value;
if (text == prevInput && posEq(sel.from, sel.to)) return false;
if (ie && !ie_lt9 && cm.display.inputHasSelection === text) {
on(d.scroller, "dragover", drag_);
on(d.scroller, "drop", operation(cm, onDrop));
}
- on(d.scroller, "paste", function(e){
+ on(d.scroller, "paste", function(e) {
if (eventInWidget(d, e)) return;
focusInput(cm);
fastPoll(cm);
});
on(d.input, "paste", function() {
+ // Workaround for webkit bug https://bugs.webkit.org/show_bug.cgi?id=90206
+ // Add a char to the end of textarea before paste occur so that
+ // selection doesn't span to the end of textarea.
+ if (webkit && !cm.state.fakedLastChar && !(new Date - cm.state.lastMiddleDown < 200)) {
+ var start = d.input.selectionStart, end = d.input.selectionEnd;
+ d.input.value += "$";
+ d.input.selectionStart = start;
+ d.input.selectionEnd = end;
+ cm.state.fakedLastChar = true;
+ }
cm.state.pasteIncoming = true;
fastPoll(cm);
});
if (captureMiddleClick) onContextMenu.call(cm, cm, e);
return;
case 2:
+ if (webkit) cm.state.lastMiddleDown = +new Date;
if (start) extendSelection(cm.doc, start);
setTimeout(bind(focusInput, cm), 20);
e_preventDefault(e);
on(document, "mouseup", up);
}
- function clickInGutter(cm, e) {
- var display = cm.display;
+ function gutterEvent(cm, e, type, prevent, signalfn) {
try { var mX = e.clientX, mY = e.clientY; }
catch(e) { return false; }
+ if (mX >= Math.floor(getRect(cm.display.gutters).right)) return false;
+ if (prevent) e_preventDefault(e);
- if (mX >= Math.floor(getRect(display.gutters).right)) return false;
- e_preventDefault(e);
- if (!hasHandler(cm, "gutterClick")) return true;
-
+ var display = cm.display;
var lineBox = getRect(display.lineDiv);
- if (mY > lineBox.bottom) return true;
+
+ if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e);
mY -= lineBox.top - display.viewOffset;
for (var i = 0; i < cm.options.gutters.length; ++i) {
if (g && getRect(g).right >= mX) {
var line = lineAtHeight(cm.doc, mY);
var gutter = cm.options.gutters[i];
- signalLater(cm, "gutterClick", cm, line, gutter, e);
- break;
+ signalfn(cm, type, cm, line, gutter, e);
+ return e_defaultPrevented(e);
}
}
- return true;
+ }
+
+ function contextMenuInGutter(cm, e) {
+ if (!hasHandler(cm, "gutterContextMenu")) return false;
+ return gutterEvent(cm, e, "gutterContextMenu", false, signal);
+ }
+
+ function clickInGutter(cm, e) {
+ return gutterEvent(cm, e, "gutterClick", true, signalLater);
}
// Kludge to work around strange IE behavior where it'll sometimes
function onKeyDown(e) {
var cm = this;
if (!cm.state.focused) onFocus(cm);
- if (ie && e.keyCode == 27) { e.returnValue = false; }
if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
+ if (ie && e.keyCode == 27) e.returnValue = false;
var code = e.keyCode;
// IE does strange things with escape.
cm.doc.sel.shift = code == 16 || e.shiftKey;
cm.state.focused = true;
if (cm.display.wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
cm.display.wrapper.className += " CodeMirror-focused";
- resetInput(cm, true);
+ if (!cm.curOp) {
+ resetInput(cm, true);
+ if (webkit) setTimeout(bind(resetInput, cm, true), 0); // Issue #1730
+ }
}
slowPoll(cm);
restartBlink(cm);
function onContextMenu(cm, e) {
if (signalDOMEvent(cm, e, "contextmenu")) return;
var display = cm.display, sel = cm.doc.sel;
- if (eventInWidget(display, e)) return;
+ if (eventInWidget(display, e) || contextMenuInGutter(cm, e)) return;
var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
if (!pos || opera) return; // Opera is difficult.
function prepareSelectAllHack() {
if (display.input.selectionStart != null) {
- var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value);
- display.prevInput = " ";
+ var extval = display.input.value = "\u200b" + (posEq(sel.from, sel.to) ? "" : display.input.value);
+ display.prevInput = "\u200b";
display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
}
}
updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop);
}),
- setSize: function(width, height) {
+ setSize: operation(null, function(width, height) {
function interpret(val) {
return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
}
if (width != null) this.display.wrapper.style.width = interpret(width);
if (height != null) this.display.wrapper.style.height = interpret(height);
- this.refresh();
- },
+ if (this.options.lineWrapping)
+ this.display.measureLineCache.length = this.display.measureLineCachePos = 0;
+ this.curOp.forceUpdate = true;
+ }),
operation: function(f){return runInOp(this, f);},
CodeMirror.innerMode = function(mode, state) {
while (mode.innerMode) {
var info = mode.innerMode(state);
+ if (!info || info.mode == mode) break;
state = info.state;
mode = info.mode;
}
if (this.explicitlyCleared) return;
var cm = this.doc.cm, withOp = cm && !cm.curOp;
if (withOp) startOperation(cm);
+ if (hasHandler(this, "clear")) {
+ var found = this.find();
+ if (found) signalLater(this, "clear", found.from, found.to);
+ }
var min = null, max = null;
for (var i = 0; i < this.lines.length; ++i) {
var line = this.lines[i];
if (cm) reCheckSelection(cm);
}
if (withOp) endOperation(cm);
- signalLater(this, "clear");
};
TextMarker.prototype.find = function() {
TextMarker.prototype.changed = function() {
var pos = this.find(), cm = this.doc.cm;
if (!pos || !cm) return;
- var line = getLine(this.doc, pos.from.line);
+ if (this.type != "bookmark") pos = pos.from;
+ var line = getLine(this.doc, pos.line);
clearCachedMeasurement(cm, line);
- if (pos.from.line >= cm.display.showingFrom && pos.from.line < cm.display.showingTo) {
+ if (pos.line >= cm.display.showingFrom && pos.line < cm.display.showingTo) {
for (var node = cm.display.lineDiv.firstChild; node; node = node.nextSibling) if (node.lineObj == line) {
if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight);
break;
}
- runInOp(cm, function() { cm.curOp.selectionChanged = true; });
+ runInOp(cm, function() {
+ cm.curOp.selectionChanged = cm.curOp.forceUpdate = cm.curOp.updateMaxLine = true;
+ });
}
};
(styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-"));
}
- function lineContent(cm, realLine, measure) {
+ function lineContent(cm, realLine, measure, copyWidgets) {
var merged, line = realLine, empty = true;
while (merged = collapsedSpanAtStart(line))
line = getLine(cm.doc, merged.find().from.line);
- var builder = {pre: elt("pre"), col: 0, pos: 0, display: !measure,
- measure: null, measuredSomething: false, cm: cm};
+ var builder = {pre: elt("pre"), col: 0, pos: 0,
+ measure: null, measuredSomething: false, cm: cm,
+ copyWidgets: copyWidgets};
if (line.textClass) builder.pre.className = line.textClass;
do {
function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
var widget = !ignoreWidget && marker.replacedWith;
if (widget) {
- if (!builder.display) widget = widget.cloneNode(true);
+ if (builder.copyWidgets) widget = widget.cloneNode(true);
builder.pre.appendChild(widget);
if (builder.measure) {
if (size) {
builder.measure[builder.pos] = widget;
} else {
- var elt = builder.measure[builder.pos] = zeroWidthElement(builder.cm.display.measure);
- if (marker.type != "bookmark" || marker.insertLeft)
- builder.pre.insertBefore(elt, widget);
+ var elt = zeroWidthElement(builder.cm.display.measure);
+ if (marker.type == "bookmark" && !marker.insertLeft)
+ builder.measure[builder.pos] = builder.pre.appendChild(elt);
+ else if (builder.measure[builder.pos])
+ return;
else
- builder.pre.appendChild(elt);
+ builder.measure[builder.pos] = builder.pre.insertBefore(elt, widget);
}
builder.measuredSomething = true;
}
if (nextChange == pos) { // Update current marker set
spanStyle = spanEndStyle = spanStartStyle = title = "";
collapsed = null; nextChange = Infinity;
- var foundBookmark = null;
+ 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)) {
} else if (sp.from > pos && nextChange > sp.from) {
nextChange = sp.from;
}
- if (m.type == "bookmark" && sp.from == pos && m.replacedWith) foundBookmark = m;
+ if (m.type == "bookmark" && sp.from == pos && m.replacedWith) foundBookmarks.push(m);
}
if (collapsed && (collapsed.from || 0) == pos) {
buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos,
collapsed.marker, collapsed.from == null);
if (collapsed.to == null) return collapsed.marker.find();
}
- if (foundBookmark && !collapsed) buildCollapsedSpan(builder, 0, foundBookmark);
+ if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)
+ buildCollapsedSpan(builder, 0, foundBookmarks[j]);
}
if (pos >= len) break;
if (extend) extendSelection(this, pos);
else setSelection(this, pos, pos);
}),
- setSelection: docOperation(function(anchor, head) {
- setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor));
+ setSelection: docOperation(function(anchor, head, bias) {
+ setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), bias);
}),
- extendSelection: docOperation(function(from, to) {
- extendSelection(this, clipPos(this, from), to && clipPos(this, to));
+ extendSelection: docOperation(function(from, to, bias) {
+ extendSelection(this, clipPos(this, from), to && clipPos(this, to), bias);
}),
getSelection: function(lineSep) {return this.getRange(this.sel.from, this.sel.to, lineSep);},
function signalDOMEvent(cm, e, override) {
signal(cm, override || e.type, cm, e);
- return e_defaultPrevented(e);
+ return e_defaultPrevented(e) || e.codemirrorIgnore;
}
function fireDelayed() {
// THE END
- CodeMirror.version = "3.14.1";
+ CodeMirror.version = "3.16.1";
return CodeMirror;
})();
// Push/pop context stack
if (type == "{") {
if (context == "@media" || context == "@mediaType") {
- state.stack.pop();
state.stack[state.stack.length-1] = "@media{";
}
else {
}
}
else if (type == "}") {
- var lastState = state.stack[state.stack.length - 1];
- if (lastState == "interpolation") style = "operator";
+ if (context == "interpolation") style = "operator";
state.stack.pop();
if (context == "propertyValue") state.stack.pop();
}
else if (type == "@media") state.stack.push("@media");
else if (type == "@import") state.stack.push("@import");
else if (context == "@media" && /\b(keyword|attribute)\b/.test(style))
- state.stack.push("@mediaType");
- else if (context == "@mediaType" && stream.current() == ",") state.stack.pop();
- else if (context == "@mediaType" && type == "(") state.stack.push("@mediaType(");
- else if (context == "@mediaType(" && type == ")") state.stack.pop();
+ state.stack[state.stack.length-1] = "@mediaType";
+ else if (context == "@mediaType" && stream.current() == ",")
+ state.stack[state.stack.length-1] = "@media";
+ else if (type == "(") {
+ if (context == "@media" || context == "@mediaType") {
+ // Make sure @mediaType is used to avoid error on {
+ state.stack[state.stack.length-1] = "@mediaType";
+ state.stack.push("@mediaType(");
+ }
+ }
+ else if (type == ")") {
+ if (context == "propertyValue" && state.stack[state.stack.length-2] == "@mediaType(") {
+ // In @mediaType( without closing ; after propertyValue
+ state.stack.pop();
+ state.stack.pop();
+ }
+ else if (context == "@mediaType(") {
+ state.stack.pop();
+ }
+ }
else if (type == ":" && state.lastToken == "property") state.stack.push("propertyValue");
else if (context == "propertyValue" && type == ";") state.stack.pop();
else if (context == "@import" && type == ";") state.stack.pop();
+
return state.lastToken = style;
},
indent: function(state, textAfter) {
var n = state.stack.length;
if (/^\}/.test(textAfter))
- n -= state.stack[state.stack.length-1] == "propertyValue" ? 2 : 1;
+ n -= state.stack[n-1] == "propertyValue" ? 2 : 1;
return state.baseIndent + n * indentUnit;
},
"drop-initial-before-align", "drop-initial-size", "drop-initial-value",
"elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
"flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
- "float", "float-offset", "font", "font-feature-settings", "font-family",
- "font-kerning", "font-language-override", "font-size", "font-size-adjust",
+ "float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings",
+ "font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust",
"font-stretch", "font-style", "font-synthesis", "font-variant",
"font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
"font-variant-ligatures", "font-variant-numeric", "font-variant-position",
"page", "page-break-after", "page-break-before", "page-break-inside",
"page-policy", "pause", "pause-after", "pause-before", "perspective",
"perspective-origin", "pitch", "pitch-range", "play-during", "position",
- "presentation-level", "punctuation-trim", "quotes", "rendering-intent",
- "resize", "rest", "rest-after", "rest-before", "richness", "right",
- "rotation", "rotation-point", "ruby-align", "ruby-overhang",
- "ruby-position", "ruby-span", "size", "speak", "speak-as", "speak-header",
+ "presentation-level", "punctuation-trim", "quotes", "region-break-after",
+ "region-break-before", "region-break-inside", "region-fragment",
+ "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
+ "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang",
+ "ruby-position", "ruby-span", "shape-inside", "shape-outside", "size",
+ "speak", "speak-as", "speak-header",
"speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
"tab-size", "table-layout", "target", "target-name", "target-new",
"target-position", "text-align", "text-align-last", "text-decoration",
"text-decoration-color", "text-decoration-line", "text-decoration-skip",
"text-decoration-style", "text-emphasis", "text-emphasis-color",
"text-emphasis-position", "text-emphasis-style", "text-height",
- "text-indent", "text-justify", "text-outline", "text-shadow",
- "text-space-collapse", "text-transform", "text-underline-position",
+ "text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow",
+ "text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position",
"text-wrap", "top", "transform", "transform-origin", "transform-style",
"transition", "transition-delay", "transition-duration",
"transition-property", "transition-timing-function", "unicode-bidi",
"vertical-align", "visibility", "voice-balance", "voice-duration",
"voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
"voice-volume", "volume", "white-space", "widows", "width", "word-break",
- "word-spacing", "word-wrap", "z-index",
+ "word-spacing", "word-wrap", "z-index", "zoom",
// SVG-specific
"clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
"flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
"darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
"deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
"floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
- "gold", "goldenrod", "gray", "green", "greenyellow", "honeydew",
+ "gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
"hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
"lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
"lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
"above", "absolute", "activeborder", "activecaption", "afar",
"after-white-space", "ahead", "alias", "all", "all-scroll", "alternate",
"always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
- "arabic-indic", "armenian", "asterisks", "auto", "avoid", "background",
- "backwards", "baseline", "below", "bidi-override", "binary", "bengali",
- "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
- "both", "bottom", "break-all", "break-word", "button", "button-bevel",
+ "arabic-indic", "armenian", "asterisks", "auto", "avoid", "avoid-column", "avoid-page",
+ "avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary",
+ "bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
+ "both", "bottom", "break", "break-all", "break-word", "button", "button-bevel",
"buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian",
"capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
"cell", "center", "checkbox", "circle", "cjk-earthly-branch",
"cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
- "col-resize", "collapse", "compact", "condensed", "contain", "content",
+ "col-resize", "collapse", "column", "compact", "condensed", "contain", "content",
"content-box", "context-menu", "continuous", "copy", "cover", "crop",
"cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal",
"decimal-leading-zero", "default", "default-button", "destination-atop",
"destination-in", "destination-out", "destination-over", "devanagari",
"disc", "discard", "document", "dot-dash", "dot-dot-dash", "dotted",
"double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
- "element", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
+ "element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
"ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
"ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
"ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
"inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
"infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
"inline-block", "inline-table", "inset", "inside", "intrinsic", "invert",
- "italic", "justify", "kannada", "katakana", "katakana-iroha", "khmer",
+ "italic", "justify", "kannada", "katakana", "katakana-iroha", "keep-all", "khmer",
"landscape", "lao", "large", "larger", "left", "level", "lighter",
"line-through", "linear", "lines", "list-item", "listbox", "listitem",
"local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
"no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
"ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
"optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
- "outside", "overlay", "overline", "padding", "padding-box", "painted",
- "paused", "persian", "plus-darker", "plus-lighter", "pointer", "portrait",
- "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button",
- "radio", "read-only", "read-write", "read-write-plaintext-only", "relative",
- "repeat", "repeat-x", "repeat-y", "reset", "reverse", "rgb", "rgba",
+ "outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
+ "painted", "page", "paused", "persian", "plus-darker", "plus-lighter", "pointer",
+ "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button",
+ "radio", "read-only", "read-write", "read-write-plaintext-only", "rectangle", "region",
+ "relative", "repeat", "repeat-x", "repeat-y", "reset", "reverse", "rgb", "rgba",
"ridge", "right", "round", "row-resize", "rtl", "run-in", "running",
"s-resize", "sans-serif", "scroll", "scrollbar", "se-resize", "searchfield",
"searchfield-cancel-button", "searchfield-decoration",
type = tp; content = cont;
return style;
}
-
function jsTokenBase(stream, state) {
var ch = stream.next();
if (ch == '"' || ch == "'")
return chain(stream, state, jsTokenString(ch));
+ else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/))
+ return ret("number", "number");
else if (/[\[\]{}\(\),;\:\.]/.test(ch))
return ret(ch);
else if (ch == "0" && stream.eat(/x/i)) {
stream.eatWhile(/[\da-f]/i);
return ret("number", "number");
}
- else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) {
+ else if (/\d/.test(ch)) {
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
return ret("number", "number");
}
function maybeoperatorComma(type, value) {
if (type == ",") return cont(expression);
- return maybeoperatorNoComma(type, value, maybeoperatorComma);
+ return maybeoperatorNoComma(type, value, false);
}
- function maybeoperatorNoComma(type, value, me) {
- if (!me) me = maybeoperatorNoComma;
+ function maybeoperatorNoComma(type, value, noComma) {
+ var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
+ var expr = noComma == false ? expression : expressionNoComma;
if (type == "operator") {
if (/\+\+|--/.test(value)) return cont(me);
- if (value == "?") return cont(expression, expect(":"), expression);
- return cont(expression);
+ if (value == "?") return cont(expression, expect(":"), expr);
+ return cont(expr);
}
if (type == ";") return;
if (type == "(") return cont(pushlex(")", "call"), commasep(expressionNoComma, ")"), poplex, me);
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
+.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */
white-space: pre-wrap;
word-break: normal;
}
+.CodeMirror-code pre {
+ border-right: 30px solid transparent;
+ width: -webkit-fit-content;
+ width: -moz-fit-content;
+ width: fit-content;
+}
+.CodeMirror-wrap .CodeMirror-code pre {
+ border-right: none;
+ width: auto;
+}
.CodeMirror-linebackground {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
// This is woefully incomplete. Suggestions for alternative methods welcome.
var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
var mac = ios || /Mac/.test(navigator.platform);
- var windows = /windows/i.test(navigator.platform);
+ var windows = /win/i.test(navigator.platform);
var opera_version = opera && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
if (opera_version) opera_version = Number(opera_version[1]);
+ if (opera_version && opera_version >= 15) { opera = false; webkit = true; }
// Some browsers use the wrong event properties to signal cmd/ctrl on OS X
var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11));
var captureMiddleClick = gecko || (ie && !ie_lt9);
d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
d.scrollbarV.firstChild.style.height =
(scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px";
- } else d.scrollbarV.style.display = "";
+ } else {
+ d.scrollbarV.style.display = "";
+ d.scrollbarV.firstChild.style.height = "0";
+ }
if (needsH) {
d.scrollbarH.style.display = "block";
d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0";
d.scrollbarH.firstChild.style.width =
(d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px";
- } else d.scrollbarH.style.display = "";
+ } else {
+ d.scrollbarH.style.display = "";
+ d.scrollbarH.firstChild.style.width = "0";
+ }
if (needsH && needsV) {
d.scrollbarFiller.style.display = "block";
d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
// DISPLAY DRAWING
- function updateDisplay(cm, changes, viewPort) {
+ function updateDisplay(cm, changes, viewPort, forced) {
var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
var visible = visibleLines(cm.display, cm.doc, viewPort);
for (;;) {
- if (!updateDisplayInner(cm, changes, visible)) break;
+ if (!updateDisplayInner(cm, changes, visible, forced)) break;
+ forced = false;
updated = true;
updateSelection(cm);
updateScrollbars(cm);
// Uses a set of changes plus the current scroll position to
// determine which DOM updates have to be made, and makes the
// updates.
- function updateDisplayInner(cm, changes, visible) {
+ function updateDisplayInner(cm, changes, visible, forced) {
var display = cm.display, doc = cm.doc;
if (!display.wrapper.clientWidth) {
display.showingFrom = display.showingTo = doc.first;
}
// Bail out if the visible area is already rendered and nothing changed.
- if (changes.length == 0 &&
+ if (!forced && changes.length == 0 &&
visible.from > display.showingFrom && visible.to < display.showingTo)
return;
var positionsChangedFrom = Infinity;
if (cm.options.lineNumbers)
for (var i = 0; i < changes.length; ++i)
- if (changes[i].diff) { positionsChangedFrom = changes[i].from; break; }
+ if (changes[i].diff && changes[i].from < positionsChangedFrom) { positionsChangedFrom = changes[i].from; }
var end = doc.first + doc.size;
var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);
if (range.from >= range.to) intact.splice(i--, 1);
else intactLines += range.to - range.from;
}
- if (intactLines == to - from && from == display.showingFrom && to == display.showingTo) {
+ if (!forced && intactLines == to - from && from == display.showingFrom && to == display.showingTo) {
updateViewOffset(cm);
return;
}
}
display.showingFrom = from; display.showingTo = to;
+ updateHeightsInViewport(cm);
+ updateViewOffset(cm);
+
+ return true;
+ }
+
+ function updateHeightsInViewport(cm) {
+ var display = cm.display;
var prevBottom = display.lineDiv.offsetTop;
for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {
if (ie_lt8) {
widgets[i].height = widgets[i].node.offsetHeight;
}
}
- updateViewOffset(cm);
-
- return true;
}
function updateViewOffset(cm) {
if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();
if (lineIsHidden(cm.doc, line)) {
if (line.height != 0) updateLineHeight(line, 0);
- if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {
+ if (line.widgets && cur && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {
var w = line.widgets[i];
if (w.showIfHidden) {
var prev = cur.previousSibling;
clearInterval(display.blinker);
var on = true;
display.cursor.style.visibility = display.otherCursor.style.visibility = "";
- display.blinker = setInterval(function() {
- display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
- }, cm.options.cursorBlinkRate);
+ if (cm.options.cursorBlinkRate > 0)
+ display.blinker = setInterval(function() {
+ display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
+ }, cm.options.cursorBlinkRate);
}
// HIGHLIGHT WORKER
// smallest indentation, which tends to need the least context to
// parse correctly.
function findStartLine(cm, n, precise) {
- var minindent, minline, doc = cm.doc;
- for (var search = n, lim = n - 100; search > lim; --search) {
+ var minindent, minline, doc = cm.doc, maxScan = cm.doc.mode.innerMode ? 1000 : 100;
+ for (var search = n, lim = n - maxScan; search > lim; --search) {
if (search <= doc.first) return doc.first;
var line = getLine(doc, search - 1);
if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
function getStateBefore(cm, n, precise) {
var doc = cm.doc, display = cm.display;
- if (!doc.mode.startState) return true;
+ if (!doc.mode.startState) return true;
var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
if (!state) state = startState(doc.mode);
else state = copyState(doc.mode, state);
function measureLineInner(cm, line) {
var display = cm.display, measure = emptyArray(line.text.length);
- var pre = lineContent(cm, line, measure);
+ var pre = lineContent(cm, line, measure, true);
// IE does not cache element positions of inline elements between
// calls to getBoundingClientRect. This makes the loop below,
if (cur.measureRight) rect.right = getRect(cur.measureRight).left;
if (cur.leftSide) rect.leftSide = measureRect(getRect(cur.leftSide));
}
+ removeChildren(cm.display.measure);
for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
finishRect(cur);
if (cur.leftSide) finishRect(cur.leftSide);
var cached = !hasBadSpan && findCachedMeasurement(cm, line);
if (cached) return measureChar(cm, line, line.text.length, cached.measure, "right").right;
- var pre = lineContent(cm, line);
+ var pre = lineContent(cm, line, null, true);
var end = pre.appendChild(zeroWidthElement(cm.display.measure));
removeChildrenAndAdd(cm.display.measure, pre);
return getRect(end).right - getRect(cm.display.lineDiv).left;
// An array of ranges of lines that have to be updated. See
// updateDisplay.
changes: [],
+ forceUpdate: false,
updateInput: null,
userSelChange: null,
textChanged: null,
var coords = cursorCoords(cm, doc.sel.head);
newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
}
- if (op.changes.length || newScrollPos && newScrollPos.scrollTop != null) {
- updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop);
+ if (op.changes.length || op.forceUpdate || newScrollPos && newScrollPos.scrollTop != null) {
+ updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop, op.forceUpdate);
if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop;
}
if (!updated && op.selectionChanged) updateSelection(cm);
function readInput(cm) {
var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;
if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.state.disableInput) return false;
+ if (cm.state.pasteIncoming && cm.state.fakedLastChar) {
+ input.value = input.value.substring(0, input.value.length - 1);
+ cm.state.fakedLastChar = false;
+ }
var text = input.value;
if (text == prevInput && posEq(sel.from, sel.to)) return false;
if (ie && !ie_lt9 && cm.display.inputHasSelection === text) {
on(d.scroller, "dragover", drag_);
on(d.scroller, "drop", operation(cm, onDrop));
}
- on(d.scroller, "paste", function(e){
+ on(d.scroller, "paste", function(e) {
if (eventInWidget(d, e)) return;
focusInput(cm);
fastPoll(cm);
});
on(d.input, "paste", function() {
+ // Workaround for webkit bug https://bugs.webkit.org/show_bug.cgi?id=90206
+ // Add a char to the end of textarea before paste occur so that
+ // selection doesn't span to the end of textarea.
+ if (webkit && !cm.state.fakedLastChar && !(new Date - cm.state.lastMiddleDown < 200)) {
+ var start = d.input.selectionStart, end = d.input.selectionEnd;
+ d.input.value += "$";
+ d.input.selectionStart = start;
+ d.input.selectionEnd = end;
+ cm.state.fakedLastChar = true;
+ }
cm.state.pasteIncoming = true;
fastPoll(cm);
});
if (captureMiddleClick) onContextMenu.call(cm, cm, e);
return;
case 2:
+ if (webkit) cm.state.lastMiddleDown = +new Date;
if (start) extendSelection(cm.doc, start);
setTimeout(bind(focusInput, cm), 20);
e_preventDefault(e);
on(document, "mouseup", up);
}
- function clickInGutter(cm, e) {
- var display = cm.display;
+ function gutterEvent(cm, e, type, prevent, signalfn) {
try { var mX = e.clientX, mY = e.clientY; }
catch(e) { return false; }
+ if (mX >= Math.floor(getRect(cm.display.gutters).right)) return false;
+ if (prevent) e_preventDefault(e);
- if (mX >= Math.floor(getRect(display.gutters).right)) return false;
- e_preventDefault(e);
- if (!hasHandler(cm, "gutterClick")) return true;
-
+ var display = cm.display;
var lineBox = getRect(display.lineDiv);
- if (mY > lineBox.bottom) return true;
+
+ if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e);
mY -= lineBox.top - display.viewOffset;
for (var i = 0; i < cm.options.gutters.length; ++i) {
if (g && getRect(g).right >= mX) {
var line = lineAtHeight(cm.doc, mY);
var gutter = cm.options.gutters[i];
- signalLater(cm, "gutterClick", cm, line, gutter, e);
- break;
+ signalfn(cm, type, cm, line, gutter, e);
+ return e_defaultPrevented(e);
}
}
- return true;
+ }
+
+ function contextMenuInGutter(cm, e) {
+ if (!hasHandler(cm, "gutterContextMenu")) return false;
+ return gutterEvent(cm, e, "gutterContextMenu", false, signal);
+ }
+
+ function clickInGutter(cm, e) {
+ return gutterEvent(cm, e, "gutterClick", true, signalLater);
}
// Kludge to work around strange IE behavior where it'll sometimes
function onKeyDown(e) {
var cm = this;
if (!cm.state.focused) onFocus(cm);
- if (ie && e.keyCode == 27) { e.returnValue = false; }
if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
+ if (ie && e.keyCode == 27) e.returnValue = false;
var code = e.keyCode;
// IE does strange things with escape.
cm.doc.sel.shift = code == 16 || e.shiftKey;
cm.state.focused = true;
if (cm.display.wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
cm.display.wrapper.className += " CodeMirror-focused";
- resetInput(cm, true);
+ if (!cm.curOp) {
+ resetInput(cm, true);
+ if (webkit) setTimeout(bind(resetInput, cm, true), 0); // Issue #1730
+ }
}
slowPoll(cm);
restartBlink(cm);
function onContextMenu(cm, e) {
if (signalDOMEvent(cm, e, "contextmenu")) return;
var display = cm.display, sel = cm.doc.sel;
- if (eventInWidget(display, e)) return;
+ if (eventInWidget(display, e) || contextMenuInGutter(cm, e)) return;
var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
if (!pos || opera) return; // Opera is difficult.
function prepareSelectAllHack() {
if (display.input.selectionStart != null) {
- var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value);
- display.prevInput = " ";
+ var extval = display.input.value = "\u200b" + (posEq(sel.from, sel.to) ? "" : display.input.value);
+ display.prevInput = "\u200b";
display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
}
}
updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop);
}),
- setSize: function(width, height) {
+ setSize: operation(null, function(width, height) {
function interpret(val) {
return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
}
if (width != null) this.display.wrapper.style.width = interpret(width);
if (height != null) this.display.wrapper.style.height = interpret(height);
- this.refresh();
- },
+ if (this.options.lineWrapping)
+ this.display.measureLineCache.length = this.display.measureLineCachePos = 0;
+ this.curOp.forceUpdate = true;
+ }),
operation: function(f){return runInOp(this, f);},
CodeMirror.innerMode = function(mode, state) {
while (mode.innerMode) {
var info = mode.innerMode(state);
+ if (!info || info.mode == mode) break;
state = info.state;
mode = info.mode;
}
if (this.explicitlyCleared) return;
var cm = this.doc.cm, withOp = cm && !cm.curOp;
if (withOp) startOperation(cm);
+ if (hasHandler(this, "clear")) {
+ var found = this.find();
+ if (found) signalLater(this, "clear", found.from, found.to);
+ }
var min = null, max = null;
for (var i = 0; i < this.lines.length; ++i) {
var line = this.lines[i];
if (cm) reCheckSelection(cm);
}
if (withOp) endOperation(cm);
- signalLater(this, "clear");
};
TextMarker.prototype.find = function() {
TextMarker.prototype.changed = function() {
var pos = this.find(), cm = this.doc.cm;
if (!pos || !cm) return;
- var line = getLine(this.doc, pos.from.line);
+ if (this.type != "bookmark") pos = pos.from;
+ var line = getLine(this.doc, pos.line);
clearCachedMeasurement(cm, line);
- if (pos.from.line >= cm.display.showingFrom && pos.from.line < cm.display.showingTo) {
+ if (pos.line >= cm.display.showingFrom && pos.line < cm.display.showingTo) {
for (var node = cm.display.lineDiv.firstChild; node; node = node.nextSibling) if (node.lineObj == line) {
if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight);
break;
}
- runInOp(cm, function() { cm.curOp.selectionChanged = true; });
+ runInOp(cm, function() {
+ cm.curOp.selectionChanged = cm.curOp.forceUpdate = cm.curOp.updateMaxLine = true;
+ });
}
};
(styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-"));
}
- function lineContent(cm, realLine, measure) {
+ function lineContent(cm, realLine, measure, copyWidgets) {
var merged, line = realLine, empty = true;
while (merged = collapsedSpanAtStart(line))
line = getLine(cm.doc, merged.find().from.line);
- var builder = {pre: elt("pre"), col: 0, pos: 0, display: !measure,
- measure: null, measuredSomething: false, cm: cm};
+ var builder = {pre: elt("pre"), col: 0, pos: 0,
+ measure: null, measuredSomething: false, cm: cm,
+ copyWidgets: copyWidgets};
if (line.textClass) builder.pre.className = line.textClass;
do {
function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
var widget = !ignoreWidget && marker.replacedWith;
if (widget) {
- if (!builder.display) widget = widget.cloneNode(true);
+ if (builder.copyWidgets) widget = widget.cloneNode(true);
builder.pre.appendChild(widget);
if (builder.measure) {
if (size) {
builder.measure[builder.pos] = widget;
} else {
- var elt = builder.measure[builder.pos] = zeroWidthElement(builder.cm.display.measure);
- if (marker.type != "bookmark" || marker.insertLeft)
- builder.pre.insertBefore(elt, widget);
+ var elt = zeroWidthElement(builder.cm.display.measure);
+ if (marker.type == "bookmark" && !marker.insertLeft)
+ builder.measure[builder.pos] = builder.pre.appendChild(elt);
+ else if (builder.measure[builder.pos])
+ return;
else
- builder.pre.appendChild(elt);
+ builder.measure[builder.pos] = builder.pre.insertBefore(elt, widget);
}
builder.measuredSomething = true;
}
if (nextChange == pos) { // Update current marker set
spanStyle = spanEndStyle = spanStartStyle = title = "";
collapsed = null; nextChange = Infinity;
- var foundBookmark = null;
+ 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)) {
} else if (sp.from > pos && nextChange > sp.from) {
nextChange = sp.from;
}
- if (m.type == "bookmark" && sp.from == pos && m.replacedWith) foundBookmark = m;
+ if (m.type == "bookmark" && sp.from == pos && m.replacedWith) foundBookmarks.push(m);
}
if (collapsed && (collapsed.from || 0) == pos) {
buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos,
collapsed.marker, collapsed.from == null);
if (collapsed.to == null) return collapsed.marker.find();
}
- if (foundBookmark && !collapsed) buildCollapsedSpan(builder, 0, foundBookmark);
+ if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)
+ buildCollapsedSpan(builder, 0, foundBookmarks[j]);
}
if (pos >= len) break;
if (extend) extendSelection(this, pos);
else setSelection(this, pos, pos);
}),
- setSelection: docOperation(function(anchor, head) {
- setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor));
+ setSelection: docOperation(function(anchor, head, bias) {
+ setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), bias);
}),
- extendSelection: docOperation(function(from, to) {
- extendSelection(this, clipPos(this, from), to && clipPos(this, to));
+ extendSelection: docOperation(function(from, to, bias) {
+ extendSelection(this, clipPos(this, from), to && clipPos(this, to), bias);
}),
getSelection: function(lineSep) {return this.getRange(this.sel.from, this.sel.to, lineSep);},
function signalDOMEvent(cm, e, override) {
signal(cm, override || e.type, cm, e);
- return e_defaultPrevented(e);
+ return e_defaultPrevented(e) || e.codemirrorIgnore;
}
function fireDelayed() {
};
else if (safari && !/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent))
spanAffectsWrapping = function(str, i) {
- return (/\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/).test(str.slice(i - 1, i + 1));
+ return /\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/.test(str.slice(i - 1, i + 1));
};
else if (webkit && !/Chrome\/(?:29|[3-9]\d|\d\d\d)\./.test(navigator.userAgent))
spanAffectsWrapping = function(str, i) {
if (/\w/.test(str.charAt(i - 2)) && /[^\-?\.]/.test(str.charAt(i))) return true;
if (i > 2 && /[\d\.,]/.test(str.charAt(i - 2)) && /[\d\.,]/.test(str.charAt(i))) return false;
}
- return (/[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/).test(str.slice(i - 1, i + 1));
+ return /[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1));
};
var knownScrollbarWidth;
// THE END
- CodeMirror.version = "3.14.1";
+ CodeMirror.version = "3.16.1";
return CodeMirror;
})();
// Push/pop context stack
if (type == "{") {
if (context == "@media" || context == "@mediaType") {
- state.stack.pop();
state.stack[state.stack.length-1] = "@media{";
}
else {
}
}
else if (type == "}") {
- var lastState = state.stack[state.stack.length - 1];
- if (lastState == "interpolation") style = "operator";
+ if (context == "interpolation") style = "operator";
state.stack.pop();
if (context == "propertyValue") state.stack.pop();
}
else if (type == "@media") state.stack.push("@media");
else if (type == "@import") state.stack.push("@import");
else if (context == "@media" && /\b(keyword|attribute)\b/.test(style))
- state.stack.push("@mediaType");
- else if (context == "@mediaType" && stream.current() == ",") state.stack.pop();
- else if (context == "@mediaType" && type == "(") state.stack.push("@mediaType(");
- else if (context == "@mediaType(" && type == ")") state.stack.pop();
+ state.stack[state.stack.length-1] = "@mediaType";
+ else if (context == "@mediaType" && stream.current() == ",")
+ state.stack[state.stack.length-1] = "@media";
+ else if (type == "(") {
+ if (context == "@media" || context == "@mediaType") {
+ // Make sure @mediaType is used to avoid error on {
+ state.stack[state.stack.length-1] = "@mediaType";
+ state.stack.push("@mediaType(");
+ }
+ }
+ else if (type == ")") {
+ if (context == "propertyValue" && state.stack[state.stack.length-2] == "@mediaType(") {
+ // In @mediaType( without closing ; after propertyValue
+ state.stack.pop();
+ state.stack.pop();
+ }
+ else if (context == "@mediaType(") {
+ state.stack.pop();
+ }
+ }
else if (type == ":" && state.lastToken == "property") state.stack.push("propertyValue");
else if (context == "propertyValue" && type == ";") state.stack.pop();
else if (context == "@import" && type == ";") state.stack.pop();
+
return state.lastToken = style;
},
indent: function(state, textAfter) {
var n = state.stack.length;
if (/^\}/.test(textAfter))
- n -= state.stack[state.stack.length-1] == "propertyValue" ? 2 : 1;
+ n -= state.stack[n-1] == "propertyValue" ? 2 : 1;
return state.baseIndent + n * indentUnit;
},
"drop-initial-before-align", "drop-initial-size", "drop-initial-value",
"elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
"flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
- "float", "float-offset", "font", "font-feature-settings", "font-family",
- "font-kerning", "font-language-override", "font-size", "font-size-adjust",
+ "float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings",
+ "font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust",
"font-stretch", "font-style", "font-synthesis", "font-variant",
"font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
"font-variant-ligatures", "font-variant-numeric", "font-variant-position",
"page", "page-break-after", "page-break-before", "page-break-inside",
"page-policy", "pause", "pause-after", "pause-before", "perspective",
"perspective-origin", "pitch", "pitch-range", "play-during", "position",
- "presentation-level", "punctuation-trim", "quotes", "rendering-intent",
- "resize", "rest", "rest-after", "rest-before", "richness", "right",
- "rotation", "rotation-point", "ruby-align", "ruby-overhang",
- "ruby-position", "ruby-span", "size", "speak", "speak-as", "speak-header",
+ "presentation-level", "punctuation-trim", "quotes", "region-break-after",
+ "region-break-before", "region-break-inside", "region-fragment",
+ "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
+ "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang",
+ "ruby-position", "ruby-span", "shape-inside", "shape-outside", "size",
+ "speak", "speak-as", "speak-header",
"speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
"tab-size", "table-layout", "target", "target-name", "target-new",
"target-position", "text-align", "text-align-last", "text-decoration",
"text-decoration-color", "text-decoration-line", "text-decoration-skip",
"text-decoration-style", "text-emphasis", "text-emphasis-color",
"text-emphasis-position", "text-emphasis-style", "text-height",
- "text-indent", "text-justify", "text-outline", "text-shadow",
- "text-space-collapse", "text-transform", "text-underline-position",
+ "text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow",
+ "text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position",
"text-wrap", "top", "transform", "transform-origin", "transform-style",
"transition", "transition-delay", "transition-duration",
"transition-property", "transition-timing-function", "unicode-bidi",
"vertical-align", "visibility", "voice-balance", "voice-duration",
"voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
"voice-volume", "volume", "white-space", "widows", "width", "word-break",
- "word-spacing", "word-wrap", "z-index",
+ "word-spacing", "word-wrap", "z-index", "zoom",
// SVG-specific
"clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
"flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
"darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
"deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
"floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
- "gold", "goldenrod", "gray", "green", "greenyellow", "honeydew",
+ "gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
"hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
"lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
"lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
"above", "absolute", "activeborder", "activecaption", "afar",
"after-white-space", "ahead", "alias", "all", "all-scroll", "alternate",
"always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
- "arabic-indic", "armenian", "asterisks", "auto", "avoid", "background",
- "backwards", "baseline", "below", "bidi-override", "binary", "bengali",
- "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
- "both", "bottom", "break-all", "break-word", "button", "button-bevel",
+ "arabic-indic", "armenian", "asterisks", "auto", "avoid", "avoid-column", "avoid-page",
+ "avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary",
+ "bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
+ "both", "bottom", "break", "break-all", "break-word", "button", "button-bevel",
"buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian",
"capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
"cell", "center", "checkbox", "circle", "cjk-earthly-branch",
"cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
- "col-resize", "collapse", "compact", "condensed", "contain", "content",
+ "col-resize", "collapse", "column", "compact", "condensed", "contain", "content",
"content-box", "context-menu", "continuous", "copy", "cover", "crop",
"cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal",
"decimal-leading-zero", "default", "default-button", "destination-atop",
"destination-in", "destination-out", "destination-over", "devanagari",
"disc", "discard", "document", "dot-dash", "dot-dot-dash", "dotted",
"double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
- "element", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
+ "element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
"ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
"ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
"ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
"inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
"infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
"inline-block", "inline-table", "inset", "inside", "intrinsic", "invert",
- "italic", "justify", "kannada", "katakana", "katakana-iroha", "khmer",
+ "italic", "justify", "kannada", "katakana", "katakana-iroha", "keep-all", "khmer",
"landscape", "lao", "large", "larger", "left", "level", "lighter",
"line-through", "linear", "lines", "list-item", "listbox", "listitem",
"local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
"no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
"ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
"optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
- "outside", "overlay", "overline", "padding", "padding-box", "painted",
- "paused", "persian", "plus-darker", "plus-lighter", "pointer", "portrait",
- "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button",
- "radio", "read-only", "read-write", "read-write-plaintext-only", "relative",
- "repeat", "repeat-x", "repeat-y", "reset", "reverse", "rgb", "rgba",
+ "outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
+ "painted", "page", "paused", "persian", "plus-darker", "plus-lighter", "pointer",
+ "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button",
+ "radio", "read-only", "read-write", "read-write-plaintext-only", "rectangle", "region",
+ "relative", "repeat", "repeat-x", "repeat-y", "reset", "reverse", "rgb", "rgba",
"ridge", "right", "round", "row-resize", "rtl", "run-in", "running",
"s-resize", "sans-serif", "scroll", "scrollbar", "se-resize", "searchfield",
"searchfield-cancel-button", "searchfield-decoration",
type = tp; content = cont;
return style;
}
-
function jsTokenBase(stream, state) {
var ch = stream.next();
if (ch == '"' || ch == "'")
return chain(stream, state, jsTokenString(ch));
+ else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/))
+ return ret("number", "number");
else if (/[\[\]{}\(\),;\:\.]/.test(ch))
return ret(ch);
else if (ch == "0" && stream.eat(/x/i)) {
stream.eatWhile(/[\da-f]/i);
return ret("number", "number");
}
- else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) {
+ else if (/\d/.test(ch)) {
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
return ret("number", "number");
}
function maybeoperatorComma(type, value) {
if (type == ",") return cont(expression);
- return maybeoperatorNoComma(type, value, maybeoperatorComma);
+ return maybeoperatorNoComma(type, value, false);
}
- function maybeoperatorNoComma(type, value, me) {
- if (!me) me = maybeoperatorNoComma;
+ function maybeoperatorNoComma(type, value, noComma) {
+ var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
+ var expr = noComma == false ? expression : expressionNoComma;
if (type == "operator") {
if (/\+\+|--/.test(value)) return cont(me);
- if (value == "?") return cont(expression, expect(":"), expression);
- return cont(expression);
+ if (value == "?") return cont(expression, expect(":"), expr);
+ return cont(expr);
}
if (type == ";") return;
if (type == "(") return cont(pushlex(")", "call"), commasep(expressionNoComma, ")"), poplex, me);
CodeMirror.defineMode("xml", function(config, parserConfig) {
var indentUnit = config.indentUnit;
var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1;
+ var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag || true;
var Kludges = parserConfig.htmlMode ? {
autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
return "error";
} else if (/[\'\"]/.test(ch)) {
state.tokenize = inAttribute(ch);
+ state.stringStartCol = stream.column();
return state.tokenize(stream, state);
} else {
stream.eatWhile(/[^\s\u00a0=<>\"\']/);
}
function inAttribute(quote) {
- return function(stream, state) {
+ var closure = function(stream, state) {
while (!stream.eol()) {
if (stream.next() == quote) {
state.tokenize = inTag;
}
return "string";
};
+ closure.isInAttribute = true;
+ return closure;
}
function inBlock(style, terminator) {
function attribute(type) {
if (type == "equals") return cont(attvalue, attributes);
if (!Kludges.allowMissing) setStyle = "error";
- else if (type == "word") setStyle = "attribute";
+ else if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);}
return (type == "endTag" || type == "selfcloseTag") ? pass() : cont();
}
function attvalue(type) {
indent: function(state, textAfter, fullLine) {
var context = state.context;
+ // Indent multi-line strings (e.g. css).
+ if (state.tokenize.isInAttribute) {
+ return state.stringStartCol + 1;
+ }
if ((state.tokenize != inTag && state.tokenize != inText) ||
context && context.noIndent)
return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
- if (state.tagName) return state.tagStart + indentUnit * multilineTagIndentFactor;
+ // Indent the starts of attribute names.
+ if (state.tagName) {
+ if (multilineTagIndentPastTag)
+ return state.tagStart + state.tagName.length + 2;
+ else
+ return state.tagStart + indentUnit * multilineTagIndentFactor;
+ }
if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
if (context && /^<\//.test(textAfter))
context = context.prev;