Index: Source/devtools/front_end/cm/codemirror.js |
diff --git a/Source/devtools/front_end/cm/codemirror.js b/Source/devtools/front_end/cm/codemirror.js |
index 1570e4997ce1eb19a3ab28e5ecf5af022292f39f..b92b3a9bbc74a639caeccb20e30b754e2a7cd9f9 100644 |
--- a/Source/devtools/front_end/cm/codemirror.js |
+++ b/Source/devtools/front_end/cm/codemirror.js |
@@ -1,5 +1,3 @@ |
-// CodeMirror version 3.12 |
-// |
// CodeMirror is the only global var we claim |
window.CodeMirror = (function() { |
"use strict"; |
@@ -99,7 +97,7 @@ window.CodeMirror = (function() { |
else input.setAttribute("wrap", "off"); |
// if border: 0; -- iOS fails to open keyboard (issue #1287) |
if (ios) input.style.border = "1px solid black"; |
- input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); |
+ input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); input.setAttribute("spellcheck", "false"); |
// Wraps and hides input textarea |
d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); |
@@ -107,8 +105,9 @@ window.CodeMirror = (function() { |
d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar"); |
d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar"); |
d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler"); |
+ d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler"); |
// DIVs containing the selection and the actual code |
- d.lineDiv = elt("div"); |
+ d.lineDiv = elt("div", null, "CodeMirror-code"); |
d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1"); |
// Blinky cursor, and element used to ensure cursor fits at the end of a line |
d.cursor = elt("div", "\u00a0", "CodeMirror-cursor"); |
@@ -128,14 +127,12 @@ window.CodeMirror = (function() { |
// Will contain the gutters, if any |
d.gutters = elt("div", null, "CodeMirror-gutters"); |
d.lineGutter = null; |
- // Helper element to properly size the gutter backgrounds |
- var scrollerInner = elt("div", [d.sizer, d.heightForcer, d.gutters], null, "position: relative; min-height: 100%"); |
// Provides scrolling |
- d.scroller = elt("div", [scrollerInner], "CodeMirror-scroll"); |
+ d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll"); |
d.scroller.setAttribute("tabIndex", "-1"); |
// The element in which the editor lives. |
d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV, |
- d.scrollbarFiller, d.scroller], "CodeMirror"); |
+ d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror"); |
// Work around IE7 z-index bug |
if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; } |
if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper); |
@@ -214,7 +211,7 @@ window.CodeMirror = (function() { |
estimateLineHeights(cm); |
regChange(cm); |
clearCaches(cm); |
- setTimeout(function(){updateScrollbars(cm.display, cm.doc.height);}, 100); |
+ setTimeout(function(){updateScrollbars(cm);}, 100); |
} |
function estimateHeight(cm) { |
@@ -253,6 +250,7 @@ window.CodeMirror = (function() { |
function guttersChanged(cm) { |
updateGutters(cm); |
regChange(cm); |
+ setTimeout(function(){alignHorizontally(cm);}, 20); |
} |
function updateGutters(cm) { |
@@ -319,9 +317,11 @@ window.CodeMirror = (function() { |
// Re-synchronize the fake scrollbars with the actual size of the |
// content. Optionally force a scrollTop. |
- function updateScrollbars(d /* display */, docHeight) { |
+ function updateScrollbars(cm) { |
+ var d = cm.display, docHeight = cm.doc.height; |
var totalHeight = docHeight + paddingVert(d); |
d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px"; |
+ d.gutters.style.height = Math.max(totalHeight, d.scroller.clientHeight - scrollerCutOff) + "px"; |
var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight); |
var needsH = d.scroller.scrollWidth > d.scroller.clientWidth; |
var needsV = scrollHeight > d.scroller.clientHeight; |
@@ -341,6 +341,11 @@ window.CodeMirror = (function() { |
d.scrollbarFiller.style.display = "block"; |
d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px"; |
} else d.scrollbarFiller.style.display = ""; |
+ if (needsH && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) { |
+ d.gutterFiller.style.display = "block"; |
+ d.gutterFiller.style.height = scrollbarWidth(d.measure) + "px"; |
+ d.gutterFiller.style.width = d.gutters.offsetWidth + "px"; |
+ } else d.gutterFiller.style.display = ""; |
if (mac_geLion && scrollbarWidth(d.measure) === 0) |
d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px"; |
@@ -399,14 +404,10 @@ window.CodeMirror = (function() { |
var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated; |
var visible = visibleLines(cm.display, cm.doc, viewPort); |
for (;;) { |
- if (updateDisplayInner(cm, changes, visible)) { |
- updated = true; |
- signalLater(cm, "update", cm); |
- if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo) |
- signalLater(cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo); |
- } else break; |
+ if (!updateDisplayInner(cm, changes, visible)) break; |
+ updated = true; |
updateSelection(cm); |
- updateScrollbars(cm.display, cm.doc.height); |
+ updateScrollbars(cm); |
// Clip forced viewport to actual scrollable area |
if (viewPort) |
@@ -418,6 +419,11 @@ window.CodeMirror = (function() { |
changes = []; |
} |
+ if (updated) { |
+ signalLater(cm, "update", cm); |
+ if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo) |
+ signalLater(cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo); |
+ } |
return updated; |
} |
@@ -978,23 +984,28 @@ window.CodeMirror = (function() { |
if (memo.text == line.text && memo.markedSpans == line.markedSpans && |
cm.display.scroller.clientWidth == memo.width && |
memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass) |
- return memo.measure; |
+ return memo; |
} |
} |
+ function clearCachedMeasurement(cm, line) { |
+ var exists = findCachedMeasurement(cm, line); |
+ if (exists) exists.text = exists.measure = exists.markedSpans = null; |
+ } |
+ |
function measureLine(cm, line) { |
// First look in the cache |
- var measure = findCachedMeasurement(cm, line); |
- if (!measure) { |
- // Failing that, recompute and store result in cache |
- measure = measureLineInner(cm, line); |
- var cache = cm.display.measureLineCache; |
- var memo = {text: line.text, width: cm.display.scroller.clientWidth, |
- markedSpans: line.markedSpans, measure: measure, |
- classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass}; |
- if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo; |
- else cache.push(memo); |
- } |
+ var cached = findCachedMeasurement(cm, line); |
+ if (cached) return cached.measure; |
+ |
+ // Failing that, recompute and store result in cache |
+ var measure = measureLineInner(cm, line); |
+ var cache = cm.display.measureLineCache; |
+ var memo = {text: line.text, width: cm.display.scroller.clientWidth, |
+ markedSpans: line.markedSpans, measure: measure, |
+ classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass}; |
+ if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo; |
+ else cache.push(memo); |
return measure; |
} |
@@ -1070,7 +1081,7 @@ window.CodeMirror = (function() { |
if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true; |
} |
var cached = !hasBadSpan && findCachedMeasurement(cm, line); |
- if (cached) return measureChar(cm, line, line.text.length, cached).right; |
+ if (cached) return measureChar(cm, line, line.text.length, cached.measure).right; |
var pre = lineContent(cm, line); |
var end = pre.appendChild(zeroWidthElement(cm.display.measure)); |
@@ -1138,32 +1149,26 @@ window.CodeMirror = (function() { |
if (right) m.left = m.right; else m.right = m.left; |
return intoCoordSystem(cm, lineObj, m, context); |
} |
- var order = getOrder(lineObj), ch = pos.ch; |
- if (!order) return get(ch); |
- var main, other, linedir = order[0].level; |
- for (var i = 0; i < order.length; ++i) { |
- var part = order[i], rtl = part.level % 2, nb, here; |
- if (part.from < ch && part.to > ch) return get(ch, rtl); |
- var left = rtl ? part.to : part.from, right = rtl ? part.from : part.to; |
- if (left == ch) { |
- // IE returns bogus offsets and widths for edges where the |
- // direction flips, but only for the side with the lower |
- // level. So we try to use the side with the higher level. |
- if (i && part.level < (nb = order[i-1]).level) here = get(nb.level % 2 ? nb.from : nb.to - 1, true); |
- else here = get(rtl && part.from != part.to ? ch - 1 : ch); |
- if (rtl == linedir) main = here; else other = here; |
- } else if (right == ch) { |
- var nb = i < order.length - 1 && order[i+1]; |
- if (!rtl && nb && nb.from == nb.to) continue; |
- if (nb && part.level < nb.level) here = get(nb.level % 2 ? nb.to - 1 : nb.from); |
- else here = get(rtl ? ch : ch - 1, true); |
- if (rtl == linedir) main = here; else other = here; |
+ function getBidi(ch, partPos) { |
+ var part = order[partPos], right = part.level % 2; |
+ if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) { |
+ part = order[--partPos]; |
+ ch = bidiRight(part) - (part.level % 2 ? 0 : 1); |
+ right = true; |
+ } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) { |
+ part = order[++partPos]; |
+ ch = bidiLeft(part) - part.level % 2; |
+ right = false; |
} |
+ if (right && ch == part.to && ch > part.from) return get(ch - 1); |
+ return get(ch, right); |
} |
- if (linedir && !ch) other = get(order[0].to - 1); |
- if (!main) return other; |
- if (other) main.other = other; |
- return main; |
+ var order = getOrder(lineObj), ch = pos.ch; |
+ if (!order) return get(ch); |
+ var partPos = getBidiPartAt(order, ch); |
+ var val = getBidi(ch, partPos); |
+ if (bidiOther != null) val.other = getBidi(ch, bidiOther); |
+ return val; |
} |
function PosMaybeOutside(line, ch, outside) { |
@@ -1508,11 +1513,14 @@ window.CodeMirror = (function() { |
// Prevent wrapper from ever scrolling |
on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }); |
+ var resizeTimer = new Delayed(); |
function onResize() { |
- // Might be a text scaling operation, clear size caches. |
- d.cachedCharWidth = d.cachedTextHeight = null; |
- clearCaches(cm); |
- runInOp(cm, bind(regChange, cm)); |
+ resizeTimer.set(function() { |
+ // Might be a text scaling operation, clear size caches. |
+ d.cachedCharWidth = d.cachedTextHeight = null; |
+ clearCaches(cm); |
+ runInOp(cm, bind(regChange, cm)); |
+ }, 200); |
} |
on(window, "resize", onResize); |
// Above handler holds on to the editor and its data structures. |
@@ -1587,7 +1595,7 @@ window.CodeMirror = (function() { |
var target = e_target(e); |
if (target == display.scrollbarH || target == display.scrollbarH.firstChild || |
target == display.scrollbarV || target == display.scrollbarV.firstChild || |
- target == display.scrollbarFiller) return null; |
+ target == display.scrollbarFiller || target == display.gutterFiller) return null; |
} |
var x, y, space = getRect(display.lineSpace); |
// Fails unpredictably on IE[67] when mouse is dragged around quickly. |
@@ -1720,8 +1728,6 @@ window.CodeMirror = (function() { |
function done(e) { |
counter = Infinity; |
- var cur = posFromMouse(cm, e); |
- if (cur) doSelect(cur); |
e_preventDefault(e); |
focusInput(cm); |
off(document, "mousemove", move); |
@@ -2092,6 +2098,13 @@ window.CodeMirror = (function() { |
// Adds "Select all" to context menu in FF |
if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " "; |
+ function prepareSelectAllHack() { |
+ if (display.input.selectionStart != null) { |
+ var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value); |
+ display.prevInput = " "; |
+ display.input.selectionStart = 1; display.input.selectionEnd = extval.length; |
+ } |
+ } |
function rehide() { |
display.inputDiv.style.position = "relative"; |
display.input.style.cssText = oldCSS; |
@@ -2099,12 +2112,10 @@ window.CodeMirror = (function() { |
slowPoll(cm); |
// Try to detect the user choosing select-all |
- if (display.input.selectionStart != null && (!ie || ie_lt9)) { |
+ if (display.input.selectionStart != null) { |
+ if (!ie || ie_lt9) prepareSelectAllHack(); |
clearTimeout(detectingSelectAll); |
- var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value), i = 0; |
- display.prevInput = " "; |
- display.input.selectionStart = 1; display.input.selectionEnd = extval.length; |
- var poll = function(){ |
+ var i = 0, poll = function(){ |
if (display.prevInput == " " && display.input.selectionStart == 0) |
operation(cm, commands.selectAll)(cm); |
else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500); |
@@ -2114,6 +2125,7 @@ window.CodeMirror = (function() { |
} |
} |
+ if (ie && !ie_lt9) prepareSelectAllHack(); |
if (captureMiddleClick) { |
e_stop(e); |
var mouseup = function() { |
@@ -2174,21 +2186,21 @@ window.CodeMirror = (function() { |
return {anchor: adjustPos(doc.sel.anchor), head: adjustPos(doc.sel.head)}; |
} |
- function filterChange(doc, change) { |
+ function filterChange(doc, change, update) { |
var obj = { |
canceled: false, |
from: change.from, |
to: change.to, |
text: change.text, |
origin: change.origin, |
- update: function(from, to, text, origin) { |
- if (from) this.from = clipPos(doc, from); |
- if (to) this.to = clipPos(doc, to); |
- if (text) this.text = text; |
- if (origin !== undefined) this.origin = origin; |
- }, |
cancel: function() { this.canceled = true; } |
}; |
+ if (update) obj.update = function(from, to, text, origin) { |
+ if (from) this.from = clipPos(doc, from); |
+ if (to) this.to = clipPos(doc, to); |
+ if (text) this.text = text; |
+ if (origin !== undefined) this.origin = origin; |
+ }; |
signal(doc, "beforeChange", doc, obj); |
if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj); |
@@ -2205,7 +2217,7 @@ window.CodeMirror = (function() { |
} |
if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) { |
- change = filterChange(doc, change); |
+ change = filterChange(doc, change, true); |
if (!change) return; |
} |
@@ -2250,9 +2262,16 @@ window.CodeMirror = (function() { |
anchorAfter: event.anchorBefore, headAfter: event.headBefore}; |
(type == "undo" ? hist.undone : hist.done).push(anti); |
+ var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange"); |
+ |
for (var i = event.changes.length - 1; i >= 0; --i) { |
var change = event.changes[i]; |
change.origin = type; |
+ if (filter && !filterChange(doc, change, false)) { |
+ (type == "undo" ? hist.done : hist.undone).length = 0; |
+ return; |
+ } |
+ |
anti.changes.push(historyChangeFromChange(doc, change)); |
var after = i ? computeSelAfterChange(doc, change, null) |
@@ -2514,7 +2533,7 @@ window.CodeMirror = (function() { |
// SCROLLING |
function scrollCursorIntoView(cm) { |
- var coords = scrollPosIntoView(cm, cm.doc.sel.head); |
+ var coords = scrollPosIntoView(cm, cm.doc.sel.head, cm.options.cursorScrollMargin); |
if (!cm.state.focused) return; |
var display = cm.display, box = getRect(display.sizer), doScroll = null, pTop = paddingTop(cm.display); |
if (coords.top + pTop + box.top < 0) doScroll = true; |
@@ -2645,7 +2664,7 @@ window.CodeMirror = (function() { |
} |
function findPosH(doc, pos, dir, unit, visually) { |
- var line = pos.line, ch = pos.ch; |
+ var line = pos.line, ch = pos.ch, origDir = dir; |
var lineObj = getLine(doc, line); |
var possible = true; |
function findNextLine() { |
@@ -2684,7 +2703,7 @@ window.CodeMirror = (function() { |
if (dir > 0 && !moveOnce(!first)) break; |
} |
} |
- var result = skipAtomic(doc, Pos(line, ch), dir, true); |
+ var result = skipAtomic(doc, Pos(line, ch), origDir, true); |
if (!possible) result.hitSide = true; |
return result; |
} |
@@ -2730,6 +2749,7 @@ window.CodeMirror = (function() { |
// 'wrap f in an operation, performed on its `this` parameter' |
CodeMirror.prototype = { |
+ constructor: CodeMirror, |
focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);}, |
setOption: function(option, value) { |
@@ -2765,7 +2785,8 @@ window.CodeMirror = (function() { |
removeOverlay: operation(null, function(spec) { |
var overlays = this.state.overlays; |
for (var i = 0; i < overlays.length; ++i) { |
- if (overlays[i].modeSpec == spec) { |
+ var cur = overlays[i].modeSpec; |
+ if (cur == spec || typeof spec == "string" && cur.name == spec) { |
overlays.splice(i, 1); |
this.state.modeGen++; |
regChange(this); |
@@ -2990,7 +3011,8 @@ window.CodeMirror = (function() { |
sel.goalColumn = pos.left; |
}), |
- toggleOverwrite: function() { |
+ toggleOverwrite: function(value) { |
+ if (value != null && value == this.state.overwrite) return; |
if (this.state.overwrite = !this.state.overwrite) |
this.display.cursor.className += " CodeMirror-overwrite"; |
else |
@@ -3113,6 +3135,7 @@ window.CodeMirror = (function() { |
cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"; |
cm.refresh(); |
}, true); |
+ option("coverGutterNextToScrollbar", false, updateScrollbars, true); |
option("lineNumbers", false, function(cm) { |
setGuttersForLineNumbers(cm.options); |
guttersChanged(cm); |
@@ -3128,6 +3151,7 @@ window.CodeMirror = (function() { |
option("dragDrop", true); |
option("cursorBlinkRate", 530); |
+ option("cursorScrollMargin", 0); |
option("cursorHeight", 1); |
option("workTime", 100); |
option("workDelay", 100); |
@@ -3165,10 +3189,15 @@ window.CodeMirror = (function() { |
}; |
CodeMirror.resolveMode = function(spec) { |
- if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) |
+ if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { |
spec = mimeModes[spec]; |
- else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) |
+ } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { |
+ var found = mimeModes[spec.name]; |
+ spec = createObj(found, spec); |
+ spec.name = found.name; |
+ } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { |
return CodeMirror.resolveMode("application/xml"); |
+ } |
if (typeof spec == "string") return {name: spec}; |
else return spec || {name: "null"}; |
}; |
@@ -3598,15 +3627,18 @@ window.CodeMirror = (function() { |
return from && {from: from, to: to}; |
}; |
- TextMarker.prototype.getOptions = function(copyWidget) { |
- var repl = this.replacedWith; |
- return {className: this.className, |
- inclusiveLeft: this.inclusiveLeft, inclusiveRight: this.inclusiveRight, |
- atomic: this.atomic, |
- collapsed: this.collapsed, |
- replacedWith: copyWidget ? repl && repl.cloneNode(true) : repl, |
- readOnly: this.readOnly, |
- startStyle: this.startStyle, endStyle: this.endStyle}; |
+ TextMarker.prototype.changed = function() { |
+ var pos = this.find(), cm = this.doc.cm; |
+ if (!pos || !cm) return; |
+ var line = getLine(this.doc, pos.from.line); |
+ clearCachedMeasurement(cm, line); |
+ if (pos.from.line >= cm.display.showingFrom && pos.from.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; }); |
+ } |
}; |
TextMarker.prototype.attachLine = function(line) { |
@@ -3706,11 +3738,6 @@ window.CodeMirror = (function() { |
SharedTextMarker.prototype.find = function() { |
return this.primary.find(); |
}; |
- SharedTextMarker.prototype.getOptions = function(copyWidget) { |
- var inner = this.primary.getOptions(copyWidget); |
- inner.shared = true; |
- return inner; |
- }; |
function markTextShared(doc, from, to, options, type) { |
options = copyObj(options); |
@@ -4218,8 +4245,7 @@ window.CodeMirror = (function() { |
if (ch >= "\ud800" && ch < "\udbff" && i < text.length - 1) { |
ch = text.slice(i, i + 2); |
++i; |
- } else if (i && wrapping && |
- spanAffectsWrapping.test(text.slice(i - 1, i + 1))) { |
+ } else if (i && wrapping && spanAffectsWrapping(text, i)) { |
builder.pre.appendChild(elt("wbr")); |
} |
var span = builder.measure[builder.pos] = |
@@ -4518,6 +4544,7 @@ window.CodeMirror = (function() { |
}; |
Doc.prototype = createObj(BranchChunk.prototype, { |
+ constructor: Doc, |
iter: function(from, to, op) { |
if (op) this.iterN(from - this.first, to - from, op); |
else this.iterN(this.first, this.first + this.size, from); |
@@ -5182,7 +5209,7 @@ window.CodeMirror = (function() { |
return function(){return f.apply(null, args);}; |
} |
- var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc]/; |
+ var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; |
function isWordChar(ch) { |
return /\w/.test(ch) || ch > "\x80" && |
(ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)); |
@@ -5243,13 +5270,24 @@ window.CodeMirror = (function() { |
// word wrapping between certain characters *only* if a new inline |
// element is started between them. This makes it hard to reliably |
// measure the position of things, since that requires inserting an |
- // extra span. This terribly fragile set of regexps matches the |
+ // extra span. This terribly fragile set of tests matches the |
// character combinations that suffer from this phenomenon on the |
// various browsers. |
- var spanAffectsWrapping = /^$/; // Won't match any two-character string |
- if (gecko) spanAffectsWrapping = /$'/; |
- else if (safari && !/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent)) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/; |
- else if (webkit) spanAffectsWrapping = /[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.]|\?[\w~`@#$%\^&*(_=+{[|><]/; |
+ function spanAffectsWrapping() { return false; } |
+ if (gecko) // Only for "$'" |
+ spanAffectsWrapping = function(str, i) { |
+ return str.charCodeAt(i - 1) == 36 && str.charCodeAt(i) == 39; |
+ }; |
+ else if (safari && !/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent)) |
+ spanAffectsWrapping = function(str, i) { |
+ return /\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/.test(str.slice(i - 1, i + 1)); |
+ }; |
+ else if (webkit) |
+ spanAffectsWrapping = function(str, i) { |
+ if (i > 1 && str.charCodeAt(i - 1) == 45 && /\w/.test(str.charAt(i - 2)) && /[^\-?\.]/.test(str.charAt(i))) |
+ return true; |
+ return /[~!#%&*)=+}\]|\"\.>,:;][({[<]|\?[\w~`@#$%\^&*(_=+{[|><]/.test(str.slice(i - 1, i + 1)); |
+ }; |
var knownScrollbarWidth; |
function scrollbarWidth(measure) { |
@@ -5368,6 +5406,40 @@ window.CodeMirror = (function() { |
return Pos(lineN, ch); |
} |
+ function compareBidiLevel(order, a, b) { |
+ var linedir = order[0].level; |
+ if (a == linedir) return true; |
+ if (b == linedir) return false; |
+ return a < b; |
+ } |
+ var bidiOther; |
+ function getBidiPartAt(order, pos) { |
+ for (var i = 0, found; i < order.length; ++i) { |
+ var cur = order[i]; |
+ if (cur.from < pos && cur.to > pos) { bidiOther = null; return i; } |
+ if (cur.from == pos || cur.to == pos) { |
+ if (found == null) { |
+ found = i; |
+ } else if (compareBidiLevel(order, cur.level, order[found].level)) { |
+ bidiOther = found; |
+ return i; |
+ } else { |
+ bidiOther = i; |
+ return found; |
+ } |
+ } |
+ } |
+ bidiOther = null; |
+ return found; |
+ } |
+ |
+ function moveInLine(line, pos, dir, byUnit) { |
+ if (!byUnit) return pos + dir; |
+ do pos += dir; |
+ while (pos > 0 && isExtendingChar.test(line.text.charAt(pos))); |
+ return pos; |
+ } |
+ |
// This is somewhat involved. It is needed in order to move |
// 'visually' through bi-directional text -- i.e., pressing left |
// should make the cursor go left, even when in RTL text. The |
@@ -5377,37 +5449,24 @@ window.CodeMirror = (function() { |
function moveVisually(line, start, dir, byUnit) { |
var bidi = getOrder(line); |
if (!bidi) return moveLogically(line, start, dir, byUnit); |
- var moveOneUnit = byUnit ? function(pos, dir) { |
- do pos += dir; |
- while (pos > 0 && isExtendingChar.test(line.text.charAt(pos))); |
- return pos; |
- } : function(pos, dir) { return pos + dir; }; |
- var linedir = bidi[0].level; |
- for (var i = 0; i < bidi.length; ++i) { |
- var part = bidi[i], sticky = part.level % 2 == linedir; |
- if ((part.from < start && part.to > start) || |
- (sticky && (part.from == start || part.to == start))) break; |
- } |
- var target = moveOneUnit(start, part.level % 2 ? -dir : dir); |
- |
- while (target != null) { |
- if (part.level % 2 == linedir) { |
- if (target < part.from || target > part.to) { |
- part = bidi[i += dir]; |
- target = part && (dir > 0 == part.level % 2 ? moveOneUnit(part.to, -1) : moveOneUnit(part.from, 1)); |
- } else break; |
+ var pos = getBidiPartAt(bidi, start), part = bidi[pos]; |
+ var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit); |
+ |
+ for (;;) { |
+ if (target > part.from && target < part.to) return target; |
+ if (target == part.from || target == part.to) { |
+ if (getBidiPartAt(bidi, target) == pos) return target; |
+ part = bidi[pos += dir]; |
+ return (dir > 0) == part.level % 2 ? part.to : part.from; |
} else { |
- if (target == bidiLeft(part)) { |
- part = bidi[--i]; |
- target = part && bidiRight(part); |
- } else if (target == bidiRight(part)) { |
- part = bidi[++i]; |
- target = part && bidiLeft(part); |
- } else break; |
+ part = bidi[pos += dir]; |
+ if (!part) return null; |
+ if ((dir > 0) == part.level % 2) |
+ target = moveInLine(line, part.to, -1, byUnit); |
+ else |
+ target = moveInLine(line, part.from, 1, byUnit); |
} |
} |
- |
- return target < 0 || target > line.text.length ? null : target; |
} |
function moveLogically(line, start, dir, byUnit) { |
@@ -5579,7 +5638,7 @@ window.CodeMirror = (function() { |
// THE END |
- CodeMirror.version = "3.12"; |
+ CodeMirror.version = "3.13 +"; |
return CodeMirror; |
})(); |