+2014-06-17 Jono Wells <jonowells@apple.com>
+
+ Web Inspector: Two lines in CSS rule are hidden until resize or click
+ https://bugs.webkit.org/show_bug.cgi?id=133951
+
+ Reviewed by Joseph Pecoraro.
+
+ Update to CodeMirror 4.2 fixed the issue.
+
+ * Tools/PrettyPrinting/codemirror.js:
+ * Tools/PrettyPrinting/css.js:
+ * Tools/PrettyPrinting/javascript.js:
+ * UserInterface/External/CodeMirror/clojure.js:
+ * UserInterface/External/CodeMirror/closebrackets.js:
+ * UserInterface/External/CodeMirror/codemirror.js:
+ * UserInterface/External/CodeMirror/coffeescript.js:
+ * UserInterface/External/CodeMirror/comment.js:
+ * UserInterface/External/CodeMirror/css.js:
+ * UserInterface/External/CodeMirror/htmlmixed.js:
+ * UserInterface/External/CodeMirror/javascript.js:
+ * UserInterface/External/CodeMirror/livescript.js:
+ * UserInterface/External/CodeMirror/matchbrackets.js:
+ * UserInterface/External/CodeMirror/overlay.js:
+ * UserInterface/External/CodeMirror/placeholder.js:
+ * UserInterface/External/CodeMirror/runmode.js:
+ * UserInterface/External/CodeMirror/sass.js:
+ * UserInterface/External/CodeMirror/searchcursor.js:
+ * UserInterface/External/CodeMirror/sql.js:
+ * UserInterface/External/CodeMirror/xml.js:
+ Update CodeMirror 4.1 to CodeMirror 4.2.0.
+
2014-06-17 Jono Wells <jonowells@apple.com>
Web Inspector: style declaration editor: visual highlight doesn't match actual selected text
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
// This is CodeMirror (http://codemirror.net), a code editor
// implemented in JavaScript on top of the browser's DOM.
//
if (ie_upto10) setTimeout(bind(resetInput, this, true), 20);
registerEventHandlers(this);
+ ensureGlobalHandlers();
var cm = this;
runInOp(this, function() {
// the the current scroll position). viewPort may contain top,
// height, and ensure (see op.scrollToPos) properties.
function visibleLines(display, doc, viewPort) {
- var top = viewPort && viewPort.top != null ? viewPort.top : display.scroller.scrollTop;
+ var top = viewPort && viewPort.top != null ? Math.max(0, viewPort.top) : display.scroller.scrollTop;
top = Math.floor(top - paddingTop(display));
var bottom = viewPort && viewPort.bottom != null ? viewPort.bottom : top + display.wrapper.clientHeight;
return {from: lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight),
to: ensureTo};
}
- return {from: from, to: to};
+ return {from: from, to: Math.max(to, from + 1)};
}
// LINE NUMBERS
cm.display.gutters.style.height = Math.max(measure.docHeight, measure.clientHeight - scrollerCutOff) + "px";
}
-
function checkForWebkitWidthBug(cm, measure) {
// Work around Webkit bug where it sometimes reserves space for a
// non-existing phantom scrollbar in the scroller (Issue #2420)
if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
sel = filterSelectionChange(doc, sel);
- var bias = cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1;
+ var bias = options && options.bias ||
+ (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);
setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));
if (!(options && options.scroll === false) && doc.cm)
if (!updated && op.selectionChanged) updateSelection(cm);
if (!updated && op.startHeight != cm.doc.height) updateScrollbars(cm);
+ // Abort mouse wheel delta measurement, when scrolling explicitly
+ if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
+ display.wheelStartX = display.wheelStartY = null;
+
// Propagate the scroll position to the actual DOM scroller
if (op.scrollTop != null && display.scroller.scrollTop != op.scrollTop) {
var top = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop));
function viewCuttingPoint(cm, oldN, newN, dir) {
var index = findViewIndex(cm, oldN), diff, view = cm.display.view;
- if (!sawCollapsedSpans) return {index: index, lineN: newN};
+ if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
+ return {index: index, lineN: newN};
for (var i = 0, n = cm.display.viewFrom; i < index; i++)
n += view[i].size;
if (n != oldN) {
var pos = posFromMouse(cm, e);
if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
e_preventDefault(e);
- var word = findWordAt(cm.doc, pos);
+ var word = findWordAt(cm, pos);
extendSelection(cm.doc, word.anchor, word.head);
}));
else
// Prevent wrapper from ever scrolling
on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
- // When the window resizes, we need to refresh active editors.
- var resizeTimer;
- function onResize() {
- if (resizeTimer == null) resizeTimer = setTimeout(function() {
- resizeTimer = null;
- // Might be a text scaling operation, clear size caches.
- d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = knownScrollbarWidth = null;
- cm.setSize();
- }, 100);
- }
- on(window, "resize", onResize);
- // The above handler holds on to the editor and its data
- // structures. Here we poll to unregister it when the editor is no
- // longer in the document, so that it can be garbage-collected.
- function unregister() {
- if (contains(document.body, d.wrapper)) setTimeout(unregister, 5000);
- else off(window, "resize", onResize);
- }
- setTimeout(unregister, 5000);
-
on(d.input, "keyup", operation(cm, onKeyUp));
on(d.input, "input", function() {
if (ie && !ie_upto8 && cm.display.inputHasSelection) cm.display.inputHasSelection = null;
});
}
+ // Called when the window resizes
+ function onResize(cm) {
+ // Might be a text scaling operation, clear size caches.
+ var d = cm.display;
+ d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
+ cm.setSize();
+ }
+
// MOUSE EVENTS
// Return true when the given mouse event happened in a widget
lastClick = {time: now, pos: start};
}
- var sel = cm.doc.sel, addNew = mac ? e.metaKey : e.ctrlKey;
- if (cm.options.dragDrop && dragAndDrop && !addNew && !isReadOnly(cm) &&
+ var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey;
+ if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) &&
type == "single" && sel.contains(start) > -1 && sel.somethingSelected())
- leftButtonStartDrag(cm, e, start);
+ leftButtonStartDrag(cm, e, start, modifier);
else
- leftButtonSelect(cm, e, start, type, addNew);
+ leftButtonSelect(cm, e, start, type, modifier);
}
// 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) {
+ function leftButtonStartDrag(cm, e, start, modifier) {
var display = cm.display;
var dragEnd = operation(cm, function(e2) {
if (webkit) display.scroller.draggable = false;
off(display.scroller, "drop", dragEnd);
if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
e_preventDefault(e2);
- extendSelection(cm.doc, start);
+ if (!modifier)
+ extendSelection(cm.doc, start);
focusInput(cm);
// Work around unexplainable focus problem in IE9 (#2127)
if (ie_upto10 && !ie_upto8)
start = posFromMouse(cm, e, true, true);
ourIndex = -1;
} else if (type == "double") {
- var word = findWordAt(doc, start);
+ var word = findWordAt(cm, start);
if (cm.display.shift || doc.extend)
ourRange = extendRange(doc, ourRange, word.anchor, word.head);
else
ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize))));
}
if (!ranges.length) ranges.push(new Range(start, start));
- setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), sel_mouse);
+ setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),
+ {origin: "*mouse", scroll: false});
+ cm.scrollIntoView(pos);
} else {
var oldRange = ourRange;
var anchor = oldRange.anchor, head = pos;
if (type != "single") {
if (type == "double")
- var range = findWordAt(doc, pos);
+ var range = findWordAt(cm, pos);
else
var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0)));
if (cmp(range.anchor, anchor) > 0) {
try {
var text = e.dataTransfer.getData("Text");
if (text) {
- var selected = cm.state.draggingText && cm.listSelections();
+ if (cm.state.draggingText && !(mac ? e.metaKey : e.ctrlKey))
+ var selected = cm.listSelections();
setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));
if (selected) for (var i = 0; i < selected.length; ++i)
replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag");
var extval = display.input.value = "\u200b" + (selected ? display.input.value : "");
display.prevInput = selected ? "" : "\u200b";
display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
+ // Re-set this, in case some other handler touched the
+ // selection in the meantime.
+ display.selForContextMenu = cm.doc.sel;
}
}
function rehide() {
else if (unit == "column") moveOnce(true);
else if (unit == "word" || unit == "group") {
var sawType = null, group = unit == "group";
+ var helper = doc.cm && doc.cm.getHelper(pos, "wordChars");
for (var first = true;; first = false) {
if (dir < 0 && !moveOnce(!first)) break;
var cur = lineObj.text.charAt(ch) || "\n";
- var type = isWordChar(cur) ? "w"
+ var type = isWordChar(cur, helper) ? "w"
: group && cur == "\n" ? "n"
: !group || /\s/.test(cur) ? null
: "p";
}
// Find the word at the given position (as returned by coordsChar).
- function findWordAt(doc, pos) {
- var line = getLine(doc, pos.line).text;
+ function findWordAt(cm, pos) {
+ var doc = cm.doc, line = getLine(doc, pos.line).text;
var start = pos.ch, end = pos.ch;
if (line) {
+ var helper = cm.getHelper(pos, "wordChars");
if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
var startChar = line.charAt(start);
- var check = isWordChar(startChar) ? isWordChar
+ var check = isWordChar(startChar, helper)
+ ? function(ch) { return isWordChar(ch, helper); }
: /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
: function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
while (start > 0 && check(line.charAt(start - 1))) --start;
},
transposeChars: function(cm) {
runInOp(cm, function() {
- var ranges = cm.listSelections();
+ var ranges = cm.listSelections(), newSel = [];
for (var i = 0; i < ranges.length; i++) {
var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text;
- if (cur.ch > 0 && cur.ch < line.length - 1)
- cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
- Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
+ if (line) {
+ if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1);
+ if (cur.ch > 0) {
+ cur = new Pos(cur.line, cur.ch + 1);
+ cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),
+ Pos(cur.line, cur.ch - 2), cur, "+transpose");
+ } else if (cur.line > cm.doc.first) {
+ var prev = getLine(cm.doc, cur.line - 1).text;
+ if (prev)
+ cm.replaceRange(line.charAt(0) + "\n" + prev.charAt(prev.length - 1),
+ Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), "+transpose");
+ }
+ }
+ newSel.push(new Range(cur, cur));
}
+ cm.setSelections(newSel);
});
},
newlineAndIndent: function(cm) {
}
function readToken(mode, stream, state) {
- var style = mode.token(stream, state);
- if (stream.pos <= stream.start)
- throw new Error("Mode " + mode.name + " failed to advance stream.");
- return style;
+ for (var i = 0; i < 10; i++) {
+ var style = mode.token(stream, state);
+ if (stream.pos > stream.start) return style;
+ }
+ throw new Error("Mode " + mode.name + " failed to advance stream.");
}
// Run the given mode's parser over a line, calling f for each token.
}
signal(cm, "renderLine", cm, lineView.line, builder.pre);
+ if (builder.pre.className)
+ builder.textClass = joinClasses(builder.pre.className, builder.textClass || "");
return builder;
}
}
var nonASCIISingleCaseWordChar = /[\u00df\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
- var isWordChar = CodeMirror.isWordChar = function(ch) {
+ 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;
+ return helper.test(ch);
+ }
function isEmpty(obj) {
for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
return b;
}
+ // WINDOW-WIDE EVENTS
+
+ // These must be handled carefully, because naively registering a
+ // handler for each editor will cause the editors to never be
+ // garbage collected.
+
+ function forEachCodeMirror(f) {
+ if (!document.body.getElementsByClassName) return;
+ var byClass = document.body.getElementsByClassName("CodeMirror");
+ for (var i = 0; i < byClass.length; i++) {
+ var cm = byClass[i].CodeMirror;
+ if (cm) f(cm);
+ }
+ }
+
+ var globalsRegistered = false;
+ function ensureGlobalHandlers() {
+ if (globalsRegistered) return;
+ registerGlobalHandlers();
+ globalsRegistered = true;
+ }
+ function registerGlobalHandlers() {
+ // When the window resizes, we need to refresh active editors.
+ var resizeTimer;
+ on(window, "resize", function() {
+ if (resizeTimer == null) resizeTimer = setTimeout(function() {
+ resizeTimer = null;
+ knownScrollbarWidth = null;
+ forEachCodeMirror(onResize);
+ }, 100);
+ });
+ // When the window loses focus, we want to show the editor as blurred
+ on(window, "blur", function() {
+ forEachCodeMirror(onBlur);
+ });
+ }
+
// FEATURE DETECTION
// Detect drag-and-drop
// THE END
- CodeMirror.version = "4.1.1";
+ CodeMirror.version = "4.2.0";
return CodeMirror;
});
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
if (/[\d.]/.test(stream.peek())) {
stream.eatWhile(/[\w.%]/);
return ret("number", "unit");
- } else if (stream.match(/^[^-]+-/)) {
+ } else if (stream.match(/^\w+-/)) {
return ret("meta", "meta");
}
} else if (/[,+>*\/]/.test(ch)) {
} else if (type == ":") {
return "pseudo";
} else if (allowNested && type == "(") {
- return pushContext(state, stream, "params");
+ return pushContext(state, stream, "parens");
}
return state.context.type;
};
states.parens = function(type, stream, state) {
if (type == "{" || type == "}") return popAndPass(type, stream, state);
if (type == ")") return popContext(state);
+ if (type == "(") return pushContext(state, stream, "parens");
+ if (type == "word") wordAsValue(stream);
return "parens";
};
return "interpolation";
};
- states.params = function(type, stream, state) {
- if (type == ")") return popContext(state);
- if (type == "{" || type == "}") return popAndPass(type, stream, state);
- if (type == "word") wordAsValue(stream);
- return "params";
- };
-
return {
startState: function(base) {
return {tokenize: null,
indent: function(state, textAfter) {
var cx = state.context, ch = textAfter && textAfter.charAt(0);
var indent = cx.indent;
- if (cx.type == "prop" && ch == "}") cx = cx.prev;
+ if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
if (cx.prev &&
(ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "font_face") ||
- ch == ")" && (cx.type == "parens" || cx.type == "params" || cx.type == "media_parens") ||
+ ch == ")" && (cx.type == "parens" || cx.type == "media_parens") ||
ch == "{" && (cx.type == "at" || cx.type == "media"))) {
indent = cx.indent - indentUnit;
cx = cx.prev;
"marker-offset", "marks", "marquee-direction", "marquee-loop",
"marquee-play-count", "marquee-speed", "marquee-style", "max-height",
"max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",
- "nav-left", "nav-right", "nav-up", "opacity", "order", "orphans", "outline",
+ "nav-left", "nav-right", "nav-up", "object-fit", "object-position",
+ "opacity", "order", "orphans", "outline",
"outline-color", "outline-offset", "outline-style", "outline-width",
"overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
"padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
"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",
+ "ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin",
+ "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",
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
// TODO actually recognize syntax of TypeScript constructs
(function(mod) {
};
});
+CodeMirror.registerHelper("wordChars", "javascript", /[\\w$]/);
+
CodeMirror.defineMIME("text/javascript", "javascript");
CodeMirror.defineMIME("text/ecmascript", "javascript");
CodeMirror.defineMIME("application/javascript", "javascript");
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
/**
* Author: Hans Engel
* Branched from CodeMirror's Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun)
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
// This is CodeMirror (http://codemirror.net), a code editor
// implemented in JavaScript on top of the browser's DOM.
//
if (ie_upto10) setTimeout(bind(resetInput, this, true), 20);
registerEventHandlers(this);
+ ensureGlobalHandlers();
var cm = this;
runInOp(this, function() {
// the the current scroll position). viewPort may contain top,
// height, and ensure (see op.scrollToPos) properties.
function visibleLines(display, doc, viewPort) {
- var top = viewPort && viewPort.top != null ? viewPort.top : display.scroller.scrollTop;
+ var top = viewPort && viewPort.top != null ? Math.max(0, viewPort.top) : display.scroller.scrollTop;
top = Math.floor(top - paddingTop(display));
var bottom = viewPort && viewPort.bottom != null ? viewPort.bottom : top + display.wrapper.clientHeight;
return {from: lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight),
to: ensureTo};
}
- return {from: from, to: to};
+ return {from: from, to: Math.max(to, from + 1)};
}
// LINE NUMBERS
cm.display.gutters.style.height = Math.max(measure.docHeight, measure.clientHeight - scrollerCutOff) + "px";
}
-
function checkForWebkitWidthBug(cm, measure) {
// Work around Webkit bug where it sometimes reserves space for a
// non-existing phantom scrollbar in the scroller (Issue #2420)
if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
sel = filterSelectionChange(doc, sel);
- var bias = cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1;
+ var bias = options && options.bias ||
+ (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);
setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));
if (!(options && options.scroll === false) && doc.cm)
if (!updated && op.selectionChanged) updateSelection(cm);
if (!updated && op.startHeight != cm.doc.height) updateScrollbars(cm);
+ // Abort mouse wheel delta measurement, when scrolling explicitly
+ if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
+ display.wheelStartX = display.wheelStartY = null;
+
// Propagate the scroll position to the actual DOM scroller
if (op.scrollTop != null && display.scroller.scrollTop != op.scrollTop) {
var top = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop));
function viewCuttingPoint(cm, oldN, newN, dir) {
var index = findViewIndex(cm, oldN), diff, view = cm.display.view;
- if (!sawCollapsedSpans) return {index: index, lineN: newN};
+ if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
+ return {index: index, lineN: newN};
for (var i = 0, n = cm.display.viewFrom; i < index; i++)
n += view[i].size;
if (n != oldN) {
var pos = posFromMouse(cm, e);
if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
e_preventDefault(e);
- var word = findWordAt(cm.doc, pos);
+ var word = findWordAt(cm, pos);
extendSelection(cm.doc, word.anchor, word.head);
}));
else
// Prevent wrapper from ever scrolling
on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
- // When the window resizes, we need to refresh active editors.
- var resizeTimer;
- function onResize() {
- if (resizeTimer == null) resizeTimer = setTimeout(function() {
- resizeTimer = null;
- // Might be a text scaling operation, clear size caches.
- d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = knownScrollbarWidth = null;
- cm.setSize();
- }, 100);
- }
- on(window, "resize", onResize);
- // The above handler holds on to the editor and its data
- // structures. Here we poll to unregister it when the editor is no
- // longer in the document, so that it can be garbage-collected.
- function unregister() {
- if (contains(document.body, d.wrapper)) setTimeout(unregister, 5000);
- else off(window, "resize", onResize);
- }
- setTimeout(unregister, 5000);
-
on(d.input, "keyup", operation(cm, onKeyUp));
on(d.input, "input", function() {
if (ie && !ie_upto8 && cm.display.inputHasSelection) cm.display.inputHasSelection = null;
});
}
+ // Called when the window resizes
+ function onResize(cm) {
+ // Might be a text scaling operation, clear size caches.
+ var d = cm.display;
+ d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
+ cm.setSize();
+ }
+
// MOUSE EVENTS
// Return true when the given mouse event happened in a widget
lastClick = {time: now, pos: start};
}
- var sel = cm.doc.sel, addNew = mac ? e.metaKey : e.ctrlKey;
- if (cm.options.dragDrop && dragAndDrop && !addNew && !isReadOnly(cm) &&
+ var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey;
+ if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) &&
type == "single" && sel.contains(start) > -1 && sel.somethingSelected())
- leftButtonStartDrag(cm, e, start);
+ leftButtonStartDrag(cm, e, start, modifier);
else
- leftButtonSelect(cm, e, start, type, addNew);
+ leftButtonSelect(cm, e, start, type, modifier);
}
// 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) {
+ function leftButtonStartDrag(cm, e, start, modifier) {
var display = cm.display;
var dragEnd = operation(cm, function(e2) {
if (webkit) display.scroller.draggable = false;
off(display.scroller, "drop", dragEnd);
if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
e_preventDefault(e2);
- extendSelection(cm.doc, start);
+ if (!modifier)
+ extendSelection(cm.doc, start);
focusInput(cm);
// Work around unexplainable focus problem in IE9 (#2127)
if (ie_upto10 && !ie_upto8)
start = posFromMouse(cm, e, true, true);
ourIndex = -1;
} else if (type == "double") {
- var word = findWordAt(doc, start);
+ var word = findWordAt(cm, start);
if (cm.display.shift || doc.extend)
ourRange = extendRange(doc, ourRange, word.anchor, word.head);
else
ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize))));
}
if (!ranges.length) ranges.push(new Range(start, start));
- setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), sel_mouse);
+ setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),
+ {origin: "*mouse", scroll: false});
+ cm.scrollIntoView(pos);
} else {
var oldRange = ourRange;
var anchor = oldRange.anchor, head = pos;
if (type != "single") {
if (type == "double")
- var range = findWordAt(doc, pos);
+ var range = findWordAt(cm, pos);
else
var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0)));
if (cmp(range.anchor, anchor) > 0) {
try {
var text = e.dataTransfer.getData("Text");
if (text) {
- var selected = cm.state.draggingText && cm.listSelections();
+ if (cm.state.draggingText && !(mac ? e.metaKey : e.ctrlKey))
+ var selected = cm.listSelections();
setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));
if (selected) for (var i = 0; i < selected.length; ++i)
replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag");
var extval = display.input.value = "\u200b" + (selected ? display.input.value : "");
display.prevInput = selected ? "" : "\u200b";
display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
+ // Re-set this, in case some other handler touched the
+ // selection in the meantime.
+ display.selForContextMenu = cm.doc.sel;
}
}
function rehide() {
else if (unit == "column") moveOnce(true);
else if (unit == "word" || unit == "group") {
var sawType = null, group = unit == "group";
+ var helper = doc.cm && doc.cm.getHelper(pos, "wordChars");
for (var first = true;; first = false) {
if (dir < 0 && !moveOnce(!first)) break;
var cur = lineObj.text.charAt(ch) || "\n";
- var type = isWordChar(cur) ? "w"
+ var type = isWordChar(cur, helper) ? "w"
: group && cur == "\n" ? "n"
: !group || /\s/.test(cur) ? null
: "p";
}
// Find the word at the given position (as returned by coordsChar).
- function findWordAt(doc, pos) {
- var line = getLine(doc, pos.line).text;
+ function findWordAt(cm, pos) {
+ var doc = cm.doc, line = getLine(doc, pos.line).text;
var start = pos.ch, end = pos.ch;
if (line) {
+ var helper = cm.getHelper(pos, "wordChars");
if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
var startChar = line.charAt(start);
- var check = isWordChar(startChar) ? isWordChar
+ var check = isWordChar(startChar, helper)
+ ? function(ch) { return isWordChar(ch, helper); }
: /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
: function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
while (start > 0 && check(line.charAt(start - 1))) --start;
},
transposeChars: function(cm) {
runInOp(cm, function() {
- var ranges = cm.listSelections();
+ var ranges = cm.listSelections(), newSel = [];
for (var i = 0; i < ranges.length; i++) {
var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text;
- if (cur.ch > 0 && cur.ch < line.length - 1)
- cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
- Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
+ if (line) {
+ if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1);
+ if (cur.ch > 0) {
+ cur = new Pos(cur.line, cur.ch + 1);
+ cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),
+ Pos(cur.line, cur.ch - 2), cur, "+transpose");
+ } else if (cur.line > cm.doc.first) {
+ var prev = getLine(cm.doc, cur.line - 1).text;
+ if (prev)
+ cm.replaceRange(line.charAt(0) + "\n" + prev.charAt(prev.length - 1),
+ Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), "+transpose");
+ }
+ }
+ newSel.push(new Range(cur, cur));
}
+ cm.setSelections(newSel);
});
},
newlineAndIndent: function(cm) {
}
function readToken(mode, stream, state) {
- var style = mode.token(stream, state);
- if (stream.pos <= stream.start)
- throw new Error("Mode " + mode.name + " failed to advance stream.");
- return style;
+ for (var i = 0; i < 10; i++) {
+ var style = mode.token(stream, state);
+ if (stream.pos > stream.start) return style;
+ }
+ throw new Error("Mode " + mode.name + " failed to advance stream.");
}
// Run the given mode's parser over a line, calling f for each token.
}
signal(cm, "renderLine", cm, lineView.line, builder.pre);
+ if (builder.pre.className)
+ builder.textClass = joinClasses(builder.pre.className, builder.textClass || "");
return builder;
}
}
var nonASCIISingleCaseWordChar = /[\u00df\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
- var isWordChar = CodeMirror.isWordChar = function(ch) {
+ 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;
+ return helper.test(ch);
+ }
function isEmpty(obj) {
for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
return b;
}
+ // WINDOW-WIDE EVENTS
+
+ // These must be handled carefully, because naively registering a
+ // handler for each editor will cause the editors to never be
+ // garbage collected.
+
+ function forEachCodeMirror(f) {
+ if (!document.body.getElementsByClassName) return;
+ var byClass = document.body.getElementsByClassName("CodeMirror");
+ for (var i = 0; i < byClass.length; i++) {
+ var cm = byClass[i].CodeMirror;
+ if (cm) f(cm);
+ }
+ }
+
+ var globalsRegistered = false;
+ function ensureGlobalHandlers() {
+ if (globalsRegistered) return;
+ registerGlobalHandlers();
+ globalsRegistered = true;
+ }
+ function registerGlobalHandlers() {
+ // When the window resizes, we need to refresh active editors.
+ var resizeTimer;
+ on(window, "resize", function() {
+ if (resizeTimer == null) resizeTimer = setTimeout(function() {
+ resizeTimer = null;
+ knownScrollbarWidth = null;
+ forEachCodeMirror(onResize);
+ }, 100);
+ });
+ // When the window loses focus, we want to show the editor as blurred
+ on(window, "blur", function() {
+ forEachCodeMirror(onBlur);
+ });
+ }
+
// FEATURE DETECTION
// Detect drag-and-drop
// THE END
- CodeMirror.version = "4.1.1";
+ CodeMirror.version = "4.2.0";
return CodeMirror;
});
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
/**
* Link to the project's GitHub page:
* https://github.com/pickhardt/coffeescript-codemirror-mode
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
if (/[\d.]/.test(stream.peek())) {
stream.eatWhile(/[\w.%]/);
return ret("number", "unit");
- } else if (stream.match(/^[^-]+-/)) {
+ } else if (stream.match(/^\w+-/)) {
return ret("meta", "meta");
}
} else if (/[,+>*\/]/.test(ch)) {
} else if (type == ":") {
return "pseudo";
} else if (allowNested && type == "(") {
- return pushContext(state, stream, "params");
+ return pushContext(state, stream, "parens");
}
return state.context.type;
};
states.parens = function(type, stream, state) {
if (type == "{" || type == "}") return popAndPass(type, stream, state);
if (type == ")") return popContext(state);
+ if (type == "(") return pushContext(state, stream, "parens");
+ if (type == "word") wordAsValue(stream);
return "parens";
};
return "interpolation";
};
- states.params = function(type, stream, state) {
- if (type == ")") return popContext(state);
- if (type == "{" || type == "}") return popAndPass(type, stream, state);
- if (type == "word") wordAsValue(stream);
- return "params";
- };
-
return {
startState: function(base) {
return {tokenize: null,
indent: function(state, textAfter) {
var cx = state.context, ch = textAfter && textAfter.charAt(0);
var indent = cx.indent;
- if (cx.type == "prop" && ch == "}") cx = cx.prev;
+ if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
if (cx.prev &&
(ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "font_face") ||
- ch == ")" && (cx.type == "parens" || cx.type == "params" || cx.type == "media_parens") ||
+ ch == ")" && (cx.type == "parens" || cx.type == "media_parens") ||
ch == "{" && (cx.type == "at" || cx.type == "media"))) {
indent = cx.indent - indentUnit;
cx = cx.prev;
"marker-offset", "marks", "marquee-direction", "marquee-loop",
"marquee-play-count", "marquee-speed", "marquee-style", "max-height",
"max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",
- "nav-left", "nav-right", "nav-up", "opacity", "order", "orphans", "outline",
+ "nav-left", "nav-right", "nav-up", "object-fit", "object-position",
+ "opacity", "order", "orphans", "outline",
"outline-color", "outline-offset", "outline-style", "outline-width",
"overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
"padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
"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",
+ "ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin",
+ "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",
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css"));
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
// TODO actually recognize syntax of TypeScript constructs
(function(mod) {
};
});
+CodeMirror.registerHelper("wordChars", "javascript", /[\\w$]/);
+
CodeMirror.defineMIME("text/javascript", "javascript");
CodeMirror.defineMIME("text/ecmascript", "javascript");
CodeMirror.defineMIME("application/javascript", "javascript");
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
/**
* Link to the project's GitHub page:
* https://github.com/duralog/CodeMirror
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
// Utility function that allows modes to be combined. The mode given
// as the base argument takes care of most of the normal mode
// functionality, but a second (typically simple) mode is used, which
// can override the style of text. Both modes get to parse all of the
// text, but when both assign a non-null style to a piece of code, the
-// overlay wins, unless the combine argument was true, in which case
-// the styles are combined.
+// overlay wins, unless the combine argument was true and not overridden,
+// or state.overlay.combineTokens was true, in which case the styles are
+// combined.
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
}
stream.pos = Math.min(state.basePos, state.overlayPos);
+ // state.overlay.combineTokens always takes precedence over combine,
+ // unless set to null
if (state.overlayCur == null) return state.baseCur;
- if (state.baseCur != null && combine) return state.baseCur + " " + state.overlayCur;
+ else if (state.baseCur != null &&
+ state.overlay.combineTokens ||
+ combine && state.overlay.combineTokens == null)
+ return state.baseCur + " " + state.overlayCur;
else return state.overlayCur;
},
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
state.state = baseState;
state.tagName = state.tagStart = null;
var next = state.tokenize(stream, state);
- return next ? next + " error" : "error";
+ return next ? next + " tag error" : "tag error";
} else if (/[\'\"]/.test(ch)) {
state.tokenize = inAttribute(ch);
state.stringStartCol = stream.column();