From b7b6ed2ff5eb69a937e020581fd89b513664c694 Mon Sep 17 00:00:00 2001 From: Rob Garrison Date: Mon, 8 Jul 2019 04:59:04 -0500 Subject: [PATCH] Update vendor libraries Codemirror & Dropbox sdk --- edit/codemirror-themes.js | 2 + manifest.json | 2 +- vendor/codemirror/README.md | 2 +- vendor/codemirror/addon/edit/closebrackets.js | 6 +- vendor/codemirror/addon/edit/matchbrackets.js | 15 +- vendor/codemirror/addon/hint/show-hint.js | 38 +- .../addon/search/matchesonscrollbar.js | 2 +- vendor/codemirror/keymap/emacs.js | 1 + vendor/codemirror/keymap/sublime.js | 4 +- vendor/codemirror/keymap/vim.js | 133 +- vendor/codemirror/lib/codemirror.js | 1821 +++++++++-------- vendor/codemirror/mode/css/css.js | 13 +- .../codemirror/mode/javascript/javascript.js | 77 +- vendor/codemirror/theme/base16-light.css | 2 +- vendor/codemirror/theme/lesser-dark.css | 2 +- vendor/codemirror/theme/midnight.css | 4 - vendor/codemirror/theme/nord.css | 42 + vendor/codemirror/theme/panda-syntax.css | 2 +- vendor/codemirror/theme/vibrant-ink.css | 2 +- vendor/codemirror/theme/yonce.css | 59 + vendor/dropbox/README.md | 4 +- vendor/dropbox/dropbox-sdk.js | 154 +- 22 files changed, 1328 insertions(+), 1059 deletions(-) create mode 100644 vendor/codemirror/theme/nord.css create mode 100644 vendor/codemirror/theme/yonce.css diff --git a/edit/codemirror-themes.js b/edit/codemirror-themes.js index f0501a4d..433a185c 100644 --- a/edit/codemirror-themes.js +++ b/edit/codemirror-themes.js @@ -37,6 +37,7 @@ const CODEMIRROR_THEMES = [ 'neat', 'neo', 'night', + 'nord', 'oceanic-next', 'panda-syntax', 'paraiso-dark', @@ -57,5 +58,6 @@ const CODEMIRROR_THEMES = [ 'xq-dark', 'xq-light', 'yeti', + 'yonce', 'zenburn' ]; diff --git a/manifest.json b/manifest.json index b8eab624..ae582708 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { "name": "Stylus", - "version": "1.5.2", + "version": "1.5.3", "minimum_chrome_version": "49", "description": "__MSG_description__", "homepage_url": "https://add0n.com/stylus.html", diff --git a/vendor/codemirror/README.md b/vendor/codemirror/README.md index d57ae9f9..1d40e0e4 100644 --- a/vendor/codemirror/README.md +++ b/vendor/codemirror/README.md @@ -1,3 +1,3 @@ -## CodeMirror v5.42.0 +## CodeMirror v5.48.0 Only files & folders that exist in the `vendor/codemirror` folder are copied from the `node_modules/codemirror` folder. Except all theme files are copied, in case new themes have been added. diff --git a/vendor/codemirror/addon/edit/closebrackets.js b/vendor/codemirror/addon/edit/closebrackets.js index ce1a4ac6..4415c393 100644 --- a/vendor/codemirror/addon/edit/closebrackets.js +++ b/vendor/codemirror/addon/edit/closebrackets.js @@ -11,6 +11,7 @@ })(function(CodeMirror) { var defaults = { pairs: "()[]{}''\"\"", + closeBefore: ")]}'\":;>", triples: "", explode: "[]{}" }; @@ -109,6 +110,9 @@ var pairs = getOption(conf, "pairs"); var pos = pairs.indexOf(ch); if (pos == -1) return CodeMirror.Pass; + + var closeBefore = getOption(conf,"closeBefore"); + var triples = getOption(conf, "triples"); var identical = pairs.charAt(pos + 1) == ch; @@ -136,7 +140,7 @@ var prev = cur.ch == 0 ? " " : cm.getRange(Pos(cur.line, cur.ch - 1), cur) if (!CodeMirror.isWordChar(next) && prev != ch && !CodeMirror.isWordChar(prev)) curType = "both"; else return CodeMirror.Pass; - } else if (opening) { + } else if (opening && (next.length === 0 || /\s/.test(next) || closeBefore.indexOf(next) > -1)) { curType = "both"; } else { return CodeMirror.Pass; diff --git a/vendor/codemirror/addon/edit/matchbrackets.js b/vendor/codemirror/addon/edit/matchbrackets.js index c918c3f9..2a147282 100644 --- a/vendor/codemirror/addon/edit/matchbrackets.js +++ b/vendor/codemirror/addon/edit/matchbrackets.js @@ -14,20 +14,25 @@ var Pos = CodeMirror.Pos; - var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"}; + var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<", "<": ">>", ">": "<<"}; + + function bracketRegex(config) { + return config && config.bracketRegex || /[(){}[\]]/ + } function findMatchingBracket(cm, where, config) { var line = cm.getLineHandle(where.line), pos = where.ch - 1; var afterCursor = config && config.afterCursor if (afterCursor == null) afterCursor = /(^| )cm-fat-cursor($| )/.test(cm.getWrapperElement().className) + var re = bracketRegex(config) // A cursor is defined as between two characters, but in in vim command mode // (i.e. not insert mode), the cursor is visually represented as a // highlighted box on top of the 2nd character. Otherwise, we allow matches // from before or after the cursor. - var match = (!afterCursor && pos >= 0 && matching[line.text.charAt(pos)]) || - matching[line.text.charAt(++pos)]; + var match = (!afterCursor && pos >= 0 && re.test(line.text.charAt(pos)) && matching[line.text.charAt(pos)]) || + re.test(line.text.charAt(pos + 1)) && matching[line.text.charAt(++pos)]; if (!match) return null; var dir = match.charAt(1) == ">" ? 1 : -1; if (config && config.strict && (dir > 0) != (pos == where.ch)) return null; @@ -51,7 +56,7 @@ var maxScanLines = (config && config.maxScanLines) || 1000; var stack = []; - var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/; + var re = bracketRegex(config) var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1) : Math.max(cm.firstLine() - 1, where.line - maxScanLines); for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) { @@ -64,7 +69,7 @@ var ch = line.charAt(pos); if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) { var match = matching[ch]; - if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch); + if (match && (match.charAt(1) == ">") == (dir > 0)) stack.push(ch); else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch}; else stack.pop(); } diff --git a/vendor/codemirror/addon/hint/show-hint.js b/vendor/codemirror/addon/hint/show-hint.js index 28025775..d70b2ab1 100644 --- a/vendor/codemirror/addon/hint/show-hint.js +++ b/vendor/codemirror/addon/hint/show-hint.js @@ -46,6 +46,10 @@ completion.update(true); }); + CodeMirror.defineExtension("closeHint", function() { + if (this.state.completionActive) this.state.completionActive.close() + }) + function Completion(cm, options) { this.cm = cm; this.options = options; @@ -163,6 +167,14 @@ Tab: handle.pick, Esc: handle.close }; + + var mac = /Mac/.test(navigator.platform); + + if (mac) { + baseMap["Ctrl-P"] = function() {handle.moveFocus(-1);}; + baseMap["Ctrl-N"] = function() {handle.moveFocus(1);}; + } + var custom = completion.options.customKeys; var ourMap = custom ? {} : baseMap; function addBinding(key, val) { @@ -217,14 +229,26 @@ elt.hintId = i; } + var container = completion.options.container || ownerDocument.body; var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null); var left = pos.left, top = pos.bottom, below = true; - hints.style.left = left + "px"; - hints.style.top = top + "px"; + var offsetLeft = 0, offsetTop = 0; + if (container !== ownerDocument.body) { + // We offset the cursor position because left and top are relative to the offsetParent's top left corner. + var isContainerPositioned = ['absolute', 'relative', 'fixed'].indexOf(parentWindow.getComputedStyle(container).position) !== -1; + var offsetParent = isContainerPositioned ? container : container.offsetParent; + var offsetParentPosition = offsetParent.getBoundingClientRect(); + var bodyPosition = ownerDocument.body.getBoundingClientRect(); + offsetLeft = (offsetParentPosition.left - bodyPosition.left - offsetParent.scrollLeft); + offsetTop = (offsetParentPosition.top - bodyPosition.top - offsetParent.scrollTop); + } + hints.style.left = (left - offsetLeft) + "px"; + hints.style.top = (top - offsetTop) + "px"; + // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor. var winW = parentWindow.innerWidth || Math.max(ownerDocument.body.offsetWidth, ownerDocument.documentElement.offsetWidth); var winH = parentWindow.innerHeight || Math.max(ownerDocument.body.offsetHeight, ownerDocument.documentElement.offsetHeight); - (completion.options.container || ownerDocument.body).appendChild(hints); + container.appendChild(hints); var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH; var scrolls = hints.scrollHeight > hints.clientHeight + 1 var startScroll = cm.getScrollInfo(); @@ -232,15 +256,15 @@ if (overlapY > 0) { var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top); if (curTop - height > 0) { // Fits above cursor - hints.style.top = (top = pos.top - height) + "px"; + hints.style.top = (top = pos.top - height - offsetTop) + "px"; below = false; } else if (height > winH) { hints.style.height = (winH - 5) + "px"; - hints.style.top = (top = pos.bottom - box.top) + "px"; + hints.style.top = (top = pos.bottom - box.top - offsetTop) + "px"; var cursor = cm.getCursor(); if (data.from.ch != cursor.ch) { pos = cm.cursorCoords(cursor); - hints.style.left = (left = pos.left) + "px"; + hints.style.left = (left = pos.left - offsetLeft) + "px"; box = hints.getBoundingClientRect(); } } @@ -251,7 +275,7 @@ hints.style.width = (winW - 5) + "px"; overlapX -= (box.right - box.left) - winW; } - hints.style.left = (left = pos.left - overlapX) + "px"; + hints.style.left = (left = pos.left - overlapX - offsetLeft) + "px"; } if (scrolls) for (var node = hints.firstChild; node; node = node.nextSibling) node.style.paddingRight = cm.display.nativeBarWidth + "px" diff --git a/vendor/codemirror/addon/search/matchesonscrollbar.js b/vendor/codemirror/addon/search/matchesonscrollbar.js index 4645f5eb..8a4a8275 100644 --- a/vendor/codemirror/addon/search/matchesonscrollbar.js +++ b/vendor/codemirror/addon/search/matchesonscrollbar.js @@ -46,7 +46,7 @@ if (match.from.line >= this.gap.to) break; if (match.to.line >= this.gap.from) this.matches.splice(i--, 1); } - var cursor = this.cm.getSearchCursor(this.query, CodeMirror.Pos(this.gap.from, 0), this.caseFold); + var cursor = this.cm.getSearchCursor(this.query, CodeMirror.Pos(this.gap.from, 0), {caseFold: this.caseFold, multiline: this.options.multiline}); var maxMatches = this.options && this.options.maxMatches || MAX_MATCHES; while (cursor.findNext()) { var match = {from: cursor.from(), to: cursor.to()}; diff --git a/vendor/codemirror/keymap/emacs.js b/vendor/codemirror/keymap/emacs.js index d96a6fbe..fe62d44f 100644 --- a/vendor/codemirror/keymap/emacs.js +++ b/vendor/codemirror/keymap/emacs.js @@ -369,6 +369,7 @@ "Ctrl-/": repeated("undo"), "Shift-Ctrl--": repeated("undo"), "Ctrl-Z": repeated("undo"), "Cmd-Z": repeated("undo"), + "Shift-Ctrl-Z": "redo", "Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd", "Ctrl-S": "findPersistentNext", "Ctrl-R": "findPersistentPrev", "Ctrl-G": quit, "Shift-Alt-5": "replace", "Alt-/": "autocomplete", diff --git a/vendor/codemirror/keymap/sublime.js b/vendor/codemirror/keymap/sublime.js index b4799fd6..799641af 100644 --- a/vendor/codemirror/keymap/sublime.js +++ b/vendor/codemirror/keymap/sublime.js @@ -589,8 +589,8 @@ "Cmd-/": "toggleCommentIndented", "Cmd-J": "joinLines", "Shift-Cmd-D": "duplicateLine", - "F9": "sortLines", - "Cmd-F9": "sortLinesInsensitive", + "F5": "sortLines", + "Cmd-F5": "sortLinesInsensitive", "F2": "nextBookmark", "Shift-F2": "prevBookmark", "Cmd-F2": "toggleBookmark", diff --git a/vendor/codemirror/keymap/vim.js b/vendor/codemirror/keymap/vim.js index aed0957d..3be7a3f4 100644 --- a/vendor/codemirror/keymap/vim.js +++ b/vendor/codemirror/keymap/vim.js @@ -53,6 +53,7 @@ { keys: '', type: 'keyToKey', toKeys: 'j' }, { keys: '', type: 'keyToKey', toKeys: 'l' }, { keys: '', type: 'keyToKey', toKeys: 'h', context: 'normal'}, + { keys: '', type: 'keyToKey', toKeys: 'x', context: 'normal'}, { keys: '', type: 'keyToKey', toKeys: 'W' }, { keys: '', type: 'keyToKey', toKeys: 'B', context: 'normal' }, { keys: '', type: 'keyToKey', toKeys: 'w' }, @@ -152,6 +153,8 @@ { keys: '~', type: 'operatorMotion', operator: 'changeCase', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorArgs: { shouldMoveCursor: true }, context: 'normal'}, { keys: '~', type: 'operator', operator: 'changeCase', context: 'visual'}, { keys: '', type: 'operatorMotion', operator: 'delete', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }, context: 'insert' }, + //ignore C-w in normal mode + { keys: '', type: 'idle', context: 'normal' }, // Actions { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: true }}, { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: false }}, @@ -283,7 +286,9 @@ enterVimMode(cm); } - function fatCursorMarks(cm) { + function updateFatCursorMark(cm) { + if (!cm.state.fatCursorMarks) return; + clearFatCursorMark(cm); var ranges = cm.listSelections(), result = [] for (var i = 0; i < ranges.length; i++) { var range = ranges[i] @@ -299,25 +304,26 @@ } } } - return result + cm.state.fatCursorMarks = result; } - function updateFatCursorMark(cm) { - var marks = cm.state.fatCursorMarks - if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear() - cm.state.fatCursorMarks = fatCursorMarks(cm) + function clearFatCursorMark(cm) { + var marks = cm.state.fatCursorMarks; + if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear(); } function enableFatCursorMark(cm) { - cm.state.fatCursorMarks = fatCursorMarks(cm) + cm.state.fatCursorMarks = []; + updateFatCursorMark(cm) cm.on("cursorActivity", updateFatCursorMark) } function disableFatCursorMark(cm) { - var marks = cm.state.fatCursorMarks - if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear() - cm.state.fatCursorMarks = null - cm.off("cursorActivity", updateFatCursorMark) + clearFatCursorMark(cm); + cm.off("cursorActivity", updateFatCursorMark); + // explicitly set fatCursorMarks to null because event listener above + // can be invoke after removing it, if off is called from operation + cm.state.fatCursorMarks = null; } // Deprecated, simply setting the keymap works again. @@ -1711,6 +1717,7 @@ vim.lastEditActionCommand = actionCommand; macroModeState.lastInsertModeChanges.changes = []; macroModeState.lastInsertModeChanges.expectCursorActivityForChange = false; + macroModeState.lastInsertModeChanges.visualBlock = vim.visualBlock ? vim.sel.head.line - vim.sel.anchor.line : 0; } }; @@ -1841,7 +1848,7 @@ if (line < first && cur.line == first){ return this.moveToStartOfLine(cm, head, motionArgs, vim); }else if (line > last && cur.line == last){ - return this.moveToEol(cm, head, motionArgs, vim); + return this.moveToEol(cm, head, motionArgs, vim, true); } if (motionArgs.toFirstChar){ endCh=findFirstNonWhiteSpaceCharacter(cm.getLine(line)); @@ -1943,13 +1950,15 @@ vim.lastHSPos = cm.charCoords(head,'div').left; return moveToColumn(cm, repeat); }, - moveToEol: function(cm, head, motionArgs, vim) { + moveToEol: function(cm, head, motionArgs, vim, keepHPos) { var cur = head; - vim.lastHPos = Infinity; var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity); var end=cm.clipPos(retval); end.ch--; - vim.lastHSPos = cm.charCoords(end,'div').left; + if (!keepHPos) { + vim.lastHPos = Infinity; + vim.lastHSPos = cm.charCoords(end,'div').left; + } return retval; }, moveToFirstNonWhiteSpaceCharacter: function(cm, head) { @@ -1975,7 +1984,9 @@ } } if (ch < lineText.length) { - var matched = cm.findMatchingBracket(Pos(line, ch)); + // Only include angle brackets in analysis if they are being matched. + var re = (ch === '<' || ch === '>') ? /[(){}[\]<>]/ : /[(){}[\]]/; + var matched = cm.findMatchingBracket(Pos(line, ch), {bracketRegex: re}); return matched.to; } else { return cursor; @@ -1995,13 +2006,11 @@ textObjectManipulation: function(cm, head, motionArgs, vim) { // TODO: lots of possible exceptions that can be thrown here. Try da( // outside of a () block. - - // TODO: adding <> >< to this map doesn't work, presumably because - // they're operators var mirroredPairs = {'(': ')', ')': '(', '{': '}', '}': '{', - '[': ']', ']': '['}; - var selfPaired = {'\'': true, '"': true}; + '[': ']', ']': '[', + '<': '>', '>': '<'}; + var selfPaired = {'\'': true, '"': true, '`': true}; var character = motionArgs.selectedCharacter; // 'b' refers to '()' block. @@ -2089,7 +2098,6 @@ change: function(cm, args, ranges) { var finalHead, text; var vim = cm.state.vim; - vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock = vim.visualBlock; if (!vim.visualMode) { var anchor = ranges[0].anchor, head = ranges[0].head; @@ -2312,6 +2320,8 @@ var macroModeState = vimGlobalState.macroModeState; if (registerName == '@') { registerName = macroModeState.latestRegister; + } else { + macroModeState.latestRegister = registerName; } while(repeat--){ executeMacroRegister(cm, vim, macroModeState, registerName); @@ -2350,6 +2360,8 @@ } else if (insertAt == 'firstNonBlank') { head = motions.moveToFirstNonWhiteSpaceCharacter(cm, head); } else if (insertAt == 'startOfSelectedArea') { + if (!vim.visualMode) + return; if (!vim.visualBlock) { if (sel.head.line < sel.anchor.line) { head = sel.head; @@ -2363,6 +2375,8 @@ height = Math.abs(sel.head.line - sel.anchor.line) + 1; } } else if (insertAt == 'endOfSelectedArea') { + if (!vim.visualMode) + return; if (!vim.visualBlock) { if (sel.head.line >= sel.anchor.line) { head = offsetCursor(sel.head, 0, 1); @@ -2556,7 +2570,17 @@ } var linewise = register.linewise; var blockwise = register.blockwise; - if (linewise) { + if (blockwise) { + text = text.split('\n'); + if (linewise) { + text.pop(); + } + for (var i = 0; i < text.length; i++) { + text[i] = (text[i] == '') ? ' ' : text[i]; + } + cur.ch += actionArgs.after ? 1 : 0; + cur.ch = Math.min(lineLength(cm, cur.line), cur.ch); + } else if (linewise) { if(vim.visualMode) { text = vim.visualLine ? text.slice(0, -1) : '\n' + text.slice(0, text.length - 1) + '\n'; } else if (actionArgs.after) { @@ -2568,12 +2592,6 @@ cur.ch = 0; } } else { - if (blockwise) { - text = text.split('\n'); - for (var i = 0; i < text.length; i++) { - text[i] = (text[i] == '') ? ' ' : text[i]; - } - } cur.ch += actionArgs.after ? 1 : 0; } var curPosFinal; @@ -2808,12 +2826,6 @@ } return Pos(cur.line + offsetLine, cur.ch + offsetCh); } - function getOffset(anchor, head) { - return { - line: head.line - anchor.line, - ch: head.line - anchor.line - }; - } function commandMatches(keys, keyMap, context, inputState) { // Partial matches are not applied. They inform the key handler // that the current key sequence is a subsequence of a valid key @@ -3802,11 +3814,13 @@ var bracketRegexp = ({ '(': /[()]/, ')': /[()]/, '[': /[[\]]/, ']': /[[\]]/, - '{': /[{}]/, '}': /[{}]/})[symb]; + '{': /[{}]/, '}': /[{}]/, + '<': /[<>]/, '>': /[<>]/})[symb]; var openSym = ({ '(': '(', ')': '(', '[': '[', ']': '[', - '{': '{', '}': '{'})[symb]; + '{': '{', '}': '{', + '<': '<', '>': '<'})[symb]; var curChar = cm.getLine(cur.line).charAt(cur.ch); // Due to the behavior of scanForBracket, we need to add an offset if the // cursor is on a matching open bracket. @@ -4215,23 +4229,27 @@ query: query }; } + var highlightTimeout = 0; function highlightSearchMatches(cm, query) { - var searchState = getSearchState(cm); - var overlay = searchState.getOverlay(); - if (!overlay || query != overlay.query) { - if (overlay) { - cm.removeOverlay(overlay); - } - overlay = searchOverlay(query); - cm.addOverlay(overlay); - if (cm.showMatchesOnScrollbar) { - if (searchState.getScrollbarAnnotate()) { - searchState.getScrollbarAnnotate().clear(); + clearTimeout(highlightTimeout); + highlightTimeout = setTimeout(function() { + var searchState = getSearchState(cm); + var overlay = searchState.getOverlay(); + if (!overlay || query != overlay.query) { + if (overlay) { + cm.removeOverlay(overlay); } - searchState.setScrollbarAnnotate(cm.showMatchesOnScrollbar(query)); + overlay = searchOverlay(query); + cm.addOverlay(overlay); + if (cm.showMatchesOnScrollbar) { + if (searchState.getScrollbarAnnotate()) { + searchState.getScrollbarAnnotate().clear(); + } + searchState.setScrollbarAnnotate(cm.showMatchesOnScrollbar(query)); + } + searchState.setOverlay(overlay); } - searchState.setOverlay(overlay); - } + }, 50); } function findNext(cm, prev, query, repeat) { if (repeat === undefined) { repeat = 1; } @@ -5431,18 +5449,15 @@ return true; } var head = cm.getCursor('head'); - var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock; - if (inVisualBlock) { + var visualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.visualBlock; + if (visualBlock) { // Set up block selection again for repeating the changes. - var vim = cm.state.vim; - var lastSel = vim.lastSelection; - var offset = getOffset(lastSel.anchor, lastSel.head); - selectForInsert(cm, head, offset.line + 1); + selectForInsert(cm, head, visualBlock + 1); repeat = cm.listSelections().length; cm.setCursor(head); } for (var i = 0; i < repeat; i++) { - if (inVisualBlock) { + if (visualBlock) { cm.setCursor(offsetCursor(head, i, 0)); } for (var j = 0; j < changes.length; j++) { @@ -5459,7 +5474,7 @@ } } } - if (inVisualBlock) { + if (visualBlock) { cm.setCursor(offsetCursor(head, 0, 1)); } } diff --git a/vendor/codemirror/lib/codemirror.js b/vendor/codemirror/lib/codemirror.js index c5a9da5f..3ca19118 100644 --- a/vendor/codemirror/lib/codemirror.js +++ b/vendor/codemirror/lib/codemirror.js @@ -292,622 +292,6 @@ } } - // The display handles the DOM integration, both for input reading - // and content drawing. It holds references to DOM nodes and - // display-related state. - - function Display(place, doc, input) { - var d = this; - this.input = input; - - // Covers bottom-right square when both scrollbars are present. - d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler"); - d.scrollbarFiller.setAttribute("cm-not-content", "true"); - // Covers bottom of gutter when coverGutterNextToScrollbar is on - // and h scrollbar is present. - d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler"); - d.gutterFiller.setAttribute("cm-not-content", "true"); - // Will contain the actual code, positioned to cover the viewport. - d.lineDiv = eltP("div", null, "CodeMirror-code"); - // Elements are added to these to represent selection and cursors. - d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1"); - d.cursorDiv = elt("div", null, "CodeMirror-cursors"); - // A visibility: hidden element used to find the size of things. - d.measure = elt("div", null, "CodeMirror-measure"); - // When lines outside of the viewport are measured, they are drawn in this. - d.lineMeasure = elt("div", null, "CodeMirror-measure"); - // Wraps everything that needs to exist inside the vertically-padded coordinate system - d.lineSpace = eltP("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv], - null, "position: relative; outline: none"); - var lines = eltP("div", [d.lineSpace], "CodeMirror-lines"); - // Moved around its parent to cover visible view. - d.mover = elt("div", [lines], null, "position: relative"); - // Set to the height of the document, allowing scrolling. - d.sizer = elt("div", [d.mover], "CodeMirror-sizer"); - d.sizerWidth = null; - // Behavior of elts with overflow: auto and padding is - // inconsistent across browsers. This is used to ensure the - // scrollable area is big enough. - d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;"); - // Will contain the gutters, if any. - d.gutters = elt("div", null, "CodeMirror-gutters"); - d.lineGutter = null; - // Actual scrollable element. - 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.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror"); - - // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported) - if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; } - if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true; } - - if (place) { - if (place.appendChild) { place.appendChild(d.wrapper); } - else { place(d.wrapper); } - } - - // Current rendered range (may be bigger than the view window). - d.viewFrom = d.viewTo = doc.first; - d.reportedViewFrom = d.reportedViewTo = doc.first; - // Information about the rendered lines. - d.view = []; - d.renderedView = null; - // Holds info about a single rendered line when it was rendered - // for measurement, while not in view. - d.externalMeasured = null; - // Empty space (in pixels) above the view - d.viewOffset = 0; - d.lastWrapHeight = d.lastWrapWidth = 0; - d.updateLineNumbers = null; - - d.nativeBarWidth = d.barHeight = d.barWidth = 0; - d.scrollbarsClipped = false; - - // Used to only resize the line number gutter when necessary (when - // the amount of lines crosses a boundary that makes its width change) - d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null; - // Set to true when a non-horizontal-scrolling line widget is - // added. As an optimization, line widget aligning is skipped when - // this is false. - d.alignWidgets = false; - - d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; - - // Tracks the maximum line length so that the horizontal scrollbar - // can be kept static when scrolling. - d.maxLine = null; - d.maxLineLength = 0; - d.maxLineChanged = false; - - // Used for measuring wheel scrolling granularity - d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null; - - // True when shift is held down. - d.shift = false; - - // Used to track whether anything happened since the context menu - // was opened. - d.selForContextMenu = null; - - d.activeTouch = null; - - input.init(d); - } - - // Find the line object corresponding to the given line number. - function getLine(doc, n) { - n -= doc.first; - if (n < 0 || n >= doc.size) { throw new Error("There is no line " + (n + doc.first) + " in the document.") } - var chunk = doc; - while (!chunk.lines) { - for (var i = 0;; ++i) { - var child = chunk.children[i], sz = child.chunkSize(); - if (n < sz) { chunk = child; break } - n -= sz; - } - } - return chunk.lines[n] - } - - // Get the part of a document between two positions, as an array of - // strings. - function getBetween(doc, start, end) { - var out = [], n = start.line; - doc.iter(start.line, end.line + 1, function (line) { - var text = line.text; - if (n == end.line) { text = text.slice(0, end.ch); } - if (n == start.line) { text = text.slice(start.ch); } - out.push(text); - ++n; - }); - return out - } - // Get the lines between from and to, as array of strings. - function getLines(doc, from, to) { - var out = []; - doc.iter(from, to, function (line) { out.push(line.text); }); // iter aborts when callback returns truthy value - return out - } - - // Update the height of a line, propagating the height change - // upwards to parent nodes. - function updateLineHeight(line, height) { - var diff = height - line.height; - if (diff) { for (var n = line; n; n = n.parent) { n.height += diff; } } - } - - // Given a line object, find its line number by walking up through - // its parent links. - function lineNo(line) { - if (line.parent == null) { return null } - var cur = line.parent, no = indexOf(cur.lines, line); - for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { - for (var i = 0;; ++i) { - if (chunk.children[i] == cur) { break } - no += chunk.children[i].chunkSize(); - } - } - return no + cur.first - } - - // Find the line at the given vertical position, using the height - // information in the document tree. - function lineAtHeight(chunk, h) { - var n = chunk.first; - outer: do { - for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) { - var child = chunk.children[i$1], ch = child.height; - if (h < ch) { chunk = child; continue outer } - h -= ch; - n += child.chunkSize(); - } - return n - } while (!chunk.lines) - var i = 0; - for (; i < chunk.lines.length; ++i) { - var line = chunk.lines[i], lh = line.height; - if (h < lh) { break } - h -= lh; - } - return n + i - } - - function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size} - - function lineNumberFor(options, i) { - return String(options.lineNumberFormatter(i + options.firstLineNumber)) - } - - // A Pos instance represents a position within the text. - function Pos(line, ch, sticky) { - if ( sticky === void 0 ) sticky = null; - - if (!(this instanceof Pos)) { return new Pos(line, ch, sticky) } - this.line = line; - this.ch = ch; - this.sticky = sticky; - } - - // Compare two positions, return 0 if they are the same, a negative - // number when a is less, and a positive number otherwise. - function cmp(a, b) { return a.line - b.line || a.ch - b.ch } - - function equalCursorPos(a, b) { return a.sticky == b.sticky && cmp(a, b) == 0 } - - function copyPos(x) {return Pos(x.line, x.ch)} - function maxPos(a, b) { return cmp(a, b) < 0 ? b : a } - function minPos(a, b) { return cmp(a, b) < 0 ? a : b } - - // Most of the external API clips given positions to make sure they - // actually exist within the document. - function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))} - function clipPos(doc, pos) { - if (pos.line < doc.first) { return Pos(doc.first, 0) } - var last = doc.first + doc.size - 1; - if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) } - return clipToLen(pos, getLine(doc, pos.line).text.length) - } - function clipToLen(pos, linelen) { - var ch = pos.ch; - if (ch == null || ch > linelen) { return Pos(pos.line, linelen) } - else if (ch < 0) { return Pos(pos.line, 0) } - else { return pos } - } - function clipPosArray(doc, array) { - var out = []; - for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]); } - return out - } - - // Optimize some code when these features are not used. - var sawReadOnlySpans = false, sawCollapsedSpans = false; - - function seeReadOnlySpans() { - sawReadOnlySpans = true; - } - - function seeCollapsedSpans() { - sawCollapsedSpans = true; - } - - // TEXTMARKER SPANS - - function MarkedSpan(marker, from, to) { - this.marker = marker; - this.from = from; this.to = to; - } - - // Search an array of spans for a span matching the given marker. - function getMarkedSpanFor(spans, marker) { - if (spans) { for (var i = 0; i < spans.length; ++i) { - var span = spans[i]; - if (span.marker == marker) { return span } - } } - } - // Remove a span from an array, returning undefined if no spans are - // left (we don't store arrays for lines without spans). - function removeMarkedSpan(spans, span) { - var r; - for (var i = 0; i < spans.length; ++i) - { if (spans[i] != span) { (r || (r = [])).push(spans[i]); } } - return r - } - // Add a span to a line. - function addMarkedSpan(line, span) { - line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]; - span.marker.attachLine(line); - } - - // Used for the algorithm that adjusts markers for a change in the - // document. These functions cut an array of spans at a given - // character position, returning an array of remaining chunks (or - // undefined if nothing remains). - function markedSpansBefore(old, startCh, isInsert) { - var nw; - if (old) { for (var i = 0; i < old.length; ++i) { - var span = old[i], marker = span.marker; - var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); - if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) { - var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh) - ;(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to)); - } - } } - return nw - } - function markedSpansAfter(old, endCh, isInsert) { - var nw; - if (old) { for (var i = 0; i < old.length; ++i) { - var span = old[i], marker = span.marker; - var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); - if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) { - var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh) - ;(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh, - span.to == null ? null : span.to - endCh)); - } - } } - return nw - } - - // Given a change object, compute the new set of marker spans that - // cover the line in which the change took place. Removes spans - // entirely within the change, reconnects spans belonging to the - // same marker that appear on both sides of the change, and cuts off - // spans partially within the change. Returns an array of span - // arrays with one element for each line in (after) the change. - function stretchSpansOverChange(doc, change) { - if (change.full) { return null } - var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans; - var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans; - if (!oldFirst && !oldLast) { return null } - - var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0; - // Get the spans that 'stick out' on both sides - var first = markedSpansBefore(oldFirst, startCh, isInsert); - var last = markedSpansAfter(oldLast, endCh, isInsert); - - // Next, merge those two ends - var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0); - if (first) { - // Fix up .to properties of first - for (var i = 0; i < first.length; ++i) { - var span = first[i]; - if (span.to == null) { - var found = getMarkedSpanFor(last, span.marker); - if (!found) { span.to = startCh; } - else if (sameLine) { span.to = found.to == null ? null : found.to + offset; } - } - } - } - if (last) { - // Fix up .from in last (or move them into first in case of sameLine) - for (var i$1 = 0; i$1 < last.length; ++i$1) { - var span$1 = last[i$1]; - if (span$1.to != null) { span$1.to += offset; } - if (span$1.from == null) { - var found$1 = getMarkedSpanFor(first, span$1.marker); - if (!found$1) { - span$1.from = offset; - if (sameLine) { (first || (first = [])).push(span$1); } - } - } else { - span$1.from += offset; - if (sameLine) { (first || (first = [])).push(span$1); } - } - } - } - // Make sure we didn't create any zero-length spans - if (first) { first = clearEmptySpans(first); } - if (last && last != first) { last = clearEmptySpans(last); } - - var newMarkers = [first]; - if (!sameLine) { - // Fill gap with whole-line-spans - var gap = change.text.length - 2, gapMarkers; - if (gap > 0 && first) - { for (var i$2 = 0; i$2 < first.length; ++i$2) - { if (first[i$2].to == null) - { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)); } } } - for (var i$3 = 0; i$3 < gap; ++i$3) - { newMarkers.push(gapMarkers); } - newMarkers.push(last); - } - return newMarkers - } - - // Remove spans that are empty and don't have a clearWhenEmpty - // option of false. - function clearEmptySpans(spans) { - for (var i = 0; i < spans.length; ++i) { - var span = spans[i]; - if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false) - { spans.splice(i--, 1); } - } - if (!spans.length) { return null } - return spans - } - - // Used to 'clip' out readOnly ranges when making a change. - function removeReadOnlyRanges(doc, from, to) { - var markers = null; - doc.iter(from.line, to.line + 1, function (line) { - if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { - var mark = line.markedSpans[i].marker; - if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) - { (markers || (markers = [])).push(mark); } - } } - }); - if (!markers) { return null } - var parts = [{from: from, to: to}]; - for (var i = 0; i < markers.length; ++i) { - var mk = markers[i], m = mk.find(0); - for (var j = 0; j < parts.length; ++j) { - var p = parts[j]; - if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue } - var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to); - if (dfrom < 0 || !mk.inclusiveLeft && !dfrom) - { newParts.push({from: p.from, to: m.from}); } - if (dto > 0 || !mk.inclusiveRight && !dto) - { newParts.push({from: m.to, to: p.to}); } - parts.splice.apply(parts, newParts); - j += newParts.length - 3; - } - } - return parts - } - - // Connect or disconnect spans from a line. - function detachMarkedSpans(line) { - var spans = line.markedSpans; - if (!spans) { return } - for (var i = 0; i < spans.length; ++i) - { spans[i].marker.detachLine(line); } - line.markedSpans = null; - } - function attachMarkedSpans(line, spans) { - if (!spans) { return } - for (var i = 0; i < spans.length; ++i) - { spans[i].marker.attachLine(line); } - line.markedSpans = spans; - } - - // Helpers used when computing which overlapping collapsed span - // counts as the larger one. - function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 } - function extraRight(marker) { return marker.inclusiveRight ? 1 : 0 } - - // Returns a number indicating which of two overlapping collapsed - // spans is larger (and thus includes the other). Falls back to - // comparing ids when the spans cover exactly the same range. - function compareCollapsedMarkers(a, b) { - var lenDiff = a.lines.length - b.lines.length; - if (lenDiff != 0) { return lenDiff } - var aPos = a.find(), bPos = b.find(); - var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b); - if (fromCmp) { return -fromCmp } - var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b); - if (toCmp) { return toCmp } - return b.id - a.id - } - - // Find out whether a line ends or starts in a collapsed span. If - // so, return the marker for that span. - function collapsedSpanAtSide(line, start) { - var sps = sawCollapsedSpans && line.markedSpans, found; - if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { - sp = sps[i]; - if (sp.marker.collapsed && (start ? sp.from : sp.to) == null && - (!found || compareCollapsedMarkers(found, sp.marker) < 0)) - { found = sp.marker; } - } } - return found - } - function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) } - function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) } - - function collapsedSpanAround(line, ch) { - var sps = sawCollapsedSpans && line.markedSpans, found; - if (sps) { for (var i = 0; i < sps.length; ++i) { - var 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 - // overlaps (covers the start or end, but not both) of a new span. - // Such overlap is not allowed. - function conflictingCollapsedRange(doc, lineNo$$1, from, to, marker) { - var line = getLine(doc, lineNo$$1); - var sps = sawCollapsedSpans && line.markedSpans; - if (sps) { for (var i = 0; i < sps.length; ++i) { - var sp = sps[i]; - if (!sp.marker.collapsed) { continue } - var found = sp.marker.find(0); - var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker); - var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker); - if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue } - if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) || - fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0)) - { return true } - } } - } - - // A visual line is a line as drawn on the screen. Folding, for - // example, can cause multiple logical lines to appear on the same - // visual line. This finds the start of the visual line that the - // given line is part of (usually that is the line itself). - function visualLine(line) { - var merged; - while (merged = collapsedSpanAtStart(line)) - { line = merged.find(-1, true).line; } - return line - } - - function visualLineEnd(line) { - var merged; - while (merged = collapsedSpanAtEnd(line)) - { line = merged.find(1, true).line; } - return line - } - - // Returns an array of logical lines that continue the visual line - // started by the argument, or undefined if there are no such lines. - function visualLineContinued(line) { - var merged, lines; - while (merged = collapsedSpanAtEnd(line)) { - line = merged.find(1, true).line - ;(lines || (lines = [])).push(line); - } - return lines - } - - // Get the line number of the start of the visual line that the - // given line number is part of. - function visualLineNo(doc, lineN) { - var line = getLine(doc, lineN), vis = visualLine(line); - if (line == vis) { return lineN } - return lineNo(vis) - } - - // Get the line number of the start of the next visual line after - // the given line. - function visualLineEndNo(doc, lineN) { - if (lineN > doc.lastLine()) { return lineN } - var line = getLine(doc, lineN), merged; - if (!lineIsHidden(doc, line)) { return lineN } - while (merged = collapsedSpanAtEnd(line)) - { line = merged.find(1, true).line; } - return lineNo(line) + 1 - } - - // Compute whether a line is hidden. Lines count as hidden when they - // are part of a visual line that starts with another line, or when - // they are entirely covered by collapsed, non-widget span. - function lineIsHidden(doc, line) { - var sps = sawCollapsedSpans && line.markedSpans; - if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { - sp = sps[i]; - if (!sp.marker.collapsed) { continue } - if (sp.from == null) { return true } - if (sp.marker.widgetNode) { continue } - if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) - { return true } - } } - } - function lineIsHiddenInner(doc, line, span) { - if (span.to == null) { - var end = span.marker.find(1, true); - return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker)) - } - if (span.marker.inclusiveRight && span.to == line.text.length) - { return true } - for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) { - sp = line.markedSpans[i]; - if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to && - (sp.to == null || sp.to != span.from) && - (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && - lineIsHiddenInner(doc, line, sp)) { return true } - } - } - - // Find the height above the given line. - function heightAtLine(lineObj) { - lineObj = visualLine(lineObj); - - var h = 0, chunk = lineObj.parent; - for (var i = 0; i < chunk.lines.length; ++i) { - var line = chunk.lines[i]; - if (line == lineObj) { break } - else { h += line.height; } - } - for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { - for (var i$1 = 0; i$1 < p.children.length; ++i$1) { - var cur = p.children[i$1]; - if (cur == chunk) { break } - else { h += cur.height; } - } - } - return h - } - - // Compute the character length of a line, taking into account - // collapsed ranges (see markText) that might hide parts, and join - // other lines onto it. - function lineLength(line) { - if (line.height == 0) { return 0 } - var len = line.text.length, merged, cur = line; - while (merged = collapsedSpanAtStart(cur)) { - var found = merged.find(0, true); - cur = found.from.line; - len += found.from.ch - found.to.ch; - } - cur = line; - while (merged = collapsedSpanAtEnd(cur)) { - var found$1 = merged.find(0, true); - len -= cur.text.length - found$1.from.ch; - cur = found$1.to.line; - len += cur.text.length - found$1.to.ch; - } - return len - } - - // Find the longest line in the document. - function findMaxLine(cm) { - var d = cm.display, doc = cm.doc; - d.maxLine = getLine(doc, doc.first); - d.maxLineLength = lineLength(d.maxLine); - d.maxLineChanged = true; - doc.iter(function (line) { - var len = lineLength(line); - if (len > d.maxLineLength) { - d.maxLineLength = len; - d.maxLine = line; - } - }); - } - // BIDI HELPERS function iterateBidiSections(order, from, to, f) { @@ -1486,6 +870,131 @@ return oracle && oracle.baseToken(this.pos) }; + // Find the line object corresponding to the given line number. + function getLine(doc, n) { + n -= doc.first; + if (n < 0 || n >= doc.size) { throw new Error("There is no line " + (n + doc.first) + " in the document.") } + var chunk = doc; + while (!chunk.lines) { + for (var i = 0;; ++i) { + var child = chunk.children[i], sz = child.chunkSize(); + if (n < sz) { chunk = child; break } + n -= sz; + } + } + return chunk.lines[n] + } + + // Get the part of a document between two positions, as an array of + // strings. + function getBetween(doc, start, end) { + var out = [], n = start.line; + doc.iter(start.line, end.line + 1, function (line) { + var text = line.text; + if (n == end.line) { text = text.slice(0, end.ch); } + if (n == start.line) { text = text.slice(start.ch); } + out.push(text); + ++n; + }); + return out + } + // Get the lines between from and to, as array of strings. + function getLines(doc, from, to) { + var out = []; + doc.iter(from, to, function (line) { out.push(line.text); }); // iter aborts when callback returns truthy value + return out + } + + // Update the height of a line, propagating the height change + // upwards to parent nodes. + function updateLineHeight(line, height) { + var diff = height - line.height; + if (diff) { for (var n = line; n; n = n.parent) { n.height += diff; } } + } + + // Given a line object, find its line number by walking up through + // its parent links. + function lineNo(line) { + if (line.parent == null) { return null } + var cur = line.parent, no = indexOf(cur.lines, line); + for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { + for (var i = 0;; ++i) { + if (chunk.children[i] == cur) { break } + no += chunk.children[i].chunkSize(); + } + } + return no + cur.first + } + + // Find the line at the given vertical position, using the height + // information in the document tree. + function lineAtHeight(chunk, h) { + var n = chunk.first; + outer: do { + for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) { + var child = chunk.children[i$1], ch = child.height; + if (h < ch) { chunk = child; continue outer } + h -= ch; + n += child.chunkSize(); + } + return n + } while (!chunk.lines) + var i = 0; + for (; i < chunk.lines.length; ++i) { + var line = chunk.lines[i], lh = line.height; + if (h < lh) { break } + h -= lh; + } + return n + i + } + + function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size} + + function lineNumberFor(options, i) { + return String(options.lineNumberFormatter(i + options.firstLineNumber)) + } + + // A Pos instance represents a position within the text. + function Pos(line, ch, sticky) { + if ( sticky === void 0 ) sticky = null; + + if (!(this instanceof Pos)) { return new Pos(line, ch, sticky) } + this.line = line; + this.ch = ch; + this.sticky = sticky; + } + + // Compare two positions, return 0 if they are the same, a negative + // number when a is less, and a positive number otherwise. + function cmp(a, b) { return a.line - b.line || a.ch - b.ch } + + function equalCursorPos(a, b) { return a.sticky == b.sticky && cmp(a, b) == 0 } + + function copyPos(x) {return Pos(x.line, x.ch)} + function maxPos(a, b) { return cmp(a, b) < 0 ? b : a } + function minPos(a, b) { return cmp(a, b) < 0 ? a : b } + + // Most of the external API clips given positions to make sure they + // actually exist within the document. + function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))} + function clipPos(doc, pos) { + if (pos.line < doc.first) { return Pos(doc.first, 0) } + var last = doc.first + doc.size - 1; + if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) } + return clipToLen(pos, getLine(doc, pos.line).text.length) + } + function clipToLen(pos, linelen) { + var ch = pos.ch; + if (ch == null || ch > linelen) { return Pos(pos.line, linelen) } + else if (ch < 0) { return Pos(pos.line, 0) } + else { return pos } + } + function clipPosArray(doc, array) { + var out = []; + for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]); } + return out + } + var SavedContext = function(state, lookAhead) { this.state = state; this.lookAhead = lookAhead; @@ -1762,6 +1271,394 @@ doc.highlightFrontier = Math.min(doc.highlightFrontier, start); } + // Optimize some code when these features are not used. + var sawReadOnlySpans = false, sawCollapsedSpans = false; + + function seeReadOnlySpans() { + sawReadOnlySpans = true; + } + + function seeCollapsedSpans() { + sawCollapsedSpans = true; + } + + // TEXTMARKER SPANS + + function MarkedSpan(marker, from, to) { + this.marker = marker; + this.from = from; this.to = to; + } + + // Search an array of spans for a span matching the given marker. + function getMarkedSpanFor(spans, marker) { + if (spans) { for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if (span.marker == marker) { return span } + } } + } + // Remove a span from an array, returning undefined if no spans are + // left (we don't store arrays for lines without spans). + function removeMarkedSpan(spans, span) { + var r; + for (var i = 0; i < spans.length; ++i) + { if (spans[i] != span) { (r || (r = [])).push(spans[i]); } } + return r + } + // Add a span to a line. + function addMarkedSpan(line, span) { + line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]; + span.marker.attachLine(line); + } + + // Used for the algorithm that adjusts markers for a change in the + // document. These functions cut an array of spans at a given + // character position, returning an array of remaining chunks (or + // undefined if nothing remains). + function markedSpansBefore(old, startCh, isInsert) { + var nw; + if (old) { for (var i = 0; i < old.length; ++i) { + var span = old[i], marker = span.marker; + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); + if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) { + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh) + ;(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to)); + } + } } + return nw + } + function markedSpansAfter(old, endCh, isInsert) { + var nw; + if (old) { for (var i = 0; i < old.length; ++i) { + var span = old[i], marker = span.marker; + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); + if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) { + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh) + ;(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh, + span.to == null ? null : span.to - endCh)); + } + } } + return nw + } + + // Given a change object, compute the new set of marker spans that + // cover the line in which the change took place. Removes spans + // entirely within the change, reconnects spans belonging to the + // same marker that appear on both sides of the change, and cuts off + // spans partially within the change. Returns an array of span + // arrays with one element for each line in (after) the change. + function stretchSpansOverChange(doc, change) { + if (change.full) { return null } + var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans; + var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans; + if (!oldFirst && !oldLast) { return null } + + var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0; + // Get the spans that 'stick out' on both sides + var first = markedSpansBefore(oldFirst, startCh, isInsert); + var last = markedSpansAfter(oldLast, endCh, isInsert); + + // Next, merge those two ends + var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0); + if (first) { + // Fix up .to properties of first + for (var i = 0; i < first.length; ++i) { + var span = first[i]; + if (span.to == null) { + var found = getMarkedSpanFor(last, span.marker); + if (!found) { span.to = startCh; } + else if (sameLine) { span.to = found.to == null ? null : found.to + offset; } + } + } + } + if (last) { + // Fix up .from in last (or move them into first in case of sameLine) + for (var i$1 = 0; i$1 < last.length; ++i$1) { + var span$1 = last[i$1]; + if (span$1.to != null) { span$1.to += offset; } + if (span$1.from == null) { + var found$1 = getMarkedSpanFor(first, span$1.marker); + if (!found$1) { + span$1.from = offset; + if (sameLine) { (first || (first = [])).push(span$1); } + } + } else { + span$1.from += offset; + if (sameLine) { (first || (first = [])).push(span$1); } + } + } + } + // Make sure we didn't create any zero-length spans + if (first) { first = clearEmptySpans(first); } + if (last && last != first) { last = clearEmptySpans(last); } + + var newMarkers = [first]; + if (!sameLine) { + // Fill gap with whole-line-spans + var gap = change.text.length - 2, gapMarkers; + if (gap > 0 && first) + { for (var i$2 = 0; i$2 < first.length; ++i$2) + { if (first[i$2].to == null) + { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)); } } } + for (var i$3 = 0; i$3 < gap; ++i$3) + { newMarkers.push(gapMarkers); } + newMarkers.push(last); + } + return newMarkers + } + + // Remove spans that are empty and don't have a clearWhenEmpty + // option of false. + function clearEmptySpans(spans) { + for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false) + { spans.splice(i--, 1); } + } + if (!spans.length) { return null } + return spans + } + + // Used to 'clip' out readOnly ranges when making a change. + function removeReadOnlyRanges(doc, from, to) { + var markers = null; + doc.iter(from.line, to.line + 1, function (line) { + if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { + var mark = line.markedSpans[i].marker; + if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) + { (markers || (markers = [])).push(mark); } + } } + }); + if (!markers) { return null } + var parts = [{from: from, to: to}]; + for (var i = 0; i < markers.length; ++i) { + var mk = markers[i], m = mk.find(0); + for (var j = 0; j < parts.length; ++j) { + var p = parts[j]; + if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue } + var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to); + if (dfrom < 0 || !mk.inclusiveLeft && !dfrom) + { newParts.push({from: p.from, to: m.from}); } + if (dto > 0 || !mk.inclusiveRight && !dto) + { newParts.push({from: m.to, to: p.to}); } + parts.splice.apply(parts, newParts); + j += newParts.length - 3; + } + } + return parts + } + + // Connect or disconnect spans from a line. + function detachMarkedSpans(line) { + var spans = line.markedSpans; + if (!spans) { return } + for (var i = 0; i < spans.length; ++i) + { spans[i].marker.detachLine(line); } + line.markedSpans = null; + } + function attachMarkedSpans(line, spans) { + if (!spans) { return } + for (var i = 0; i < spans.length; ++i) + { spans[i].marker.attachLine(line); } + line.markedSpans = spans; + } + + // Helpers used when computing which overlapping collapsed span + // counts as the larger one. + function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 } + function extraRight(marker) { return marker.inclusiveRight ? 1 : 0 } + + // Returns a number indicating which of two overlapping collapsed + // spans is larger (and thus includes the other). Falls back to + // comparing ids when the spans cover exactly the same range. + function compareCollapsedMarkers(a, b) { + var lenDiff = a.lines.length - b.lines.length; + if (lenDiff != 0) { return lenDiff } + var aPos = a.find(), bPos = b.find(); + var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b); + if (fromCmp) { return -fromCmp } + var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b); + if (toCmp) { return toCmp } + return b.id - a.id + } + + // Find out whether a line ends or starts in a collapsed span. If + // so, return the marker for that span. + function collapsedSpanAtSide(line, start) { + var sps = sawCollapsedSpans && line.markedSpans, found; + if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { + sp = sps[i]; + if (sp.marker.collapsed && (start ? sp.from : sp.to) == null && + (!found || compareCollapsedMarkers(found, sp.marker) < 0)) + { found = sp.marker; } + } } + return found + } + function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) } + function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) } + + function collapsedSpanAround(line, ch) { + var sps = sawCollapsedSpans && line.markedSpans, found; + if (sps) { for (var i = 0; i < sps.length; ++i) { + var 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 + // overlaps (covers the start or end, but not both) of a new span. + // Such overlap is not allowed. + function conflictingCollapsedRange(doc, lineNo$$1, from, to, marker) { + var line = getLine(doc, lineNo$$1); + var sps = sawCollapsedSpans && line.markedSpans; + if (sps) { for (var i = 0; i < sps.length; ++i) { + var sp = sps[i]; + if (!sp.marker.collapsed) { continue } + var found = sp.marker.find(0); + var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker); + var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker); + if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue } + if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) || + fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0)) + { return true } + } } + } + + // A visual line is a line as drawn on the screen. Folding, for + // example, can cause multiple logical lines to appear on the same + // visual line. This finds the start of the visual line that the + // given line is part of (usually that is the line itself). + function visualLine(line) { + var merged; + while (merged = collapsedSpanAtStart(line)) + { line = merged.find(-1, true).line; } + return line + } + + function visualLineEnd(line) { + var merged; + while (merged = collapsedSpanAtEnd(line)) + { line = merged.find(1, true).line; } + return line + } + + // Returns an array of logical lines that continue the visual line + // started by the argument, or undefined if there are no such lines. + function visualLineContinued(line) { + var merged, lines; + while (merged = collapsedSpanAtEnd(line)) { + line = merged.find(1, true).line + ;(lines || (lines = [])).push(line); + } + return lines + } + + // Get the line number of the start of the visual line that the + // given line number is part of. + function visualLineNo(doc, lineN) { + var line = getLine(doc, lineN), vis = visualLine(line); + if (line == vis) { return lineN } + return lineNo(vis) + } + + // Get the line number of the start of the next visual line after + // the given line. + function visualLineEndNo(doc, lineN) { + if (lineN > doc.lastLine()) { return lineN } + var line = getLine(doc, lineN), merged; + if (!lineIsHidden(doc, line)) { return lineN } + while (merged = collapsedSpanAtEnd(line)) + { line = merged.find(1, true).line; } + return lineNo(line) + 1 + } + + // Compute whether a line is hidden. Lines count as hidden when they + // are part of a visual line that starts with another line, or when + // they are entirely covered by collapsed, non-widget span. + function lineIsHidden(doc, line) { + var sps = sawCollapsedSpans && line.markedSpans; + if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { + sp = sps[i]; + if (!sp.marker.collapsed) { continue } + if (sp.from == null) { return true } + if (sp.marker.widgetNode) { continue } + if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) + { return true } + } } + } + function lineIsHiddenInner(doc, line, span) { + if (span.to == null) { + var end = span.marker.find(1, true); + return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker)) + } + if (span.marker.inclusiveRight && span.to == line.text.length) + { return true } + for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) { + sp = line.markedSpans[i]; + if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to && + (sp.to == null || sp.to != span.from) && + (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && + lineIsHiddenInner(doc, line, sp)) { return true } + } + } + + // Find the height above the given line. + function heightAtLine(lineObj) { + lineObj = visualLine(lineObj); + + var h = 0, chunk = lineObj.parent; + for (var i = 0; i < chunk.lines.length; ++i) { + var line = chunk.lines[i]; + if (line == lineObj) { break } + else { h += line.height; } + } + for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { + for (var i$1 = 0; i$1 < p.children.length; ++i$1) { + var cur = p.children[i$1]; + if (cur == chunk) { break } + else { h += cur.height; } + } + } + return h + } + + // Compute the character length of a line, taking into account + // collapsed ranges (see markText) that might hide parts, and join + // other lines onto it. + function lineLength(line) { + if (line.height == 0) { return 0 } + var len = line.text.length, merged, cur = line; + while (merged = collapsedSpanAtStart(cur)) { + var found = merged.find(0, true); + cur = found.from.line; + len += found.from.ch - found.to.ch; + } + cur = line; + while (merged = collapsedSpanAtEnd(cur)) { + var found$1 = merged.find(0, true); + len -= cur.text.length - found$1.from.ch; + cur = found$1.to.line; + len += cur.text.length - found$1.to.ch; + } + return len + } + + // Find the longest line in the document. + function findMaxLine(cm) { + var d = cm.display, doc = cm.doc; + d.maxLine = getLine(doc, doc.first); + d.maxLineLength = lineLength(d.maxLine); + d.maxLineChanged = true; + doc.iter(function (line) { + var len = lineLength(line); + if (len > d.maxLineLength) { + d.maxLineLength = len; + d.maxLine = line; + } + }); + } + // LINE DATA STRUCTURE // Line objects. These hold state related to a line, including @@ -2283,8 +2180,8 @@ elt("div", lineNumberFor(cm.options, lineN), "CodeMirror-linenumber CodeMirror-gutter-elt", ("left: " + (dims.gutterLeft["CodeMirror-linenumbers"]) + "px; width: " + (cm.display.lineNumInnerWidth) + "px"))); } - if (markers) { for (var k = 0; k < cm.options.gutters.length; ++k) { - var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id]; + if (markers) { for (var k = 0; k < cm.display.gutterSpecs.length; ++k) { + var id = cm.display.gutterSpecs[k].className, found = markers.hasOwnProperty(id) && markers[id]; if (found) { gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", ("left: " + (dims.gutterLeft[id]) + "px; width: " + (dims.gutterWidth[id]) + "px"))); } @@ -2989,8 +2886,9 @@ var d = cm.display, left = {}, width = {}; var gutterLeft = d.gutters.clientLeft; for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { - left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft; - width[cm.options.gutters[i]] = n.clientWidth; + var id = cm.display.gutterSpecs[i].className; + left[id] = n.offsetLeft + n.clientLeft + gutterLeft; + width[id] = n.clientWidth; } return {fixedPos: compensateForHScroll(d), gutterTotalWidth: d.gutters.offsetWidth, @@ -3069,6 +2967,154 @@ } } + // Updates the display.view data structure for a given change to the + // document. From and to are in pre-change coordinates. Lendiff is + // the amount of lines added or subtracted by the change. This is + // used for changes that span multiple lines, or change the way + // lines are divided into visual lines. regLineChange (below) + // registers single-line changes. + function regChange(cm, from, to, lendiff) { + if (from == null) { from = cm.doc.first; } + if (to == null) { to = cm.doc.first + cm.doc.size; } + if (!lendiff) { lendiff = 0; } + + var display = cm.display; + if (lendiff && to < display.viewTo && + (display.updateLineNumbers == null || display.updateLineNumbers > from)) + { display.updateLineNumbers = from; } + + cm.curOp.viewChanged = true; + + if (from >= display.viewTo) { // Change after + if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo) + { resetView(cm); } + } else if (to <= display.viewFrom) { // Change before + if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) { + resetView(cm); + } else { + display.viewFrom += lendiff; + display.viewTo += lendiff; + } + } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap + resetView(cm); + } else if (from <= display.viewFrom) { // Top overlap + var cut = viewCuttingPoint(cm, to, to + lendiff, 1); + if (cut) { + display.view = display.view.slice(cut.index); + display.viewFrom = cut.lineN; + display.viewTo += lendiff; + } else { + resetView(cm); + } + } else if (to >= display.viewTo) { // Bottom overlap + var cut$1 = viewCuttingPoint(cm, from, from, -1); + if (cut$1) { + display.view = display.view.slice(0, cut$1.index); + display.viewTo = cut$1.lineN; + } else { + resetView(cm); + } + } else { // Gap in the middle + var cutTop = viewCuttingPoint(cm, from, from, -1); + var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1); + if (cutTop && cutBot) { + display.view = display.view.slice(0, cutTop.index) + .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN)) + .concat(display.view.slice(cutBot.index)); + display.viewTo += lendiff; + } else { + resetView(cm); + } + } + + var ext = display.externalMeasured; + if (ext) { + if (to < ext.lineN) + { ext.lineN += lendiff; } + else if (from < ext.lineN + ext.size) + { display.externalMeasured = null; } + } + } + + // Register a change to a single line. Type must be one of "text", + // "gutter", "class", "widget" + function regLineChange(cm, line, type) { + cm.curOp.viewChanged = true; + var display = cm.display, ext = cm.display.externalMeasured; + if (ext && line >= ext.lineN && line < ext.lineN + ext.size) + { display.externalMeasured = null; } + + if (line < display.viewFrom || line >= display.viewTo) { return } + var lineView = display.view[findViewIndex(cm, line)]; + if (lineView.node == null) { return } + var arr = lineView.changes || (lineView.changes = []); + if (indexOf(arr, type) == -1) { arr.push(type); } + } + + // Clear the view. + function resetView(cm) { + cm.display.viewFrom = cm.display.viewTo = cm.doc.first; + cm.display.view = []; + cm.display.viewOffset = 0; + } + + function viewCuttingPoint(cm, oldN, newN, dir) { + var index = findViewIndex(cm, oldN), diff, view = cm.display.view; + if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size) + { return {index: index, lineN: newN} } + var n = cm.display.viewFrom; + for (var i = 0; i < index; i++) + { n += view[i].size; } + if (n != oldN) { + if (dir > 0) { + if (index == view.length - 1) { return null } + diff = (n + view[index].size) - oldN; + index++; + } else { + diff = n - oldN; + } + oldN += diff; newN += diff; + } + while (visualLineNo(cm.doc, newN) != newN) { + if (index == (dir < 0 ? 0 : view.length - 1)) { return null } + newN += dir * view[index - (dir < 0 ? 1 : 0)].size; + index += dir; + } + return {index: index, lineN: newN} + } + + // Force the view to cover a given range, adding empty view element + // or clipping off existing ones as needed. + function adjustView(cm, from, to) { + var display = cm.display, view = display.view; + if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) { + display.view = buildViewArray(cm, from, to); + display.viewFrom = from; + } else { + if (display.viewFrom > from) + { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); } + else if (display.viewFrom < from) + { display.view = display.view.slice(findViewIndex(cm, from)); } + display.viewFrom = from; + if (display.viewTo < to) + { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); } + else if (display.viewTo > to) + { display.view = display.view.slice(0, findViewIndex(cm, to)); } + } + display.viewTo = to; + } + + // Count the number of lines in the view whose DOM representation is + // out of date (or nonexistent). + function countDirtyView(cm) { + var view = cm.display.view, dirty = 0; + for (var i = 0; i < view.length; i++) { + var lineView = view[i]; + if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty; } + } + return dirty + } + function updateSelection(cm) { cm.display.input.showSelection(cm.display.input.prepareSelection()); } @@ -3286,7 +3332,6 @@ { width = cur.text.firstChild.getBoundingClientRect().right - box.left - 1; } } var diff = cur.line.height - height; - if (height < 2) { height = textHeight(display); } if (diff > .005 || diff < -.005) { updateLineHeight(cur.line, height); updateWidgetHeight(cur.line); @@ -3337,49 +3382,6 @@ return {from: from, to: Math.max(to, from + 1)} } - // Re-align line numbers and gutter marks to compensate for - // horizontal scrolling. - function alignHorizontally(cm) { - var display = cm.display, view = display.view; - if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return } - var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft; - var gutterW = display.gutters.offsetWidth, left = comp + "px"; - for (var i = 0; i < view.length; i++) { if (!view[i].hidden) { - if (cm.options.fixedGutter) { - if (view[i].gutter) - { view[i].gutter.style.left = left; } - if (view[i].gutterBackground) - { view[i].gutterBackground.style.left = left; } - } - var align = view[i].alignable; - if (align) { for (var j = 0; j < align.length; j++) - { align[j].style.left = left; } } - } } - if (cm.options.fixedGutter) - { display.gutters.style.left = (comp + gutterW) + "px"; } - } - - // Used to ensure that the line number gutter is still the right - // size for the current document size. Returns true when an update - // is needed. - function maybeUpdateLineNumberWidth(cm) { - if (!cm.options.lineNumbers) { return false } - var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display; - if (last.length != display.lineNumChars) { - var test = display.measure.appendChild(elt("div", [elt("div", last)], - "CodeMirror-linenumber CodeMirror-gutter-elt")); - var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW; - display.lineGutter.style.width = ""; - display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1; - display.lineNumWidth = display.lineNumInnerWidth + padding; - display.lineNumChars = display.lineNumInnerWidth ? last.length : -1; - display.lineGutter.style.width = display.lineNumWidth + "px"; - updateGutterSpace(cm); - return true - } - return false - } - // SCROLLING THINGS INTO VIEW // If an editor sits on the top or bottom of the window, partially @@ -3749,7 +3751,7 @@ viewChanged: false, // Flag that indicates that lines might need to be redrawn startHeight: cm.doc.height, // Used to detect need to update scrollbar forceUpdate: false, // Used to force a redraw - updateInput: null, // Whether to reset the input textarea + updateInput: 0, // Whether to reset the input textarea typing: false, // Whether this reset should be careful to leave existing text (for compositing) changeObjs: null, // Accumulated changes, for firing change events cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on @@ -3927,154 +3929,6 @@ } } - // Updates the display.view data structure for a given change to the - // document. From and to are in pre-change coordinates. Lendiff is - // the amount of lines added or subtracted by the change. This is - // used for changes that span multiple lines, or change the way - // lines are divided into visual lines. regLineChange (below) - // registers single-line changes. - function regChange(cm, from, to, lendiff) { - if (from == null) { from = cm.doc.first; } - if (to == null) { to = cm.doc.first + cm.doc.size; } - if (!lendiff) { lendiff = 0; } - - var display = cm.display; - if (lendiff && to < display.viewTo && - (display.updateLineNumbers == null || display.updateLineNumbers > from)) - { display.updateLineNumbers = from; } - - cm.curOp.viewChanged = true; - - if (from >= display.viewTo) { // Change after - if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo) - { resetView(cm); } - } else if (to <= display.viewFrom) { // Change before - if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) { - resetView(cm); - } else { - display.viewFrom += lendiff; - display.viewTo += lendiff; - } - } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap - resetView(cm); - } else if (from <= display.viewFrom) { // Top overlap - var cut = viewCuttingPoint(cm, to, to + lendiff, 1); - if (cut) { - display.view = display.view.slice(cut.index); - display.viewFrom = cut.lineN; - display.viewTo += lendiff; - } else { - resetView(cm); - } - } else if (to >= display.viewTo) { // Bottom overlap - var cut$1 = viewCuttingPoint(cm, from, from, -1); - if (cut$1) { - display.view = display.view.slice(0, cut$1.index); - display.viewTo = cut$1.lineN; - } else { - resetView(cm); - } - } else { // Gap in the middle - var cutTop = viewCuttingPoint(cm, from, from, -1); - var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1); - if (cutTop && cutBot) { - display.view = display.view.slice(0, cutTop.index) - .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN)) - .concat(display.view.slice(cutBot.index)); - display.viewTo += lendiff; - } else { - resetView(cm); - } - } - - var ext = display.externalMeasured; - if (ext) { - if (to < ext.lineN) - { ext.lineN += lendiff; } - else if (from < ext.lineN + ext.size) - { display.externalMeasured = null; } - } - } - - // Register a change to a single line. Type must be one of "text", - // "gutter", "class", "widget" - function regLineChange(cm, line, type) { - cm.curOp.viewChanged = true; - var display = cm.display, ext = cm.display.externalMeasured; - if (ext && line >= ext.lineN && line < ext.lineN + ext.size) - { display.externalMeasured = null; } - - if (line < display.viewFrom || line >= display.viewTo) { return } - var lineView = display.view[findViewIndex(cm, line)]; - if (lineView.node == null) { return } - var arr = lineView.changes || (lineView.changes = []); - if (indexOf(arr, type) == -1) { arr.push(type); } - } - - // Clear the view. - function resetView(cm) { - cm.display.viewFrom = cm.display.viewTo = cm.doc.first; - cm.display.view = []; - cm.display.viewOffset = 0; - } - - function viewCuttingPoint(cm, oldN, newN, dir) { - var index = findViewIndex(cm, oldN), diff, view = cm.display.view; - if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size) - { return {index: index, lineN: newN} } - var n = cm.display.viewFrom; - for (var i = 0; i < index; i++) - { n += view[i].size; } - if (n != oldN) { - if (dir > 0) { - if (index == view.length - 1) { return null } - diff = (n + view[index].size) - oldN; - index++; - } else { - diff = n - oldN; - } - oldN += diff; newN += diff; - } - while (visualLineNo(cm.doc, newN) != newN) { - if (index == (dir < 0 ? 0 : view.length - 1)) { return null } - newN += dir * view[index - (dir < 0 ? 1 : 0)].size; - index += dir; - } - return {index: index, lineN: newN} - } - - // Force the view to cover a given range, adding empty view element - // or clipping off existing ones as needed. - function adjustView(cm, from, to) { - var display = cm.display, view = display.view; - if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) { - display.view = buildViewArray(cm, from, to); - display.viewFrom = from; - } else { - if (display.viewFrom > from) - { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); } - else if (display.viewFrom < from) - { display.view = display.view.slice(findViewIndex(cm, from)); } - display.viewFrom = from; - if (display.viewTo < to) - { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); } - else if (display.viewTo > to) - { display.view = display.view.slice(0, findViewIndex(cm, to)); } - } - display.viewTo = to; - } - - // Count the number of lines in the view whose DOM representation is - // out of date (or nonexistent). - function countDirtyView(cm) { - var view = cm.display.view, dirty = 0; - for (var i = 0; i < view.length; i++) { - var lineView = view[i]; - if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty; } - } - return dirty - } - // HIGHLIGHT WORKER function startWorker(cm, time) { @@ -4356,9 +4210,9 @@ while (cur) { cur = rm(cur); } } - function updateGutterSpace(cm) { - var width = cm.display.gutters.offsetWidth; - cm.display.sizer.style.marginLeft = width + "px"; + function updateGutterSpace(display) { + var width = display.gutters.offsetWidth; + display.sizer.style.marginLeft = width + "px"; } function setDocumentHeight(cm, measure) { @@ -4367,34 +4221,195 @@ cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px"; } - // Rebuild the gutter elements, ensure the margin to the left of the - // code matches their width. - function updateGutters(cm) { - var gutters = cm.display.gutters, specs = cm.options.gutters; - removeChildren(gutters); - var i = 0; - for (; i < specs.length; ++i) { - var gutterClass = specs[i]; - var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass)); - if (gutterClass == "CodeMirror-linenumbers") { - cm.display.lineGutter = gElt; - gElt.style.width = (cm.display.lineNumWidth || 1) + "px"; + // Re-align line numbers and gutter marks to compensate for + // horizontal scrolling. + function alignHorizontally(cm) { + var display = cm.display, view = display.view; + if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return } + var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft; + var gutterW = display.gutters.offsetWidth, left = comp + "px"; + for (var i = 0; i < view.length; i++) { if (!view[i].hidden) { + if (cm.options.fixedGutter) { + if (view[i].gutter) + { view[i].gutter.style.left = left; } + if (view[i].gutterBackground) + { view[i].gutterBackground.style.left = left; } } - } - gutters.style.display = i ? "" : "none"; - updateGutterSpace(cm); + var align = view[i].alignable; + if (align) { for (var j = 0; j < align.length; j++) + { align[j].style.left = left; } } + } } + if (cm.options.fixedGutter) + { display.gutters.style.left = (comp + gutterW) + "px"; } } - // Make sure the gutters options contains the element - // "CodeMirror-linenumbers" when the lineNumbers option is true. - function setGuttersForLineNumbers(options) { - var found = indexOf(options.gutters, "CodeMirror-linenumbers"); - if (found == -1 && options.lineNumbers) { - options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]); - } else if (found > -1 && !options.lineNumbers) { - options.gutters = options.gutters.slice(0); - options.gutters.splice(found, 1); + // Used to ensure that the line number gutter is still the right + // size for the current document size. Returns true when an update + // is needed. + function maybeUpdateLineNumberWidth(cm) { + if (!cm.options.lineNumbers) { return false } + var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display; + if (last.length != display.lineNumChars) { + var test = display.measure.appendChild(elt("div", [elt("div", last)], + "CodeMirror-linenumber CodeMirror-gutter-elt")); + var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW; + display.lineGutter.style.width = ""; + display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1; + display.lineNumWidth = display.lineNumInnerWidth + padding; + display.lineNumChars = display.lineNumInnerWidth ? last.length : -1; + display.lineGutter.style.width = display.lineNumWidth + "px"; + updateGutterSpace(cm.display); + return true } + return false + } + + function getGutters(gutters, lineNumbers) { + var result = [], sawLineNumbers = false; + for (var i = 0; i < gutters.length; i++) { + var name = gutters[i], style = null; + if (typeof name != "string") { style = name.style; name = name.className; } + if (name == "CodeMirror-linenumbers") { + if (!lineNumbers) { continue } + else { sawLineNumbers = true; } + } + result.push({className: name, style: style}); + } + if (lineNumbers && !sawLineNumbers) { result.push({className: "CodeMirror-linenumbers", style: null}); } + return result + } + + // Rebuild the gutter elements, ensure the margin to the left of the + // code matches their width. + function renderGutters(display) { + var gutters = display.gutters, specs = display.gutterSpecs; + removeChildren(gutters); + display.lineGutter = null; + for (var i = 0; i < specs.length; ++i) { + var ref = specs[i]; + var className = ref.className; + var style = ref.style; + var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + className)); + if (style) { gElt.style.cssText = style; } + if (className == "CodeMirror-linenumbers") { + display.lineGutter = gElt; + gElt.style.width = (display.lineNumWidth || 1) + "px"; + } + } + gutters.style.display = specs.length ? "" : "none"; + updateGutterSpace(display); + } + + function updateGutters(cm) { + renderGutters(cm.display); + regChange(cm); + alignHorizontally(cm); + } + + // The display handles the DOM integration, both for input reading + // and content drawing. It holds references to DOM nodes and + // display-related state. + + function Display(place, doc, input, options) { + var d = this; + this.input = input; + + // Covers bottom-right square when both scrollbars are present. + d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler"); + d.scrollbarFiller.setAttribute("cm-not-content", "true"); + // Covers bottom of gutter when coverGutterNextToScrollbar is on + // and h scrollbar is present. + d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler"); + d.gutterFiller.setAttribute("cm-not-content", "true"); + // Will contain the actual code, positioned to cover the viewport. + d.lineDiv = eltP("div", null, "CodeMirror-code"); + // Elements are added to these to represent selection and cursors. + d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1"); + d.cursorDiv = elt("div", null, "CodeMirror-cursors"); + // A visibility: hidden element used to find the size of things. + d.measure = elt("div", null, "CodeMirror-measure"); + // When lines outside of the viewport are measured, they are drawn in this. + d.lineMeasure = elt("div", null, "CodeMirror-measure"); + // Wraps everything that needs to exist inside the vertically-padded coordinate system + d.lineSpace = eltP("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv], + null, "position: relative; outline: none"); + var lines = eltP("div", [d.lineSpace], "CodeMirror-lines"); + // Moved around its parent to cover visible view. + d.mover = elt("div", [lines], null, "position: relative"); + // Set to the height of the document, allowing scrolling. + d.sizer = elt("div", [d.mover], "CodeMirror-sizer"); + d.sizerWidth = null; + // Behavior of elts with overflow: auto and padding is + // inconsistent across browsers. This is used to ensure the + // scrollable area is big enough. + d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;"); + // Will contain the gutters, if any. + d.gutters = elt("div", null, "CodeMirror-gutters"); + d.lineGutter = null; + // Actual scrollable element. + 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.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror"); + + // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported) + if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; } + if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true; } + + if (place) { + if (place.appendChild) { place.appendChild(d.wrapper); } + else { place(d.wrapper); } + } + + // Current rendered range (may be bigger than the view window). + d.viewFrom = d.viewTo = doc.first; + d.reportedViewFrom = d.reportedViewTo = doc.first; + // Information about the rendered lines. + d.view = []; + d.renderedView = null; + // Holds info about a single rendered line when it was rendered + // for measurement, while not in view. + d.externalMeasured = null; + // Empty space (in pixels) above the view + d.viewOffset = 0; + d.lastWrapHeight = d.lastWrapWidth = 0; + d.updateLineNumbers = null; + + d.nativeBarWidth = d.barHeight = d.barWidth = 0; + d.scrollbarsClipped = false; + + // Used to only resize the line number gutter when necessary (when + // the amount of lines crosses a boundary that makes its width change) + d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null; + // Set to true when a non-horizontal-scrolling line widget is + // added. As an optimization, line widget aligning is skipped when + // this is false. + d.alignWidgets = false; + + d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; + + // Tracks the maximum line length so that the horizontal scrollbar + // can be kept static when scrolling. + d.maxLine = null; + d.maxLineLength = 0; + d.maxLineChanged = false; + + // Used for measuring wheel scrolling granularity + d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null; + + // True when shift is held down. + d.shift = false; + + // Used to track whether anything happened since the context menu + // was opened. + d.selForContextMenu = null; + + d.activeTouch = null; + + d.gutterSpecs = getGutters(options.gutters, options.lineNumbers); + renderGutters(d); + + input.init(d); } // Since the delta values reported on mouse wheel events are @@ -5098,7 +5113,8 @@ doc.sel = sel; if (doc.cm) { - doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true; + doc.cm.curOp.updateInput = 1; + doc.cm.curOp.selectionChanged = true; signalCursorActivity(doc.cm); } signalLater(doc, "cursorActivity", doc); @@ -5131,8 +5147,15 @@ var line = getLine(doc, pos.line); if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { var sp = line.markedSpans[i], m = sp.marker; - if ((sp.from == null || (m.inclusiveLeft ? sp.from <= pos.ch : sp.from < pos.ch)) && - (sp.to == null || (m.inclusiveRight ? sp.to >= pos.ch : sp.to > pos.ch))) { + + // Determine if we should prevent the cursor being placed to the left/right of an atomic marker + // Historically this was determined using the inclusiveLeft/Right option, but the new way to control it + // is with selectLeft/Right + var preventCursorLeft = ("selectLeft" in m) ? !m.selectLeft : m.inclusiveLeft; + var preventCursorRight = ("selectRight" in m) ? !m.selectRight : m.inclusiveRight; + + if ((sp.from == null || (preventCursorLeft ? sp.from <= pos.ch : sp.from < pos.ch)) && + (sp.to == null || (preventCursorRight ? sp.to >= pos.ch : sp.to > pos.ch))) { if (mayClear) { signal(m, "beforeCursorEnter"); if (m.explicitlyCleared) { @@ -5144,14 +5167,14 @@ if (oldPos) { var near = m.find(dir < 0 ? 1 : -1), diff = (void 0); - if (dir < 0 ? m.inclusiveRight : m.inclusiveLeft) + if (dir < 0 ? preventCursorRight : preventCursorLeft) { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null); } if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0)) { return skipAtomicInner(doc, near, pos, dir, mayClear) } } var far = m.find(dir < 0 ? -1 : 1); - if (dir < 0 ? m.inclusiveLeft : m.inclusiveRight) + if (dir < 0 ? preventCursorLeft : preventCursorRight) { far = movePos(doc, far, dir, far.line == pos.line ? line : null); } return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null } @@ -5210,7 +5233,10 @@ signal(doc, "beforeChange", doc, obj); if (doc.cm) { signal(doc.cm, "beforeChange", doc.cm, obj); } - if (obj.canceled) { return null } + if (obj.canceled) { + if (doc.cm) { doc.cm.curOp.updateInput = 2; } + return null + } return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin} } @@ -6628,7 +6654,7 @@ 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", - 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 127: "Delete", 145: "ScrollLock", + 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 145: "ScrollLock", 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete", 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert" @@ -7515,8 +7541,13 @@ function done(e) { cm.state.selectingText = false; counter = Infinity; - e_preventDefault(e); - display.input.focus(); + // If e is null or undefined we interpret this as someone trying + // to explicitly cancel the selection rather than the user + // letting go of the mouse button. + if (e) { + e_preventDefault(e); + display.input.focus(); + } off(display.wrapper.ownerDocument, "mousemove", move); off(display.wrapper.ownerDocument, "mouseup", up); doc.history.lastSelOrigin = null; @@ -7587,12 +7618,12 @@ 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) { + for (var i = 0; i < cm.display.gutterSpecs.length; ++i) { var g = display.gutters.childNodes[i]; if (g && g.getBoundingClientRect().right >= mX) { var line = lineAtHeight(cm.doc, mY); - var gutter = cm.options.gutters[i]; - signal(cm, type, cm, line, gutter, e); + var gutter = cm.display.gutterSpecs[i]; + signal(cm, type, cm, line, gutter.className, e); return e_defaultPrevented(e) } } @@ -7676,7 +7707,7 @@ for (var i = newBreaks.length - 1; i >= 0; i--) { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)); } }); - option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff]/g, function (cm, val, old) { + option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g, function (cm, val, old) { cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g"); if (old != Init) { cm.refresh(); } }); @@ -7686,12 +7717,14 @@ throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME }, true); option("spellcheck", false, function (cm, val) { return cm.getInputField().spellcheck = val; }, true); + option("autocorrect", false, function (cm, val) { return cm.getInputField().autocorrect = val; }, true); + option("autocapitalize", false, function (cm, val) { return cm.getInputField().autocapitalize = val; }, true); option("rtlMoveVisually", !windows); option("wholeLineUpdateBefore", true); option("theme", "default", function (cm) { themeChanged(cm); - guttersChanged(cm); + updateGutters(cm); }, true); option("keyMap", "default", function (cm, val, old) { var next = getKeyMap(val); @@ -7703,9 +7736,9 @@ option("configureMouse", null); option("lineWrapping", false, wrappingChanged, true); - option("gutters", [], function (cm) { - setGuttersForLineNumbers(cm.options); - guttersChanged(cm); + option("gutters", [], function (cm, val) { + cm.display.gutterSpecs = getGutters(val, cm.options.lineNumbers); + updateGutters(cm); }, true); option("fixedGutter", true, function (cm, val) { cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"; @@ -7718,12 +7751,12 @@ cm.display.scrollbars.setScrollTop(cm.doc.scrollTop); cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft); }, true); - option("lineNumbers", false, function (cm) { - setGuttersForLineNumbers(cm.options); - guttersChanged(cm); + option("lineNumbers", false, function (cm, val) { + cm.display.gutterSpecs = getGutters(cm.options.gutters, val); + updateGutters(cm); }, true); - option("firstLineNumber", 1, guttersChanged, true); - option("lineNumberFormatter", function (integer) { return integer; }, guttersChanged, true); + option("firstLineNumber", 1, updateGutters, true); + option("lineNumberFormatter", function (integer) { return integer; }, updateGutters, true); option("showCursorWhenSelecting", false, updateSelection, true); option("resetSelectionOnContextMenu", true); @@ -7765,12 +7798,6 @@ option("phrases", null); } - function guttersChanged(cm) { - updateGutters(cm); - regChange(cm); - alignHorizontally(cm); - } - function dragDropChanged(cm, value, old) { var wasOn = old && old != Init; if (!value != !wasOn) { @@ -7810,7 +7837,6 @@ this.options = options = options ? copyObj(options) : {}; // Determine effective options based on given values and defaults. copyObj(defaults, options, false); - setGuttersForLineNumbers(options); var doc = options.value; if (typeof doc == "string") { doc = new Doc(doc, options.mode, null, options.lineSeparator, options.direction); } @@ -7818,9 +7844,8 @@ this.doc = doc; var input = new CodeMirror.inputStyles[options.inputStyle](this); - var display = this.display = new Display(place, doc, input); + var display = this.display = new Display(place, doc, input, options); display.wrapper.CodeMirror = this; - updateGutters(this); themeChanged(this); if (options.lineWrapping) { this.display.wrapper.className += " CodeMirror-wrap"; } @@ -7834,7 +7859,7 @@ delayingBlurEvent: false, focused: false, suppressEdits: false, // used to disable editing during key handlers when in readOnly mode - pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll + pasteIncoming: -1, cutIncoming: -1, // help recognize paste/cut edits in input.poll selectingText: false, draggingText: false, highlight: new Delayed(), // stores highlight worker timeout @@ -8067,7 +8092,8 @@ cm.display.shift = false; if (!sel) { sel = doc.sel; } - var paste = cm.state.pasteIncoming || origin == "paste"; + var recent = +new Date - 200; + var paste = origin == "paste" || cm.state.pasteIncoming > recent; var textLines = splitLinesAuto(inserted), multiPaste = null; // When pasting N lines into N selections, insert one line per selection if (paste && sel.ranges.length > 1) { @@ -8082,7 +8108,7 @@ } } - var updateInput; + var updateInput = cm.curOp.updateInput; // Normal behavior is to insert the new text into every selection for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) { var range$$1 = sel.ranges[i$1]; @@ -8095,9 +8121,8 @@ else if (paste && lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == inserted) { from = to = Pos(from.line, 0); } } - updateInput = cm.curOp.updateInput; var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines, - origin: origin || (paste ? "paste" : cm.state.cutIncoming ? "cut" : "+input")}; + origin: origin || (paste ? "paste" : cm.state.cutIncoming > recent ? "cut" : "+input")}; makeChange(cm.doc, changeEvent); signalLater(cm, "inputRead", cm, changeEvent); } @@ -8105,9 +8130,9 @@ { triggerElectric(cm, inserted); } ensureCursorVisible(cm); - cm.curOp.updateInput = updateInput; + if (cm.curOp.updateInput < 2) { cm.curOp.updateInput = updateInput; } cm.curOp.typing = true; - cm.state.pasteIncoming = cm.state.cutIncoming = false; + cm.state.pasteIncoming = cm.state.cutIncoming = -1; } function handlePaste(e, cm) { @@ -8155,9 +8180,9 @@ return {text: text, ranges: ranges} } - function disableBrowserMagic(field, spellcheck) { - field.setAttribute("autocorrect", "off"); - field.setAttribute("autocapitalize", "off"); + function disableBrowserMagic(field, spellcheck, autocorrect, autocapitalize) { + field.setAttribute("autocorrect", autocorrect ? "" : "off"); + field.setAttribute("autocapitalize", autocapitalize ? "" : "off"); field.setAttribute("spellcheck", !!spellcheck); } @@ -8583,7 +8608,7 @@ this.curOp.forceUpdate = true; clearCaches(this); scrollToCoords(this, this.doc.scrollLeft, this.doc.scrollTop); - updateGutterSpace(this); + updateGutterSpace(this.display); if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5) { estimateLineHeights(this); } signal(this, "refresh", this); @@ -8592,6 +8617,8 @@ swapDoc: methodOp(function(doc) { var old = this.doc; old.cm = null; + // Cancel the current text selection if any (#5821) + if (this.state.selectingText) { this.state.selectingText(); } attachDoc(this, doc); clearCaches(this); this.display.input.reset(); @@ -8728,7 +8755,7 @@ var input = this, cm = input.cm; var div = input.div = display.lineDiv; - disableBrowserMagic(div, cm.options.spellcheck); + disableBrowserMagic(div, cm.options.spellcheck, cm.options.autocorrect, cm.options.autocapitalize); on(div, "paste", function (e) { if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } @@ -8937,7 +8964,7 @@ // Because Android doesn't allow us to actually detect backspace // presses in a sane way, this code checks for when that happens // and simulates a backspace press in this case. - if (android && chrome && this.cm.options.gutters.length && isInGutter(sel.anchorNode)) { + if (android && chrome && this.cm.display.gutterSpecs.length && isInGutter(sel.anchorNode)) { this.cm.triggerOnKeyDown({type: "keydown", keyCode: 8, preventDefault: Math.abs}); this.blur(); this.focus(); @@ -9268,7 +9295,7 @@ on(te, "paste", function (e) { if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } - cm.state.pasteIncoming = true; + cm.state.pasteIncoming = +new Date; input.fastPoll(); }); @@ -9289,15 +9316,23 @@ selectInput(te); } } - if (e.type == "cut") { cm.state.cutIncoming = true; } + if (e.type == "cut") { cm.state.cutIncoming = +new Date; } } on(te, "cut", prepareCopyCut); on(te, "copy", prepareCopyCut); on(display.scroller, "paste", function (e) { if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { return } - cm.state.pasteIncoming = true; - input.focus(); + if (!te.dispatchEvent) { + cm.state.pasteIncoming = +new Date; + input.focus(); + return + } + + // Pass the `paste` event to the textarea so it's handled by its event listener. + var event = new Event("paste"); + event.clipboardData = e.clipboardData; + te.dispatchEvent(event); }); // Prevent normal selection in the editor (we handle our own) @@ -9488,6 +9523,7 @@ TextareaInput.prototype.onContextMenu = function (e) { var input = this, cm = input.cm, display = cm.display, te = input.textarea; + if (input.contextMenuPending) { input.contextMenuPending(); } var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop; if (!pos || presto) { return } // Opera is difficult. @@ -9498,8 +9534,8 @@ { operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll); } var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText; - input.wrapper.style.cssText = "position: absolute"; - var wrapperBox = input.wrapper.getBoundingClientRect(); + var wrapperBox = input.wrapper.offsetParent.getBoundingClientRect(); + input.wrapper.style.cssText = "position: static"; te.style.cssText = "position: absolute; width: 30px; height: 30px;\n top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; var oldScrollY; if (webkit) { oldScrollY = window.scrollY; } // Work around Chrome issue (#2712) @@ -9508,7 +9544,7 @@ display.input.reset(); // Adds "Select all" to context menu in FF if (!cm.somethingSelected()) { te.value = input.prevInput = " "; } - input.contextMenuPending = true; + input.contextMenuPending = rehide; display.selForContextMenu = cm.doc.sel; clearTimeout(display.detectingSelectAll); @@ -9529,6 +9565,7 @@ } } function rehide() { + if (input.contextMenuPending != rehide) { return } input.contextMenuPending = false; input.wrapper.style.cssText = oldWrapperCSS; te.style.cssText = oldCSS; @@ -9718,7 +9755,7 @@ addLegacyProps(CodeMirror); - CodeMirror.version = "5.42.0"; + CodeMirror.version = "5.48.0"; return CodeMirror; diff --git a/vendor/codemirror/mode/css/css.js b/vendor/codemirror/mode/css/css.js index 22b463c9..05742c5c 100644 --- a/vendor/codemirror/mode/css/css.js +++ b/vendor/codemirror/mode/css/css.js @@ -63,7 +63,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) { if (/[\d.]/.test(stream.peek())) { stream.eatWhile(/[\w.%]/); return ret("number", "unit"); - } else if (stream.match(/^-[\w\\\-]+/)) { + } else if (stream.match(/^-[\w\\\-]*/)) { stream.eatWhile(/[\w\\\-]/); if (stream.match(/^\s*:/, false)) return ret("variable-2", "variable-definition"); @@ -77,12 +77,11 @@ CodeMirror.defineMode("css", function(config, parserConfig) { return ret("qualifier", "qualifier"); } else if (/[:;{}\[\]\(\)]/.test(ch)) { return ret(null, ch); - } else if (((ch == "u" || ch == "U") && stream.match(/rl(-prefix)?\(/i)) || - ((ch == "d" || ch == "D") && stream.match("omain(", true, true)) || - ((ch == "r" || ch == "R") && stream.match("egexp(", true, true))) { - stream.backUp(1); - state.tokenize = tokenParenthesized; - return ret("property", "word"); + } else if (stream.match(/[\w-.]+(?=\()/)) { + if (/^(url(-prefix)?|domain|regexp)$/.test(stream.current().toLowerCase())) { + state.tokenize = tokenParenthesized; + } + return ret("variable callee", "variable"); } else if (/[\w\\\-]/.test(ch)) { stream.eatWhile(/[\w\\\-]/); return ret("property", "word"); diff --git a/vendor/codemirror/mode/javascript/javascript.js b/vendor/codemirror/mode/javascript/javascript.js index 42b4b191..eb67187d 100644 --- a/vendor/codemirror/mode/javascript/javascript.js +++ b/vendor/codemirror/mode/javascript/javascript.js @@ -365,7 +365,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } if (type == "function") return cont(functiondef); if (type == "for") return cont(pushlex("form"), forspec, statement, poplex); - if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword"; return cont(pushlex("form"), className, poplex); } + if (type == "class" || (isTS && value == "interface")) { + cx.marked = "keyword" + return cont(pushlex("form", type == "class" ? type : value), className, poplex) + } if (type == "variable") { if (isTS && value == "declare") { cx.marked = "keyword" @@ -373,11 +376,11 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } else if (isTS && (value == "module" || value == "enum" || value == "type") && cx.stream.match(/^\s*\w/, false)) { cx.marked = "keyword" if (value == "enum") return cont(enumdef); - else if (value == "type") return cont(typeexpr, expect("operator"), typeexpr, expect(";")); + else if (value == "type") return cont(typename, expect("operator"), typeexpr, expect(";")); else return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex) } else if (isTS && value == "namespace") { cx.marked = "keyword" - return cont(pushlex("form"), expression, block, poplex) + return cont(pushlex("form"), expression, statement, poplex) } else if (isTS && value == "abstract") { cx.marked = "keyword" return cont(statement) @@ -522,7 +525,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { cx.marked = "keyword" return cont(objprop) } else if (type == "[") { - return cont(expression, maybetype, expect("]"), afterprop); + return cont(expression, maybetypeOrIn, expect("]"), afterprop); } else if (type == "spread") { return cont(expressionNoComma, afterprop); } else if (value == "*") { @@ -552,6 +555,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { }, proceed); } if (type == end || value == end) return cont(); + if (sep && sep.indexOf(";") > -1) return pass(what) return cont(expect(end)); } return function(type, value) { @@ -574,6 +578,9 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (value == "?") return cont(maybetype); } } + function maybetypeOrIn(type, value) { + if (isTS && (type == ":" || value == "in")) return cont(typeexpr) + } function mayberettype(type) { if (isTS && type == ":") { if (cx.stream.match(/^\s*\w+\s+is\b/, false)) return cont(expression, isKW, typeexpr) @@ -587,18 +594,19 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } } function typeexpr(type, value) { - if (value == "keyof" || value == "typeof") { + if (value == "keyof" || value == "typeof" || value == "infer") { cx.marked = "keyword" - return cont(value == "keyof" ? typeexpr : expressionNoComma) + return cont(value == "typeof" ? expressionNoComma : typeexpr) } if (type == "variable" || value == "void") { cx.marked = "type" return cont(afterType) } + if (value == "|" || value == "&") return cont(typeexpr) if (type == "string" || type == "number" || type == "atom") return cont(afterType); if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType) if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType) - if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType) + if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType, afterType) if (type == "<") return cont(commasep(typeexpr, ">"), typeexpr) } function maybeReturnType(type) { @@ -608,24 +616,28 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == "variable" || cx.style == "keyword") { cx.marked = "property" return cont(typeprop) - } else if (value == "?") { + } else if (value == "?" || type == "number" || type == "string") { return cont(typeprop) } else if (type == ":") { return cont(typeexpr) } else if (type == "[") { - return cont(expression, maybetype, expect("]"), typeprop) + return cont(expect("variable"), maybetype, expect("]"), typeprop) + } else if (type == "(") { + return pass(functiondecl, typeprop) } } function typearg(type, value) { if (type == "variable" && cx.stream.match(/^\s*[?:]/, false) || value == "?") return cont(typearg) if (type == ":") return cont(typeexpr) + if (type == "spread") return cont(typearg) return pass(typeexpr) } function afterType(type, value) { if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType) if (value == "|" || type == "." || value == "&") return cont(typeexpr) - if (type == "[") return cont(expect("]"), afterType) + if (type == "[") return cont(typeexpr, expect("]"), afterType) if (value == "extends" || value == "implements") { cx.marked = "keyword"; return cont(typeexpr) } + if (value == "?") return cont(typeexpr, expect(":"), typeexpr) } function maybeTypeArgs(_, value) { if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType) @@ -672,25 +684,18 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { } function forspec(type, value) { if (value == "await") return cont(forspec); - if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex); + if (type == "(") return cont(pushlex(")"), forspec1, poplex); } function forspec1(type) { - if (type == "var") return cont(vardef, expect(";"), forspec2); - if (type == ";") return cont(forspec2); - if (type == "variable") return cont(formaybeinof); - return pass(expression, expect(";"), forspec2); - } - function formaybeinof(_type, value) { - if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } - return cont(maybeoperatorComma, forspec2); + if (type == "var") return cont(vardef, forspec2); + if (type == "variable") return cont(forspec2); + return pass(forspec2) } function forspec2(type, value) { - if (type == ";") return cont(forspec3); - if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } - return pass(expression, expect(";"), forspec3); - } - function forspec3(type) { - if (type != ")") cont(expression); + if (type == ")") return cont() + if (type == ";") return cont(forspec2) + if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression, forspec2) } + return pass(expression, forspec2) } function functiondef(type, value) { if (value == "*") {cx.marked = "keyword"; return cont(functiondef);} @@ -698,10 +703,25 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, statement, popcontext); if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondef) } + function functiondecl(type, value) { + if (value == "*") {cx.marked = "keyword"; return cont(functiondecl);} + if (type == "variable") {register(value); return cont(functiondecl);} + if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, popcontext); + if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondecl) + } + function typename(type, value) { + if (type == "keyword" || type == "variable") { + cx.marked = "type" + return cont(typename) + } else if (value == "<") { + return cont(pushlex(">"), commasep(typeparam, ">"), poplex) + } + } function funarg(type, value) { if (value == "@") cont(expression, funarg) if (type == "spread") return cont(funarg); if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(funarg); } + if (isTS && type == "this") return cont(maybetype, maybeAssign) return pass(pattern, maybetype, maybeAssign); } function classExpression(type, value) { @@ -732,13 +752,15 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { cx.marked = "property"; return cont(isTS ? classfield : functiondef, classBody); } + if (type == "number" || type == "string") return cont(isTS ? classfield : functiondef, classBody); if (type == "[") return cont(expression, maybetype, expect("]"), isTS ? classfield : functiondef, classBody) if (value == "*") { cx.marked = "keyword"; return cont(classBody); } - if (type == ";") return cont(classBody); + if (isTS && type == "(") return pass(functiondecl, classBody) + if (type == ";" || type == ",") return cont(classBody); if (type == "}") return cont(); if (value == "@") return cont(expression, classBody) } @@ -746,7 +768,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) { if (value == "?") return cont(classfield) if (type == ":") return cont(typeexpr, maybeAssign) if (value == "=") return cont(expressionNoComma) - return pass(functiondef) + var context = cx.state.lexical.prev, isInterface = context && context.info == "interface" + return pass(isInterface ? functiondecl : functiondef) } function afterExport(type, value) { if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); } diff --git a/vendor/codemirror/theme/base16-light.css b/vendor/codemirror/theme/base16-light.css index 474e0ca9..1d5f582f 100644 --- a/vendor/codemirror/theme/base16-light.css +++ b/vendor/codemirror/theme/base16-light.css @@ -35,4 +35,4 @@ .cm-s-base16-light span.cm-error { background: #ac4142; color: #505050; } .cm-s-base16-light .CodeMirror-activeline-background { background: #DDDCDC; } -.cm-s-base16-light .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; } +.cm-s-base16-light .CodeMirror-matchingbracket { color: #f5f5f5 !important; background-color: #6A9FB5 !important} diff --git a/vendor/codemirror/theme/lesser-dark.css b/vendor/codemirror/theme/lesser-dark.css index 4b347db0..f96bf430 100644 --- a/vendor/codemirror/theme/lesser-dark.css +++ b/vendor/codemirror/theme/lesser-dark.css @@ -40,7 +40,7 @@ Ported to CodeMirror by Peter Kroon .cm-s-lesser-dark span.cm-tag { color: #669199; } .cm-s-lesser-dark span.cm-attribute { color: #81a4d5; } .cm-s-lesser-dark span.cm-hr { color: #999; } -.cm-s-lesser-dark span.cm-link { color: #00c; } +.cm-s-lesser-dark span.cm-link { color: #7070E6; } .cm-s-lesser-dark span.cm-error { color: #9d1e15; } .cm-s-lesser-dark .CodeMirror-activeline-background { background: #3C3A3A; } diff --git a/vendor/codemirror/theme/midnight.css b/vendor/codemirror/theme/midnight.css index 17ed39c8..fc26474a 100644 --- a/vendor/codemirror/theme/midnight.css +++ b/vendor/codemirror/theme/midnight.css @@ -1,9 +1,5 @@ /* Based on the theme at http://bonsaiden.github.com/JavaScript-Garden */ -/**/ -.cm-s-midnight span.CodeMirror-matchhighlight { background: #494949; } -.cm-s-midnight.CodeMirror-focused span.CodeMirror-matchhighlight { background: #314D67 !important; } - /**/ .cm-s-midnight .CodeMirror-activeline-background { background: #253540; } diff --git a/vendor/codemirror/theme/nord.css b/vendor/codemirror/theme/nord.css new file mode 100644 index 00000000..41a8ad77 --- /dev/null +++ b/vendor/codemirror/theme/nord.css @@ -0,0 +1,42 @@ +/* Based on arcticicestudio's Nord theme */ +/* https://github.com/arcticicestudio/nord */ + +.cm-s-nord.CodeMirror { background: #2e3440; color: #d8dee9; } +.cm-s-nord div.CodeMirror-selected { background: #434c5e; } +.cm-s-nord .CodeMirror-line::selection, .cm-s-nord .CodeMirror-line > span::selection, .cm-s-nord .CodeMirror-line > span > span::selection { background: #3b4252; } +.cm-s-nord .CodeMirror-line::-moz-selection, .cm-s-nord .CodeMirror-line > span::-moz-selection, .cm-s-nord .CodeMirror-line > span > span::-moz-selection { background: #3b4252; } +.cm-s-nord .CodeMirror-gutters { background: #2e3440; border-right: 0px; } +.cm-s-nord .CodeMirror-guttermarker { color: #4c566a; } +.cm-s-nord .CodeMirror-guttermarker-subtle { color: #4c566a; } +.cm-s-nord .CodeMirror-linenumber { color: #4c566a; } +.cm-s-nord .CodeMirror-cursor { border-left: 1px solid #f8f8f0; } + +.cm-s-nord span.cm-comment { color: #4c566a; } +.cm-s-nord span.cm-atom { color: #b48ead; } +.cm-s-nord span.cm-number { color: #b48ead; } + +.cm-s-nord span.cm-comment.cm-attribute { color: #97b757; } +.cm-s-nord span.cm-comment.cm-def { color: #bc9262; } +.cm-s-nord span.cm-comment.cm-tag { color: #bc6283; } +.cm-s-nord span.cm-comment.cm-type { color: #5998a6; } + +.cm-s-nord span.cm-property, .cm-s-nord span.cm-attribute { color: #8FBCBB; } +.cm-s-nord span.cm-keyword { color: #81A1C1; } +.cm-s-nord span.cm-builtin { color: #81A1C1; } +.cm-s-nord span.cm-string { color: #A3BE8C; } + +.cm-s-nord span.cm-variable { color: #d8dee9; } +.cm-s-nord span.cm-variable-2 { color: #d8dee9; } +.cm-s-nord span.cm-variable-3, .cm-s-nord span.cm-type { color: #d8dee9; } +.cm-s-nord span.cm-def { color: #8FBCBB; } +.cm-s-nord span.cm-bracket { color: #81A1C1; } +.cm-s-nord span.cm-tag { color: #bf616a; } +.cm-s-nord span.cm-header { color: #b48ead; } +.cm-s-nord span.cm-link { color: #b48ead; } +.cm-s-nord span.cm-error { background: #bf616a; color: #f8f8f0; } + +.cm-s-nord .CodeMirror-activeline-background { background: #3b4252; } +.cm-s-nord .CodeMirror-matchingbracket { + text-decoration: underline; + color: white !important; +} diff --git a/vendor/codemirror/theme/panda-syntax.css b/vendor/codemirror/theme/panda-syntax.css index 6de58b56..de14e911 100644 --- a/vendor/codemirror/theme/panda-syntax.css +++ b/vendor/codemirror/theme/panda-syntax.css @@ -7,7 +7,7 @@ background: #292A2B; color: #E6E6E6; line-height: 1.5; - font-family: 'Operator Mono', 'Source Sans Pro', Menlo, Monaco, Consolas, Courier New, monospace; + font-family: 'Operator Mono', 'Source Code Pro', Menlo, Monaco, Consolas, Courier New, monospace; } .cm-s-panda-syntax .CodeMirror-cursor { border-color: #ff2c6d; } .cm-s-panda-syntax .CodeMirror-activeline-background { diff --git a/vendor/codemirror/theme/vibrant-ink.css b/vendor/codemirror/theme/vibrant-ink.css index b13ecf21..6358ad36 100644 --- a/vendor/codemirror/theme/vibrant-ink.css +++ b/vendor/codemirror/theme/vibrant-ink.css @@ -27,7 +27,7 @@ .cm-s-vibrant-ink .cm-attribute { color: #8DA6CE; } .cm-s-vibrant-ink .cm-header { color: #FF6400; } .cm-s-vibrant-ink .cm-hr { color: #AEAEAE; } -.cm-s-vibrant-ink .cm-link { color: blue; } +.cm-s-vibrant-ink .cm-link { color: #5656F3; } .cm-s-vibrant-ink .cm-error { border-bottom: 1px solid red; } .cm-s-vibrant-ink .CodeMirror-activeline-background { background: #27282E; } diff --git a/vendor/codemirror/theme/yonce.css b/vendor/codemirror/theme/yonce.css new file mode 100644 index 00000000..e01c0c3b --- /dev/null +++ b/vendor/codemirror/theme/yonce.css @@ -0,0 +1,59 @@ +/* + + Name: yoncé + Author: Thomas MacLean (http://github.com/thomasmaclean) + + Original yoncé color scheme by Mina Markham (https://github.com/minamarkham) + +*/ + +.cm-s-yonce.CodeMirror { background: #1C1C1C; color: #d4d4d4; } /**/ +.cm-s-yonce div.CodeMirror-selected { background: rgba(252, 69, 133, 0.478); } /**/ +.cm-s-yonce .CodeMirror-selectedtext, +.cm-s-yonce .CodeMirror-selected, +.cm-s-yonce .CodeMirror-line::selection, +.cm-s-yonce .CodeMirror-line > span::selection, +.cm-s-yonce .CodeMirror-line > span > span::selection, +.cm-s-yonce .CodeMirror-line::-moz-selection, +.cm-s-yonce .CodeMirror-line > span::-moz-selection, +.cm-s-yonce .CodeMirror-line > span > span::-moz-selection { background: rgba(252, 67, 132, 0.47); } + +.cm-s-yonce.CodeMirror pre { padding-left: 0px; } +.cm-s-yonce .CodeMirror-gutters {background: #1C1C1C; border-right: 0px;} +.cm-s-yonce .CodeMirror-linenumber {color: #777777; padding-right: 10px; } +.cm-s-yonce .CodeMirror-activeline .CodeMirror-linenumber.CodeMirror-gutter-elt { background: #1C1C1C; color: #fc4384; } +.cm-s-yonce .CodeMirror-linenumber { color: #777; } +.cm-s-yonce .CodeMirror-cursor { border-left: 2px solid #FC4384; } +.cm-s-yonce .cm-searching { background: rgb(243, 155, 53, .3) !important; outline: 1px solid #F39B35; } +.cm-s-yonce .cm-searching.CodeMirror-selectedtext { background: rgb(243, 155, 53, .7) !important; color: white; } + +.cm-s-yonce .cm-keyword { color: #00A7AA; } /**/ +.cm-s-yonce .cm-atom { color: #F39B35; } +.cm-s-yonce .cm-number, .cm-s-yonce span.cm-type { color: #A06FCA; } /**/ +.cm-s-yonce .cm-def { color: #98E342; } +.cm-s-yonce .cm-property, +.cm-s-yonce span.cm-variable { color: #D4D4D4; font-style: italic; } +.cm-s-yonce span.cm-variable-2 { color: #da7dae; font-style: italic; } +.cm-s-yonce span.cm-variable-3 { color: #A06FCA; } +.cm-s-yonce .cm-type.cm-def { color: #FC4384; font-style: normal; text-decoration: underline; } +.cm-s-yonce .cm-property.cm-def { color: #FC4384; font-style: normal; } +.cm-s-yonce .cm-callee { color: #FC4384; font-style: normal; } +.cm-s-yonce .cm-operator { color: #FC4384; } /**/ +.cm-s-yonce .cm-qualifier, +.cm-s-yonce .cm-tag { color: #FC4384; } +.cm-s-yonce .cm-tag.cm-bracket { color: #D4D4D4; } +.cm-s-yonce .cm-attribute { color: #A06FCA; } +.cm-s-yonce .cm-comment { color:#696d70; font-style:italic; font-weight:normal; } /**/ +.cm-s-yonce .cm-comment.cm-tag { color: #FC4384 } +.cm-s-yonce .cm-comment.cm-attribute { color: #D4D4D4; } +.cm-s-yonce .cm-string { color:#E6DB74; } /**/ +.cm-s-yonce .cm-string-2 { color:#F39B35; } /*?*/ +.cm-s-yonce .cm-meta { color: #D4D4D4; background: inherit; } +.cm-s-yonce .cm-builtin { color: #FC4384; } /*?*/ +.cm-s-yonce .cm-header { color: #da7dae; } +.cm-s-yonce .cm-hr { color: #98E342; } +.cm-s-yonce .cm-link { color:#696d70; font-style:italic; text-decoration:none; } /**/ +.cm-s-yonce .cm-error { border-bottom: 1px solid #C42412; } + +.cm-s-yonce .CodeMirror-activeline-background { background: #272727; } +.cm-s-yonce .CodeMirror-matchingbracket { outline:1px solid grey; color:#D4D4D4 !important; } diff --git a/vendor/dropbox/README.md b/vendor/dropbox/README.md index b058d75e..b31319b1 100644 --- a/vendor/dropbox/README.md +++ b/vendor/dropbox/README.md @@ -1,8 +1,8 @@ -## Dropbox SDK v4.0.13 +## Dropbox SDK v4.0.28 Dropbox SDK JS installed via npm - source repo: -https://github.com/dropbox/dropbox-sdk-js/tree/v4.0.13 +https://github.com/dropbox/dropbox-sdk-js/tree/v4.0.28 The source repo **does not** include the `dist` folder with the generated `dropbox-sdk.js` distribution file. It can only be obtained from the npm `node_modules` folder after installing diff --git a/vendor/dropbox/dropbox-sdk.js b/vendor/dropbox/dropbox-sdk.js index 10407105..41de986f 100644 --- a/vendor/dropbox/dropbox-sdk.js +++ b/vendor/dropbox/dropbox-sdk.js @@ -328,6 +328,21 @@ routes.filesCopy = function (arg) { return this.request('files/copy', arg, 'user', 'api', 'rpc'); }; +/** + * Copy multiple files or folders to different locations at once in the user's + * Dropbox. This route will replace copy_batch. The main difference is this + * route will return stutus for each entry, while copy_batch raises failure if + * any entry fails. This route will either finish synchronously, or return a job + * ID and do the async copy job in background. Please use copy_batch/check_v2 to + * check the job status. + * @function Dropbox#filesCopyBatchV2 + * @arg {Object} arg - The request parameters. + * @returns {Promise.>} + */ +routes.filesCopyBatchV2 = function (arg) { + return this.request('files/copy_batch_v2', arg, 'user', 'api', 'rpc'); +}; + /** * Copy multiple files or folders to different locations at once in the user's * Dropbox. If RelocationBatchArg.allow_shared_folder is false, this route is @@ -337,6 +352,7 @@ routes.filesCopy = function (arg) { * This route will return job ID immediately and do the async copy job in * background. Please use copy_batch/check to check the job status. * @function Dropbox#filesCopyBatch + * @deprecated * @arg {FilesRelocationBatchArg} arg - The request parameters. * @returns {Promise.>} */ @@ -344,10 +360,22 @@ routes.filesCopyBatch = function (arg) { return this.request('files/copy_batch', arg, 'user', 'api', 'rpc'); }; +/** + * Returns the status of an asynchronous job for copy_batch_v2. It returns list + * of results for each entry. + * @function Dropbox#filesCopyBatchCheckV2 + * @arg {AsyncPollArg} arg - The request parameters. + * @returns {Promise.>} + */ +routes.filesCopyBatchCheckV2 = function (arg) { + return this.request('files/copy_batch/check_v2', arg, 'user', 'api', 'rpc'); +}; + /** * Returns the status of an asynchronous job for copy_batch. If success, it * returns list of results for each entry. * @function Dropbox#filesCopyBatchCheck + * @deprecated * @arg {AsyncPollArg} arg - The request parameters. * @returns {Promise.>} */ @@ -706,6 +734,21 @@ routes.filesMove = function (arg) { return this.request('files/move', arg, 'user', 'api', 'rpc'); }; +/** + * Move multiple files or folders to different locations at once in the user's + * Dropbox. This route will replace move_batch_v2. The main difference is this + * route will return stutus for each entry, while move_batch raises failure if + * any entry fails. This route will either finish synchronously, or return a job + * ID and do the async move job in background. Please use move_batch/check_v2 to + * check the job status. + * @function Dropbox#filesMoveBatchV2 + * @arg {FilesMoveBatchArg} arg - The request parameters. + * @returns {Promise.>} + */ +routes.filesMoveBatchV2 = function (arg) { + return this.request('files/move_batch_v2', arg, 'user', 'api', 'rpc'); +}; + /** * Move multiple files or folders to different locations at once in the user's * Dropbox. This route is 'all or nothing', which means if one entry fails, the @@ -720,6 +763,17 @@ routes.filesMoveBatch = function (arg) { return this.request('files/move_batch', arg, 'user', 'api', 'rpc'); }; +/** + * Returns the status of an asynchronous job for move_batch_v2. It returns list + * of results for each entry. + * @function Dropbox#filesMoveBatchCheckV2 + * @arg {AsyncPollArg} arg - The request parameters. + * @returns {Promise.>} + */ +routes.filesMoveBatchCheckV2 = function (arg) { + return this.request('files/move_batch/check_v2', arg, 'user', 'api', 'rpc'); +}; + /** * Returns the status of an asynchronous job for move_batch. If success, it * returns list of results for each entry. @@ -814,8 +868,10 @@ routes.filesRestore = function (arg) { }; /** - * Save a specified URL into a file in user's Dropbox. If the given path already - * exists, the file will be renamed to avoid the conflict (e.g. myfile (1).txt). + * Save the data from a specified URL into a file in user's Dropbox. Note that + * the transfer from the URL must complete within 5 minutes, or the operation + * will time out and the job will fail. If the given path already exists, the + * file will be renamed to avoid the conflict (e.g. myfile (1).txt). * @function Dropbox#filesSaveUrl * @arg {FilesSaveUrlArg} arg - The request parameters. * @returns {Promise.>} @@ -1169,7 +1225,7 @@ routes.sharingAddFileMember = function (arg) { * Allows an owner or editor (if the ACL update policy allows) of a shared * folder to add another member. For the new member to get access to all the * functionality for this folder, you will need to call mount_folder on their - * behalf. Apps must have full Dropbox access to use this endpoint. + * behalf. * @function Dropbox#sharingAddFolderMember * @arg {SharingAddFolderMemberArg} arg - The request parameters. * @returns {Promise.>} @@ -1190,8 +1246,7 @@ routes.sharingChangeFileMemberAccess = function (arg) { }; /** - * Returns the status of an asynchronous job. Apps must have full Dropbox access - * to use this endpoint. + * Returns the status of an asynchronous job. * @function Dropbox#sharingCheckJobStatus * @arg {AsyncPollArg} arg - The request parameters. * @returns {Promise.>} @@ -1201,8 +1256,7 @@ routes.sharingCheckJobStatus = function (arg) { }; /** - * Returns the status of an asynchronous job for sharing a folder. Apps must - * have full Dropbox access to use this endpoint. + * Returns the status of an asynchronous job for sharing a folder. * @function Dropbox#sharingCheckRemoveMemberJobStatus * @arg {AsyncPollArg} arg - The request parameters. * @returns {Promise.>} @@ -1212,8 +1266,7 @@ routes.sharingCheckRemoveMemberJobStatus = function (arg) { }; /** - * Returns the status of an asynchronous job for sharing a folder. Apps must - * have full Dropbox access to use this endpoint. + * Returns the status of an asynchronous job for sharing a folder. * @function Dropbox#sharingCheckShareJobStatus * @arg {AsyncPollArg} arg - The request parameters. * @returns {Promise.>} @@ -1273,8 +1326,7 @@ routes.sharingGetFileMetadataBatch = function (arg) { }; /** - * Returns shared folder metadata by its folder ID. Apps must have full Dropbox - * access to use this endpoint. + * Returns shared folder metadata by its folder ID. * @function Dropbox#sharingGetFolderMetadata * @arg {SharingGetMetadataArgs} arg - The request parameters. * @returns {Promise.>} @@ -1357,8 +1409,7 @@ routes.sharingListFileMembersContinue = function (arg) { }; /** - * Returns shared folder membership by its folder ID. Apps must have full - * Dropbox access to use this endpoint. + * Returns shared folder membership by its folder ID. * @function Dropbox#sharingListFolderMembers * @arg {SharingListFolderMembersArgs} arg - The request parameters. * @returns {Promise.>} @@ -1369,8 +1420,7 @@ routes.sharingListFolderMembers = function (arg) { /** * Once a cursor has been retrieved from list_folder_members, use this to - * paginate through all shared folder members. Apps must have full Dropbox - * access to use this endpoint. + * paginate through all shared folder members. * @function Dropbox#sharingListFolderMembersContinue * @arg {SharingListFolderMembersContinueArg} arg - The request parameters. * @returns {Promise.>} @@ -1380,8 +1430,7 @@ routes.sharingListFolderMembersContinue = function (arg) { }; /** - * Return the list of all shared folders the current user has access to. Apps - * must have full Dropbox access to use this endpoint. + * Return the list of all shared folders the current user has access to. * @function Dropbox#sharingListFolders * @arg {SharingListFoldersArgs} arg - The request parameters. * @returns {Promise.>} @@ -1393,8 +1442,7 @@ routes.sharingListFolders = function (arg) { /** * Once a cursor has been retrieved from list_folders, use this to paginate * through all shared folders. The cursor must come from a previous call to - * list_folders or list_folders/continue. Apps must have full Dropbox access to - * use this endpoint. + * list_folders or list_folders/continue. * @function Dropbox#sharingListFoldersContinue * @arg {SharingListFoldersContinueArg} arg - The request parameters. * @returns {Promise.>} @@ -1405,7 +1453,6 @@ routes.sharingListFoldersContinue = function (arg) { /** * Return the list of all shared folders the current user can mount or unmount. - * Apps must have full Dropbox access to use this endpoint. * @function Dropbox#sharingListMountableFolders * @arg {SharingListFoldersArgs} arg - The request parameters. * @returns {Promise.>} @@ -1418,7 +1465,6 @@ routes.sharingListMountableFolders = function (arg) { * Once a cursor has been retrieved from list_mountable_folders, use this to * paginate through all mountable shared folders. The cursor must come from a * previous call to list_mountable_folders or list_mountable_folders/continue. - * Apps must have full Dropbox access to use this endpoint. * @function Dropbox#sharingListMountableFoldersContinue * @arg {SharingListFoldersContinueArg} arg - The request parameters. * @returns {Promise.>} @@ -1481,8 +1527,7 @@ routes.sharingModifySharedLinkSettings = function (arg) { /** * The current user mounts the designated folder. Mount a shared folder for a * user after they have been added as a member. Once mounted, the shared folder - * will appear in their Dropbox. Apps must have full Dropbox access to use this - * endpoint. + * will appear in their Dropbox. * @function Dropbox#sharingMountFolder * @arg {SharingMountFolderArg} arg - The request parameters. * @returns {Promise.>} @@ -1494,7 +1539,7 @@ routes.sharingMountFolder = function (arg) { /** * The current user relinquishes their membership in the designated file. Note * that the current user may still have inherited access to this file through - * the parent folder. Apps must have full Dropbox access to use this endpoint. + * the parent folder. * @function Dropbox#sharingRelinquishFileMembership * @arg {SharingRelinquishFileMembershipArg} arg - The request parameters. * @returns {Promise.>} @@ -1507,8 +1552,7 @@ routes.sharingRelinquishFileMembership = function (arg) { * The current user relinquishes their membership in the designated shared * folder and will no longer have access to the folder. A folder owner cannot * relinquish membership in their own folder. This will run synchronously if - * leave_a_copy is false, and asynchronously if leave_a_copy is true. Apps must - * have full Dropbox access to use this endpoint. + * leave_a_copy is false, and asynchronously if leave_a_copy is true. * @function Dropbox#sharingRelinquishFolderMembership * @arg {SharingRelinquishFolderMembershipArg} arg - The request parameters. * @returns {Promise.>} @@ -1540,8 +1584,7 @@ routes.sharingRemoveFileMember2 = function (arg) { /** * Allows an owner or editor (if the ACL update policy allows) of a shared - * folder to remove another member. Apps must have full Dropbox access to use - * this endpoint. + * folder to remove another member. * @function Dropbox#sharingRemoveFolderMember * @arg {SharingRemoveFolderMemberArg} arg - The request parameters. * @returns {Promise.>} @@ -1583,7 +1626,7 @@ routes.sharingSetAccessInheritance = function (arg) { * testing the async case repeatable, set `ShareFolderArg.force_async`. If a * ShareFolderLaunch.async_job_id is returned, you'll need to call * check_share_job_status until the action completes to get the metadata for the - * folder. Apps must have full Dropbox access to use this endpoint. + * folder. * @function Dropbox#sharingShareFolder * @arg {SharingShareFolderArg} arg - The request parameters. * @returns {Promise.>} @@ -1595,7 +1638,7 @@ routes.sharingShareFolder = function (arg) { /** * Transfer ownership of a shared folder to a member of the shared folder. User * must have AccessLevel.owner access to the shared folder to perform a - * transfer. Apps must have full Dropbox access to use this endpoint. + * transfer. * @function Dropbox#sharingTransferFolder * @arg {SharingTransferFolderArg} arg - The request parameters. * @returns {Promise.>} @@ -1606,8 +1649,7 @@ routes.sharingTransferFolder = function (arg) { /** * The current user unmounts the designated folder. They can re-mount the folder - * at a later time using mount_folder. Apps must have full Dropbox access to use - * this endpoint. + * at a later time using mount_folder. * @function Dropbox#sharingUnmountFolder * @arg {SharingUnmountFolderArg} arg - The request parameters. * @returns {Promise.>} @@ -1628,8 +1670,7 @@ routes.sharingUnshareFile = function (arg) { /** * Allows a shared folder owner to unshare the folder. You'll need to call - * check_job_status to determine if the action has completed successfully. Apps - * must have full Dropbox access to use this endpoint. + * check_job_status to determine if the action has completed successfully. * @function Dropbox#sharingUnshareFolder * @arg {SharingUnshareFolderArg} arg - The request parameters. * @returns {Promise.>} @@ -1650,7 +1691,7 @@ routes.sharingUpdateFileMember = function (arg) { /** * Allows an owner or editor of a shared folder to update another member's - * permissions. Apps must have full Dropbox access to use this endpoint. + * permissions. * @function Dropbox#sharingUpdateFolderMember * @arg {SharingUpdateFolderMemberArg} arg - The request parameters. * @returns {Promise.>} @@ -1661,8 +1702,7 @@ routes.sharingUpdateFolderMember = function (arg) { /** * Update the sharing policies for a shared folder. User must have - * AccessLevel.owner access to the shared folder to update its policies. Apps - * must have full Dropbox access to use this endpoint. + * AccessLevel.owner access to the shared folder to update its policies. * @function Dropbox#sharingUpdateFolderPolicy * @arg {SharingUpdateFolderPolicyArg} arg - The request parameters. * @returns {Promise.>} @@ -1920,6 +1960,9 @@ function downloadRequest(fetch) { if (options.selectAdmin) { fetchOptions.headers['Dropbox-API-Select-Admin'] = options.selectAdmin; } + if (options.pathRoot) { + fetchOptions.headers['Dropbox-API-Path-Root'] = options.pathRoot; + } } return fetch(getBaseURL(host) + path, fetchOptions).then(function (res) { @@ -1978,6 +2021,9 @@ function uploadRequest(fetch) { if (options.selectAdmin) { fetchOptions.headers['Dropbox-API-Select-Admin'] = options.selectAdmin; } + if (options.pathRoot) { + fetchOptions.headers['Dropbox-API-Path-Root'] = options.pathRoot; + } } return fetch(getBaseURL(host) + path, fetchOptions).then(function (res) { @@ -3982,6 +4028,9 @@ function rpcRequest(fetch) { if (options.selectAdmin) { headers['Dropbox-API-Select-Admin'] = options.selectAdmin; } + if (options.pathRoot) { + headers['Dropbox-API-Path-Root'] = options.pathRoot; + } } fetchOptions.headers = headers; @@ -4111,6 +4160,8 @@ if (!Array.prototype.includes) { * to act as. * @arg {String} [options.selectAdmin] - Team admin that the team access token would like * to act as. + * @arg {String} [options.pathRoot] - root pass to access other namespaces + * Use to access team folders for example */ function parseBodyToType(res) { @@ -4139,6 +4190,7 @@ var DropboxBase = function () { this.selectUser = options.selectUser; this.selectAdmin = options.selectAdmin; this.fetch = options.fetch || fetch; + this.pathRoot = options.pathRoot; if (!options.fetch) { console.warn('Global fetch is deprecated and will be unsupported in a future version. Please pass fetch function as option when instantiating dropbox instance: new Dropbox({fetch})'); } // eslint-disable-line no-console @@ -4332,12 +4384,15 @@ var DropboxBase = function () { var removed = false; var browser = window.open(url, '_blank'); - function onLoadError() { - // Try to avoid a browser crash on browser.close(). - window.setTimeout(function () { - browser.close(); - }, 10); - errorCallback(); + function onLoadError(event) { + if (event.code !== -999) { + // Workaround to fix wrong behavior on cordova-plugin-inappbrowser + // Try to avoid a browser crash on browser.close(). + window.setTimeout(function () { + browser.close(); + }, 10); + errorCallback(); + } } function onLoadStop(event) { @@ -4402,7 +4457,8 @@ var DropboxBase = function () { selectUser: this.selectUser, selectAdmin: this.selectAdmin, clientId: this.getClientId(), - clientSecret: this.getClientSecret() + clientSecret: this.getClientSecret(), + pathRoot: this.pathRoot }; return request(path, args, auth, host, this.getAccessToken(), options); } @@ -4462,6 +4518,8 @@ var DropboxBase = function () { * authentication URL. * @arg {String} [options.selectUser] - Select user is only used by DropboxTeam. * It specifies which user the team access token should be acting as. + * @arg {String} [options.pathRoot] - root pass to access other namespaces + * Use to access team folders for example */ var Dropbox = function (_DropboxBase) { inherits(Dropbox, _DropboxBase); @@ -4504,7 +4562,7 @@ routes$1.teamDevicesListMemberDevices = function (arg) { }; /** - * List all device sessions of a team. + * List all device sessions of a team. Permission : Team member file access. * @function DropboxTeam#teamDevicesListMembersDevices * @arg {TeamListMembersDevicesArg} arg - The request parameters. * @returns {Promise.>} @@ -4514,7 +4572,7 @@ routes$1.teamDevicesListMembersDevices = function (arg) { }; /** - * List all device sessions of a team. + * List all device sessions of a team. Permission : Team member file access. * @function DropboxTeam#teamDevicesListTeamDevices * @deprecated * @arg {TeamListTeamDevicesArg} arg - The request parameters. @@ -5046,6 +5104,7 @@ routes$1.teamNamespacesListContinue = function (arg) { }; /** + * Permission : Team member file access. * @function DropboxTeam#teamPropertiesTemplateAdd * @deprecated * @arg {FilePropertiesAddTemplateArg} arg - The request parameters. @@ -5056,6 +5115,7 @@ routes$1.teamPropertiesTemplateAdd = function (arg) { }; /** + * Permission : Team member file access. * @function DropboxTeam#teamPropertiesTemplateGet * @deprecated * @arg {FilePropertiesGetTemplateArg} arg - The request parameters. @@ -5066,6 +5126,7 @@ routes$1.teamPropertiesTemplateGet = function (arg) { }; /** + * Permission : Team member file access. * @function DropboxTeam#teamPropertiesTemplateList * @deprecated * @arg {void} arg - The request parameters. @@ -5076,6 +5137,7 @@ routes$1.teamPropertiesTemplateList = function (arg) { }; /** + * Permission : Team member file access. * @function DropboxTeam#teamPropertiesTemplateUpdate * @deprecated * @arg {FilePropertiesUpdateTemplateArg} arg - The request parameters.