From c8ca347f5dca7f0ec7d5496c1a06efce98d3cea2 Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 6 Apr 2018 14:45:02 +0400 Subject: [PATCH] update ace --- plugins/node_modules/ace/lib/ace/ace.js | 2 +- plugins/node_modules/ace/lib/ace/ace_test.js | 89 ++++ .../node_modules/ace/lib/ace/css/editor.css | 62 ++- .../node_modules/ace/lib/ace/edit_session.js | 5 +- plugins/node_modules/ace/lib/ace/editor.js | 64 ++- .../node_modules/ace/lib/ace/ext/beautify.js | 444 ++++++++++++------ .../ace/lib/ace/ext/beautify_test.js | 173 ++++++- plugins/node_modules/ace/lib/ace/ext/emmet.js | 2 +- .../node_modules/ace/lib/ace/ext/modelist.js | 1 + .../node_modules/ace/lib/ace/ext/options.js | 9 + .../ace/lib/ace/ext/static_highlight.js | 112 ++++- .../ace/lib/ace/ext/static_highlight_test.js | 12 +- .../node_modules/ace/lib/ace/ext/textarea.js | 4 +- .../node_modules/ace/lib/ace/ext/themelist.js | 1 - .../node_modules/ace/lib/ace/keyboard/vim.js | 40 +- .../ace/lib/ace/keyboard/vim_test.js | 1 + .../node_modules/ace/lib/ace/layer/cursor.js | 87 ++-- .../ace/lib/ace/layer/font_metrics.js | 5 +- .../node_modules/ace/lib/ace/layer/gutter.js | 319 ++++++++++--- .../node_modules/ace/lib/ace/layer/lines.js | 154 ++++++ .../node_modules/ace/lib/ace/layer/marker.js | 164 +++---- .../node_modules/ace/lib/ace/layer/text.js | 339 +++++++------ .../ace/lib/ace/layer/text_test.js | 53 ++- plugins/node_modules/ace/lib/ace/lib/dom.js | 58 +++ plugins/node_modules/ace/lib/ace/lib/event.js | 31 +- .../ace/lib/ace/lib/event_emitter.js | 1 - plugins/node_modules/ace/lib/ace/lib/keys.js | 2 - .../ace/lib/ace/mode/java_highlight_rules.js | 33 ++ .../ace/lib/ace/mode/php_highlight_rules.js | 3 + .../ace/lib/ace/mouse/default_handlers.js | 2 - .../ace/lib/ace/mouse/mouse_handler.js | 2 +- .../ace/lib/ace/mouse/mouse_handler_test.js | 72 ++- .../ace/lib/ace/mouse/multi_select_handler.js | 1 + .../node_modules/ace/lib/ace/multi_select.js | 2 + .../ace/lib/ace/multi_select_test.js | 25 + .../node_modules/ace/lib/ace/range_list.js | 103 ++-- .../node_modules/ace/lib/ace/renderloop.js | 21 +- .../ace/lib/ace/requirejs/text.js | 10 +- .../lib/ace/requirejs/text_loader_webpack.js | 45 ++ plugins/node_modules/ace/lib/ace/selection.js | 3 +- .../ace/lib/ace/selection_test.js | 12 + .../ace/lib/ace/test/assertions.js | 26 +- .../node_modules/ace/lib/ace/test/mockdom.js | 377 ++++++++++++++- .../node_modules/ace/lib/ace/undomanager.js | 13 +- .../ace/lib/ace/undomanager_test.js | 226 ++++++++- .../ace/lib/ace/virtual_renderer.js | 116 ++--- .../ace/lib/ace/virtual_renderer_test.js | 14 +- 47 files changed, 2566 insertions(+), 774 deletions(-) create mode 100644 plugins/node_modules/ace/lib/ace/ace_test.js create mode 100644 plugins/node_modules/ace/lib/ace/layer/lines.js create mode 100644 plugins/node_modules/ace/lib/ace/requirejs/text_loader_webpack.js diff --git a/plugins/node_modules/ace/lib/ace/ace.js b/plugins/node_modules/ace/lib/ace/ace.js index 6cc536c3..13d38a72 100644 --- a/plugins/node_modules/ace/lib/ace/ace.js +++ b/plugins/node_modules/ace/lib/ace/ace.js @@ -131,5 +131,5 @@ exports.Range = Range; exports.EditSession = EditSession; exports.UndoManager = UndoManager; exports.VirtualRenderer = Renderer; -exports.version = "1.3.1"; +exports.version = "1.3.3"; }); diff --git a/plugins/node_modules/ace/lib/ace/ace_test.js b/plugins/node_modules/ace/lib/ace/ace_test.js new file mode 100644 index 00000000..0943015b --- /dev/null +++ b/plugins/node_modules/ace/lib/ace/ace_test.js @@ -0,0 +1,89 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +if (typeof process !== "undefined") { + require("amd-loader"); + require("./test/mockdom"); +} + +define(function(require, exports, module) { +"use strict"; + +var ace = require("./ace"); +var assert = require("./test/assertions"); + +module.exports = { + "test: ace edit" : function() { + var editor = ace.edit(null, { + value: "Helo world" + }); + assert.equal(editor.getValue(), "Helo world"); + + var session = ace.createEditSession("Juhu kinners!"); + editor.setSession(session); + assert.equal(editor.getValue(), "Juhu kinners!"); + + assert.equal(editor, ace.edit(editor.container)); + editor.destroy(); + }, + "test: edit textarea" : function() { + var el = document.createElement("textarea"); + document.body.appendChild(el); + var editor = ace.edit(el); + assert.notEqual(editor.container, el); + + editor.container.id = "editor1"; + assert.equal(editor, ace.edit("editor1")); + editor.destroy(); + document.body.removeChild(editor.container); + }, + "test: edit element by id" : function() { + var el = document.createElement("div"); + document.body.appendChild(el); + var editor = null; + try { + editor = ace.edit("x"); + } catch(e) { + } + assert.equal(editor, null); + + el.id = "editor2"; + el.textContent = "h"; + editor = ace.edit("editor2"); + assert.equal(el, editor.container); + assert.equal("h", editor.getValue()); + document.body.removeChild(el); + } +}; +}); + +if (typeof module !== "undefined" && module === require.main) { + require("asyncjs").test.testcase(module.exports).exec(); +} diff --git a/plugins/node_modules/ace/lib/ace/css/editor.css b/plugins/node_modules/ace/lib/ace/css/editor.css index 9d7cf9d8..bae0a2ab 100644 --- a/plugins/node_modules/ace/lib/ace/css/editor.css +++ b/plugins/node_modules/ace/lib/ace/css/editor.css @@ -24,6 +24,7 @@ position: absolute; box-sizing: border-box; min-width: 100%; + contain: style size layout; } .ace_dragging .ace_scroller:before{ @@ -57,6 +58,7 @@ -moz-user-select: none; -webkit-user-select: none; user-select: none; + contain: style size layout; } .ace_gutter-active-line { @@ -70,6 +72,10 @@ } .ace_gutter-cell { + position: absolute; + top: 0; + left: 0; + right: 0; padding-left: 19px; padding-right: 6px; background-repeat: no-repeat; @@ -95,6 +101,7 @@ } .ace_scrollbar { + contain: strict; position: absolute; right: 0; bottom: 0; @@ -188,10 +195,36 @@ width: auto; text-align: right; pointer-events: auto; + height: 1000000px; + contain: style size layout; } .ace_text-layer { font: inherit !important; + position: absolute; + height: 1000000px; + width: 1000000px; + contain: style size layout; +} + +.ace_text-layer > .ace_line, .ace_text-layer > .ace_line_group { + contain: style size layout; + position: absolute; + top: 0; + left: 0; + right: 0; +} + +.ace_hidpi .ace_text-layer, +.ace_hidpi .ace_gutter-layer, +.ace_hidpi .ace_content, +.ace_hidpi .ace_gutter { + contain: strict; + will-change: transform; +} +.ace_hidpi .ace_text-layer > .ace_line, +.ace_hidpi .ace_text-layer > .ace_line_group { + contain: strict; } .ace_cjk { @@ -233,6 +266,31 @@ transition: opacity 0.18s; } +.ace_animate-blinking .ace_cursor { + animation-duration: 1000ms; + animation-timing-function: step-end; + animation-name: blink-ace-animate; + animation-iteration-count: infinite; +} + +.ace_animate-blinking.ace_smooth-blinking .ace_cursor { + animation-duration: 1000ms; + animation-timing-function: ease-in-out; + animation-name: blink-ace-animate-smooth; +} + +@keyframes blink-ace-animate { + from, to { opacity: 1; } + 60% { opacity: 0; } +} + +@keyframes blink-ace-animate-smooth { + from, to { opacity: 1; } + 45% { opacity: 1; } + 60% { opacity: 0; } + 85% { opacity: 0; } +} + .ace_marker-layer .ace_step, .ace_marker-layer .ace_stack { position: absolute; z-index: 3; @@ -435,10 +493,6 @@ position: absolute; z-index: 8; } -.ace_lineWidgetContainer { - z-index: 5; - position: absolute; -} /* styles = [] diff --git a/plugins/node_modules/ace/lib/ace/edit_session.js b/plugins/node_modules/ace/lib/ace/edit_session.js index e09b7e9c..c48400ae 100644 --- a/plugins/node_modules/ace/lib/ace/edit_session.js +++ b/plugins/node_modules/ace/lib/ace/edit_session.js @@ -1159,7 +1159,6 @@ EditSession.$uid = 0; } } if (!dontSelect && this.$undoSelect) { - // console.log(deltas.selectionBefore + "uuu") if (deltas.selectionBefore) this.selection.fromJSON(deltas.selectionBefore); else @@ -2379,6 +2378,7 @@ EditSession.$uid = 0; * */ this.$setFontMetrics = function(fm) { + if (!this.$enableVarChar) return; this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) { if (maxScreenColumn === 0) return [0, 0]; @@ -2555,7 +2555,8 @@ config.defineOptions(EditSession.prototype, "session", { }, mode: { set: function(val) { this.setMode(val); }, - get: function() { return this.$modeId; } + get: function() { return this.$modeId; }, + handlesSet: true } }); diff --git a/plugins/node_modules/ace/lib/ace/editor.js b/plugins/node_modules/ace/lib/ace/editor.js index 9dfc7513..46560297 100644 --- a/plugins/node_modules/ace/lib/ace/editor.js +++ b/plugins/node_modules/ace/lib/ace/editor.js @@ -31,8 +31,6 @@ define(function(require, exports, module) { "use strict"; -require("./lib/fixoldbrowsers"); - var oop = require("./lib/oop"); var dom = require("./lib/dom"); var lang = require("./lib/lang"); @@ -876,8 +874,8 @@ Editor.$uid = 0; * Returns the string of text currently highlighted. * @returns {String} **/ - this.getSelectedText = function(newLineCharacter) { - return this.session.getTextRange(this.getSelectionRange(), newLineCharacter); + this.getSelectedText = function() { + return this.session.getTextRange(this.getSelectionRange()); }; /** @@ -891,7 +889,7 @@ Editor.$uid = 0; * @returns {String} **/ this.getCopyText = function() { - var text = this.getSelectedText(useragent.isWin ? "\r\n" : "\n"); + var text = this.getSelectedText(); var nl = this.session.doc.getNewLineCharacter(); var copyLine= false; if (!text && this.$copyWithEmptySelection) { @@ -980,10 +978,6 @@ Editor.$uid = 0; return this.commands.exec(command, this, args); }; - this.transformAction = function(type, text) { - - }; - /** * Inserts `text` into wherever the cursor is pointing. * @param {String} text The new text to add @@ -2693,6 +2687,26 @@ config.defineOptions(Editor.prototype, "editor", { handlesSet: true, hidden: true }, + + showLineNumbers: { + set: function(show) { + this.renderer.$gutterLayer.setShowLineNumbers(show); + this.renderer.$loop.schedule(this.renderer.CHANGE_GUTTER); + if (show && this.$relativeLineNumbers) + relativeNumberRenderer.attach(this); + else + relativeNumberRenderer.detach(this); + }, + initialValue: true + }, + relativeLineNumbers: { + set: function(value) { + if (this.$showLineNumbers && value) + relativeNumberRenderer.attach(this); + else + relativeNumberRenderer.detach(this); + } + }, hScrollBarAlwaysVisible: "renderer", vScrollBarAlwaysVisible: "renderer", @@ -2704,9 +2718,8 @@ config.defineOptions(Editor.prototype, "editor", { printMargin: "renderer", fadeFoldWidgets: "renderer", showFoldWidgets: "renderer", - showLineNumbers: "renderer", - showGutter: "renderer", displayIndentGuides: "renderer", + showGutter: "renderer", fontSize: "renderer", fontFamily: "renderer", maxLines: "renderer", @@ -2715,6 +2728,7 @@ config.defineOptions(Editor.prototype, "editor", { fixedWidthGutter: "renderer", theme: "renderer", hasCssTransforms: "renderer", + maxPixelHeight: "renderer", scrollSpeed: "$mouseHandler", dragDelay: "$mouseHandler", @@ -2735,5 +2749,33 @@ config.defineOptions(Editor.prototype, "editor", { mode: "session" }); + +var relativeNumberRenderer = { + getText: function(session, row) { + return (Math.abs(session.selection.lead.row - row) || (row + 1 + (row < 9 ? "\xb7" : ""))) + ""; + }, + getWidth: function(session, lastLineNumber, config) { + return Math.max( + lastLineNumber.toString().length, + (config.lastRow + 1).toString().length, + 2 + ) * config.characterWidth; + }, + update: function(e, editor) { + editor.renderer.$loop.schedule(editor.renderer.CHANGE_GUTTER); + }, + attach: function(editor) { + editor.renderer.$gutterLayer.$renderer = this; + editor.on("changeSelection", this.update); + this.update(null, editor); + }, + detach: function(editor) { + if (editor.renderer.$gutterLayer.$renderer == this) + editor.renderer.$gutterLayer.$renderer = null; + editor.off("changeSelection", this.update); + this.update(null, editor); + } +}; + exports.Editor = Editor; }); diff --git a/plugins/node_modules/ace/lib/ace/ext/beautify.js b/plugins/node_modules/ace/lib/ace/ext/beautify.js index f6347b8f..ba2b511f 100644 --- a/plugins/node_modules/ace/lib/ace/ext/beautify.js +++ b/plugins/node_modules/ace/lib/ace/ext/beautify.js @@ -52,13 +52,17 @@ exports.beautify = function(session) { var blockTags = exports.blockTags; var nextToken; var breakBefore = false; + var spaceBefore = false; + var spaceAfter = false; var code = ""; var value = ""; var tagName = ""; + var depth = 0; + var lastDepth = 0; + var lastIndent = 0; var indent = 0; - var inBlock = false; - var inComment = false; - var inCase = false; + var unindent = 0; + var roundDepth = 0; var onCaseLine = false; var row; var curRow = 0; @@ -67,176 +71,314 @@ exports.beautify = function(session) { var abort = false; var i; var indentNextLine = false; + var inTag = false; + var inCSS = false; + var inBlock = false; + var levels = {0: 0}; + var parents = {}; + + var trimNext = function() { + if (nextToken && nextToken.value && nextToken.type !== 'string.regexp') + nextToken.value = nextToken.value.trim(); + }; + + var trimLine = function() { + code = code.replace(/ +$/, ""); + }; + + var trimCode = function() { + code = code.trimRight(); + breakBefore = false; + }; while (token !== null) { - value = token.value; curRow = iterator.getCurrentTokenRow(); rowTokens = iterator.$rowTokens; nextToken = iterator.stepForward(); - // are we in a block tag - if (is(token, "tag-open") && value === "<" && nextToken) - inBlock = (blockTags.indexOf(nextToken.value) !== -1); + if (typeof token !== "undefined") { + value = token.value; + unindent = 0; - // comments - if (is(token, "comment.start")) { - inComment = true; - inBlock = true; - } else if (is(token, "comment.end")) { - inComment = false; - inBlock = false; - } + // mode + inCSS = (tagName === "style" || session.$modeId === "ace/mode/css"); - // html indentation - if (is(token, "tag-open") && value === " 0; rowsToAdd--) - code += "\n"; - - breakBefore = true; - - // trim value if not in a comment - if (!inComment) - value = value.trimLeft(); - } - - if (value) { - // whitespace - if (token.type === "keyword" && value.match(/^(if|else|elseif|for|while|switch)$/)) { - value += " "; - nextToken.value = nextToken.value.trim(); - - // space before else, elseif - if (!breakBefore && token.type === "keyword" && value.trim().match(/^(else|elseif)$/)) { - code = code.trimRight(); - value = " "+value; - } - // trim value after opening paren - } else if (token.type === "paren.lparen") { - nextToken.value = nextToken.value.trim(); - - // whitepace after { - if (value.substr(-1) === "{") { - code = code.replace(/ +$/, ""); - value = value + " "; - } - - // ensure curly brace is preceeded by whitespace - if (value.substr(0, 1) === "{" && !code.match(/\s$/)) - value = " " + value; - // remove space before closing paren - } else if (token.type === "paren.rparen") { - code = code.replace(/ +$/, ""); - - // ensure curly brace is preceeded by whitespace - if (value.substr(0, 1) === "}" && !code.match(/\s$/)) - value = " " + value; - // add spaces around conditional operators - } else if ((token.type === "keyword.operator" || token.type === "keyword") && value.match(/^(=|==|===|!=|!==|&&|\|\||and|or|xor|\+=|.=|>|>=|<|<=)$/)) { - code = code.trimRight(); - value = " " + value + " "; - nextToken.value = nextToken.value.trim(); - } else if (token.type === "support.php_tag" && value === "?>" && !breakBefore) { - code = code.trimRight(); - value = " " + value; } - // unindent if first paren is closing - if (curRow != row && rowTokens) { - abort = false; - for (i = 0; i 0; rowsToAdd--) + code += "\n"; - if (indentNextLine) { - count++; - indentNextLine = false; - } + breakBefore = true; - for (i = 0; i < count; i++) - code += tabString; + // trim value if not in a comment or string + if (!is(token, "comment") && !token.type.match(/^(comment|string)$/)) + value = value.trimLeft(); } - // indent if there are last paren is opening - if (curRow != row && rowTokens) { - indentNextLine = null; - abort = false; - for (i = rowTokens.length-1; i>=0 && !abort; i--) { - if (rowTokens[i].type == "paren.rparen") { - abort = true; - } else if (rowTokens[i].type == "paren.lparen") { + if (value) { + // whitespace + if (token.type === "keyword" && value.match(/^(if|else|elseif|for|foreach|while|switch)$/)) { + parents[depth] = value; + + trimNext(); + spaceAfter = true; + + // space before else, elseif + if (value.match(/^(else|elseif)$/)) { + if (code.match(/\}[\s]*$/)) { + trimCode(); + spaceBefore = true; + } + } + // trim value after opening paren + } else if (token.type === "paren.lparen") { + trimNext(); + + // whitespace after { + if (value.substr(-1) === "{") { + spaceAfter = true; + indentNextLine = false; + + if(!inTag) + rowsToAdd = 1; + } + + // ensure curly brace is preceeded by whitespace + if (value.substr(0, 1) === "{") { + spaceBefore = true; + + // collapse square and curly brackets together + if (code.substr(-1) !== '[' && code.trimRight().substr(-1) === '[') { + trimCode(); + spaceBefore = false; + } else if (code.trimRight().substr(-1) === ')') { + trimCode(); + } else { + trimLine(); + } + } + // remove space before closing paren + } else if (token.type === "paren.rparen") { + unindent = 1; + + // ensure curly brace is preceeded by whitespace + if (value.substr(0, 1) === "}") { + if (parents[depth-1] === 'case') + unindent++; + + if (code.trimRight().substr(-1) === '{') { + trimCode(); + } else { + spaceBefore = true; + + if (inCSS) + rowsToAdd+=2; + } + } + + // collapse square and curly brackets together + if (value.substr(0, 1) === "]") { + if (code.substr(-1) !== '}' && code.trimRight().substr(-1) === '}') { + spaceBefore = false; + indent++; + trimCode(); + } + } + + // collapse round brackets together + if (value.substr(0, 1) === ")") { + if (code.substr(-1) !== '(' && code.trimRight().substr(-1) === '(') { + spaceBefore = false; + indent++; + trimCode(); + } + } + + trimLine(); + // add spaces around conditional operators + } else if ((token.type === "keyword.operator" || token.type === "keyword") && value.match(/^(=|==|===|!=|!==|&&|\|\||and|or|xor|\+=|.=|>|>=|<|<=|=>)$/)) { + trimCode(); + trimNext(); + spaceBefore = true; + spaceAfter = true; + // remove space before semicolon + } else if (token.type === "punctuation.operator" && value === ';') { + trimCode(); + trimNext(); + spaceAfter = true; + + if (inCSS) + rowsToAdd++; + // space after colon or comma + } else if (token.type === "punctuation.operator" && value.match(/^(:|,)$/)) { + trimCode(); + trimNext(); + spaceAfter = true; + breakBefore = false; + // ensure space before php closing tag + } else if (token.type === "support.php_tag" && value === "?>" && !breakBefore) { + trimCode(); + spaceBefore = true; + // remove excess space before HTML attribute + } else if (is(token, "attribute-name") && code.substr(-1).match(/^\s$/)) { + spaceBefore = true; + // remove space around attribute equals + } else if (is(token, "attribute-equals")) { + trimLine(); + trimNext(); + // remove space before HTML closing tag + } else if (is(token, "tag-close")) { + trimLine(); + if(value === "/>") + spaceBefore = true; + } + + // add indent to code unless multiline string or comment + if (breakBefore && !(token.type.match(/^(comment)$/) && !value.substr(0, 1).match(/^[/#]$/)) && !(token.type.match(/^(string)$/) && !value.substr(0, 1).match(/^['"]$/))) { + + indent = lastIndent; + + if(depth > lastDepth) { + indent++; + + for (i=depth; i > lastDepth; i--) + levels[i] = indent; + } else if(depth < lastDepth) + indent = levels[depth]; + + lastDepth = depth; + lastIndent = indent; + + if(unindent) + indent -= unindent; + + if (indentNextLine && !roundDepth) { indent++; indentNextLine = false; - abort = true; + } + + for (i = 0; i < indent; i++) + code += tabString; + } + + + if (token.type === "keyword" && value.match(/^(case|default)$/)) { + parents[depth] = value; + depth++; + } + + + if (token.type === "keyword" && value.match(/^(break)$/)) { + if(parents[depth-1] && parents[depth-1].match(/^(case|default)$/)) { + depth--; } } + + // indent one line after if or else + if (token.type === "paren.lparen") { + roundDepth += (value.match(/\(/g) || []).length; + depth += value.length; + } + + if (token.type === "keyword" && value.match(/^(if|else|elseif|for|while)$/)) { + indentNextLine = true; + roundDepth = 0; + } else if (!roundDepth && value.trim() && token.type !== "comment") + indentNextLine = false; + + if (token.type === "paren.rparen") { + roundDepth -= (value.match(/\)/g) || []).length; + + for (i = 0; i < value.length; i++) { + depth--; + if(value.substr(i, 1)==='}' && parents[depth]==='case') { + depth--; + } + } + } + + // add to code + if (spaceBefore && !breakBefore) { + trimLine(); + if (code.substr(-1) !== "\n") + code += " "; + } + + code += value; + + if (spaceAfter) + code += " "; + + breakBefore = false; + spaceBefore = false; + spaceAfter = false; + + // line break after block tag or doctype + if ((is(token, "tag-close") && (inBlock || blockTags.indexOf(tagName) !== -1)) || (is(token, "doctype") && value === ">")) { + // undo linebreak if tag is immediately closed + if (inBlock && nextToken && nextToken.value === "" && singletonTags.indexOf(tagName) === -1){ + depth--; + } + + row = curRow; } - - // indent one line after if or else - if (indentNextLine !== false && token.type === "keyword" && value.trim().match(/^(if|else|elseif|for|while)$/)) - indentNextLine = true; - - // add to code - code += value; - breakBefore = false; - - // line break after opening block tag or doctype - if ((is(token, "tag-close") && (inBlock || blockTags.indexOf(tagName) !== -1)) || (is(token, "doctype") && value==">")) { - // undo linebreak if tag is immediately closed - if (inBlock && nextToken && nextToken.value === "" && singletonTags.indexOf(tagName) === -1) - indent--; - - row = curRow; } token = nextToken; diff --git a/plugins/node_modules/ace/lib/ace/ext/beautify_test.js b/plugins/node_modules/ace/lib/ace/ext/beautify_test.js index aff7021c..5f7eb054 100644 --- a/plugins/node_modules/ace/lib/ace/ext/beautify_test.js +++ b/plugins/node_modules/ace/lib/ace/ext/beautify_test.js @@ -14,17 +14,31 @@ var PHPMode = require("../mode/php").Mode; module.exports = { timeout: 10000, + "test beautify first line empty": function(next) { + var s = new EditSession([ + "", + "hello world" + ], new PHPMode()); + s.setUseSoftTabs(false); + + beautify.beautify(s); + assert.equal(s.getValue(), "hello world"); + + next(); + }, + "test beautify block tag indentation": function(next) { var s = new EditSession([ "
", - "

test

", - "
" + "

hello

", + "world" ], new PHPMode()); s.setUseSoftTabs(false); beautify.beautify(s); assert.equal(s.getValue(), "
\n" - + "\t

test

\n" + + "\t

hello

\n" + + "\tworld\n" + "
"); next(); @@ -133,16 +147,24 @@ module.exports = { "test beautify curly indentation": function(next) { var s = new EditSession([ "", + "\n" + + "", + "\t
", + "" + ], new PHPMode()); + s.setUseSoftTabs(false); + + beautify.beautify(s); + assert.equal(s.getValue(), "
\n" + + "\t
\n" + + "
"); + + next(); + }, + + "test beautify css": function(next) { + var s = new EditSession([ + "" + ], new PHPMode()); + s.setUseSoftTabs(false); + + beautify.beautify(s); + assert.equal(s.getValue(), ""); + + next(); + }, + + "test beautify comments": function(next) { + var s = new EditSession([ + "\n", + "" + ], new PHPMode()); + s.setUseSoftTabs(false); + + beautify.beautify(s); + assert.equal(s.getValue(), "\n" + + ""); + + next(); + }, + + "test beautify js array of objects": function(next) { + var s = new EditSession([ + "" + ], new PHPMode()); + s.setUseSoftTabs(false); + + beautify.beautify(s); + assert.equal(s.getValue(), ""); + next(); } }; diff --git a/plugins/node_modules/ace/lib/ace/ext/emmet.js b/plugins/node_modules/ace/lib/ace/ext/emmet.js index e2cc28ae..2587d44e 100644 --- a/plugins/node_modules/ace/lib/ace/ext/emmet.js +++ b/plugins/node_modules/ace/lib/ace/ext/emmet.js @@ -414,7 +414,7 @@ exports.isAvailable = function(editor, command) { // TODO refactor mode delegates to make this simpler try { editorProxy.setupContext(editor); - if (/^(js|php)/.test(editorProxy.getSyntax())) + if (/js|php/.test(editorProxy.getSyntax())) isSupported = false; } catch(e) {} } diff --git a/plugins/node_modules/ace/lib/ace/ext/modelist.js b/plugins/node_modules/ace/lib/ace/ext/modelist.js index 942ce142..08deec8f 100644 --- a/plugins/node_modules/ace/lib/ace/ext/modelist.js +++ b/plugins/node_modules/ace/lib/ace/ext/modelist.js @@ -49,6 +49,7 @@ var supportedModes = { ADA: ["ada|adb"], Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"], AsciiDoc: ["asciidoc|adoc"], + ASL: ["dsl|asl"], Assembly_x86:["asm|a"], AutoHotKey: ["ahk"], BatchFile: ["bat|cmd"], diff --git a/plugins/node_modules/ace/lib/ace/ext/options.js b/plugins/node_modules/ace/lib/ace/ext/options.js index 9014aeb5..48359643 100644 --- a/plugins/node_modules/ace/lib/ace/ext/options.js +++ b/plugins/node_modules/ace/lib/ace/ext/options.js @@ -129,6 +129,15 @@ var optionGroups = { "Show Gutter": { path: "showGutter" }, + "Show Line Numbers": { + path: "showLineNumbers" + }, + "Relative Line Numbers": { + path: "relativeLineNumbers" + }, + "Fixed Gutter Width": { + path: "fixedWidthGutter" + }, "Show Print Margin": [{ path: "showPrintMargin" }, { diff --git a/plugins/node_modules/ace/lib/ace/ext/static_highlight.js b/plugins/node_modules/ace/lib/ace/ext/static_highlight.js index fc1928fc..e45e83cc 100644 --- a/plugins/node_modules/ace/lib/ace/ext/static_highlight.js +++ b/plugins/node_modules/ace/lib/ace/ext/static_highlight.js @@ -37,8 +37,77 @@ var baseStyles = require("../requirejs/text!./static.css"); var config = require("../config"); var dom = require("../lib/dom"); +var simpleDom = { + createTextNode: function(textContent) { + return textContent; + }, + createElement: function(type) { + var element = { + type: type, + style: {}, + childNodes: [], + appendChild: function(child) { + element.childNodes.push(child); + }, + toString: function() { + var internal = { + type: 1, + style: 1, + className: 1, + textContent: 1, + childNodes: 1, + appendChild: 1, + toString: 1 + }; + var stringBuilder = []; + + if (element.type != "fragment") { + stringBuilder.push("<", element.type); + if (element.className) + stringBuilder.push(" class='", element.className, "'"); + var styleStr = []; + for (var key in element.style) { + styleStr.push(key, ":", element.style[key]); + } + if (styleStr.length) + stringBuilder.push(" style='", styleStr.join(""), "'"); + for (var key in element) { + if (!internal[key]) { + stringBuilder.push(" ", key, "='", element[key], "'"); + } + } + stringBuilder.push(">"); + } + + if (element.textContent) { + stringBuilder.push(element.textContent); + } else { + for (var i=0; i"); + } + + return stringBuilder.join(""); + } + }; + return element; + }, + createFragment: function() { + return this.createElement("fragment"); + } +}; + var SimpleTextLayer = function() { this.config = {}; + this.dom = simpleDom; }; SimpleTextLayer.prototype = TextLayer.prototype; @@ -64,7 +133,7 @@ var highlight = function(el, opts, callback) { } } } else { - data = dom.getInnerText(el); + data = el.textContent; if (opts.trim) data = data.trim(); } @@ -157,31 +226,38 @@ highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) { textLayer.setSession(session); session.setValue(input); - - var stringBuilder = []; var length = session.getLength(); + + var outerEl = simpleDom.createElement("div"); + outerEl.className = theme.cssClass; + + var innerEl = simpleDom.createElement("div"); + innerEl.className = "ace_static_highlight" + (disableGutter ? "" : " ace_show_gutter"); + innerEl.style["counter-reset"] = "ace_line " + (lineStart - 1); + outerEl.appendChild(innerEl); - for(var ix = 0; ix < length; ix++) { - stringBuilder.push("
"); - if (!disableGutter) - stringBuilder.push("" + /*(ix + lineStart) + */ ""); - textLayer.$renderLine(stringBuilder, ix, true, false); - stringBuilder.push("\n
"); + for (var ix = 0; ix < length; ix++) { + var lineEl = simpleDom.createElement("div"); + lineEl.className = "ace_line"; + + if (!disableGutter) { + var gutterEl = simpleDom.createElement("span"); + gutterEl.className ="ace_gutter ace_gutter-cell"; + gutterEl.unselectable ="on"; + gutterEl.textContent = ""; /*(ix + lineStart) + */ + lineEl.appendChild(gutterEl); + } + textLayer.$renderLine(lineEl, ix, false); + innerEl.appendChild(lineEl); } - // let's prepare the whole html - var html = "
" + - "
" + - stringBuilder.join("") + - "
" + - "
"; - + //console.log(JSON.stringify(outerEl, null, 2)); + //console.log(outerEl.toString()); textLayer.destroy(); return { css: baseStyles + theme.cssText, - html: html, + html: outerEl.toString(), session: session }; }; diff --git a/plugins/node_modules/ace/lib/ace/ext/static_highlight_test.js b/plugins/node_modules/ace/lib/ace/ext/static_highlight_test.js index b091bad7..bbefef41 100644 --- a/plugins/node_modules/ace/lib/ace/ext/static_highlight_test.js +++ b/plugins/node_modules/ace/lib/ace/ext/static_highlight_test.js @@ -35,12 +35,12 @@ module.exports = { var result = highlighter.render(snippet, mode, theme); assert.equal(result.html, "
" - + "
/** this is a function\n
" - + "
*\n
" - + "
*/\n
" - + "
function hello (a, b, c) {\n
" - + "
console.log(a * b + c + 'sup$');\n
" - + "
}\n
" + + "
/** this is a function
" + + "
*
" + + "
*/
" + + "
function hello (a, b, c) {
" + + "
console.log(a * b + c + 'sup$');
" + + "
}
" + "
"); assert.ok(!!result.css); next(); diff --git a/plugins/node_modules/ace/lib/ace/ext/textarea.js b/plugins/node_modules/ace/lib/ace/ext/textarea.js index cced80dc..f74d5be5 100644 --- a/plugins/node_modules/ace/lib/ace/ext/textarea.js +++ b/plugins/node_modules/ace/lib/ace/ext/textarea.js @@ -156,6 +156,7 @@ function setupContainer(element, getValue) { } exports.transformTextarea = function(element, options) { + var isFocused = element.autofocus || document.activeElement == element; var session; var container = setupContainer(element, function() { return session.getValue(); @@ -218,7 +219,8 @@ exports.transformTextarea = function(element, options) { session = editor.getSession(); session.setValue(element.value || element.innerHTML); - editor.focus(); + if (isFocused) + editor.focus(); // Add the settingPanel opener to the editor's div. container.appendChild(settingOpener); diff --git a/plugins/node_modules/ace/lib/ace/ext/themelist.js b/plugins/node_modules/ace/lib/ace/ext/themelist.js index aa8b79d4..beacc552 100644 --- a/plugins/node_modules/ace/lib/ace/ext/themelist.js +++ b/plugins/node_modules/ace/lib/ace/ext/themelist.js @@ -41,7 +41,6 @@ define(function(require, exports, module) { "use strict"; -require("ace/lib/fixoldbrowsers"); var themeData = [ ["Chrome" ], diff --git a/plugins/node_modules/ace/lib/ace/keyboard/vim.js b/plugins/node_modules/ace/lib/ace/keyboard/vim.js index c0a474c8..de9f1601 100644 --- a/plugins/node_modules/ace/lib/ace/keyboard/vim.js +++ b/plugins/node_modules/ace/lib/ace/keyboard/vim.js @@ -715,16 +715,18 @@ dom.importCssString(".normal-mode .ace_cursor{\ .ace_dialog {\ position: absolute;\ left: 0; right: 0;\ - background: inherit;\ + background: white;\ z-index: 15;\ padding: .1em .8em;\ overflow: hidden;\ - color: inherit;\ + color: #333;\ }\ .ace_dialog-top {\ + border-bottom: 1px solid #eee;\ top: 0;\ }\ .ace_dialog-bottom {\ + border-top: 1px solid #eee;\ bottom: 0;\ }\ .ace_dialog input {\ @@ -4456,8 +4458,10 @@ dom.importCssString(".normal-mode .ace_cursor{\ cm.openDialog(template, onClose, { bottom: true, value: options.value, onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp, selectValueOnOpen: false, onClose: function() { - cm.state.vim.status = ""; - cm.ace.renderer.$loop.schedule(cm.ace.renderer.CHANGE_CURSOR); + if (cm.state.vim) { + cm.state.vim.status = ""; + cm.ace.renderer.$loop.schedule(cm.ace.renderer.CHANGE_CURSOR); + } }}); } else { @@ -6108,7 +6112,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ var getVim = Vim.maybeInitVimState_; exports.handler = { $id: "ace/keyboard/vim", - drawCursor: function(style, pixelPos, config, sel, session) { + drawCursor: function(element, pixelPos, config, sel, session) { var vim = this.state.vim || {}; var w = config.characterWidth; var h = config.lineHeight; @@ -6125,10 +6129,9 @@ dom.importCssString(".normal-mode .ace_cursor{\ h = h / 2; top += h; } - style.left = left + "px"; - style.top = top + "px"; - style.width = w + "px"; - style.height = h + "px"; + dom.translate(element, left, top); + dom.setStyle(element.style, "width", w + "px"); + dom.setStyle(element.style, "height", h + "px"); }, handleKeyboard: function(data, hashId, key, keyCode, e) { var editor = data.editor; @@ -6301,25 +6304,6 @@ dom.importCssString(".normal-mode .ace_cursor{\ } } }; - var renderVirtualNumbers = { - getText: function(session, row) { - return (Math.abs(session.selection.lead.row - row) || (row + 1 + (row < 9? "\xb7" : "" ))) + ""; - }, - getWidth: function(session, lastLineNumber, config) { - return session.getLength().toString().length * config.characterWidth; - }, - update: function(e, editor) { - editor.renderer.$loop.schedule(editor.renderer.CHANGE_GUTTER); - }, - attach: function(editor) { - editor.renderer.$gutterLayer.$renderer = this; - editor.on("changeSelection", this.update); - }, - detach: function(editor) { - editor.renderer.$gutterLayer.$renderer = null; - editor.off("changeSelection", this.update); - } - }; Vim.defineOption({ name: "wrap", set: function(value, cm) { diff --git a/plugins/node_modules/ace/lib/ace/keyboard/vim_test.js b/plugins/node_modules/ace/lib/ace/keyboard/vim_test.js index 3a9ead85..c64e17f8 100644 --- a/plugins/node_modules/ace/lib/ace/keyboard/vim_test.js +++ b/plugins/node_modules/ace/lib/ace/keyboard/vim_test.js @@ -1,6 +1,7 @@ if (typeof process !== "undefined") { require("amd-loader"); + require("../test/mockdom"); } define(function(require, exports, module) { diff --git a/plugins/node_modules/ace/lib/ace/layer/cursor.js b/plugins/node_modules/ace/lib/ace/layer/cursor.js index 14edaebb..ccc6d3f7 100644 --- a/plugins/node_modules/ace/lib/ace/layer/cursor.js +++ b/plugins/node_modules/ace/lib/ace/layer/cursor.js @@ -32,16 +32,12 @@ define(function(require, exports, module) { "use strict"; var dom = require("../lib/dom"); -var isIE8; var Cursor = function(parentEl) { this.element = dom.createElement("div"); this.element.className = "ace_layer ace_cursor-layer"; parentEl.appendChild(this.element); - if (isIE8 === undefined) - isIE8 = !("opacity" in this.element.style); - this.isVisible = false; this.isBlinking = true; this.blinkInterval = 1000; @@ -50,24 +46,30 @@ var Cursor = function(parentEl) { this.cursors = []; this.cursor = this.addCursor(); dom.addCssClass(this.element, "ace_hidden-cursors"); - this.$updateCursors = (isIE8 - ? this.$updateVisibility - : this.$updateOpacity).bind(this); + this.$updateCursors = this.$updateOpacity.bind(this); }; (function() { - this.$updateVisibility = function(val) { - var cursors = this.cursors; - for (var i = cursors.length; i--; ) - cursors[i].style.visibility = val ? "" : "hidden"; - }; this.$updateOpacity = function(val) { var cursors = this.cursors; for (var i = cursors.length; i--; ) - cursors[i].style.opacity = val ? "" : "0"; + dom.setStyle(cursors[i].style, "opacity", val ? "" : "0"); + }; + + this.$startCssAnimation = function() { + var cursors = this.cursors; + for (var i = cursors.length; i--; ) + cursors[i].style.animationDuration = this.blinkInterval + "ms"; + + setTimeout(function() { + dom.addCssClass(this.element, "ace_animate-blinking"); + }.bind(this)); }; + this.$stopCssAnimation = function() { + dom.removeCssClass(this.element, "ace_animate-blinking"); + }; this.$padding = 0; this.setPadding = function(padding) { @@ -79,25 +81,24 @@ var Cursor = function(parentEl) { }; this.setBlinking = function(blinking) { - if (blinking != this.isBlinking){ + if (blinking != this.isBlinking) { this.isBlinking = blinking; this.restartTimer(); } }; this.setBlinkInterval = function(blinkInterval) { - if (blinkInterval != this.blinkInterval){ + if (blinkInterval != this.blinkInterval) { this.blinkInterval = blinkInterval; this.restartTimer(); } }; this.setSmoothBlinking = function(smoothBlinking) { - if (smoothBlinking != this.smoothBlinking && !isIE8) { + if (smoothBlinking != this.smoothBlinking) { this.smoothBlinking = smoothBlinking; dom.setCssClass(this.element, "ace_smooth-blinking", smoothBlinking); this.$updateCursors(true); - this.$updateCursors = (this.$updateOpacity).bind(this); this.restartTimer(); } }; @@ -134,14 +135,18 @@ var Cursor = function(parentEl) { var update = this.$updateCursors; clearInterval(this.intervalId); clearTimeout(this.timeoutId); + this.$stopCssAnimation(); + if (this.smoothBlinking) { dom.removeCssClass(this.element, "ace_smooth-blinking"); } update(true); - if (!this.isBlinking || !this.blinkInterval || !this.isVisible) + if (!this.isBlinking || !this.blinkInterval || !this.isVisible) { + this.$stopCssAnimation(); return; + } if (this.smoothBlinking) { setTimeout(function(){ @@ -149,18 +154,21 @@ var Cursor = function(parentEl) { }.bind(this)); } - var blink = function(){ - this.timeoutId = setTimeout(function() { - update(false); - }, 0.6 * this.blinkInterval); - }.bind(this); - - this.intervalId = setInterval(function() { - update(true); + if (dom.HAS_CSS_ANIMATION) { + this.$startCssAnimation(); + } else { + var blink = function(){ + this.timeoutId = setTimeout(function() { + update(false); + }, 0.6 * this.blinkInterval); + }.bind(this); + + this.intervalId = setInterval(function() { + update(true); + blink(); + }, this.blinkInterval); blink(); - }, this.blinkInterval); - - blink(); + } }; this.getPixelPosition = function(position, onScreen) { @@ -180,6 +188,10 @@ var Cursor = function(parentEl) { return {left : cursorLeft, top : cursorTop}; }; + this.isCursorInView = function(pixelPos, config) { + return pixelPos.top >= 0 && pixelPos.top < config.maxHeight; + }; + this.update = function(config) { this.config = config; @@ -197,15 +209,20 @@ var Cursor = function(parentEl) { continue; } - var style = (this.cursors[cursorIndex++] || this.addCursor()).style; + var element = this.cursors[cursorIndex++] || this.addCursor(); + var style = element.style; if (!this.drawCursor) { - style.left = pixelPos.left + "px"; - style.top = pixelPos.top + "px"; - style.width = config.characterWidth + "px"; - style.height = config.lineHeight + "px"; + if (!this.isCursorInView(pixelPos, config)) { + dom.setStyle(style, "display", "none"); + } else { + dom.setStyle(style, "display", "block"); + dom.translate(element, pixelPos.left, pixelPos.top); + dom.setStyle(style, "width", Math.round(config.characterWidth) + "px"); + dom.setStyle(style, "height", config.lineHeight + "px"); + } } else { - this.drawCursor(style, pixelPos, config, selections[i], this.session); + this.drawCursor(element, pixelPos, config, selections[i], this.session); } } while (this.cursors.length > cursorIndex) diff --git a/plugins/node_modules/ace/lib/ace/layer/font_metrics.js b/plugins/node_modules/ace/lib/ace/layer/font_metrics.js index 5f2a81fd..6864108f 100644 --- a/plugins/node_modules/ace/lib/ace/layer/font_metrics.js +++ b/plugins/node_modules/ace/lib/ace/layer/font_metrics.js @@ -33,6 +33,7 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var dom = require("../lib/dom"); var lang = require("../lib/lang"); +var event = require("../lib/event"); var useragent = require("../lib/useragent"); var EventEmitter = require("../lib/event_emitter").EventEmitter; @@ -117,8 +118,10 @@ var FontMetrics = exports.FontMetrics = function(parentEl) { if (this.$pollSizeChangesTimer || this.$observer) return this.$pollSizeChangesTimer; var self = this; - return this.$pollSizeChangesTimer = setInterval(function() { + + return this.$pollSizeChangesTimer = event.onIdle(function cb() { self.checkForSizeChanges(); + event.onIdle(cb, 500); }, 500); }; diff --git a/plugins/node_modules/ace/lib/ace/layer/gutter.js b/plugins/node_modules/ace/lib/ace/layer/gutter.js index 18fe3358..fc372e10 100644 --- a/plugins/node_modules/ace/lib/ace/layer/gutter.js +++ b/plugins/node_modules/ace/lib/ace/layer/gutter.js @@ -35,6 +35,7 @@ var dom = require("../lib/dom"); var oop = require("../lib/oop"); var lang = require("../lib/lang"); var EventEmitter = require("../lib/event_emitter").EventEmitter; +var Lines = require("./lines").Lines; var Gutter = function(parentEl) { this.element = dom.createElement("div"); @@ -46,8 +47,8 @@ var Gutter = function(parentEl) { this.$annotations = []; this.$updateAnnotations = this.$updateAnnotations.bind(this); - - this.$cells = []; + + this.$lines = new Lines(this.element); }; (function() { @@ -62,13 +63,13 @@ var Gutter = function(parentEl) { session.on("change", this.$updateAnnotations); }; - this.addGutterDecoration = function(row, className){ + this.addGutterDecoration = function(row, className) { if (window.console) console.warn && console.warn("deprecated use session.addGutterDecoration"); this.session.addGutterDecoration(row, className); }; - this.removeGutterDecoration = function(row, className){ + this.removeGutterDecoration = function(row, className) { if (window.console) console.warn && console.warn("deprecated use session.removeGutterDecoration"); this.session.removeGutterDecoration(row, className); @@ -117,23 +118,28 @@ var Gutter = function(parentEl) { }; this.update = function(config) { + this.config = config; + var session = this.session; var firstRow = config.firstRow; var lastRow = Math.min(config.lastRow + config.gutterOffset, // needed to compensate for hor scollbar session.getLength() - 1); + + this.oldLastRow = lastRow; + this.config = config; + + this.$lines.moveContainer(config); + this.$updateCursorRow(); + var fold = session.getNextFoldLine(firstRow); var foldStart = fold ? fold.start.row : Infinity; - var foldWidgets = this.$showFoldWidgets && session.foldWidgets; - var breakpoints = session.$breakpoints; - var decorations = session.$decorations; - var firstLineNumber = session.$firstLineNumber; - var lastLineNumber = 0; - - var gutterRenderer = session.gutterRenderer || this.$renderer; var cell = null; var index = -1; var row = firstRow; + + var cells = Array.prototype.slice.call(this.element.childNodes, 0); + while (true) { if (row > foldStart) { row = fold.end.row + 1; @@ -141,96 +147,243 @@ var Gutter = function(parentEl) { foldStart = fold ? fold.start.row : Infinity; } if (row > lastRow) { - while (this.$cells.length > index + 1) { - cell = this.$cells.pop(); - this.element.removeChild(cell.element); - } + while (this.$lines.getLength() > index + 1) + this.$lines.pop(); + break; } - cell = this.$cells[++index]; + cell = this.$lines.get(++index); if (!cell) { - cell = {element: null, textNode: null, foldWidget: null}; - cell.element = dom.createElement("div"); - cell.textNode = document.createTextNode(''); - cell.element.appendChild(cell.textNode); - this.element.appendChild(cell.element); - this.$cells[index] = cell; + cell = this.$lines.createCell(row, config, this.session, onCreateCell); + this.$lines.push(cell); } - var className = "ace_gutter-cell "; - if (breakpoints[row]) - className += breakpoints[row]; - if (decorations[row]) - className += decorations[row]; - if (this.$annotations[row]) - className += this.$annotations[row].className; - if (cell.element.className != className) - cell.element.className = className; - - var height = session.getRowLength(row) * config.lineHeight + "px"; - if (height != cell.element.style.height) - cell.element.style.height = height; - - if (foldWidgets) { - var c = foldWidgets[row]; - // check if cached value is invalidated and we need to recompute - if (c == null) - c = foldWidgets[row] = session.getFoldWidget(row); - } - - if (c) { - if (!cell.foldWidget) { - cell.foldWidget = dom.createElement("span"); - cell.element.appendChild(cell.foldWidget); - } - var className = "ace_fold-widget ace_" + c; - if (c == "start" && row == foldStart && row < fold.end.row) - className += " ace_closed"; - else - className += " ace_open"; - if (cell.foldWidget.className != className) - cell.foldWidget.className = className; - - var height = config.lineHeight + "px"; - if (cell.foldWidget.style.height != height) - cell.foldWidget.style.height = height; - } else { - if (cell.foldWidget) { - cell.element.removeChild(cell.foldWidget); - cell.foldWidget = null; - } - } - - var text = lastLineNumber = gutterRenderer - ? gutterRenderer.getText(session, row) - : row + firstLineNumber; - if (text !== cell.textNode.data) - cell.textNode.data = text; - + this.$renderCell(cell, config, fold, row); row++; } + + this.$updateGutterWidth(config); + }; - this.element.style.height = config.minHeight + "px"; - + this.$updateGutterWidth = function(config) { + var session = this.session; + + var gutterRenderer = session.gutterRenderer || this.$renderer; + + var firstLineNumber = session.$firstLineNumber; + var lastLineText = this.$lines.last() ? this.$lines.last().text : ""; + if (this.$fixedWidth || session.$useWrapMode) - lastLineNumber = session.getLength() + firstLineNumber; + lastLineText = session.getLength() + firstLineNumber; var gutterWidth = gutterRenderer - ? gutterRenderer.getWidth(session, lastLineNumber, config) - : lastLineNumber.toString().length * config.characterWidth; + ? gutterRenderer.getWidth(session, lastLineText, config) + : lastLineText.toString().length * config.characterWidth; var padding = this.$padding || this.$computePadding(); gutterWidth += padding.left + padding.right; if (gutterWidth !== this.gutterWidth && !isNaN(gutterWidth)) { this.gutterWidth = gutterWidth; + this.element.parentNode.style.width = this.element.style.width = Math.ceil(this.gutterWidth) + "px"; - this._emit("changeGutterWidth", gutterWidth); + this._signal("changeGutterWidth", gutterWidth); } }; + + this.$updateCursorRow = function() { + if (!this.$highlightGutterLine) + return; + + var position = this.session.selection.getCursor(); + if (this.$cursorRow === position.row) + return; + + this.$cursorRow = position.row; + }; + + this.updateLineHighlight = function() { + if (!this.$highlightGutterLine) + return; + var row = this.session.selection.cursor.row; + this.$cursorRow = row; + + if (this.$cursorCell && this.$cursorCell.row == row) + return; + if (this.$cursorCell) + this.$cursorCell.element.className = this.$cursorCell.element.className.replace("ace_gutter-active-line ", ""); + var cells = this.$lines.cells; + this.$cursorCell = null; + for (var i = 0; i < cells.length; i++) { + var cell = cells[i]; + if (cell.row >= this.$cursorRow) { + if (cell.row > this.$cursorRow) { + var fold = this.session.getFoldLine(this.$cursorRow); + if (i > 0 && fold && fold.start.row == cells[i - 1].row) + cell = cells[i - 1]; + else + break; + } + cell.element.className = "ace_gutter-active-line " + cell.element.className; + this.$cursorCell = cell; + break; + } + } + }; + + this.scrollLines = function(config) { + var oldConfig = this.config; + this.config = config; + + this.$updateCursorRow(); + if (this.$lines.pageChanged(oldConfig, config)) + return this.update(config); + + this.$lines.moveContainer(config); + + var lastRow = Math.min(config.lastRow + config.gutterOffset, // needed to compensate for hor scollbar + this.session.getLength() - 1); + var oldLastRow = this.oldLastRow; + this.oldLastRow = lastRow; + + if (!oldConfig || oldLastRow < config.firstRow) + return this.update(config); + + if (lastRow < oldConfig.firstRow) + return this.update(config); + + if (oldConfig.firstRow < config.firstRow) + for (var row=this.session.getFoldedRowCount(oldConfig.firstRow, config.firstRow - 1); row>0; row--) + this.$lines.shift(); + + if (oldLastRow > lastRow) + for (var row=this.session.getFoldedRowCount(lastRow + 1, oldLastRow); row>0; row--) + this.$lines.pop(); + + if (config.firstRow < oldConfig.firstRow) { + this.$lines.unshift(this.$renderLines(config, config.firstRow, oldConfig.firstRow - 1)); + } + + if (lastRow > oldLastRow) { + this.$lines.push(this.$renderLines(config, oldLastRow + 1, lastRow)); + } + + this.updateLineHighlight(); + + this.$updateGutterWidth(config); + }; + + this.$renderLines = function(config, firstRow, lastRow) { + var fragment = []; + var row = firstRow; + var foldLine = this.session.getNextFoldLine(row); + var foldStart = foldLine ? foldLine.start.row : Infinity; + + while (true) { + if (row > foldStart) { + row = foldLine.end.row+1; + foldLine = this.session.getNextFoldLine(row, foldLine); + foldStart = foldLine ? foldLine.start.row : Infinity; + } + if (row > lastRow) + break; + + var cell = this.$lines.createCell(row, config, this.session, onCreateCell); + this.$renderCell(cell, config, foldLine, row); + fragment.push(cell); + + row++; + } + return fragment; + }; + + this.$renderCell = function(cell, config, fold, row) { + var element = cell.element; + + var session = this.session; + + var textNode = element.childNodes[0]; + var foldWidget = element.childNodes[1]; + + var firstLineNumber = session.$firstLineNumber; + + var session = this.session; + var breakpoints = session.$breakpoints; + var decorations = session.$decorations; + var gutterRenderer = session.gutterRenderer || this.$renderer; + var foldWidgets = this.$showFoldWidgets && session.foldWidgets; + var foldStart = fold ? fold.start.row : Number.MAX_VALUE; + + var className = "ace_gutter-cell "; + if (this.$highlightGutterLine) { + if (row == this.$cursorRow || (fold && row < this.$cursorRow && row >= foldStart && this.$cursorRow <= fold.end.row)) { + className += "ace_gutter-active-line "; + if (this.$cursorCell != cell) { + if (this.$cursorCell) + this.$cursorCell.element.className = this.$cursorCell.element.className.replace("ace_gutter-active-line ", ""); + this.$cursorCell = cell; + } + } + } + + if (breakpoints[row]) + className += breakpoints[row]; + if (decorations[row]) + className += decorations[row]; + if (this.$annotations[row]) + className += this.$annotations[row].className; + if (element.className != className) + element.className = className; + + if (foldWidgets) { + var c = foldWidgets[row]; + // check if cached value is invalidated and we need to recompute + if (c == null) + c = foldWidgets[row] = session.getFoldWidget(row); + } + + if (c) { + var className = "ace_fold-widget ace_" + c; + if (c == "start" && row == foldStart && row < fold.end.row) + className += " ace_closed"; + else + className += " ace_open"; + if (foldWidget.className != className) + foldWidget.className = className; + + var foldHeight = config.lineHeight + "px"; + dom.setStyle(foldWidget.style, "height", foldHeight); + dom.setStyle(foldWidget.style, "display", "inline-block"); + } else { + if (foldWidget) { + dom.setStyle(foldWidget.style, "display", "none"); + } + } + + var text = (gutterRenderer + ? gutterRenderer.getText(session, row) + : row + firstLineNumber).toString(); + + if (text !== textNode.data) { + textNode.data = text; + } + + dom.setStyle(cell.element.style, "height", this.$lines.computeLineHeight(row, config, session) + "px"); + dom.setStyle(cell.element.style, "top", this.$lines.computeLineTop(row, config, session) + "px"); + + cell.text = text; + cell.row = row; + return cell; + }; this.$fixedWidth = false; + this.$highlightGutterLine = true; + this.$renderer = ""; + this.setHighlightGutterLine = function(highlightGutterLine) { + this.$highlightGutterLine = highlightGutterLine; + }; + this.$showLineNumbers = true; this.$renderer = ""; this.setShowLineNumbers = function(show) { @@ -280,6 +433,16 @@ var Gutter = function(parentEl) { }).call(Gutter.prototype); +function onCreateCell(element) { + var textNode = document.createTextNode(''); + element.appendChild(textNode); + + var foldWidget = dom.createElement("span"); + element.appendChild(foldWidget); + + return element; +} + exports.Gutter = Gutter; }); diff --git a/plugins/node_modules/ace/lib/ace/layer/lines.js b/plugins/node_modules/ace/lib/ace/layer/lines.js new file mode 100644 index 00000000..b0b31eef --- /dev/null +++ b/plugins/node_modules/ace/lib/ace/layer/lines.js @@ -0,0 +1,154 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var dom = require("../lib/dom"); + +var Lines = function(element, canvasHeight) { + this.element = element; + this.canvasHeight = canvasHeight || 500000; + this.element.style.height = (this.canvasHeight * 2) + "px"; + + this.cells = []; + this.cellCache = []; +}; + +(function() { + + this.moveContainer = function(config) { + dom.translate(this.element, 0, -((config.firstRowScreen * config.lineHeight) % this.canvasHeight)); + }; + + this.pageChanged = function(oldConfig, newConfig) { + return ( + Math.floor((oldConfig.firstRowScreen * oldConfig.lineHeight) / this.canvasHeight) !== + Math.floor((newConfig.firstRowScreen * newConfig.lineHeight) / this.canvasHeight) + ); + }; + + this.computeLineTop = function(row, config, session) { + var screenTop = config.firstRowScreen * config.lineHeight; + var screenPage = Math.floor(screenTop / this.canvasHeight); + var lineTop = session.documentToScreenRow(row, 0) * config.lineHeight; + return lineTop - (screenPage * this.canvasHeight); + }; + + this.computeLineHeight = function(row, config, session) { + return config.lineHeight * session.getRowLength(row); + }; + + this.getLength = function() { + return this.cells.length; + }; + + this.get = function(index) { + return this.cells[index]; + }; + + this.shift = function() { + this.$cacheCell(this.cells.shift()); + }; + + this.pop = function() { + this.$cacheCell(this.cells.pop()); + }; + + this.push = function(cell) { + if (cell.length) { + this.cells.push.apply(this.cells, cell); + var fragment = dom.createFragment(this.element); + for (var i=0; i next, row == end); - - if (this.session.$bidiHandler.isBidiRow(row)) { - this.drawBidiSingleLineMarker(stringBuilder, lineRange, clazzModified, - layerConfig, row == end ? 0 : 1, extraStyle); - } else { - this.drawSingleLineMarker(stringBuilder, lineRange, clazzModified, - layerConfig, row == end ? 0 : 1, extraStyle); - } + this.drawSingleLineMarker(stringBuilder, lineRange, + clazz + (row == start ? " ace_start" : "") + " ace_br" + + getBorderClass(row == start || row == start + 1 && range.start.column, prev < curr, curr > next, row == end), + layerConfig, row == end ? 0 : 1, extraStyle); } }; @@ -142,43 +145,28 @@ var Marker = function(parentEl) { this.drawMultiLineMarker = function(stringBuilder, range, clazz, config, extraStyle) { // from selection start to the end of the line var padding = this.$padding; - var height, top, left; + var height = config.lineHeight; + var top = this.$getTop(range.start.row, config); + var left = padding + range.start.column * config.characterWidth; extraStyle = extraStyle || ""; - if (this.session.$bidiHandler.isBidiRow(range.start.row)) { - var range1 = range.clone(); - range1.end.row = range1.start.row; - range1.end.column = this.session.getLine(range1.start.row).length; - this.drawBidiSingleLineMarker(stringBuilder, range1, clazz + " ace_br1 ace_start", config, null, extraStyle); - } else { - height = config.lineHeight; - top = this.$getTop(range.start.row, config); - left = padding + range.start.column * config.characterWidth; - stringBuilder.push( - "
" - ); - } + + this.elt( + clazz + " ace_br1 ace_start", + "height:"+ height+ "px;"+ "right:0;"+ "top:"+top+ "px;left:"+ left+ "px;" + (extraStyle || "") + ); + // from start of the last line to the selection end - if (this.session.$bidiHandler.isBidiRow(range.end.row)) { - var range1 = range.clone(); - range1.start.row = range1.end.row; - range1.start.column = 0; - this.drawBidiSingleLineMarker(stringBuilder, range1, clazz + " ace_br12", config, null, extraStyle); - } else { - var width = range.end.column * config.characterWidth; - height = config.lineHeight; - top = this.$getTop(range.end.row, config); - stringBuilder.push( - "
" - ); - } + top = this.$getTop(range.end.row, config); + var width = range.end.column * config.characterWidth; + + this.elt( + clazz + " ace_br12", + "height:"+ height+ "px;"+ + "width:"+ width+ "px;"+ + "top:"+ top+ "px;"+ + "left:"+ padding+ "px;"+ (extraStyle || "") + ); + // all the complete lines height = (range.end.row - range.start.row - 1) * config.lineHeight; if (height <= 0) @@ -187,12 +175,12 @@ var Marker = function(parentEl) { var radiusClass = (range.start.column ? 1 : 0) | (range.end.column ? 0 : 8); - stringBuilder.push( - "
" + this.elt( + clazz + (radiusClass ? " ace_br" + radiusClass : ""), + "height:"+ height+ "px;"+ + "right:0;"+ + "top:"+ top+ "px;"+ + "left:"+ padding+ "px;"+ (extraStyle || "") ); }; @@ -204,42 +192,26 @@ var Marker = function(parentEl) { var top = this.$getTop(range.start.row, config); var left = this.$padding + range.start.column * config.characterWidth; - stringBuilder.push( - "
" + this.elt( + clazz, + "height:"+ height+ "px;"+ + "width:"+ width+ "px;"+ + "top:"+ top+ "px;"+ + "left:"+ left+ "px;"+ (extraStyle || "") ); }; - // Draws Bidi marker which covers part or whole width of a single screen line - this.drawBidiSingleLineMarker = function(stringBuilder, range, clazz, config, extraLength, extraStyle) { - var height = config.lineHeight, top = this.$getTop(range.start.row, config), padding = this.$padding; - var selections = this.session.$bidiHandler.getSelections(range.start.column, range.end.column); - - selections.forEach(function(selection) { - stringBuilder.push( - "
" - ); - }); - }; - this.drawFullLineMarker = function(stringBuilder, range, clazz, config, extraStyle) { var top = this.$getTop(range.start.row, config); var height = config.lineHeight; if (range.start.row != range.end.row) height += this.$getTop(range.end.row, config) - top; - stringBuilder.push( - "
" + this.elt( + clazz, + "height:"+ height+ "px;"+ + "top:"+ top+ "px;"+ + "left:0;right:0;"+ (extraStyle || "") ); }; @@ -247,11 +219,11 @@ var Marker = function(parentEl) { var top = this.$getTop(range.start.row, config); var height = config.lineHeight; - stringBuilder.push( - "
" + this.elt( + clazz, + "height:"+ height+ "px;"+ + "top:"+ top+ "px;"+ + "left:0;right:0;"+ (extraStyle || "") ); }; @@ -259,4 +231,4 @@ var Marker = function(parentEl) { exports.Marker = Marker; -}); +}); \ No newline at end of file diff --git a/plugins/node_modules/ace/lib/ace/layer/text.js b/plugins/node_modules/ace/lib/ace/layer/text.js index 675a58ef..a902fb53 100644 --- a/plugins/node_modules/ace/lib/ace/layer/text.js +++ b/plugins/node_modules/ace/lib/ace/layer/text.js @@ -34,14 +34,16 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var dom = require("../lib/dom"); var lang = require("../lib/lang"); -var useragent = require("../lib/useragent"); +var Lines = require("./lines").Lines; var EventEmitter = require("../lib/event_emitter").EventEmitter; var Text = function(parentEl) { - this.element = dom.createElement("div"); + this.dom = dom; + this.element = this.dom.createElement("div"); this.element.className = "ace_layer ace_text-layer"; parentEl.appendChild(this.element); this.$updateEolChar = this.$updateEolChar.bind(this); + this.$lines = new Lines(this.element); }; (function() { @@ -69,7 +71,7 @@ var Text = function(parentEl) { this.setPadding = function(padding) { this.$padding = padding; - this.element.style.padding = "0 " + padding + "px"; + this.element.style.margin = "0 " + padding + "px"; }; this.getLineHeight = function() { @@ -128,11 +130,12 @@ var Text = function(parentEl) { var tabStr = this.$tabStrings = [0]; for (var i = 1; i < tabSize + 1; i++) { if (this.showInvisibles) { - tabStr.push("" - + lang.stringRepeat(this.TAB_CHAR, i) - + ""); + var span = this.dom.createElement("span"); + span.className = "ace_invisible ace_invisible_tab"; + span.textContent = lang.stringRepeat(this.TAB_CHAR, i); + tabStr.push(span); } else { - tabStr.push(lang.stringRepeat(" ", i)); + tabStr.push(this.dom.createTextNode(lang.stringRepeat(" ", i), this.element)); } } if (this.displayIndentGuides) { @@ -146,13 +149,20 @@ var Text = function(parentEl) { tabClass = " ace_invisible_tab"; var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize); var tabContent = lang.stringRepeat(this.TAB_CHAR, this.tabSize); - } else{ + } else { var spaceContent = lang.stringRepeat(" ", this.tabSize); var tabContent = spaceContent; } - this.$tabStrings[" "] = "" + spaceContent + ""; - this.$tabStrings["\t"] = "" + tabContent + ""; + var span = this.dom.createElement("span"); + span.className = className + spaceClass; + span.textContent = spaceContent; + this.$tabStrings[" "] = span; + + var span = this.dom.createElement("span"); + span.className = className + tabClass; + span.textContent = tabContent; + this.$tabStrings["\t"] = span; } }; @@ -161,8 +171,9 @@ var Text = function(parentEl) { // the line to updated wrapped in the meantime. if (this.config.lastRow != config.lastRow || this.config.firstRow != config.firstRow) { - this.scrollLines(config); + return this.update(config); } + this.config = config; var first = Math.max(firstRow, config.firstRow); @@ -199,12 +210,11 @@ var Text = function(parentEl) { var lineElement = lineElements[lineElementsIdx++]; if (lineElement) { - var html = []; + this.dom.removeChildren(lineElement); this.$renderLine( - html, row, !this.$useLineGroups(), row == foldStart ? foldLine : false + lineElement, row, row == foldStart ? foldLine : false ); - lineElement.style.height = config.lineHeight * this.session.getRowLength(row) + "px"; - lineElement.innerHTML = html.join(""); + lineElement.style.height = (config.lineHeight * this.session.getRowLength(row)) + "px"; } row++; } @@ -214,37 +224,45 @@ var Text = function(parentEl) { var oldConfig = this.config; this.config = config; + if (this.$lines.pageChanged(oldConfig, config)) + return this.update(config); + + this.$lines.moveContainer(config); + + var lastRow = config.lastRow; + var oldLastRow = oldConfig ? oldConfig.lastRow : -1; + + if (!oldConfig || oldLastRow < config.firstRow) + return this.update(config); + + if (lastRow < oldConfig.firstRow) + return this.update(config); + if (!oldConfig || oldConfig.lastRow < config.firstRow) return this.update(config); if (config.lastRow < oldConfig.firstRow) return this.update(config); - var el = this.element; if (oldConfig.firstRow < config.firstRow) for (var row=this.session.getFoldedRowCount(oldConfig.firstRow, config.firstRow - 1); row>0; row--) - el.removeChild(el.firstChild); + this.$lines.shift(); if (oldConfig.lastRow > config.lastRow) for (var row=this.session.getFoldedRowCount(config.lastRow + 1, oldConfig.lastRow); row>0; row--) - el.removeChild(el.lastChild); + this.$lines.pop(); if (config.firstRow < oldConfig.firstRow) { - var fragment = this.$renderLinesFragment(config, config.firstRow, oldConfig.firstRow - 1); - if (el.firstChild) - el.insertBefore(fragment, el.firstChild); - else - el.appendChild(fragment); + this.$lines.unshift(this.$renderLinesFragment(config, config.firstRow, oldConfig.firstRow - 1)); } if (config.lastRow > oldConfig.lastRow) { - var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow); - el.appendChild(fragment); + this.$lines.push(this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow)); } }; this.$renderLinesFragment = function(config, firstRow, lastRow) { - var fragment = this.element.ownerDocument.createDocumentFragment(); + var fragment = []; var row = firstRow; var foldLine = this.session.getNextFoldLine(row); var foldStart = foldLine ? foldLine.start.row : Infinity; @@ -258,23 +276,23 @@ var Text = function(parentEl) { if (row > lastRow) break; - var container = dom.createElement("div"); + var line = this.$lines.createCell(row, config, this.session); + + var lineEl = line.element; + this.dom.removeChildren(lineEl); + dom.setStyle(lineEl.style, "height", this.$lines.computeLineHeight(row, config, this.session) + "px"); + dom.setStyle(lineEl.style, "top", this.$lines.computeLineTop(row, config, this.session) + "px"); - var html = []; // Get the tokens per line as there might be some lines in between // beeing folded. - this.$renderLine(html, row, false, row == foldStart ? foldLine : false); + this.$renderLine(lineEl, row, row == foldStart ? foldLine : false); - container.innerHTML = html.join(""); if (this.$useLineGroups()) { - container.className = 'ace_line_group'; - fragment.appendChild(container); - container.style.height = config.lineHeight * this.session.getRowLength(row) + "px"; - + lineEl.className = "ace_line_group"; } else { - while(container.firstChild) - fragment.appendChild(container.firstChild); + lineEl.className = "ace_line"; } + fragment.push(line); row++; } @@ -282,35 +300,18 @@ var Text = function(parentEl) { }; this.update = function(config) { + this.$lines.moveContainer(config); + this.config = config; - var html = []; - var firstRow = config.firstRow, lastRow = config.lastRow; + var firstRow = config.firstRow; + var lastRow = config.lastRow; - var row = firstRow; - var foldLine = this.session.getNextFoldLine(row); - var foldStart = foldLine ? foldLine.start.row : Infinity; - - while (true) { - if (row > foldStart) { - row = foldLine.end.row+1; - foldLine = this.session.getNextFoldLine(row, foldLine); - foldStart = foldLine ? foldLine.start.row :Infinity; - } - if (row > lastRow) - break; - - if (this.$useLineGroups()) - html.push("
"); - - this.$renderLine(html, row, false, row == foldStart ? foldLine : false); - - if (this.$useLineGroups()) - html.push("
"); // end the line group - - row++; - } - this.element.innerHTML = html.join(""); + var lines = this.$lines; + while (lines.getLength()) + lines.pop(); + + lines.push(this.$renderLinesFragment(config, firstRow, lastRow)); }; this.$textToken = { @@ -319,110 +320,154 @@ var Text = function(parentEl) { "lparen": true }; - this.$renderToken = function(stringBuilder, screenColumn, token, value) { + this.$renderToken = function(parent, screenColumn, token, value) { var self = this; - var replaceReg = /\t|&|<|>|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF\uFFF9-\uFFFC])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g; - var replaceFunc = function(c, a, b, tabIdx, idx4) { - if (a) { - return self.showInvisibles - ? "" + lang.stringRepeat(self.SPACE_CHAR, c.length) + "" - : c; - } else if (c == "&") { - return "&"; - } else if (c == "<") { - return "<"; - } else if (c == ">") { - // normally escaping this is not needed, but xml documents throw error when setting innerHTML to ]]> - return ">"; - } else if (c == "\t") { - var tabSize = self.session.getScreenTabSize(screenColumn + tabIdx); + var re = /(\t)|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\uFEFF\uFFF9-\uFFFC]+)|(\u3000)|([\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3001-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]|[\uD800-\uDBFF][\uDC00-\uDFFF])/g; + + var valueFragment = this.dom.createFragment(this.element); + + var m; + var i = 0; + while (m = re.exec(value)) { + var tab = m[1]; + var simpleSpace = m[2]; + var controlCharacter = m[3]; + var cjkSpace = m[4]; + var cjk = m[5]; + + if (!self.showInvisibles && simpleSpace) + continue; + + var before = i != m.index ? value.slice(i, m.index) : ""; + + i = m.index + m[0].length; + + if (before) { + valueFragment.appendChild(this.dom.createTextNode(before, this.element)); + } + + if (tab) { + var tabSize = self.session.getScreenTabSize(screenColumn + m.index); + valueFragment.appendChild(self.$tabStrings[tabSize].cloneNode(true)); screenColumn += tabSize - 1; - return self.$tabStrings[tabSize]; - } else if (c == "\u3000") { + } else if (simpleSpace) { + if (self.showInvisibles) { + var span = this.dom.createElement("span"); + span.className = "ace_invisible ace_invisible_space"; + span.textContent = lang.stringRepeat(self.SPACE_CHAR, simpleSpace.length); + valueFragment.appendChild(span); + } else { + valueFragment.appendChild(this.com.createTextNode(simpleSpace, this.element)); + } + } else if (controlCharacter) { + var span = this.dom.createElement("span"); + span.className = "ace_invisible ace_invisible_space ace_invalid"; + span.textContent = lang.stringRepeat(self.SPACE_CHAR, controlCharacter.length); + valueFragment.appendChild(span); + } else if (cjkSpace) { // U+3000 is both invisible AND full-width, so must be handled uniquely - var classToUse = self.showInvisibles ? "ace_cjk ace_invisible ace_invisible_space" : "ace_cjk"; var space = self.showInvisibles ? self.SPACE_CHAR : ""; screenColumn += 1; - return "" + space + ""; - } else if (b) { - return "" + self.SPACE_CHAR + ""; - } else { + + var span = this.dom.createElement("span"); + span.style.width = (self.config.characterWidth * 2) + "px"; + span.className = self.showInvisibles ? "ace_cjk ace_invisible ace_invisible_space" : "ace_cjk"; + span.textContent = self.showInvisibles ? self.SPACE_CHAR : ""; + valueFragment.appendChild(span); + } else if (cjk) { screenColumn += 1; - return "" + c + ""; + var span = dom.createElement("span"); + span.style.width = (self.config.characterWidth * 2) + "px"; + span.className = "ace_cjk"; + span.textContent = cjk; + valueFragment.appendChild(span); } - }; - - var output = value.replace(replaceReg, replaceFunc); + } + + valueFragment.appendChild(this.dom.createTextNode(i ? value.slice(i) : value, this.element)); if (!this.$textToken[token.type]) { var classes = "ace_" + token.type.replace(/\./g, " ace_"); - var style = ""; + var span = this.dom.createElement("span"); if (token.type == "fold") - style = " style='width:" + (token.value.length * this.config.characterWidth) + "px;' "; - stringBuilder.push("", output, ""); + span.style.width = (token.value.length * this.config.characterWidth) + "px"; + + span.className = classes; + span.appendChild(valueFragment); + + parent.appendChild(span); } else { - stringBuilder.push(output); + parent.appendChild(valueFragment); } + return screenColumn + value.length; }; - this.renderIndentGuide = function(stringBuilder, value, max) { + this.renderIndentGuide = function(parent, value, max) { var cols = value.search(this.$indentGuideRe); if (cols <= 0 || cols >= max) return value; if (value[0] == " ") { cols -= cols % this.tabSize; - stringBuilder.push(lang.stringRepeat(this.$tabStrings[" "], cols/this.tabSize)); + var count = cols/this.tabSize; + for (var i=0; i= splitChars) { screenColumn = this.$renderToken( - stringBuilder, screenColumn, + lineEl, screenColumn, token, value.substring(0, splitChars - chars) ); value = value.substring(splitChars - chars); chars = splitChars; - if (!onlyContents) { - stringBuilder.push("", - "
" - ); - } + lineEl = this.$createLineElement(); + parent.appendChild(lineEl); - stringBuilder.push(lang.stringRepeat("\xa0", splits.indent)); + lineEl.appendChild(this.dom.createTextNode(lang.stringRepeat("\xa0", splits.indent), this.element)); split ++; screenColumn = 0; @@ -431,40 +476,45 @@ var Text = function(parentEl) { if (value.length != 0) { chars += value.length; screenColumn = this.$renderToken( - stringBuilder, screenColumn, token, value + lineEl, screenColumn, token, value ); } } } }; - this.$renderSimpleLine = function(stringBuilder, tokens) { + this.$renderSimpleLine = function(parent, tokens) { var screenColumn = 0; var token = tokens[0]; var value = token.value; if (this.displayIndentGuides) - value = this.renderIndentGuide(stringBuilder, value); + value = this.renderIndentGuide(parent, value); if (value) - screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); + screenColumn = this.$renderToken(parent, screenColumn, token, value); for (var i = 1; i < tokens.length; i++) { token = tokens[i]; value = token.value; if (screenColumn + value.length > this.MAX_LINE_LENGTH) - return this.$renderOverflowMessage(stringBuilder, screenColumn, token, value); - screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); + return this.$renderOverflowMessage(parent, screenColumn, token, value); + screenColumn = this.$renderToken(parent, screenColumn, token, value); } }; - this.$renderOverflowMessage = function(stringBuilder, screenColumn, token, value) { - this.$renderToken(stringBuilder, screenColumn, token, + this.$renderOverflowMessage = function(parent, screenColumn, token, value) { + this.$renderToken(parent, screenColumn, token, value.slice(0, this.MAX_LINE_LENGTH - screenColumn)); - stringBuilder.push( - "<click to see more...>" - ); + + var overflowEl = this.dom.createElement("span"); + overflowEl.className = "ace_inline_button ace_keyword ace_toggle_wrap"; + overflowEl.style.position = "absolute"; + overflowEl.style.right = "0"; + overflowEl.textContent = ""; + + parent.appendChild(overflowEl); }; // row is either first row of foldline or not in fold - this.$renderLine = function(stringBuilder, row, onlyContents, foldLine) { + this.$renderLine = function(parent, row, foldLine) { if (!foldLine && foldLine != false) foldLine = this.session.getFoldLine(row); @@ -473,36 +523,35 @@ var Text = function(parentEl) { else var tokens = this.session.getTokens(row); - - if (!onlyContents) { - stringBuilder.push( - "
" - ); - } - + var lastLineEl = parent; if (tokens.length) { var splits = this.session.getRowSplitData(row); - if (splits && splits.length) - this.$renderWrappedLine(stringBuilder, tokens, splits, onlyContents); - else - this.$renderSimpleLine(stringBuilder, tokens); + if (splits && splits.length) { + this.$renderWrappedLine(parent, tokens, splits); + var lastLineEl = parent.lastChild; + } else { + var lastLineEl = parent; + if (this.$useLineGroups()) { + lastLineEl = this.$createLineElement(); + parent.appendChild(lastLineEl); + } + this.$renderSimpleLine(lastLineEl, tokens); + } + } else if (this.$useLineGroups()) { + lastLineEl = this.$createLineElement(); + parent.appendChild(lastLineEl); } - if (this.showInvisibles) { + if (this.showInvisibles && lastLineEl) { if (foldLine) row = foldLine.end.row; - stringBuilder.push( - "", - row == this.session.getLength() - 1 ? this.EOF_CHAR : this.EOL_CHAR, - "" - ); + var invisibleEl = this.dom.createElement("span"); + invisibleEl.className = "ace_invisible ace_invisible_eol"; + invisibleEl.textContent = row == this.session.getLength() - 1 ? this.EOF_CHAR : this.EOL_CHAR; + + lastLineEl.appendChild(invisibleEl); } - if (!onlyContents) - stringBuilder.push("
"); }; this.$getFoldLineTokens = function(row, foldLine) { diff --git a/plugins/node_modules/ace/lib/ace/layer/text_test.js b/plugins/node_modules/ace/lib/ace/layer/text_test.js index b7dbcc0e..aa944821 100644 --- a/plugins/node_modules/ace/lib/ace/layer/text_test.js +++ b/plugins/node_modules/ace/lib/ace/layer/text_test.js @@ -40,6 +40,7 @@ var assert = require("../test/assertions"); var EditSession = require("../edit_session").EditSession; var TextLayer = require("./text").Text; var JavaScriptMode = require("../mode/javascript").Mode; +var dom = require("../lib/dom"); module.exports = { @@ -60,61 +61,63 @@ module.exports = { this.textLayer.$computeTabString(); // row with hard tabs - var stringBuilder = []; - this.textLayer.$renderLine(stringBuilder, 0); + var parent1 = dom.createElement("div"); + this.textLayer.$renderLine(parent1, 0); // row with soft tabs - var stringBuilder2 = []; - this.textLayer.$renderLine(stringBuilder2, 1); - assert.equal(stringBuilder.join(""), stringBuilder2.join("")); + var parent2 = dom.createElement("div"); + this.textLayer.$renderLine(parent2, 1); + assert.equal(parent1.innerHTML, parent2.innerHTML); }, "test rendering width of ideographic space (U+3000)" : function() { this.session.setValue("\u3000"); - var stringBuilder = []; - this.textLayer.$renderLine(stringBuilder, 0, true); - assert.equal(stringBuilder.join(""), ""); + var parent = dom.createElement("div"); + this.textLayer.$renderLine(parent, 0); + assert.domNode(parent, ["div", {}, ["span", {class: "ace_cjk", style: "width: 20px;"}]]); this.textLayer.setShowInvisibles(true); - var stringBuilder = []; - this.textLayer.$renderLine(stringBuilder, 0, true); - assert.equal( - stringBuilder.join(""), - "" + this.textLayer.SPACE_CHAR + "" - + "\xB6" - ); + var parent = dom.createElement("div"); + this.textLayer.$renderLine(parent, 0); + assert.domNode(parent, ["div", {}, + ["span", {class: "ace_cjk ace_invisible ace_invisible_space", style: "width: 20px;"}, this.textLayer.SPACE_CHAR], + ["span", {class: "ace_invisible ace_invisible_eol"}, "\xB6"] + ]); }, "test rendering of indent guides" : function() { var textLayer = this.textLayer; - var EOL = "" + textLayer.EOL_CHAR + ""; + var EOL = "" + textLayer.EOL_CHAR + ""; var SPACE = function(i) {return Array(i+1).join(" ");}; var DOT = function(i) {return Array(i+1).join(textLayer.SPACE_CHAR);}; var TAB = function(i) {return Array(i+1).join(textLayer.TAB_CHAR);}; function testRender(results) { for (var i = results.length; i--; ) { - var stringBuilder = []; - textLayer.$renderLine(stringBuilder, i, true); - assert.equal(stringBuilder.join(""), results[i]); + var parent = dom.createElement("div"); + textLayer.$renderLine(parent, i); + + assert.equal(parent.innerHTML, results[i]); } } this.session.setValue(" \n\t\tf\n "); testRender([ - "" + SPACE(4) + "" + SPACE(2), - "" + SPACE(4) + "" + SPACE(4) + "f", + "" + SPACE(4) + "" + SPACE(2), + "" + SPACE(4) + "" + SPACE(4) + "f", SPACE(3) ]); + this.textLayer.setShowInvisibles(true); testRender([ - "" + DOT(4) + "" + DOT(2) + "" + EOL, - "" + TAB(4) + "" + TAB(4) + "f" + EOL + "" + DOT(4) + "" + DOT(2) + "" + EOL, + "" + TAB(4) + "" + TAB(4) + "f" + EOL ]); + this.textLayer.setDisplayIndentGuides(false); testRender([ - "" + DOT(6) + "" + EOL, - "" + TAB(4) + "" + TAB(4) + "f" + EOL + "" + DOT(6) + "" + EOL, + "" + TAB(4) + "" + TAB(4) + "f" + EOL ]); } }; diff --git a/plugins/node_modules/ace/lib/ace/lib/dom.js b/plugins/node_modules/ace/lib/ace/lib/dom.js index ae3513ce..ccfda22c 100644 --- a/plugins/node_modules/ace/lib/ace/lib/dom.js +++ b/plugins/node_modules/ace/lib/ace/lib/dom.js @@ -31,6 +31,7 @@ define(function(require, exports, module) { "use strict"; +var useragent = require("./useragent"); var XHTML_NS = "http://www.w3.org/1999/xhtml"; exports.buildDom = function buildDom(arr, parent, refs) { @@ -90,6 +91,20 @@ exports.createElement = function(tag, ns) { document.createElement(tag); }; +exports.removeChildren = function(element) { + element.innerHTML = ""; +}; + +exports.createTextNode = function(textContent, element) { + var doc = element ? element.ownerDocument : document; + return doc.createTextNode(textContent); +}; + +exports.createFragment = function(element) { + var doc = element ? element.ownerDocument : document; + return doc.createDocumentFragment(); +}; + exports.hasCssClass = function(el, name) { var classes = (el.className + "").split(/\s+/g); return classes.indexOf(name) !== -1; @@ -183,6 +198,9 @@ exports.importCssString = function importCssString(cssText, id, container) { root.appendChild(style); }; +exports.importCssStylsheet = function(uri, doc) { + exports.buildDom(["link", {rel: "stylesheet", href: uri}], exports.getDocumentHead(doc)); +}; exports.scrollbarWidth = function(document) { var inner = exports.createElement("ace_inner"); inner.style.width = "100%"; @@ -228,4 +246,44 @@ exports.computedStyle = function(element, style) { return window.getComputedStyle(element, "") || {}; }; +exports.setStyle = function(styles, property, value) { + if (styles[property] !== value) { + //console.log("set style", property, styles[property], value); + styles[property] = value; + } +}; + +exports.HAS_CSS_ANIMATION = false; +if (typeof document !== "undefined") { + var div = document.createElement("div"); + if (typeof div.style.animationName !== "undefined") { + exports.HAS_CSS_ANIMATION = true; + } +} + +exports.HAS_CSS_TRANSFORMS = false; +exports.HI_DPI = useragent.isWin + ? typeof window !== "undefined" && window.devicePixelRatio >= 1.5 + : true; + +if (exports.HI_DPI && typeof document !== "undefined") { + // detect CSS transformation support + var div = document.createElement("div"); + if (div.style.transform !== undefined) + exports.HAS_CSS_TRANSFORMS = true; + div = null; + +} + +if (exports.HAS_CSS_TRANSFORMS) { + exports.translate = function(element, tx, ty) { + element.style.transform = "translate(" + Math.round(tx) + "px, " + Math.round(ty) +"px)"; + }; +} else { + exports.translate = function(element, tx, ty) { + element.style.top = Math.round(ty) + "px"; + element.style.left = Math.round(tx) + "px"; + }; +} + }); diff --git a/plugins/node_modules/ace/lib/ace/lib/event.js b/plugins/node_modules/ace/lib/ace/lib/event.js index fbbf7f7c..2b2d52f5 100644 --- a/plugins/node_modules/ace/lib/ace/lib/event.js +++ b/plugins/node_modules/ace/lib/ace/lib/event.js @@ -364,7 +364,6 @@ exports.addCommandKeyListener = function(el, callback) { } }; function resetPressedKeys() { - // console.log("resetting") pressedKeys = Object.create(null); } @@ -372,18 +371,42 @@ if (typeof window == "object" && window.postMessage && !useragent.isOldIE) { var postMessageId = 1; exports.nextTick = function(callback, win) { win = win || window; - var messageName = "zero-timeout-message-" + postMessageId; - exports.addListener(win, "message", function listener(e) { + var messageName = "zero-timeout-message-" + (postMessageId++); + + var listener = function(e) { if (e.data == messageName) { exports.stopPropagation(e); exports.removeListener(win, "message", listener); callback(); } - }); + }; + + exports.addListener(win, "message", listener); win.postMessage(messageName, "*"); }; } +exports.$idleBlocked = false; +exports.onIdle = function(cb, timeout) { + return setTimeout(function handler() { + if (!exports.$idleBlocked) { + cb(); + } else { + setTimeout(handler, 100); + } + }, timeout); +}; + +exports.$idleBlockId = null; +exports.blockIdle = function(delay) { + if (exports.$idleBlockId) + clearTimeout(exports.$idleBlockId); + + exports.$idleBlocked = true; + exports.$idleBlockId = setTimeout(function() { + exports.$idleBlocked = false; + }, delay || 100); +}; exports.nextFrame = typeof window == "object" && (window.requestAnimationFrame || window.mozRequestAnimationFrame diff --git a/plugins/node_modules/ace/lib/ace/lib/event_emitter.js b/plugins/node_modules/ace/lib/ace/lib/event_emitter.js index 4412e2be..6d5c2f0e 100644 --- a/plugins/node_modules/ace/lib/ace/lib/event_emitter.js +++ b/plugins/node_modules/ace/lib/ace/lib/event_emitter.js @@ -109,7 +109,6 @@ EventEmitter.removeDefaultHandler = function(eventName, callback) { var disabled = handlers._disabled_[eventName]; if (handlers[eventName] == callback) { - var old = handlers[eventName]; if (disabled) this.setDefaultHandler(eventName, disabled.pop()); } else if (disabled) { diff --git a/plugins/node_modules/ace/lib/ace/lib/keys.js b/plugins/node_modules/ace/lib/ace/lib/keys.js index cca7ff24..5e72b779 100644 --- a/plugins/node_modules/ace/lib/ace/lib/keys.js +++ b/plugins/node_modules/ace/lib/ace/lib/keys.js @@ -34,8 +34,6 @@ For more information about SproutCore, visit http://www.sproutcore.com define(function(require, exports, module) { "use strict"; -require("./fixoldbrowsers"); - var oop = require("./oop"); /* diff --git a/plugins/node_modules/ace/lib/ace/mode/java_highlight_rules.js b/plugins/node_modules/ace/lib/ace/mode/java_highlight_rules.js index add43eef..0f28b717 100644 --- a/plugins/node_modules/ace/lib/ace/mode/java_highlight_rules.js +++ b/plugins/node_modules/ace/lib/ace/mode/java_highlight_rules.js @@ -88,6 +88,37 @@ var JavaHighlightRules = function() { }, { token : "constant.language.boolean", regex : "(?:true|false)\\b" + }, { + regex: "(open(?:\\s+))?module(?=\\s*\\w)", + token: "keyword", + next: [{ + regex: "{", + token: "paren.lparen", + next: [{ + regex: "}", + token: "paren.rparen", + next: "start" + }, { + // From Section 3.9 of http://cr.openjdk.java.net/~mr/jigsaw/spec/java-se-9-jls-diffs.pdf + regex: "\\b(requires|transitive|exports|opens|to|uses|provides|with)\\b", + token: "keyword" + }] + }, { + token : "text", + regex : "\\s+" + }, { + token : "identifier", + regex : "\\w+" + }, { + token : "punctuation.operator", + regex : "." + }, { + token : "text", + regex : "\\s+" + }, { + regex: "", // exit if there is anything else + next: "start" + }] }, { token : keywordMapper, // TODO: Unicode escape sequences @@ -118,8 +149,10 @@ var JavaHighlightRules = function() { ] }; + this.embedRules(DocCommentHighlightRules, "doc-", [ DocCommentHighlightRules.getEndRule("start") ]); + this.normalizeRules(); }; oop.inherits(JavaHighlightRules, TextHighlightRules); diff --git a/plugins/node_modules/ace/lib/ace/mode/php_highlight_rules.js b/plugins/node_modules/ace/lib/ace/mode/php_highlight_rules.js index 7bb3e4c2..f79dea03 100644 --- a/plugins/node_modules/ace/lib/ace/mode/php_highlight_rules.js +++ b/plugins/node_modules/ace/lib/ace/mode/php_highlight_rules.js @@ -1002,6 +1002,9 @@ var PhpLangHighlightRules = function() { }, { token : "keyword.operator", regex : "::|!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|!=|!==|<=|>=|=>|<<=|>>=|>>>=|<>|<|>|\\.=|=|!|&&|\\|\\||\\?\\:|\\*=|/=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)" + }, { + token : "punctuation.operator", + regex : /[,;]/ }, { token : "paren.lparen", regex : "[[({]" diff --git a/plugins/node_modules/ace/lib/ace/mouse/default_handlers.js b/plugins/node_modules/ace/lib/ace/mouse/default_handlers.js index 140cbd50..046a8038 100644 --- a/plugins/node_modules/ace/lib/ace/mouse/default_handlers.js +++ b/plugins/node_modules/ace/lib/ace/mouse/default_handlers.js @@ -31,8 +31,6 @@ define(function(require, exports, module) { "use strict"; -var dom = require("../lib/dom"); -var event = require("../lib/event"); var useragent = require("../lib/useragent"); var DRAG_OFFSET = 0; // pixels diff --git a/plugins/node_modules/ace/lib/ace/mouse/mouse_handler.js b/plugins/node_modules/ace/lib/ace/mouse/mouse_handler.js index a383ba32..439692b5 100644 --- a/plugins/node_modules/ace/lib/ace/mouse/mouse_handler.js +++ b/plugins/node_modules/ace/lib/ace/mouse/mouse_handler.js @@ -216,7 +216,7 @@ var MouseHandler = function(editor) { config.defineOptions(MouseHandler.prototype, "mouseHandler", { scrollSpeed: {initialValue: 2}, - dragDelay: {initialValue: 150}, + dragDelay: {initialValue: (useragent.isMac ? 150 : 0)}, dragEnabled: {initialValue: true}, focusTimeout: {initialValue: 0}, tooltipFollowsMouse: {initialValue: true} diff --git a/plugins/node_modules/ace/lib/ace/mouse/mouse_handler_test.js b/plugins/node_modules/ace/lib/ace/mouse/mouse_handler_test.js index c35b09d5..fff48caf 100644 --- a/plugins/node_modules/ace/lib/ace/mouse/mouse_handler_test.js +++ b/plugins/node_modules/ace/lib/ace/mouse/mouse_handler_test.js @@ -36,8 +36,9 @@ if (typeof process !== "undefined") { define(function(require, exports, module) { "use strict"; +require("../multi_select"); var Editor = require("../editor").Editor; -var MockRenderer = require("../test/mockrenderer").MockRenderer; +var VirtualRenderer = require("../virtual_renderer").VirtualRenderer; var assert = require("../test/assertions"); var MouseEvent = function(type, opts){ var e = document.createEvent("MouseEvents"); @@ -53,20 +54,77 @@ var MouseEvent = function(type, opts){ module.exports = { setUp : function(next) { - this.editor = new Editor(new MockRenderer()); - this.editor.setValue("Juhu kinners!"); + this.editor = new Editor(new VirtualRenderer()); + this.editor.session.setValue("Juhu kinners!"); + this.editor.container.style.position = "absolute"; + this.editor.container.style.height = "500px"; + this.editor.container.style.width = "500px"; + this.editor.container.style.left = "50px"; + this.editor.container.style.top = "10px"; + document.body.appendChild(this.editor.container); next(); }, "test: double tap. issue #956" : function() { // mouse up fired immediately after mouse down + this.editor.resize(true); + var pos = this.editor.renderer.textToScreenCoordinates(0, 1); var target = this.editor.renderer.getMouseEventTarget(); - target.dispatchEvent(MouseEvent("down", {x: 1, y: 1})); - target.dispatchEvent(MouseEvent("up", {x: 1, y: 1})); - target.dispatchEvent(MouseEvent("down", {x: 1, y: 1, detail: 2})); - target.dispatchEvent(MouseEvent("up", {x: 1, y: 1, detail: 2})); + target.dispatchEvent(MouseEvent("down", {x: pos.pageX, y: pos.pageY})); + target.dispatchEvent(MouseEvent("up", {x: pos.pageX, y: pos.pageY})); + target.dispatchEvent(MouseEvent("down", {x: pos.pageX, y: pos.pageY, detail: 2})); + target.dispatchEvent(MouseEvent("up", {x: pos.pageX, y: pos.pageY, detail: 2})); assert.equal(this.editor.getSelectedText(), "Juhu"); + + target.dispatchEvent(MouseEvent("down", {x: pos.pageX, y: pos.pageY})); + target.dispatchEvent(MouseEvent("up", {x: pos.pageX, y: pos.pageY})); + assert.equal(this.editor.getSelectedText(), ""); + }, + "test: multiselect" : function() { + var target = this.editor.renderer.getMouseEventTarget(); + this.editor.session.setValue("xyz\n\nabc efg"); + this.editor.resize(true); + + var pos = this.editor.renderer.textToScreenCoordinates(0, 1); + + target.dispatchEvent(MouseEvent("down", {x: pos.pageX, y: pos.pageY})); + target.dispatchEvent(MouseEvent("up", {x: pos.pageX, y: pos.pageY})); + + pos = this.editor.renderer.textToScreenCoordinates(0, 2); + + target.dispatchEvent(MouseEvent("down", {x: pos.pageX, y: pos.pageY, ctrl: true})); + target.dispatchEvent(MouseEvent("up", {x: pos.pageX, y: pos.pageY})); + + var selection = "Range: [0/2] -> [0/2],Range: [0/1] -> [0/1]"; + assert.equal(this.editor.selection.toJSON() + "", selection); + + pos = this.editor.renderer.textToScreenCoordinates(2, 2); + + target.dispatchEvent(MouseEvent("down", {x: pos.pageX, y: pos.pageY, detail: 2, ctrl: true})); + target.dispatchEvent(MouseEvent("up", {x: pos.pageX, y: pos.pageY, detail: 2, ctrl: true})); + + selection = "Range: [2/0] -> [2/3]," + selection; + assert.equal(this.editor.selection.toJSON() + "", selection); + + var pos = this.editor.renderer.textToScreenCoordinates(0, 1); + + target.dispatchEvent(MouseEvent("down", {x: pos.pageX, y: pos.pageY, ctrl: true})); + target.dispatchEvent(MouseEvent("up", {x: pos.pageX, y: pos.pageY, ctrl: true})); + selection = selection.split(",").slice(0, -1).join(","); + assert.equal(this.editor.selection.toJSON() + "", selection); + + var pos1 = this.editor.renderer.textToScreenCoordinates(0, 2); + var pos2 = this.editor.renderer.textToScreenCoordinates(2, 2); + + target.dispatchEvent(MouseEvent("down", {x: pos1.pageX, y: pos1.pageY, alt: true})); + target.dispatchEvent(MouseEvent("move", {x: pos2.pageX, y: pos2.pageY + 1, alt: true})); + target.dispatchEvent(MouseEvent("up", {x: pos2.pageX, y: pos2.pageY + 1, alt: true})); + assert.equal(this.editor.selection.toJSON() + "", "Range: [2/2] -> [2/2],Range: [1/0] -> [1/0],Range: [0/2] -> [0/2]"); + }, + + tearDown : function() { + document.body.removeChild(this.editor.container); } }; diff --git a/plugins/node_modules/ace/lib/ace/mouse/multi_select_handler.js b/plugins/node_modules/ace/lib/ace/mouse/multi_select_handler.js index 5ec027ec..92ebc575 100644 --- a/plugins/node_modules/ace/lib/ace/mouse/multi_select_handler.js +++ b/plugins/node_modules/ace/lib/ace/mouse/multi_select_handler.js @@ -173,6 +173,7 @@ function onMouseDown(e) { screenCursor = {row: -1, column: -1}; var onMouseSelectionEnd = function(e) { + blockSelect(); clearInterval(timerId); editor.removeSelectionMarkers(rectSel); if (!rectSel.length) diff --git a/plugins/node_modules/ace/lib/ace/multi_select.js b/plugins/node_modules/ace/lib/ace/multi_select.js index a98a0d0a..ea056814 100644 --- a/plugins/node_modules/ace/lib/ace/multi_select.js +++ b/plugins/node_modules/ace/lib/ace/multi_select.js @@ -560,6 +560,8 @@ var Editor = require("./editor").Editor; if (pos.row != anchor.row || this.session.$clipPositionToDocument(pos.row, pos.column).column != anchor.column) this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange()); + else + this.multiSelect.mergeOverlappingRanges(); } }; diff --git a/plugins/node_modules/ace/lib/ace/multi_select_test.js b/plugins/node_modules/ace/lib/ace/multi_select_test.js index b08e160c..75f69ab0 100644 --- a/plugins/node_modules/ace/lib/ace/multi_select_test.js +++ b/plugins/node_modules/ace/lib/ace/multi_select_test.js @@ -275,6 +275,31 @@ module.exports = { doc.markUndoGroup(); editor.execCommand("undo"); assert.equal('l1\nl2\nl3', editor.getValue()); + }, + + "test splitIntoLines": function() { + var session = new EditSession(["l1", "l2", "l3"]); + var selection = session.selection; + editor = new Editor(new MockRenderer(), session); + + var nCursor = 0; + var nSelection = 0; + selection.on("changeCursor", function() { nCursor++; }); + selection.on("changeSelection", function() { nSelection++; }); + + selection.moveTo(0, 0); + selection.selectDown(); + selection.splitIntoLines(); + assert.equal(nCursor, 2); + assert.equal(nSelection, 2); + nCursor = nSelection = 0; + selection.selectAll(); + assert.equal(nCursor, 0); + assert.equal(nSelection, 1); + + selection.splitIntoLines(); + editor.setValue(""); + assert.equal(editor.selection.inMultiSelectMode, false); } }; diff --git a/plugins/node_modules/ace/lib/ace/range_list.js b/plugins/node_modules/ace/lib/ace/range_list.js index 149d6372..5b8f73ce 100644 --- a/plugins/node_modules/ace/lib/ace/range_list.js +++ b/plugins/node_modules/ace/lib/ace/range_list.js @@ -181,46 +181,89 @@ var RangeList = function() { }; this.$onChange = function(delta) { - if (delta.action == "insert"){ - var start = delta.start; - var end = delta.end; - } else { - var end = delta.start; - var start = delta.end; - } + var start = delta.start; + var end = delta.end; var startRow = start.row; var endRow = end.row; - var lineDif = endRow - startRow; - - var colDiff = -start.column + end.column; var ranges = this.ranges; - for (var i = 0, n = ranges.length; i < n; i++) { var r = ranges[i]; - if (r.end.row < startRow) - continue; - if (r.start.row > startRow) + if (r.end.row >= startRow) break; - - if (r.start.row == startRow && r.start.column >= start.column ) { - if (r.start.column == start.column && this.$insertRight) { - // do nothing - } else { - r.start.column += colDiff; - r.start.row += lineDif; + } + + if (delta.action == "insert") { + var lineDif = endRow - startRow; + var colDiff = -start.column + end.column; + for (; i < n; i++) { + var r = ranges[i]; + if (r.start.row > startRow) + break; + + if (r.start.row == startRow && r.start.column >= start.column) { + if (r.start.column == start.column && this.$insertRight) { + // do nothing + } else { + r.start.column += colDiff; + r.start.row += lineDif; + } + } + if (r.end.row == startRow && r.end.column >= start.column) { + if (r.end.column == start.column && this.$insertRight) { + continue; + } + // special handling for the case when two ranges share an edge + if (r.end.column == start.column && colDiff > 0 && i < n - 1) { + if (r.end.column > r.start.column && r.end.column == ranges[i+1].start.column) + r.end.column -= colDiff; + } + r.end.column += colDiff; + r.end.row += lineDif; } } - if (r.end.row == startRow && r.end.column >= start.column) { - if (r.end.column == start.column && this.$insertRight) { - continue; + } else { + var lineDif = startRow - endRow; + var colDiff = start.column - end.column; + for (; i < n; i++) { + var r = ranges[i]; + + if (r.start.row > endRow) + break; + + if (r.end.row < endRow) { + r.end.row = startRow; + r.end.column = start.column; } - // special handling for the case when two ranges share an edge - if (r.end.column == start.column && colDiff > 0 && i < n - 1) { - if (r.end.column > r.start.column && r.end.column == ranges[i+1].start.column) - r.end.column -= colDiff; + + if (r.start.row < endRow || r.start.row == endRow && r.start.column <= end.colum) { + r.start.row = startRow; + r.start.column = start.column; + } + + if (r.end.row == endRow) { + if (r.end.column <= end.column) { + if (lineDif || r.end.column > start.column) { + r.end.column = start.column; + r.end.row = start.row; + } + } + else { + r.end.column += colDiff; + r.end.row += lineDif; + } + } + if (r.start.row == endRow) { + if (r.start.column <= end.column) { + if (lineDif || r.start.column > start.column) { + r.start.column = start.column; + r.start.row = start.row; + } + } + else { + r.start.column += colDiff; + r.start.row += lineDif; + } } - r.end.column += colDiff; - r.end.row += lineDif; } } diff --git a/plugins/node_modules/ace/lib/ace/renderloop.js b/plugins/node_modules/ace/lib/ace/renderloop.js index 6d31bd13..444fe19f 100644 --- a/plugins/node_modules/ace/lib/ace/renderloop.js +++ b/plugins/node_modules/ace/lib/ace/renderloop.js @@ -50,22 +50,23 @@ var RenderLoop = function(onRender, win) { (function() { - this.schedule = function(change) { - //this.onRender(change); - //return; this.changes = this.changes | change; - if (!this.pending && this.changes) { - this.pending = true; + if (this.changes) { var _self = this; - event.nextFrame(function() { - _self.pending = false; - var changes; - while (changes = _self.changes) { + + event.nextFrame(function(ts) { + var changes = _self.changes; + + if (changes) { + event.blockIdle(100); _self.changes = 0; _self.onRender(changes); } - }, this.window); + + if (_self.changes) + _self.schedule(); + }); } }; diff --git a/plugins/node_modules/ace/lib/ace/requirejs/text.js b/plugins/node_modules/ace/lib/ace/requirejs/text.js index 8283c82f..f03c64c8 100644 --- a/plugins/node_modules/ace/lib/ace/requirejs/text.js +++ b/plugins/node_modules/ace/lib/ace/requirejs/text.js @@ -33,17 +33,17 @@ */ (function() { - -var globalRequire = typeof require != "undefined" && require; -if (typeof define !== "function") // running in webpack - return module.exports = function(source) { return source; }; +var globalRequire = typeof require != "undefined" && require; +if (typeof define !== "function" || (!define.amd && typeof XMLHttpRequest == "undefined")) { // running in webpack + return module.exports = globalRequire("./text_loader_webpack"); +} define(function (require, exports, module) { "use strict"; if (globalRequire && globalRequire.nodeRequire) { module.exports = globalRequire.nodeRequire(require.toUrl("./text_build")); } else { - exports.load = function(name, req, onLoad, config) { + exports.load = function(name, req, onLoad, config) { require("../lib/net").get(req.toUrl(name), onLoad); }; } diff --git a/plugins/node_modules/ace/lib/ace/requirejs/text_loader_webpack.js b/plugins/node_modules/ace/lib/ace/requirejs/text_loader_webpack.js new file mode 100644 index 00000000..660281b9 --- /dev/null +++ b/plugins/node_modules/ace/lib/ace/requirejs/text_loader_webpack.js @@ -0,0 +1,45 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * used by r.js during build + */ + +"use strict"; +module.exports = function(source) { + if (this.fs && this.resourcePath) + source = this.fs.readFileSync(this.resourcePath).toString("utf8"); + source = source.replace(/\/\*(?:[^*]|[*](?=[^\/]))+\*\//g, "") + .replace(/^[ \t]+/gm, ""); + var json = JSON.stringify(source) + .replace(/[\u2028\u2029]/g, function(x) { '\\u' + x.charCodeAt(0).toString(16); }); + + return "module.exports = " + json; +}; \ No newline at end of file diff --git a/plugins/node_modules/ace/lib/ace/selection.js b/plugins/node_modules/ace/lib/ace/selection.js index a9dd9251..6be44c7a 100644 --- a/plugins/node_modules/ace/lib/ace/selection.js +++ b/plugins/node_modules/ace/lib/ace/selection.js @@ -211,6 +211,7 @@ var Selection = function(session) { this.$setSelection = function(anchorRow, anchorColumn, cursorRow, cursorColumn) { var wasEmpty = this.$isEmpty; + var wasMultiselect = this.inMultiSelectMode; this.$silent = true; this.$cursorChanged = this.$anchorChanged = false; this.anchor.setPosition(anchorRow, anchorColumn); @@ -219,7 +220,7 @@ var Selection = function(session) { this.$silent = false; if (this.$cursorChanged) this._emit("changeCursor"); - if (this.$cursorChanged || this.$anchorChanged) + if (this.$cursorChanged || this.$anchorChanged || wasEmpty != this.$isEmpty || wasMultiselect) this._emit("changeSelection"); }; diff --git a/plugins/node_modules/ace/lib/ace/selection_test.js b/plugins/node_modules/ace/lib/ace/selection_test.js index 051f8748..492a64d7 100644 --- a/plugins/node_modules/ace/lib/ace/selection_test.js +++ b/plugins/node_modules/ace/lib/ace/selection_test.js @@ -507,6 +507,18 @@ module.exports = { assert.equal(nCursor, 2); assert.equal(nSelection, 3); assert.ok(selection.isEqual(data)); + + selection.moveTo(0, 0); + nCursor = nSelection = 0; + selection.selectAll(); + assert.equal(nCursor, 1); + assert.equal(nSelection, 1); + selection.moveCursorRight(); + selection.clearSelection(); + nCursor = nSelection = 0; + selection.selectAll(); + assert.equal(nCursor, 0); + assert.equal(nSelection, 1); }, "test setRange inside fold": function() { diff --git a/plugins/node_modules/ace/lib/ace/test/assertions.js b/plugins/node_modules/ace/lib/ace/test/assertions.js index 3a521003..771e775f 100644 --- a/plugins/node_modules/ace/lib/ace/test/assertions.js +++ b/plugins/node_modules/ace/lib/ace/test/assertions.js @@ -47,10 +47,34 @@ assert.notOk = function(value) { assert.equal(value, false); }; -exports.jsonEquals = function(foundJson, expectedJson) { +assert.jsonEquals = function(foundJson, expectedJson) { assert.equal(JSON.stringify(foundJson), JSON.stringify(expectedJson)); }; +assert.domNode = function(foundDom, expectedDom) { + if (!Array.isArray(foundDom)) + foundDom = serializeDom(foundDom); + assert.deepEqual(foundDom, expectedDom); +}; + +function serializeDom(node) { + var attributes = {}; + var attributeArray = node.attributes; + if (!attributeArray) + return node.data; + if (typeof attributeArray.length == "number") { + for (var i = 0; i < attributeArray.length; i++) + attributes[attributeArray[i].name] = attributeArray[i].value; + } + var result = [node.localName, attributes]; + for (var i = 0; i < node.childNodes.length; i++) { + var child = serializeDom(node.childNodes[i]); + if (child) + result.push(child); + } + return result; +} + module.exports = assert; }); diff --git a/plugins/node_modules/ace/lib/ace/test/mockdom.js b/plugins/node_modules/ace/lib/ace/test/mockdom.js index b81558fa..21febd06 100644 --- a/plugins/node_modules/ace/lib/ace/test/mockdom.js +++ b/plugins/node_modules/ace/lib/ace/test/mockdom.js @@ -1,10 +1,373 @@ +define(function(require, exports, module) { "use strict"; -var jsdom = require('jsdom/').jsdom; -var doc = jsdom(""); +var CHAR_HEIGHT = 10; +var CHAR_WIDTH = 6; +var WINDOW_HEIGHT = 768; +var WINDOW_WIDTH = 1024; -global.document = doc; -global.window = doc.defaultView; -global.self = doc.self; -global.navigator = doc.navigator; -global.location = doc.location; +function Style() { + +} +Style.prototype.__defineGetter__("cssText", function() { + var cssText = ""; + Object.keys(this).forEach(function(key) { + if (this[key]) + cssText += (cssText ? " " : "") + key + ": " + this[key] + ";"; + }, this); + return cssText; +}); +Style.prototype.__defineSetter__("cssText", function(value) { + Object.keys(this).forEach(function(key) { + delete this[key]; + }, this); + value.split(";").forEach(function(key) { + var parts = key.split(":"); + if (parts.length == 2) + this[parts[0].trim()] = parts[1].trim(); + }, this); +}); + + +function Node(name) { + this.localName = name; + this.value = ""; + this.tagName = name && name.toUpperCase(); + this.children = this.childNodes = []; + this.ownerDocument = global.document || this; + this.$attributes = {}; + this.style = new Style(); +} +(function() { + this.cloneNode = function(recursive) { + var clone = new Node(this.localName); + for (var i in this.$attributes) { + clone.setAttribute(i, this.$attributes[i]); + } + if (recursive) { + this.children.forEach(function(ch) { + clone.appendChild(ch.cloneNode(true)); + }, this); + } + return clone; + }; + this.appendChild = function(node) { + return this.insertBefore(node, null); + }; + this.removeChild = function(node) { + var i = this.children.indexOf(node); + if (i == -1) + throw new Error("not a child"); + node.parentNode = null; + this.children.splice(i, 1); + if (!document.contains(document.activeElement)) + document.activeElement = document.body; + }; + this.remove = function() { + this.parentNode && this.parentNode.removeChild(this); + }; + this.replaceChild = function(node, oldNode) { + this.insertBefore(node, oldNode); + this.removeChild(oldNode); + return oldNode; + }; + this.insertBefore = function(node, before) { + var i = this.children.indexOf(before); + if (i == -1) i = this.children.length + 1; + if (node.localName == "#fragment") + this.children.splice.apply(this.children, [i - 1, 0].concat(node.children)); + else + this.children.splice(i - 1, 0, node); + node.parentNode = this; + return node; + }; + this.querySelectorAll = function(s) { + var nodes = []; + walk(this, function(node) { + if (node.localName == s) + nodes.push(node); + }); + return nodes; + }; + this.getElementsByTagName = function(s) { + var nodes = []; + walk(this, function(node) { + if (node.localName == s) + nodes.push(node); + }); + return nodes; + }; + this.getElementById = function(s) { + return walk(this, function(node) { + // console.log(node.getAttribute && node.getAttribute("id")) + if (node.getAttribute && node.getAttribute("id") == s) + return node; + }); + }; + this.setAttribute = function(a, v) { + this.$attributes[a] = v; + }; + this.getAttribute = function(a, v) { + return String(this.$attributes[a]); + }; + this.__defineGetter__("attributes", function() { + var style = this.style.cssText; + if (style) + this.$attributes.style = style; + return Object.keys(this.$attributes).map(function(key) { + return {name: key, value: this.$attributes[key]}; + }, this); + }); + this.__defineGetter__("className", function() { + return this.$attributes.class; + }); + this.__defineSetter__("className", function(v) { + this.$attributes.class = v; + }); + this.__defineGetter__("textContent", function() { + var v = ""; + walk(this, function(node) { + if (node instanceof TextNode) + v += node.data; + }); + return v; + }); + this.__defineSetter__("textContent", function(v) { + this.children.length = 0; + this.appendChild(new TextNode(v)); + }); + this.__defineGetter__("id", function() { + return this.getAttribute("id"); + }); + this.__defineSetter__("id", function(v) { + this.setAttribute("id", v); + }); + this.__defineGetter__("parentElement", function() { + return this.parentNode == document ? null : this.parentNode; + }); + this.__defineGetter__("innerHTML", function() { + return this.children.map(function(ch) { + return "outerHTML" in ch ? ch.outerHTML : ch.data; + }).join(""); + }); + this.__defineGetter__("outerHTML", function() { + var attributes = this.attributes.map(function(attr) { + return attr.name + "=" + JSON.stringify(attr.value); + }, this).join(" "); + return "<" + this.localName + (attributes ? " " + attributes : "") + ">" + this.innerHTML + ""; + }); + this.__defineSetter__("innerHTML", function(v) { + this.children.length = 0; + + var root = this; + var tagRe = /<(\/?\w+)|&(?:(#?\w+);)|$/g; + var skipped = ""; + + for (var m, lastIndex = 0; m = tagRe.exec(v);) { + skipped += v.substring(lastIndex, m.index); + if (m[2]) { + if (m[2] == "gt") { + skipped += ">"; + } else if (m[2] == "lt") { + skipped += "<"; + } else if (m[2] == "amp") { + skipped += "&"; + } + lastIndex = tagRe.lastIndex ; + } else { + if (skipped) { + root.appendChild(document.createTextNode(skipped)); + skipped = ""; + } + var end = v.indexOf(">", tagRe.lastIndex); + tagRe.lastIndex = lastIndex = end < 0 ? v.length : end + 1; + + if (!m[1]) { + return; + } + if (m[1][0] == "/") { + if (root != this) + root = root.parentNode; + } else { + var tagName = m[1]; + root = root.appendChild(document.createElement(tagName)); + } + } + } + }); + this.getBoundingClientRect = function(v) { + var w = 0; + var h = 0; + var top = 0; + var left = 0; + if (this == document.documentElement) { + w = WINDOW_WIDTH; + h = WINDOW_HEIGHT; + } + else if (!document.contains(this)) { + w = h = 0; + } + else if (this.style.width == "auto" || this.localName == "span") { + w = this.textContent.length * CHAR_WIDTH; + h = CHAR_HEIGHT; + } + else if (this.style.width) { + w = parseFloat(this.style.width) || 0; + h = parseFloat(this.style.height) || 0; + top = parseFloat(this.style.top) || 0; + left = parseFloat(this.style.left) || 0; + } + else if (this.style.right) { + var rect = this.parentNode.getBoundingClientRect(); + w = rect.width - (parseFloat(this.style.left) || 0) - (parseFloat(this.style.right) || 0); + h = parseFloat(this.style.height) || rect.height; + top = rect.top; + left = rect.left + (parseFloat(this.style.left) || 0); + } + return {top: top, left: left, width: w, height: h}; + }; + + this.__defineGetter__("clientHeight", function() { + return this.getBoundingClientRect().height; + }); + this.__defineGetter__("clientWidth", function() { + return this.getBoundingClientRect().width; + }); + this.__defineGetter__("offsetHeight", function() { + return this.getBoundingClientRect().height; + }); + this.__defineGetter__("offsetWidth", function() { + return this.getBoundingClientRect().width; + }); + + this.__defineGetter__("lastChild", function() { + return this.childNodes[this.childNodes.length - 1]; + }); + this.__defineGetter__("firstChild", function() { + return this.childNodes[0]; + }); + + + this.addEventListener = function(name, listener, capturing) { + if (!this._events) this._events = {}; + if (!this._events[name]) this._events[name] = []; + var i = this._events[name].indexOf(listener); + if (i == -1) + this._events[name][capturing ? "unshift" : "push"](listener); + }; + this.removeEventListener = function(name, listener) { + if (!this._events) return; + if (!this._events[name]) return; + var i = this._events[name].indexOf(this._events[name]); + if (i !== -1) + this._events[name].splice(i, 1); + }; + this.createEvent = function(v) { + return { + initMouseEvent: function(type, _1, _2, window, + detail, x, y, _x, _y, + ctrl, alt, shift, meta, + button, relatedTarget + ) { + this.type = type; + this.detail = detail || 0; + this.clientX = x; + this.clientY = y; + this.button = button; + this.relatedTarget = relatedTarget; + this.ctrlKey = ctrl; + this.altKey = alt; + this.shiftKey = shift; + this.metaKey = meta; + this.preventDefault = function() {}; + this.stopPropagation = function() { + this.stopped = true; + }; + } + }; + }; + this.dispatchEvent = function(e) { + if (!e.target) e.target = this; + e.currentTarget = this; + var events = this._events && this._events[e.type]; + events && events.forEach(function(listener) { + if (!e.stopped) + listener.call(this, e); + }, this); + if (this.parentNode) + this.parentNode.dispatchEvent(e); + else if (this != window) + window.dispatchEvent(e); + }; + this.contains = function(node) { + while (node) { + if (node == this) return true; + node = node.parentNode; + } + }; + this.focus = function() { + if (document.activeElement == this) + return; + if (document.activeElement) + document.activeElement.dispatchEvent({type: "blur"}); + document.activeElement = this; + this.dispatchEvent({type: "focus"}); + }; +}).call(Node.prototype); + +function walk(node, fn) { + var ch = node.children || []; + for (var i = 0; i < ch.length; i++) { + var result = fn(ch[i]) || walk(ch[i], fn); + if (result) + return result; + } +} + +function TextNode(value) { + this.data = value || ""; +} +TextNode.prototype.cloneNode = function() { + return new TextNode(this.data); +}; +var document = new Node(); + +document.navigator = {}; +document.createElement = function(t) { + return new Node(t); +}; +document.createTextNode = function(v) { + return new TextNode(v); +}; +document.createDocumentFragment = function() { + return new Node("#fragment"); +}; +document.hasFocus = function() { + return true; +}; +document.documentElement = document.appendChild(new Node("html")); +document.body = new Node("body"); +document.head = new Node("head"); +document.documentElement.appendChild(document.head); +document.documentElement.appendChild(document.body); + +var window = {}; +window.document = document; +window.document.defaultView = window; + +window.setTimeout = setTimeout; +window.clearTimeout = clearTimeout; +window.getComputedStyle = function(node) { + return node.style; +}; +window.addEventListener = document.addEventListener; +window.removeEventListener = document.removeEventListener; +window.dispatchEvent = document.dispatchEvent; +window.name = "nodejs"; +window.focus = function() {}; + +global.Node = global.Element = Node; +global.window = window; +global.document = document; + +}); diff --git a/plugins/node_modules/ace/lib/ace/undomanager.js b/plugins/node_modules/ace/lib/ace/undomanager.js index 2091058a..27098928 100644 --- a/plugins/node_modules/ace/lib/ace/undomanager.js +++ b/plugins/node_modules/ace/lib/ace/undomanager.js @@ -277,6 +277,10 @@ var UndoManager = function() { this.isClean = this.isAtBookmark; this.markClean = this.bookmark; + this.$prettyPrint = function(delta) { + if (delta) return stringifyDelta(delta); + return stringifyDelta(this.$undoStack) + "\n---\n" + stringifyDelta(this.$redoStack); + }; }).call(UndoManager.prototype); function rearrangeUndoStack(stack, pos) { @@ -558,20 +562,23 @@ function moveDeltasByOne(redoStack, d) { d = cloneDelta(d); for (var j = redoStack.length; j--;) { var deltaSet = redoStack[j]; - for (var i = deltaSet.length; i-- > 0;) { + for (var i = 0; i < deltaSet.length; i++) { var x = deltaSet[i]; var xformed = xform(x, d); d = xformed[0]; if (xformed.length != 2) { if (xformed[2]) { - redoStack.splice(i + 1, 1, xformed[1], xformed[2]); + deltaSet.splice(i + 1, 1, xformed[1], xformed[2]); i++; } else if (!xformed[1]) { - redoStack.splice(i, 1); + deltaSet.splice(i, 1); i--; } } } + if (!deltaSet.length) { + redoStack.splice(j, 1); + } } return redoStack; } diff --git a/plugins/node_modules/ace/lib/ace/undomanager_test.js b/plugins/node_modules/ace/lib/ace/undomanager_test.js index 4a9c1028..5265ad80 100644 --- a/plugins/node_modules/ace/lib/ace/undomanager_test.js +++ b/plugins/node_modules/ace/lib/ace/undomanager_test.js @@ -44,19 +44,20 @@ var EditSession = require("./edit_session").EditSession; var MockRenderer = require("./test/mockrenderer").MockRenderer; var UndoManager = require("./undomanager").UndoManager; -var editor; - +var editor, session, undoManager; module.exports = { name: "ACE undoManager.js", + setUp: function() { + editor = editor || new Editor(new MockRenderer()); + session = new EditSession(""); + undoManager = new UndoManager(); + session.setUndoManager(undoManager); + editor.setSession(session); + }, "test: reabsing": function() { - var session = new EditSession(""); - var editor = new Editor(new MockRenderer(), session); - var undoManager = new UndoManager(); - session.setUndoManager(undoManager); - session.setValue("012345-012345-012345"); session.insert({row: 0, column: 0}, "xx"); session.markUndoGroup(); @@ -66,9 +67,9 @@ module.exports = { session.markUndoGroup(); editor.undo(); editor.undo(); - var rev = session.getUndoManager().startNewGroup(); + var rev = undoManager.startNewGroup(); session.insert({row: 0, column: 5}, "z\nz"); - session.getUndoManager().markIgnored(rev); + undoManager.markIgnored(rev); // editor.undo() editor.redo(); editor.redo(); @@ -84,11 +85,6 @@ module.exports = { assert.equal(val1, val2); }, "test: conflicting deletes": function() { - var session = new EditSession(""); - var editor = new Editor(new MockRenderer(), session); - var undoManager = new UndoManager(); - session.setUndoManager(undoManager); - session.setValue("012345\nabcdefg\nxyz"); session.remove(new Range(0, 2, 0, 4)); assert.equal(session.getLine(0), "0145"); @@ -101,6 +97,208 @@ module.exports = { assert.equal(session.getLine(0), "05"); editor.undo(); assert.equal(session.getLine(0), "012345"); + }, + "test: several deltas ignored": function() { + session.setValue("012345\nabcdefg\nxyz"); + session.insert({row: 0, column: 5}, "zzzz"); + var rev = undoManager.startNewGroup(); + session.insert({row: 0, column: 5}, "yyyy"); + session.insert({row: 0, column: 5}, "aaaa"); + undoManager.markIgnored(rev, undoManager.getRevision() + 1); + editor.undo(); + assert.equal(editor.getValue(), "01234aaaayyyy5\nabcdefg\nxyz"); + }, + "test: canUndo/canRedo and bookmarks": function() { + session.setValue("012345\nabcdefg\nxyz"); + assert.ok(undoManager.isAtBookmark()); + editor.execCommand("removewordright"); + assert.ok(!undoManager.isAtBookmark()); + var rev = undoManager.getRevision(); + undoManager.bookmark(); + assert.ok(undoManager.isAtBookmark()); + editor.undo(); + assert.ok(!undoManager.isAtBookmark()); + undoManager.bookmark(rev); + assert.ok(!undoManager.canUndo()); + assert.ok(undoManager.canRedo()); + editor.redo(); + assert.ok(undoManager.isAtBookmark()); + + session.insert({row: 0, column: 5}, "yyyy"); + assert.ok(undoManager.canUndo()); + assert.ok(!undoManager.canRedo()); + }, + "test: getRevision": function () { + session.setValue("012345\nabcdefg\nxyz"); + session.insert({row: 0, column: 5}, "yyyy"); + var rev = undoManager.getRevision(); + assert.equal(rev, 2); + editor.undo(); + rev = undoManager.getRevision(); + assert.equal(rev, 0); + }, + "test: swap deltas delete/insert": function () { + session.setValue("012345\nabcdefg\nxyz"); + session.insert({row: 0, column: 5}, "zzzz"); + undoManager.startNewGroup(); + session.insert({row: 0, column: 5}, "yyyy"); + session.remove(new Range(0, 5, 0, 9)); + var rev = undoManager.startNewGroup(); + session.insert({row: 0, column: 5}, "aaaa"); + undoManager.markIgnored(rev); + editor.undo(); + assert.equal(editor.getValue(), "01234aaaazzzz5\nabcdefg\nxyz"); + }, + "test: swap deltas insert/delete": function () { + session.setValue("012345"); + undoManager.startNewGroup(); + session.insert({row: 0, column: 5}, "yyyy"); + var rev = undoManager.startNewGroup(); + session.remove(new Range(0, 5, 0, 9)); + undoManager.markIgnored(rev); + editor.undo(); + assert.equal(editor.getValue(), "01234yyyy5"); + + editor.redo(); + undoManager.startNewGroup(); + session.insert({row: 0, column: 5}, "yyyy"); + var rev1 = undoManager.startNewGroup(); + session.remove(new Range(0, 1, 0, 4)); + undoManager.markIgnored(rev1); + editor.undo(); + assert.equal(editor.getValue(), "045"); + + editor.redo(); + undoManager.startNewGroup(); + session.insert({row: 0, column: 1}, "yyyy"); + var rev2 = undoManager.startNewGroup(); + session.remove(new Range(0, 7, 0, 9)); + undoManager.markIgnored(rev2); + editor.undo(); + assert.equal(editor.getValue(), "04yy5"); + }, + "test: swap deltas insert/insert": function () { + session.setValue("012345"); + undoManager.startNewGroup(); + session.insert({row: 0, column: 1}, "yyyy"); + var rev = undoManager.startNewGroup(); + session.insert({row: 0, column: 2}, "xxxx"); + undoManager.markIgnored(rev); + editor.undo(); + assert.equal(editor.getValue(), "0yyyy12345"); + + }, + "test: swap deltas delete/delete": function () { + session.setValue("012345"); + session.insert({row: 0, column: 5}, "zzzz"); + undoManager.startNewGroup(); + session.insert({row: 0, column: 5}, "yyyy"); + session.remove(new Range(0, 5, 0, 9)); + session.insert({row: 0, column: 5}, "aaaa"); + var rev = undoManager.startNewGroup(); + session.remove(new Range(0, 5, 0, 9)); + undoManager.markIgnored(rev); + editor.undo(); + assert.equal(editor.getValue(), "01234aaaazzzz5"); + + editor.undo(); + assert.equal(editor.getValue(), "01234zzzz5"); + + editor.redo(); + var rev1=undoManager.startNewGroup(); + session.insert({row: 0, column: 1}, "yyyy"); + session.remove(new Range(0, 0, 0, 1)); + undoManager.markIgnored(rev1); + editor.undo(); + assert.equal(editor.getValue(), "yyyy1234zzzz5"); + + undoManager.startNewGroup(); + session.remove(new Range(0, 0, 0, 1)); + var rev2=undoManager.startNewGroup(); + session.remove(new Range(0, 3, 0, 5)); + undoManager.markIgnored(rev2); + editor.undo(); + assert.equal(editor.getValue(), "yyyy34zzzz5"); + + editor.redo(); + undoManager.startNewGroup(); + session.remove(new Range(0, 3, 0, 5)); + var rev3=undoManager.startNewGroup(); + session.remove(new Range(0, 1, 0, 5)); + undoManager.markIgnored(rev3); + editor.undo(); + assert.equal(editor.getValue(), "yyyzzzz5"); + + }, + "test: xform deltas insert/insert": function () { + session.setValue("012345"); + session.insert({row: 0, column: 5}, "zzzz"); + undoManager.startNewGroup(); + session.insert({row: 0, column: 0}, "yyyy"); + editor.undo(); + session.insert({row: 0, column: 5}, "aaaa"); + editor.redo(); + assert.equal(editor.getValue(), "yyyy01234aaaazzzz5"); + }, + "test: xform deltas insert/delete": function () { + session.setValue("012345"); + session.insert({row: 0, column: 5}, "zzzz"); + undoManager.startNewGroup(); + session.insert({row: 0, column: 0}, "yyyy"); + editor.undo(); + session.remove(new Range(0, 0, 0, 1)); + editor.redo(); + assert.equal(editor.getValue(), "yyyy1234zzzz5"); + + session.setValue("012345"); + session.insert({row: 0, column: 5}, "zzzz"); + undoManager.startNewGroup(); + var rev=undoManager.startNewGroup(); + session.insert({row: 0, column: 0}, "yyyy"); + undoManager.markIgnored(rev); + editor.undo(); + session.remove(new Range(0, 0, 0, 1)); + editor.redo(); + assert.equal(editor.getValue(), "yyy01234zzzz5"); + }, + "test: xform deltas delete/insert": function () { + session.setValue("012345"); + session.insert({row: 0, column: 0}, "yyyy"); + undoManager.startNewGroup(); + session.remove(new Range(0, 0, 0, 1)); + editor.undo(); + session.insert({row: 0, column: 5}, "zzzz"); + editor.redo(); + assert.equal(editor.getValue(), "yyy0zzzz12345"); + }, + "test: xform deltas delete/delete": function () { + session.setValue("012345"); + session.insert({row: 0, column: 0}, "yyyy"); + undoManager.startNewGroup(); + session.remove(new Range(0, 3, 0, 4)); + editor.undo(); + session.remove(new Range(0, 4, 0, 5)); + editor.redo(); + assert.equal(editor.getValue(), "yyy12345"); + + session.setValue("012345"); + session.insert({row: 0, column: 0}, "yyyy"); + session.remove(new Range(0, 2, 0, 5)); + assert.equal(editor.getValue(), "yy12345"); + editor.undo(); + assert.equal(editor.getValue(), "012345"); + session.remove(new Range(0, 1, 0, 2)); + editor.redo(); + assert.equal(editor.getValue(), "yy2345"); + + session.setValue("1234abcd ---"); + session.insert({row: 0, column: 0}, "ijkl"); + session.remove(new Range(0, 2, 0, 8)); + editor.undo(); + session.remove(new Range(0, 4, 0, 7)); + editor.redo(); + assert.equal(editor.getValue(), "ijd ---"); + assert.equal(undoManager.$prettyPrint(), '-[abc]0:4=>0:7\t(12)\n+[ijkl]0:0=>0:4\t(13)\n-[kl1234]0:2=>0:8\n---\n'); } }; diff --git a/plugins/node_modules/ace/lib/ace/virtual_renderer.js b/plugins/node_modules/ace/lib/ace/virtual_renderer.js index 87ee6ad3..aa69708e 100644 --- a/plugins/node_modules/ace/lib/ace/virtual_renderer.js +++ b/plugins/node_modules/ace/lib/ace/virtual_renderer.js @@ -34,7 +34,6 @@ define(function(require, exports, module) { var oop = require("./lib/oop"); var dom = require("./lib/dom"); var config = require("./config"); -var useragent = require("./lib/useragent"); var GutterLayer = require("./layer/gutter").Gutter; var MarkerLayer = require("./layer/marker").Marker; var TextLayer = require("./layer/text").Text; @@ -68,6 +67,7 @@ var VirtualRenderer = function(container, theme) { this.container = container || dom.createElement("div"); dom.addCssClass(this.container, "ace_editor"); + if (dom.HI_DPI) dom.addCssClass(this.container, "ace_hidpi"); this.setTheme(theme); @@ -78,6 +78,7 @@ var VirtualRenderer = function(container, theme) { this.scroller = dom.createElement("div"); this.scroller.className = "ace_scroller"; + this.container.appendChild(this.scroller); this.content = dom.createElement("div"); @@ -238,7 +239,7 @@ var VirtualRenderer = function(container, theme) { return; this.$loop.schedule(this.CHANGE_FULL); - // this.session.$setFontMetrics(this.$fontMetrics); + this.session.$setFontMetrics(this.$fontMetrics); this.scrollBarH.scrollLeft = this.scrollBarV.scrollTop = null; this.onChangeNewLineMode = this.onChangeNewLineMode.bind(this); @@ -405,18 +406,20 @@ var VirtualRenderer = function(container, theme) { this.gutterWidth = gutterWidth; - this.scrollBarH.element.style.left = - this.scroller.style.left = gutterWidth + "px"; + dom.setStyle(this.scrollBarH.element.style, "left", gutterWidth + "px"); + dom.setStyle(this.scroller.style, "left", gutterWidth + "px"); size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBarV.getWidth()); - this.scrollBarH.element.style.right = - this.scroller.style.right = this.scrollBarV.getWidth() + "px"; - this.scroller.style.bottom = this.scrollBarH.getHeight() + "px"; + var right = this.scrollBarV.getWidth() + "px"; + dom.setStyle(this.scrollBarH.element.style, "right", right); + dom.setStyle(this.scroller.style, "right", right); + dom.setStyle(this.scroller.style, "bottom", this.scrollBarH.getHeight()); // this.scrollBarH.element.style.setWidth(size.scrollerWidth); - if (this.session && this.session.getUseWrapMode() && this.adjustWrapLimit() || force) + if (this.session && this.session.getUseWrapMode() && this.adjustWrapLimit() || force) { changes |= this.CHANGE_FULL; + } } size.$dirty = !width || !height; @@ -427,8 +430,8 @@ var VirtualRenderer = function(container, theme) { return changes; }; - this.onGutterResize = function() { - var gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0; + this.onGutterResize = function(width) { + var gutterWidth = this.$showGutter ? width : 0; if (gutterWidth != this.gutterWidth) this.$changes |= this.$updateCachedSize(true, gutterWidth, this.$size.width, this.$size.height); @@ -438,7 +441,6 @@ var VirtualRenderer = function(container, theme) { this.$loop.schedule(this.CHANGE_FULL); } else { this.$computeLayerConfig(); - this.$loop.schedule(this.CHANGE_MARKER); } }; @@ -559,19 +561,6 @@ var VirtualRenderer = function(container, theme) { return this.getOption("highlightGutterLine"); }; - this.$updateGutterLineHighlight = function() { - var pos = this.$cursorLayer.$pixelPos; - var height = this.layerConfig.lineHeight; - if (this.session.getUseWrapMode()) { - var cursor = this.session.selection.getCursor(); - cursor.column = 0; - pos = this.$cursorLayer.getPixelPosition(cursor, true); - height *= this.session.getRowLength(cursor.row); - } - this.$gutterLineHighlight.style.top = pos.top - this.layerConfig.offset + "px"; - this.$gutterLineHighlight.style.height = height + "px"; - }; - this.$updatePrintMargin = function() { if (!this.$showPrintMargin && !this.$printMarginEl) return; @@ -625,9 +614,11 @@ var VirtualRenderer = function(container, theme) { this.$moveTextAreaToCursor = function() { var style = this.textarea.style; if (!this.$keepTextAreaAtCursor) { - style.left = -100 + "px"; + dom.translate(this.textarea, -100, 0); return; } + if (!this.$cursorLayer.$pixelPos) + return; var config = this.layerConfig; var posTop = this.$cursorLayer.$pixelPos.top; var posLeft = this.$cursorLayer.$pixelPos.left; @@ -635,7 +626,7 @@ var VirtualRenderer = function(container, theme) { var h = this.lineHeight; if (posTop < 0 || posTop > config.height - h) { - style.top = style.left = "0"; + dom.translate(this.textarea, 0, 0); return; } @@ -650,10 +641,9 @@ var VirtualRenderer = function(container, theme) { posLeft = this.$size.scrollerWidth - w; posLeft += this.gutterWidth; - style.height = h + "px"; - style.width = w + "px"; - style.left = Math.min(posLeft, this.$size.scrollerWidth - w) + "px"; - style.top = Math.min(posTop, this.$size.height - h) + "px"; + dom.setStyle(style, "height", h + "px"); + dom.setStyle(style, "width", w + "px"); + dom.translate(this.textarea, Math.min(posLeft, this.$size.scrollerWidth - w), Math.min(posTop, this.$size.height - h)); }; /** @@ -836,15 +826,20 @@ var VirtualRenderer = function(container, theme) { this.$updateScrollBarV(); if (changes & this.CHANGE_H_SCROLL) this.$updateScrollBarH(); - this.$gutterLayer.element.style.marginTop = (-config.offset) + "px"; - this.content.style.marginTop = (-config.offset) + "px"; - this.content.style.width = config.width + 2 * this.$padding + "px"; - this.content.style.height = config.minHeight + "px"; + + dom.translate(this.$gutter, 0, -config.offset); + dom.translate(this.content, -this.scrollLeft, -config.offset); + + var width = config.width + 2 * this.$padding + "px"; + var height = config.minHeight + "px"; + + dom.setStyle(this.content.style, "width", width); + dom.setStyle(this.content.style, "height", height); } // horizontal scrolling if (changes & this.CHANGE_H_SCROLL) { - this.content.style.marginLeft = -this.scrollLeft + "px"; + dom.translate(this.content, -this.scrollLeft, -config.offset); this.scroller.className = this.scrollLeft <= 0 ? "ace_scroller" : "ace_scroller ace_scroll-left"; } @@ -857,7 +852,6 @@ var VirtualRenderer = function(container, theme) { this.$markerFront.update(config); this.$cursorLayer.update(config); this.$moveTextAreaToCursor(); - this.$highlightGutterLine && this.$updateGutterLineHighlight(); this._signal("afterRender"); return; } @@ -869,12 +863,15 @@ var VirtualRenderer = function(container, theme) { else this.$textLayer.scrollLines(config); - if (this.$showGutter) - this.$gutterLayer.update(config); + if (this.$showGutter) { + if (changes & this.CHANGE_GUTTER) + this.$gutterLayer.update(config); + else + this.$gutterLayer.scrollLines(config); + } this.$markerBack.update(config); this.$markerFront.update(config); this.$cursorLayer.update(config); - this.$highlightGutterLine && this.$updateGutterLineHighlight(); this.$moveTextAreaToCursor(); this._signal("afterRender"); return; @@ -893,11 +890,14 @@ var VirtualRenderer = function(container, theme) { if (this.$showGutter) this.$gutterLayer.update(config); } + else if (changes & this.CHANGE_CURSOR) { + if (this.$highlightGutterLine) + this.$gutterLayer.updateLineHighlight(config); + } if (changes & this.CHANGE_CURSOR) { this.$cursorLayer.update(config); this.$moveTextAreaToCursor(); - this.$highlightGutterLine && this.$updateGutterLineHighlight(); } if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT)) { @@ -922,7 +922,9 @@ var VirtualRenderer = function(container, theme) { desiredHeight += this.scrollBarH.getHeight(); if (this.$maxPixelHeight && desiredHeight > this.$maxPixelHeight) desiredHeight = this.$maxPixelHeight; - var vScroll = height > maxHeight; + + var hideScrollbars = desiredHeight <= 2 * this.lineHeight; + var vScroll = !hideScrollbars && height > maxHeight; if (desiredHeight != this.desiredHeight || this.$size.height != this.desiredHeight || vScroll != this.$vScroll) { @@ -1442,7 +1444,7 @@ var VirtualRenderer = function(container, theme) { var offset = offsetX / this.characterWidth; var col = this.$blockCursor ? Math.floor(offset) : Math.round(offset); - var row = (y + this.scrollTop - canvasPos.top) / this.lineHeight; + var row = Math.floor((y + this.scrollTop - canvasPos.top) / this.lineHeight); return this.session.screenToDocumentPosition(row, Math.max(col, 0), offsetX); }; @@ -1615,8 +1617,7 @@ var VirtualRenderer = function(container, theme) { }; this.setCursorStyle = function(style) { - if (this.scroller.style.cursor != style) - this.scroller.style.cursor = style; + dom.setStyle(this.scroller.style, "cursor", style); }; /** @@ -1624,7 +1625,7 @@ var VirtualRenderer = function(container, theme) { * **/ this.setMouseCursor = function(cursorStyle) { - this.scroller.style.cursor = cursorStyle; + dom.setStyle(this.scroller.style, "cursor", cursorStyle); }; this.attachToShadowRoot = function() { @@ -1688,13 +1689,6 @@ config.defineOptions(VirtualRenderer.prototype, "renderer", { set: function(show) {this.$gutterLayer.setShowFoldWidgets(show);}, initialValue: true }, - showLineNumbers: { - set: function(show) { - this.$gutterLayer.setShowLineNumbers(show); - this.$loop.schedule(this.CHANGE_GUTTER); - }, - initialValue: true - }, displayIndentGuides: { set: function(show) { if (this.$textLayer.setDisplayIndentGuides(show)) @@ -1704,20 +1698,10 @@ config.defineOptions(VirtualRenderer.prototype, "renderer", { }, highlightGutterLine: { set: function(shouldHighlight) { - if (!this.$gutterLineHighlight) { - this.$gutterLineHighlight = dom.createElement("div"); - this.$gutterLineHighlight.className = "ace_gutter-active-line"; - this.$gutter.appendChild(this.$gutterLineHighlight); - return; - } - - this.$gutterLineHighlight.style.display = shouldHighlight ? "" : "none"; - // if cursorlayer have never been updated there's nothing on screen to update - if (this.$cursorLayer.$pixelPos) - this.$updateGutterLineHighlight(); + this.$gutterLayer.setHighlightGutterLine(shouldHighlight); + this.$loop.schedule(this.CHANGE_GUTTER); }, - initialValue: false, - value: true + initialValue: true }, hScrollBarAlwaysVisible: { set: function(val) { @@ -1733,7 +1717,7 @@ config.defineOptions(VirtualRenderer.prototype, "renderer", { }, initialValue: false }, - fontSize: { + fontSize: { set: function(size) { if (typeof size == "number") size = size + "px"; diff --git a/plugins/node_modules/ace/lib/ace/virtual_renderer_test.js b/plugins/node_modules/ace/lib/ace/virtual_renderer_test.js index 3bb98685..f58e7bc0 100644 --- a/plugins/node_modules/ace/lib/ace/virtual_renderer_test.js +++ b/plugins/node_modules/ace/lib/ace/virtual_renderer_test.js @@ -43,9 +43,10 @@ var assert = require("./test/assertions"); require("./ext/error_marker"); function setScreenPosition(node, rect) { - node.getBoundingClientRect = function() { - return { left: rect[0], top: rect[1], width: rect[2], height: rect[3] }; - }; + node.style.left = rect[0] + "px"; + node.style.top = rect[1] + "px"; + node.style.width = rect[2] + "px"; + node.style.height = rect[3] + "px"; } var editor = null; @@ -147,8 +148,6 @@ module.exports = { editor.renderer.setScrollMargin(10, 10); editor.setValue("\n\n"); editor.setValue("\n\n\n\n"); - if (editor.container.offsetWidth == undefined) - return done(); // jsdom editor.renderer.once("afterRender", function() { setTimeout(function() { done(); @@ -162,6 +161,11 @@ module.exports = { editor.execCommand(editor.commands.byName.goToNextError); assert.position(editor.getCursorPosition(), 1, 2); assert.ok(editor.session.lineWidgets[1]); + }, + + "test resize": function() { + editor.setValue("Juhu kinners!"); + editor.resize(true); } // change tab size after setDocument (for text layer)