codemirror
Advanced tools
Comparing version 5.37.0 to 5.38.0
@@ -28,2 +28,3 @@ // CodeMirror, copyright (c) by Marijn Haverbeke and others | ||
} | ||
CodeMirror.addClass(wrap, 'dialog-opened'); | ||
return dialog; | ||
@@ -51,2 +52,3 @@ } | ||
closed = true; | ||
CodeMirror.rmClass(dialog.parentNode, 'dialog-opened'); | ||
dialog.parentNode.removeChild(dialog); | ||
@@ -107,2 +109,3 @@ me.focus(); | ||
closed = true; | ||
CodeMirror.rmClass(dialog.parentNode, 'dialog-opened'); | ||
dialog.parentNode.removeChild(dialog); | ||
@@ -147,2 +150,3 @@ me.focus(); | ||
clearTimeout(doneTimer); | ||
CodeMirror.rmClass(dialog.parentNode, 'dialog-opened'); | ||
dialog.parentNode.removeChild(dialog); | ||
@@ -149,0 +153,0 @@ } |
@@ -336,3 +336,3 @@ // CodeMirror, copyright (c) by Marijn Haverbeke and others | ||
var node = this.hints.childNodes[this.selectedHint]; | ||
node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, ""); | ||
if (node) node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, ""); | ||
node = this.hints.childNodes[this.selectedHint = i]; | ||
@@ -339,0 +339,0 @@ node.className += " " + ACTIVE_HINT_ELEMENT_CLASS; |
@@ -26,2 +26,5 @@ // CodeMirror, copyright (c) by Marijn Haverbeke and others | ||
} | ||
// for jsonlint's web dist jsonlint is exported as an object with a single property parser, of which parseError | ||
// is a subproperty | ||
var jsonlint = window.jsonlint.parser || window.jsonlint | ||
jsonlint.parseError = function(str, hash) { | ||
@@ -28,0 +31,0 @@ var loc = hash.loc; |
@@ -78,13 +78,6 @@ // CodeMirror, copyright (c) by Marijn Haverbeke and others | ||
return ret("=>", "operator"); | ||
} else if (ch == "0" && stream.eat(/x/i)) { | ||
stream.eatWhile(/[\da-f]/i); | ||
} else if (ch == "0" && stream.match(/^(?:x[\da-f]+|o[0-7]+|b[01]+)n?/i)) { | ||
return ret("number", "number"); | ||
} else if (ch == "0" && stream.eat(/o/i)) { | ||
stream.eatWhile(/[0-7]/i); | ||
return ret("number", "number"); | ||
} else if (ch == "0" && stream.eat(/b/i)) { | ||
stream.eatWhile(/[01]/i); | ||
return ret("number", "number"); | ||
} else if (/\d/.test(ch)) { | ||
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); | ||
stream.match(/^\d*(?:n|(?:\.\d*)?(?:[eE][+\-]?\d+)?)?/); | ||
return ret("number", "number"); | ||
@@ -100,3 +93,3 @@ } else if (ch == "/") { | ||
readRegexp(stream); | ||
stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/); | ||
stream.match(/^\b(([gimyus])(?![gimyus]*\2))+\b/); | ||
return ret("regexp", "string-2"); | ||
@@ -270,17 +263,38 @@ } else { | ||
} | ||
function inList(name, list) { | ||
for (var v = list; v; v = v.next) if (v.name == name) return true | ||
return false; | ||
} | ||
function register(varname) { | ||
function inList(list) { | ||
for (var v = list; v; v = v.next) | ||
if (v.name == varname) return true; | ||
return false; | ||
} | ||
var state = cx.state; | ||
cx.marked = "def"; | ||
if (state.context) { | ||
if (inList(state.localVars)) return; | ||
state.localVars = {name: varname, next: state.localVars}; | ||
if (state.lexical.info == "var" && state.context && state.context.block) { | ||
// FIXME function decls are also not block scoped | ||
var newContext = registerVarScoped(varname, state.context) | ||
if (newContext != null) { | ||
state.context = newContext | ||
return | ||
} | ||
} else if (!inList(varname, state.localVars)) { | ||
state.localVars = new Var(varname, state.localVars) | ||
return | ||
} | ||
} | ||
// Fall through means this is global | ||
if (parserConfig.globalVars && !inList(varname, state.globalVars)) | ||
state.globalVars = new Var(varname, state.globalVars) | ||
} | ||
function registerVarScoped(varname, context) { | ||
if (!context) { | ||
return null | ||
} else if (context.block) { | ||
var inner = registerVarScoped(varname, context.prev) | ||
if (!inner) return null | ||
if (inner == context.prev) return context | ||
return new Context(inner, context.vars, true) | ||
} else if (inList(varname, context.vars)) { | ||
return context | ||
} else { | ||
if (inList(state.globalVars)) return; | ||
if (parserConfig.globalVars) | ||
state.globalVars = {name: varname, next: state.globalVars}; | ||
return new Context(context.prev, new Var(varname, context.vars), false) | ||
} | ||
@@ -295,11 +309,19 @@ } | ||
var defaultVars = {name: "this", next: {name: "arguments"}}; | ||
function Context(prev, vars, block) { this.prev = prev; this.vars = vars; this.block = block } | ||
function Var(name, next) { this.name = name; this.next = next } | ||
var defaultVars = new Var("this", new Var("arguments", null)) | ||
function pushcontext() { | ||
cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; | ||
cx.state.localVars = defaultVars; | ||
cx.state.context = new Context(cx.state.context, cx.state.localVars, false) | ||
cx.state.localVars = defaultVars | ||
} | ||
function pushblockcontext() { | ||
cx.state.context = new Context(cx.state.context, cx.state.localVars, true) | ||
cx.state.localVars = null | ||
} | ||
function popcontext() { | ||
cx.state.localVars = cx.state.context.vars; | ||
cx.state.context = cx.state.context.prev; | ||
cx.state.localVars = cx.state.context.vars | ||
cx.state.context = cx.state.context.prev | ||
} | ||
popcontext.lex = true | ||
function pushlex(type, info) { | ||
@@ -336,3 +358,3 @@ var result = function() { | ||
function statement(type, value) { | ||
if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex); | ||
if (type == "var") return cont(pushlex("vardef", value), vardef, expect(";"), poplex); | ||
if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex); | ||
@@ -342,3 +364,3 @@ if (type == "keyword b") return cont(pushlex("form"), statement, poplex); | ||
if (type == "debugger") return cont(expect(";")); | ||
if (type == "{") return cont(pushlex("}"), block, poplex); | ||
if (type == "{") return cont(pushlex("}"), pushblockcontext, block, poplex, popcontext); | ||
if (type == ";") return cont(); | ||
@@ -372,8 +394,7 @@ if (type == "if") { | ||
} | ||
if (type == "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), | ||
block, poplex, poplex); | ||
if (type == "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), pushblockcontext, | ||
block, poplex, poplex, popcontext); | ||
if (type == "case") return cont(expression, expect(":")); | ||
if (type == "default") return cont(expect(":")); | ||
if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), | ||
statement, poplex, popcontext); | ||
if (type == "catch") return cont(pushlex("form"), pushcontext, maybeCatchBinding, statement, poplex, popcontext); | ||
if (type == "export") return cont(pushlex("stat"), afterExport, poplex); | ||
@@ -385,2 +406,5 @@ if (type == "import") return cont(pushlex("stat"), afterImport, poplex); | ||
} | ||
function maybeCatchBinding(type) { | ||
if (type == "(") return cont(funarg, expect(")")) | ||
} | ||
function expression(type, value) { | ||
@@ -794,3 +818,3 @@ return expressionInner(type, value, false); | ||
localVars: parserConfig.localVars, | ||
context: parserConfig.localVars && {vars: parserConfig.localVars}, | ||
context: parserConfig.localVars && new Context(null, null, false), | ||
indented: basecolumn || 0 | ||
@@ -836,3 +860,3 @@ }; | ||
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0); | ||
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info.length + 1 : 0); | ||
else if (type == "form" && firstChar == "{") return lexical.indented; | ||
@@ -839,0 +863,0 @@ else if (type == "form") return lexical.indented + indentUnit; |
@@ -622,3 +622,3 @@ // CodeMirror, copyright (c) by Marijn Haverbeke and others | ||
if (ch === ' ') { | ||
if (stream.match(/ +$/, false)) { | ||
if (stream.match(/^ +$/, false)) { | ||
state.trailingSpace++; | ||
@@ -625,0 +625,0 @@ } else if (state.trailingSpace) { |
{ | ||
"name": "codemirror", | ||
"version": "5.37.0", | ||
"version": "5.38.0", | ||
"main": "lib/codemirror.js", | ||
@@ -5,0 +5,0 @@ "style": "lib/codemirror.css", |
@@ -35,2 +35,3 @@ import { addClass, elt, rmClass } from "../util/dom.js" | ||
let horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar") | ||
vert.tabIndex = horiz.tabIndex = -1 | ||
place(vert); place(horiz) | ||
@@ -37,0 +38,0 @@ |
@@ -69,2 +69,2 @@ // EDITOR CONSTRUCTOR | ||
CodeMirror.version = "5.37.0" | ||
CodeMirror.version = "5.38.0" |
@@ -316,3 +316,3 @@ import { delayBlurEvent, ensureFocus } from "../display/focus.js" | ||
let move = operation(cm, e => { | ||
if (!e_button(e)) done(e) | ||
if (e.buttons === 0 || !e_button(e)) done(e) | ||
else extend(e) | ||
@@ -319,0 +319,0 @@ }) |
@@ -114,4 +114,8 @@ import { operation, runInOp } from "../display/operations.js" | ||
getSelection() { | ||
return this.cm.display.wrapper.ownerDocument.getSelection() | ||
} | ||
showPrimarySelection() { | ||
let sel = window.getSelection(), cm = this.cm, prim = cm.doc.sel.primary() | ||
let sel = this.getSelection(), cm = this.cm, prim = cm.doc.sel.primary() | ||
let from = prim.from(), to = prim.to() | ||
@@ -181,3 +185,3 @@ | ||
rememberSelection() { | ||
let sel = window.getSelection() | ||
let sel = this.getSelection() | ||
this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset | ||
@@ -188,3 +192,3 @@ this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset | ||
selectionInEditor() { | ||
let sel = window.getSelection() | ||
let sel = this.getSelection() | ||
if (!sel.rangeCount) return false | ||
@@ -224,3 +228,3 @@ let node = sel.getRangeAt(0).commonAncestorContainer | ||
selectionChanged() { | ||
let sel = window.getSelection() | ||
let sel = this.getSelection() | ||
return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset || | ||
@@ -232,3 +236,3 @@ sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset | ||
if (this.readDOMTimeout != null || this.gracePeriod || !this.selectionChanged()) return | ||
let sel = window.getSelection(), cm = this.cm | ||
let sel = this.getSelection(), cm = this.cm | ||
// On Android Chrome (version 56, at least), backspacing into an | ||
@@ -404,3 +408,3 @@ // uneditable block element will put the cursor in that element, | ||
function domTextBetween(cm, from, to, fromLine, toLine) { | ||
let text = "", closing = false, lineSep = cm.doc.lineSeparator() | ||
let text = "", closing = false, lineSep = cm.doc.lineSeparator(), extraLinebreak = false | ||
function recognizeMarker(id) { return marker => marker.id == id } | ||
@@ -410,3 +414,4 @@ function close() { | ||
text += lineSep | ||
closing = false | ||
if (extraLinebreak) text += lineSep | ||
closing = extraLinebreak = false | ||
} | ||
@@ -423,4 +428,4 @@ } | ||
let cmText = node.getAttribute("cm-text") | ||
if (cmText != null) { | ||
addText(cmText || node.textContent.replace(/\u200b/g, "")) | ||
if (cmText) { | ||
addText(cmText) | ||
return | ||
@@ -436,9 +441,13 @@ } | ||
if (node.getAttribute("contenteditable") == "false") return | ||
let isBlock = /^(pre|div|p)$/i.test(node.nodeName) | ||
let isBlock = /^(pre|div|p|li|table|br)$/i.test(node.nodeName) | ||
if (!/^br$/i.test(node.nodeName) && node.textContent.length == 0) return | ||
if (isBlock) close() | ||
for (let i = 0; i < node.childNodes.length; i++) | ||
walk(node.childNodes[i]) | ||
if (/^(pre|p)$/i.test(node.nodeName)) extraLinebreak = true | ||
if (isBlock) closing = true | ||
} else if (node.nodeType == 3) { | ||
addText(node.nodeValue) | ||
addText(node.nodeValue.replace(/\u200b/g, "").replace(/\u00a0/g, " ")) | ||
} | ||
@@ -450,2 +459,3 @@ } | ||
from = from.nextSibling | ||
extraLinebreak = false | ||
} | ||
@@ -452,0 +462,0 @@ return text |
@@ -221,2 +221,12 @@ import { indexOf, lst } from "../util/misc.js" | ||
export function collapsedSpanAround(line, ch) { | ||
let sps = sawCollapsedSpans && line.markedSpans, found | ||
if (sps) for (let i = 0; i < sps.length; ++i) { | ||
let sp = sps[i] | ||
if (sp.marker.collapsed && (sp.from == null || sp.from < ch) && (sp.to == null || sp.to > ch) && | ||
(!found || compareCollapsedMarkers(found, sp.marker) < 0)) found = sp.marker | ||
} | ||
return found | ||
} | ||
// Test whether there exists a collapsed span that partially | ||
@@ -223,0 +233,0 @@ // overlaps (covers the start or end, but not both) of a new span. |
import { buildLineContent, LineView } from "../line/line_data.js" | ||
import { clipPos, Pos } from "../line/pos.js" | ||
import { collapsedSpanAtEnd, heightAtLine, lineIsHidden, visualLine } from "../line/spans.js" | ||
import { collapsedSpanAround, heightAtLine, lineIsHidden, visualLine } from "../line/spans.js" | ||
import { getLine, lineAtHeight, lineNo, updateLineHeight } from "../line/utils_line.js" | ||
@@ -433,8 +433,7 @@ import { bidiOther, getBidiPartAt, getOrder } from "../util/bidi.js" | ||
let found = coordsCharInner(cm, lineObj, lineN, x, y) | ||
let merged = collapsedSpanAtEnd(lineObj) | ||
let mergedPos = merged && merged.find(0, true) | ||
if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0)) | ||
lineN = lineNo(lineObj = mergedPos.to.line) | ||
else | ||
return found | ||
let collapsed = collapsedSpanAround(lineObj, found.ch + (found.xRel > 0 ? 1 : 0)) | ||
if (!collapsed) return found | ||
let rangeEnd = collapsed.find(1) | ||
if (rangeEnd.line == lineN) return rangeEnd | ||
lineObj = getLine(doc, lineN = rangeEnd.line) | ||
} | ||
@@ -441,0 +440,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
2734068
322
62574