pull/488/merge
nightwing 2018-04-06 14:45:02 +04:00
rodzic dd1a54fd1f
commit c8ca347f5d
47 zmienionych plików z 2566 dodań i 774 usunięć

2
plugins/node_modules/ace/lib/ace/ace.js wygenerowano vendored
Wyświetl plik

@ -131,5 +131,5 @@ exports.Range = Range;
exports.EditSession = EditSession; exports.EditSession = EditSession;
exports.UndoManager = UndoManager; exports.UndoManager = UndoManager;
exports.VirtualRenderer = Renderer; exports.VirtualRenderer = Renderer;
exports.version = "1.3.1"; exports.version = "1.3.3";
}); });

89
plugins/node_modules/ace/lib/ace/ace_test.js wygenerowano vendored 100644
Wyświetl plik

@ -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();
}

Wyświetl plik

@ -24,6 +24,7 @@
position: absolute; position: absolute;
box-sizing: border-box; box-sizing: border-box;
min-width: 100%; min-width: 100%;
contain: style size layout;
} }
.ace_dragging .ace_scroller:before{ .ace_dragging .ace_scroller:before{
@ -57,6 +58,7 @@
-moz-user-select: none; -moz-user-select: none;
-webkit-user-select: none; -webkit-user-select: none;
user-select: none; user-select: none;
contain: style size layout;
} }
.ace_gutter-active-line { .ace_gutter-active-line {
@ -70,6 +72,10 @@
} }
.ace_gutter-cell { .ace_gutter-cell {
position: absolute;
top: 0;
left: 0;
right: 0;
padding-left: 19px; padding-left: 19px;
padding-right: 6px; padding-right: 6px;
background-repeat: no-repeat; background-repeat: no-repeat;
@ -95,6 +101,7 @@
} }
.ace_scrollbar { .ace_scrollbar {
contain: strict;
position: absolute; position: absolute;
right: 0; right: 0;
bottom: 0; bottom: 0;
@ -188,10 +195,36 @@
width: auto; width: auto;
text-align: right; text-align: right;
pointer-events: auto; pointer-events: auto;
height: 1000000px;
contain: style size layout;
} }
.ace_text-layer { .ace_text-layer {
font: inherit !important; 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 { .ace_cjk {
@ -233,6 +266,31 @@
transition: opacity 0.18s; 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 { .ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {
position: absolute; position: absolute;
z-index: 3; z-index: 3;
@ -435,10 +493,6 @@
position: absolute; position: absolute;
z-index: 8; z-index: 8;
} }
.ace_lineWidgetContainer {
z-index: 5;
position: absolute;
}
/* /*
styles = [] styles = []

Wyświetl plik

@ -1159,7 +1159,6 @@ EditSession.$uid = 0;
} }
} }
if (!dontSelect && this.$undoSelect) { if (!dontSelect && this.$undoSelect) {
// console.log(deltas.selectionBefore + "uuu")
if (deltas.selectionBefore) if (deltas.selectionBefore)
this.selection.fromJSON(deltas.selectionBefore); this.selection.fromJSON(deltas.selectionBefore);
else else
@ -2379,6 +2378,7 @@ EditSession.$uid = 0;
* *
*/ */
this.$setFontMetrics = function(fm) { this.$setFontMetrics = function(fm) {
if (!this.$enableVarChar) return;
this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) { this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) {
if (maxScreenColumn === 0) if (maxScreenColumn === 0)
return [0, 0]; return [0, 0];
@ -2555,7 +2555,8 @@ config.defineOptions(EditSession.prototype, "session", {
}, },
mode: { mode: {
set: function(val) { this.setMode(val); }, set: function(val) { this.setMode(val); },
get: function() { return this.$modeId; } get: function() { return this.$modeId; },
handlesSet: true
} }
}); });

Wyświetl plik

@ -31,8 +31,6 @@
define(function(require, exports, module) { define(function(require, exports, module) {
"use strict"; "use strict";
require("./lib/fixoldbrowsers");
var oop = require("./lib/oop"); var oop = require("./lib/oop");
var dom = require("./lib/dom"); var dom = require("./lib/dom");
var lang = require("./lib/lang"); var lang = require("./lib/lang");
@ -876,8 +874,8 @@ Editor.$uid = 0;
* Returns the string of text currently highlighted. * Returns the string of text currently highlighted.
* @returns {String} * @returns {String}
**/ **/
this.getSelectedText = function(newLineCharacter) { this.getSelectedText = function() {
return this.session.getTextRange(this.getSelectionRange(), newLineCharacter); return this.session.getTextRange(this.getSelectionRange());
}; };
/** /**
@ -891,7 +889,7 @@ Editor.$uid = 0;
* @returns {String} * @returns {String}
**/ **/
this.getCopyText = function() { this.getCopyText = function() {
var text = this.getSelectedText(useragent.isWin ? "\r\n" : "\n"); var text = this.getSelectedText();
var nl = this.session.doc.getNewLineCharacter(); var nl = this.session.doc.getNewLineCharacter();
var copyLine= false; var copyLine= false;
if (!text && this.$copyWithEmptySelection) { if (!text && this.$copyWithEmptySelection) {
@ -980,10 +978,6 @@ Editor.$uid = 0;
return this.commands.exec(command, this, args); return this.commands.exec(command, this, args);
}; };
this.transformAction = function(type, text) {
};
/** /**
* Inserts `text` into wherever the cursor is pointing. * Inserts `text` into wherever the cursor is pointing.
* @param {String} text The new text to add * @param {String} text The new text to add
@ -2693,6 +2687,26 @@ config.defineOptions(Editor.prototype, "editor", {
handlesSet: true, handlesSet: true,
hidden: 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", hScrollBarAlwaysVisible: "renderer",
vScrollBarAlwaysVisible: "renderer", vScrollBarAlwaysVisible: "renderer",
@ -2704,9 +2718,8 @@ config.defineOptions(Editor.prototype, "editor", {
printMargin: "renderer", printMargin: "renderer",
fadeFoldWidgets: "renderer", fadeFoldWidgets: "renderer",
showFoldWidgets: "renderer", showFoldWidgets: "renderer",
showLineNumbers: "renderer",
showGutter: "renderer",
displayIndentGuides: "renderer", displayIndentGuides: "renderer",
showGutter: "renderer",
fontSize: "renderer", fontSize: "renderer",
fontFamily: "renderer", fontFamily: "renderer",
maxLines: "renderer", maxLines: "renderer",
@ -2715,6 +2728,7 @@ config.defineOptions(Editor.prototype, "editor", {
fixedWidthGutter: "renderer", fixedWidthGutter: "renderer",
theme: "renderer", theme: "renderer",
hasCssTransforms: "renderer", hasCssTransforms: "renderer",
maxPixelHeight: "renderer",
scrollSpeed: "$mouseHandler", scrollSpeed: "$mouseHandler",
dragDelay: "$mouseHandler", dragDelay: "$mouseHandler",
@ -2735,5 +2749,33 @@ config.defineOptions(Editor.prototype, "editor", {
mode: "session" 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; exports.Editor = Editor;
}); });

Wyświetl plik

@ -52,13 +52,17 @@ exports.beautify = function(session) {
var blockTags = exports.blockTags; var blockTags = exports.blockTags;
var nextToken; var nextToken;
var breakBefore = false; var breakBefore = false;
var spaceBefore = false;
var spaceAfter = false;
var code = ""; var code = "";
var value = ""; var value = "";
var tagName = ""; var tagName = "";
var depth = 0;
var lastDepth = 0;
var lastIndent = 0;
var indent = 0; var indent = 0;
var inBlock = false; var unindent = 0;
var inComment = false; var roundDepth = 0;
var inCase = false;
var onCaseLine = false; var onCaseLine = false;
var row; var row;
var curRow = 0; var curRow = 0;
@ -67,176 +71,314 @@ exports.beautify = function(session) {
var abort = false; var abort = false;
var i; var i;
var indentNextLine = false; 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) { while (token !== null) {
value = token.value;
curRow = iterator.getCurrentTokenRow(); curRow = iterator.getCurrentTokenRow();
rowTokens = iterator.$rowTokens; rowTokens = iterator.$rowTokens;
nextToken = iterator.stepForward(); nextToken = iterator.stepForward();
// are we in a block tag if (typeof token !== "undefined") {
if (is(token, "tag-open") && value === "<" && nextToken) value = token.value;
inBlock = (blockTags.indexOf(nextToken.value) !== -1); unindent = 0;
// comments // mode
if (is(token, "comment.start")) { inCSS = (tagName === "style" || session.$modeId === "ace/mode/css");
inComment = true;
inBlock = true;
} else if (is(token, "comment.end")) {
inComment = false;
inBlock = false;
}
// html indentation // in tag
if (is(token, "tag-open") && value === "</") { if (is(token, "tag-open")) {
// line break before closing tag unless we just had one inTag = true;
if (is(token, "tag-open") && value === "</" && inBlock && !breakBefore)
// are we in a block tag
if (nextToken)
inBlock = (blockTags.indexOf(nextToken.value) !== -1);
// html indentation
if (value === "</") {
// line break before closing tag unless we just had one
if (inBlock && !breakBefore && rowsToAdd < 1)
rowsToAdd++;
if (inCSS)
rowsToAdd = 1;
unindent = 1;
inBlock = false;
}
} else if (is(token, "tag-close")) {
inTag = false;
// comments
} else if (is(token, "comment.start")) {
inBlock = true;
} else if (is(token, "comment.end")) {
inBlock = false;
}
// line break before }
if (!inTag && !rowsToAdd && token.type === "paren.rparen" && token.value.substr(0, 1) === "}") {
rowsToAdd++; rowsToAdd++;
indent--;
inBlock = false;
}
// switch case
onCaseLine = false;
if (token.type === "keyword" && value.match(/^(case|default)$/)) {
onCaseLine = true;
inCase = true;
} else if (token.type === "keyword" && value === "break")
inCase = false;
// add rows
if (curRow != row) {
rowsToAdd = curRow;
if (row)
rowsToAdd -= row;
}
if (rowsToAdd) {
code = code.trimRight();
for (; rowsToAdd > 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 // add rows
if (curRow != row && rowTokens) { if (curRow !== row) {
abort = false; rowsToAdd = curRow;
for (i = 0; i<rowTokens.length && !abort; i++) {
if (rowTokens[i].type == "paren.rparen") { if (row)
indent--; rowsToAdd -= row;
abort = true;
} else if (rowTokens[i].type == "paren.lparen")
abort = true;
}
} }
// add indent to code if (rowsToAdd) {
if (breakBefore && !is(token, "comment")) { trimCode();
var count = indent; for (; rowsToAdd > 0; rowsToAdd--)
if (inCase && !onCaseLine) code += "\n";
count++;
if (indentNextLine) { breakBefore = true;
count++;
indentNextLine = false;
}
for (i = 0; i < count; i++) // trim value if not in a comment or string
code += tabString; if (!is(token, "comment") && !token.type.match(/^(comment|string)$/))
value = value.trimLeft();
} }
// indent if there are last paren is opening if (value) {
if (curRow != row && rowTokens) { // whitespace
indentNextLine = null; if (token.type === "keyword" && value.match(/^(if|else|elseif|for|foreach|while|switch)$/)) {
abort = false; parents[depth] = value;
for (i = rowTokens.length-1; i>=0 && !abort; i--) {
if (rowTokens[i].type == "paren.rparen") { trimNext();
abort = true; spaceAfter = true;
} else if (rowTokens[i].type == "paren.lparen") {
// 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++; indent++;
indentNextLine = false; 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 === "</")
rowsToAdd = -1;
else
rowsToAdd = 1;
}
// html indentation
if (is(token, "tag-open") && value === "</") {
depth--;
// indent after opening tag
} else if (is(token, "tag-open") && value === "<" && singletonTags.indexOf(nextToken.value) === -1) {
depth++;
// remove indent if unknown singleton
} else if (is(token, "tag-name")) {
tagName = value;
} else if (is(token, "tag-close") && 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 === "</")
rowsToAdd--;
else
rowsToAdd++;
}
// indent after opening tag
if (is(token, "tag-open") && value === "<" && singletonTags.indexOf(nextToken.value) === -1)
indent++;
// remove indent if unknown singleton
if (is(token, "tag-name"))
tagName = value;
if (is(token, "tag-close") && value === "/>" && singletonTags.indexOf(tagName) === -1)
indent--;
row = curRow;
} }
token = nextToken; token = nextToken;

Wyświetl plik

@ -14,17 +14,31 @@ var PHPMode = require("../mode/php").Mode;
module.exports = { module.exports = {
timeout: 10000, 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) { "test beautify block tag indentation": function(next) {
var s = new EditSession([ var s = new EditSession([
"<div>", "<div>",
"<h1>test</h1>", "<h1>hello</h1>",
"</div>" "world</div>"
], new PHPMode()); ], new PHPMode());
s.setUseSoftTabs(false); s.setUseSoftTabs(false);
beautify.beautify(s); beautify.beautify(s);
assert.equal(s.getValue(), "<div>\n" assert.equal(s.getValue(), "<div>\n"
+ "\t<h1>test</h1>\n" + "\t<h1>hello</h1>\n"
+ "\tworld\n"
+ "</div>"); + "</div>");
next(); next();
@ -133,16 +147,24 @@ module.exports = {
"test beautify curly indentation": function(next) { "test beautify curly indentation": function(next) {
var s = new EditSession([ var s = new EditSession([
"<?php", "<?php",
"if (true) {", "if ($foo===array()) {",
"$i++;", "$i++;",
"}",
"if (($foo ||",
"$bar)) {",
"true;",
"}" "}"
], new PHPMode()); ], new PHPMode());
s.setUseSoftTabs(false); s.setUseSoftTabs(false);
beautify.beautify(s); beautify.beautify(s);
assert.equal(s.getValue(), "<?php\n" assert.equal(s.getValue(), "<?php\n"
+ "if (true) {\n" + "if ($foo === array()) {\n"
+ "\t$i++;\n" + "\t$i++;\n"
+ "}\n"
+ "if (($foo ||\n"
+ "\t$bar)) {\n"
+ "\ttrue;\n"
+ "}"); + "}");
next(); next();
@ -205,16 +227,18 @@ module.exports = {
"test beautify if without paren": function(next) { "test beautify if without paren": function(next) {
var s = new EditSession([ var s = new EditSession([
"<?php", "<?php",
"if ($foo===true)", "if ($foo)",
"$i++;", "$i++;",
"if ($foo) $j++",
"print $i" "print $i"
], new PHPMode()); ], new PHPMode());
s.setUseSoftTabs(false); s.setUseSoftTabs(false);
beautify.beautify(s); beautify.beautify(s);
assert.equal(s.getValue(), "<?php\n" assert.equal(s.getValue(), "<?php\n"
+ "if ($foo === true)\n" + "if ($foo)\n"
+ "\t$i++;\n" + "\t$i++;\n"
+ "if ($foo) $j++\n"
+ "print $i"); + "print $i");
next(); next();
@ -225,9 +249,10 @@ module.exports = {
"<?php", "<?php",
"switch ($i) {", "switch ($i) {",
"case 1;", "case 1;",
"case 2;", "print $foo;",
"print $i;",
"break;", "break;",
"case 2;",
"print $bar;",
"}" "}"
], new PHPMode()); ], new PHPMode());
s.setUseSoftTabs(false); s.setUseSoftTabs(false);
@ -236,11 +261,137 @@ module.exports = {
assert.equal(s.getValue(), "<?php\n" assert.equal(s.getValue(), "<?php\n"
+ "switch ($i) {\n" + "switch ($i) {\n"
+ "\tcase 1;\n" + "\tcase 1;\n"
+ "\t\tprint $foo;\n"
+ "\t\tbreak;\n"
+ "\tcase 2;\n" + "\tcase 2;\n"
+ "\t\tprint $i;\n" + "\t\tprint $bar;\n"
+ "\tbreak;\n"
+ "}"); + "}");
next();
},
"test beautify multiline string": function(next) {
var s = new EditSession([
"<?php",
"\tprint 'hello",
"\t\tworld'"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<?php\n"
+ "print 'hello\n"
+ "\t\tworld'");
next();
},
"test beautify remove spaces before semicolons": function(next) {
var s = new EditSession([
"<?php echo \"hello world\";?>",
"<?php",
"$foo = \"hello \" ;$bar = \"world\";",
"print $foo.$bar;"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<?php echo \"hello world\"; ?>\n"
+ "<?php\n"
+ "$foo = \"hello \"; $bar = \"world\";\n"
+ "print $foo.$bar;");
next();
},
"test beautify tag whitepace": function(next) {
var s = new EditSession([
"<form id=\"\" action = \"\" method=\"get\" >",
"\t<br />",
"</form >"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<form id=\"\" action=\"\" method=\"get\">\n"
+ "\t<br />\n"
+ "</form>");
next();
},
"test beautify css": function(next) {
var s = new EditSession([
"<style>h1{font-size: 20px;}p{font-size:14px; padding:10px;}</style>"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<style>\n"
+ "\th1 {\n"
+ "\t\tfont-size: 20px;\n"
+ "\t}\n"
+ "\n"
+ "\tp {\n"
+ "\t\tfont-size: 14px;\n"
+ "\t\tpadding: 10px;\n"
+ "\t}\n"
+ "</style>");
next();
},
"test beautify comments": function(next) {
var s = new EditSession([
"<?php\n",
"if(true) //break me\n",
"{}\n",
"?>\n",
"<!--\n",
"\thello\n",
"\t\tworld\n",
"-->"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<?php\n"
+ "if (true) //break me\n"
+ "{}\n"
+ "?>\n"
+ "<!--\n"
+ "\thello\n"
+ "\t\tworld\n"
+ "-->");
next();
},
"test beautify js array of objects": function(next) {
var s = new EditSession([
"<script>\n",
"var foo = [",
"\t{ \n",
"\t\tbar: \"hello\", \n",
"\t\tbar2: {}\n",
"\t},{\n",
"\t\t\"bar\": true\n",
"\t}\n",
"];\n",
"</script>"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<script>\n"
+ "\tvar foo = [{\n"
+ "\t\tbar: \"hello\",\n"
+ "\t\tbar2: {}\n"
+ "\t}, {\n"
+ "\t\t\"bar\": true\n"
+ "\t}];\n"
+ "</script>");
next(); next();
} }
}; };

Wyświetl plik

@ -414,7 +414,7 @@ exports.isAvailable = function(editor, command) {
// TODO refactor mode delegates to make this simpler // TODO refactor mode delegates to make this simpler
try { try {
editorProxy.setupContext(editor); editorProxy.setupContext(editor);
if (/^(js|php)/.test(editorProxy.getSyntax())) if (/js|php/.test(editorProxy.getSyntax()))
isSupported = false; isSupported = false;
} catch(e) {} } catch(e) {}
} }

Wyświetl plik

@ -49,6 +49,7 @@ var supportedModes = {
ADA: ["ada|adb"], ADA: ["ada|adb"],
Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"], Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"],
AsciiDoc: ["asciidoc|adoc"], AsciiDoc: ["asciidoc|adoc"],
ASL: ["dsl|asl"],
Assembly_x86:["asm|a"], Assembly_x86:["asm|a"],
AutoHotKey: ["ahk"], AutoHotKey: ["ahk"],
BatchFile: ["bat|cmd"], BatchFile: ["bat|cmd"],

Wyświetl plik

@ -129,6 +129,15 @@ var optionGroups = {
"Show Gutter": { "Show Gutter": {
path: "showGutter" path: "showGutter"
}, },
"Show Line Numbers": {
path: "showLineNumbers"
},
"Relative Line Numbers": {
path: "relativeLineNumbers"
},
"Fixed Gutter Width": {
path: "fixedWidthGutter"
},
"Show Print Margin": [{ "Show Print Margin": [{
path: "showPrintMargin" path: "showPrintMargin"
}, { }, {

Wyświetl plik

@ -37,8 +37,77 @@ var baseStyles = require("../requirejs/text!./static.css");
var config = require("../config"); var config = require("../config");
var dom = require("../lib/dom"); 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<element.childNodes.length; i++) {
var child = element.childNodes[i];
if (typeof child == "string")
stringBuilder.push(child);
else
stringBuilder.push(child.toString());
}
}
if (element.type != "fragment") {
stringBuilder.push("</", element.type, ">");
}
return stringBuilder.join("");
}
};
return element;
},
createFragment: function() {
return this.createElement("fragment");
}
};
var SimpleTextLayer = function() { var SimpleTextLayer = function() {
this.config = {}; this.config = {};
this.dom = simpleDom;
}; };
SimpleTextLayer.prototype = TextLayer.prototype; SimpleTextLayer.prototype = TextLayer.prototype;
@ -64,7 +133,7 @@ var highlight = function(el, opts, callback) {
} }
} }
} else { } else {
data = dom.getInnerText(el); data = el.textContent;
if (opts.trim) if (opts.trim)
data = data.trim(); data = data.trim();
} }
@ -157,31 +226,38 @@ highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) {
textLayer.setSession(session); textLayer.setSession(session);
session.setValue(input); session.setValue(input);
var stringBuilder = [];
var length = session.getLength(); 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++) { for (var ix = 0; ix < length; ix++) {
stringBuilder.push("<div class='ace_line'>"); var lineEl = simpleDom.createElement("div");
if (!disableGutter) lineEl.className = "ace_line";
stringBuilder.push("<span class='ace_gutter ace_gutter-cell' unselectable='on'>" + /*(ix + lineStart) + */ "</span>");
textLayer.$renderLine(stringBuilder, ix, true, false); if (!disableGutter) {
stringBuilder.push("\n</div>"); 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 //console.log(JSON.stringify(outerEl, null, 2));
var html = "<div class='" + theme.cssClass + "'>" + //console.log(outerEl.toString());
"<div class='ace_static_highlight" + (disableGutter ? "" : " ace_show_gutter") +
"' style='counter-reset:ace_line " + (lineStart - 1) + "'>" +
stringBuilder.join("") +
"</div>" +
"</div>";
textLayer.destroy(); textLayer.destroy();
return { return {
css: baseStyles + theme.cssText, css: baseStyles + theme.cssText,
html: html, html: outerEl.toString(),
session: session session: session
}; };
}; };

Wyświetl plik

@ -35,12 +35,12 @@ module.exports = {
var result = highlighter.render(snippet, mode, theme); var result = highlighter.render(snippet, mode, theme);
assert.equal(result.html, "<div class='ace-tomorrow'><div class='ace_static_highlight ace_show_gutter' style='counter-reset:ace_line 0'>" assert.equal(result.html, "<div class='ace-tomorrow'><div class='ace_static_highlight ace_show_gutter' style='counter-reset:ace_line 0'>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_comment ace_doc'>/** this is a function</span>\n</div>" + "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_comment ace_doc'>/** this is a function</span></div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_comment ace_doc'>*</span>\n</div>" + "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_comment ace_doc'>*</span></div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_comment ace_doc'>*/</span>\n</div>" + "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_comment ace_doc'>*/</span></div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_storage ace_type'>function</span> <span class='ace_entity ace_name ace_function'>hello</span> <span class='ace_paren ace_lparen'>(</span><span class='ace_variable ace_parameter'>a</span><span class='ace_punctuation ace_operator'>, </span><span class='ace_variable ace_parameter'>b</span><span class='ace_punctuation ace_operator'>, </span><span class='ace_variable ace_parameter'>c</span><span class='ace_paren ace_rparen'>)</span> <span class='ace_paren ace_lparen'>{</span>\n</div>" + "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_storage ace_type'>function</span> <span class='ace_entity ace_name ace_function'>hello</span> <span class='ace_paren ace_lparen'>(</span><span class='ace_variable ace_parameter'>a</span><span class='ace_punctuation ace_operator'>, </span><span class='ace_variable ace_parameter'>b</span><span class='ace_punctuation ace_operator'>, </span><span class='ace_variable ace_parameter'>c</span><span class='ace_paren ace_rparen'>)</span> <span class='ace_paren ace_lparen'>{</span></div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span> <span class='ace_storage ace_type'>console</span><span class='ace_punctuation ace_operator'>.</span><span class='ace_support ace_function ace_firebug'>log</span><span class='ace_paren ace_lparen'>(</span><span class='ace_identifier'>a</span> <span class='ace_keyword ace_operator'>*</span> <span class='ace_identifier'>b</span> <span class='ace_keyword ace_operator'>+</span> <span class='ace_identifier'>c</span> <span class='ace_keyword ace_operator'>+</span> <span class='ace_string'>'sup$'</span><span class='ace_paren ace_rparen'>)</span><span class='ace_punctuation ace_operator'>;</span>\n</div>" + "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span> <span class='ace_storage ace_type'>console</span><span class='ace_punctuation ace_operator'>.</span><span class='ace_support ace_function ace_firebug'>log</span><span class='ace_paren ace_lparen'>(</span><span class='ace_identifier'>a</span> <span class='ace_keyword ace_operator'>*</span> <span class='ace_identifier'>b</span> <span class='ace_keyword ace_operator'>+</span> <span class='ace_identifier'>c</span> <span class='ace_keyword ace_operator'>+</span> <span class='ace_string'>'sup$'</span><span class='ace_paren ace_rparen'>)</span><span class='ace_punctuation ace_operator'>;</span></div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_paren ace_rparen'>}</span>\n</div>" + "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_paren ace_rparen'>}</span></div>"
+ "</div></div>"); + "</div></div>");
assert.ok(!!result.css); assert.ok(!!result.css);
next(); next();

Wyświetl plik

@ -156,6 +156,7 @@ function setupContainer(element, getValue) {
} }
exports.transformTextarea = function(element, options) { exports.transformTextarea = function(element, options) {
var isFocused = element.autofocus || document.activeElement == element;
var session; var session;
var container = setupContainer(element, function() { var container = setupContainer(element, function() {
return session.getValue(); return session.getValue();
@ -218,7 +219,8 @@ exports.transformTextarea = function(element, options) {
session = editor.getSession(); session = editor.getSession();
session.setValue(element.value || element.innerHTML); session.setValue(element.value || element.innerHTML);
editor.focus(); if (isFocused)
editor.focus();
// Add the settingPanel opener to the editor's div. // Add the settingPanel opener to the editor's div.
container.appendChild(settingOpener); container.appendChild(settingOpener);

Wyświetl plik

@ -41,7 +41,6 @@
define(function(require, exports, module) { define(function(require, exports, module) {
"use strict"; "use strict";
require("ace/lib/fixoldbrowsers");
var themeData = [ var themeData = [
["Chrome" ], ["Chrome" ],

Wyświetl plik

@ -715,16 +715,18 @@ dom.importCssString(".normal-mode .ace_cursor{\
.ace_dialog {\ .ace_dialog {\
position: absolute;\ position: absolute;\
left: 0; right: 0;\ left: 0; right: 0;\
background: inherit;\ background: white;\
z-index: 15;\ z-index: 15;\
padding: .1em .8em;\ padding: .1em .8em;\
overflow: hidden;\ overflow: hidden;\
color: inherit;\ color: #333;\
}\ }\
.ace_dialog-top {\ .ace_dialog-top {\
border-bottom: 1px solid #eee;\
top: 0;\ top: 0;\
}\ }\
.ace_dialog-bottom {\ .ace_dialog-bottom {\
border-top: 1px solid #eee;\
bottom: 0;\ bottom: 0;\
}\ }\
.ace_dialog input {\ .ace_dialog input {\
@ -4456,8 +4458,10 @@ dom.importCssString(".normal-mode .ace_cursor{\
cm.openDialog(template, onClose, { bottom: true, value: options.value, cm.openDialog(template, onClose, { bottom: true, value: options.value,
onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp, onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp,
selectValueOnOpen: false, onClose: function() { selectValueOnOpen: false, onClose: function() {
cm.state.vim.status = ""; if (cm.state.vim) {
cm.ace.renderer.$loop.schedule(cm.ace.renderer.CHANGE_CURSOR); cm.state.vim.status = "";
cm.ace.renderer.$loop.schedule(cm.ace.renderer.CHANGE_CURSOR);
}
}}); }});
} }
else { else {
@ -6108,7 +6112,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
var getVim = Vim.maybeInitVimState_; var getVim = Vim.maybeInitVimState_;
exports.handler = { exports.handler = {
$id: "ace/keyboard/vim", $id: "ace/keyboard/vim",
drawCursor: function(style, pixelPos, config, sel, session) { drawCursor: function(element, pixelPos, config, sel, session) {
var vim = this.state.vim || {}; var vim = this.state.vim || {};
var w = config.characterWidth; var w = config.characterWidth;
var h = config.lineHeight; var h = config.lineHeight;
@ -6125,10 +6129,9 @@ dom.importCssString(".normal-mode .ace_cursor{\
h = h / 2; h = h / 2;
top += h; top += h;
} }
style.left = left + "px"; dom.translate(element, left, top);
style.top = top + "px"; dom.setStyle(element.style, "width", w + "px");
style.width = w + "px"; dom.setStyle(element.style, "height", h + "px");
style.height = h + "px";
}, },
handleKeyboard: function(data, hashId, key, keyCode, e) { handleKeyboard: function(data, hashId, key, keyCode, e) {
var editor = data.editor; 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({ Vim.defineOption({
name: "wrap", name: "wrap",
set: function(value, cm) { set: function(value, cm) {

Wyświetl plik

@ -1,6 +1,7 @@
if (typeof process !== "undefined") { if (typeof process !== "undefined") {
require("amd-loader"); require("amd-loader");
require("../test/mockdom");
} }
define(function(require, exports, module) { define(function(require, exports, module) {

Wyświetl plik

@ -32,16 +32,12 @@ define(function(require, exports, module) {
"use strict"; "use strict";
var dom = require("../lib/dom"); var dom = require("../lib/dom");
var isIE8;
var Cursor = function(parentEl) { var Cursor = function(parentEl) {
this.element = dom.createElement("div"); this.element = dom.createElement("div");
this.element.className = "ace_layer ace_cursor-layer"; this.element.className = "ace_layer ace_cursor-layer";
parentEl.appendChild(this.element); parentEl.appendChild(this.element);
if (isIE8 === undefined)
isIE8 = !("opacity" in this.element.style);
this.isVisible = false; this.isVisible = false;
this.isBlinking = true; this.isBlinking = true;
this.blinkInterval = 1000; this.blinkInterval = 1000;
@ -50,24 +46,30 @@ var Cursor = function(parentEl) {
this.cursors = []; this.cursors = [];
this.cursor = this.addCursor(); this.cursor = this.addCursor();
dom.addCssClass(this.element, "ace_hidden-cursors"); dom.addCssClass(this.element, "ace_hidden-cursors");
this.$updateCursors = (isIE8 this.$updateCursors = this.$updateOpacity.bind(this);
? this.$updateVisibility
: this.$updateOpacity).bind(this);
}; };
(function() { (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) { this.$updateOpacity = function(val) {
var cursors = this.cursors; var cursors = this.cursors;
for (var i = cursors.length; i--; ) 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.$padding = 0;
this.setPadding = function(padding) { this.setPadding = function(padding) {
@ -79,25 +81,24 @@ var Cursor = function(parentEl) {
}; };
this.setBlinking = function(blinking) { this.setBlinking = function(blinking) {
if (blinking != this.isBlinking){ if (blinking != this.isBlinking) {
this.isBlinking = blinking; this.isBlinking = blinking;
this.restartTimer(); this.restartTimer();
} }
}; };
this.setBlinkInterval = function(blinkInterval) { this.setBlinkInterval = function(blinkInterval) {
if (blinkInterval != this.blinkInterval){ if (blinkInterval != this.blinkInterval) {
this.blinkInterval = blinkInterval; this.blinkInterval = blinkInterval;
this.restartTimer(); this.restartTimer();
} }
}; };
this.setSmoothBlinking = function(smoothBlinking) { this.setSmoothBlinking = function(smoothBlinking) {
if (smoothBlinking != this.smoothBlinking && !isIE8) { if (smoothBlinking != this.smoothBlinking) {
this.smoothBlinking = smoothBlinking; this.smoothBlinking = smoothBlinking;
dom.setCssClass(this.element, "ace_smooth-blinking", smoothBlinking); dom.setCssClass(this.element, "ace_smooth-blinking", smoothBlinking);
this.$updateCursors(true); this.$updateCursors(true);
this.$updateCursors = (this.$updateOpacity).bind(this);
this.restartTimer(); this.restartTimer();
} }
}; };
@ -134,14 +135,18 @@ var Cursor = function(parentEl) {
var update = this.$updateCursors; var update = this.$updateCursors;
clearInterval(this.intervalId); clearInterval(this.intervalId);
clearTimeout(this.timeoutId); clearTimeout(this.timeoutId);
this.$stopCssAnimation();
if (this.smoothBlinking) { if (this.smoothBlinking) {
dom.removeCssClass(this.element, "ace_smooth-blinking"); dom.removeCssClass(this.element, "ace_smooth-blinking");
} }
update(true); update(true);
if (!this.isBlinking || !this.blinkInterval || !this.isVisible) if (!this.isBlinking || !this.blinkInterval || !this.isVisible) {
this.$stopCssAnimation();
return; return;
}
if (this.smoothBlinking) { if (this.smoothBlinking) {
setTimeout(function(){ setTimeout(function(){
@ -149,18 +154,21 @@ var Cursor = function(parentEl) {
}.bind(this)); }.bind(this));
} }
var blink = function(){ if (dom.HAS_CSS_ANIMATION) {
this.timeoutId = setTimeout(function() { this.$startCssAnimation();
update(false); } else {
}, 0.6 * this.blinkInterval); var blink = function(){
}.bind(this); this.timeoutId = setTimeout(function() {
update(false);
this.intervalId = setInterval(function() { }, 0.6 * this.blinkInterval);
update(true); }.bind(this);
this.intervalId = setInterval(function() {
update(true);
blink();
}, this.blinkInterval);
blink(); blink();
}, this.blinkInterval); }
blink();
}; };
this.getPixelPosition = function(position, onScreen) { this.getPixelPosition = function(position, onScreen) {
@ -180,6 +188,10 @@ var Cursor = function(parentEl) {
return {left : cursorLeft, top : cursorTop}; return {left : cursorLeft, top : cursorTop};
}; };
this.isCursorInView = function(pixelPos, config) {
return pixelPos.top >= 0 && pixelPos.top < config.maxHeight;
};
this.update = function(config) { this.update = function(config) {
this.config = config; this.config = config;
@ -197,15 +209,20 @@ var Cursor = function(parentEl) {
continue; continue;
} }
var style = (this.cursors[cursorIndex++] || this.addCursor()).style; var element = this.cursors[cursorIndex++] || this.addCursor();
var style = element.style;
if (!this.drawCursor) { if (!this.drawCursor) {
style.left = pixelPos.left + "px"; if (!this.isCursorInView(pixelPos, config)) {
style.top = pixelPos.top + "px"; dom.setStyle(style, "display", "none");
style.width = config.characterWidth + "px"; } else {
style.height = config.lineHeight + "px"; 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 { } else {
this.drawCursor(style, pixelPos, config, selections[i], this.session); this.drawCursor(element, pixelPos, config, selections[i], this.session);
} }
} }
while (this.cursors.length > cursorIndex) while (this.cursors.length > cursorIndex)

Wyświetl plik

@ -33,6 +33,7 @@ define(function(require, exports, module) {
var oop = require("../lib/oop"); var oop = require("../lib/oop");
var dom = require("../lib/dom"); var dom = require("../lib/dom");
var lang = require("../lib/lang"); var lang = require("../lib/lang");
var event = require("../lib/event");
var useragent = require("../lib/useragent"); var useragent = require("../lib/useragent");
var EventEmitter = require("../lib/event_emitter").EventEmitter; var EventEmitter = require("../lib/event_emitter").EventEmitter;
@ -117,8 +118,10 @@ var FontMetrics = exports.FontMetrics = function(parentEl) {
if (this.$pollSizeChangesTimer || this.$observer) if (this.$pollSizeChangesTimer || this.$observer)
return this.$pollSizeChangesTimer; return this.$pollSizeChangesTimer;
var self = this; var self = this;
return this.$pollSizeChangesTimer = setInterval(function() {
return this.$pollSizeChangesTimer = event.onIdle(function cb() {
self.checkForSizeChanges(); self.checkForSizeChanges();
event.onIdle(cb, 500);
}, 500); }, 500);
}; };

Wyświetl plik

@ -35,6 +35,7 @@ var dom = require("../lib/dom");
var oop = require("../lib/oop"); var oop = require("../lib/oop");
var lang = require("../lib/lang"); var lang = require("../lib/lang");
var EventEmitter = require("../lib/event_emitter").EventEmitter; var EventEmitter = require("../lib/event_emitter").EventEmitter;
var Lines = require("./lines").Lines;
var Gutter = function(parentEl) { var Gutter = function(parentEl) {
this.element = dom.createElement("div"); this.element = dom.createElement("div");
@ -46,8 +47,8 @@ var Gutter = function(parentEl) {
this.$annotations = []; this.$annotations = [];
this.$updateAnnotations = this.$updateAnnotations.bind(this); this.$updateAnnotations = this.$updateAnnotations.bind(this);
this.$cells = []; this.$lines = new Lines(this.element);
}; };
(function() { (function() {
@ -62,13 +63,13 @@ var Gutter = function(parentEl) {
session.on("change", this.$updateAnnotations); session.on("change", this.$updateAnnotations);
}; };
this.addGutterDecoration = function(row, className){ this.addGutterDecoration = function(row, className) {
if (window.console) if (window.console)
console.warn && console.warn("deprecated use session.addGutterDecoration"); console.warn && console.warn("deprecated use session.addGutterDecoration");
this.session.addGutterDecoration(row, className); this.session.addGutterDecoration(row, className);
}; };
this.removeGutterDecoration = function(row, className){ this.removeGutterDecoration = function(row, className) {
if (window.console) if (window.console)
console.warn && console.warn("deprecated use session.removeGutterDecoration"); console.warn && console.warn("deprecated use session.removeGutterDecoration");
this.session.removeGutterDecoration(row, className); this.session.removeGutterDecoration(row, className);
@ -117,23 +118,28 @@ var Gutter = function(parentEl) {
}; };
this.update = function(config) { this.update = function(config) {
this.config = config;
var session = this.session; var session = this.session;
var firstRow = config.firstRow; var firstRow = config.firstRow;
var lastRow = Math.min(config.lastRow + config.gutterOffset, // needed to compensate for hor scollbar var lastRow = Math.min(config.lastRow + config.gutterOffset, // needed to compensate for hor scollbar
session.getLength() - 1); session.getLength() - 1);
this.oldLastRow = lastRow;
this.config = config;
this.$lines.moveContainer(config);
this.$updateCursorRow();
var fold = session.getNextFoldLine(firstRow); var fold = session.getNextFoldLine(firstRow);
var foldStart = fold ? fold.start.row : Infinity; 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 cell = null;
var index = -1; var index = -1;
var row = firstRow; var row = firstRow;
var cells = Array.prototype.slice.call(this.element.childNodes, 0);
while (true) { while (true) {
if (row > foldStart) { if (row > foldStart) {
row = fold.end.row + 1; row = fold.end.row + 1;
@ -141,96 +147,243 @@ var Gutter = function(parentEl) {
foldStart = fold ? fold.start.row : Infinity; foldStart = fold ? fold.start.row : Infinity;
} }
if (row > lastRow) { if (row > lastRow) {
while (this.$cells.length > index + 1) { while (this.$lines.getLength() > index + 1)
cell = this.$cells.pop(); this.$lines.pop();
this.element.removeChild(cell.element);
}
break; break;
} }
cell = this.$cells[++index]; cell = this.$lines.get(++index);
if (!cell) { if (!cell) {
cell = {element: null, textNode: null, foldWidget: null}; cell = this.$lines.createCell(row, config, this.session, onCreateCell);
cell.element = dom.createElement("div"); this.$lines.push(cell);
cell.textNode = document.createTextNode('');
cell.element.appendChild(cell.textNode);
this.element.appendChild(cell.element);
this.$cells[index] = cell;
} }
var className = "ace_gutter-cell "; this.$renderCell(cell, config, fold, row);
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;
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) if (this.$fixedWidth || session.$useWrapMode)
lastLineNumber = session.getLength() + firstLineNumber; lastLineText = session.getLength() + firstLineNumber;
var gutterWidth = gutterRenderer var gutterWidth = gutterRenderer
? gutterRenderer.getWidth(session, lastLineNumber, config) ? gutterRenderer.getWidth(session, lastLineText, config)
: lastLineNumber.toString().length * config.characterWidth; : lastLineText.toString().length * config.characterWidth;
var padding = this.$padding || this.$computePadding(); var padding = this.$padding || this.$computePadding();
gutterWidth += padding.left + padding.right; gutterWidth += padding.left + padding.right;
if (gutterWidth !== this.gutterWidth && !isNaN(gutterWidth)) { if (gutterWidth !== this.gutterWidth && !isNaN(gutterWidth)) {
this.gutterWidth = gutterWidth; this.gutterWidth = gutterWidth;
this.element.parentNode.style.width =
this.element.style.width = Math.ceil(this.gutterWidth) + "px"; 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.$fixedWidth = false;
this.$highlightGutterLine = true;
this.$renderer = "";
this.setHighlightGutterLine = function(highlightGutterLine) {
this.$highlightGutterLine = highlightGutterLine;
};
this.$showLineNumbers = true; this.$showLineNumbers = true;
this.$renderer = ""; this.$renderer = "";
this.setShowLineNumbers = function(show) { this.setShowLineNumbers = function(show) {
@ -280,6 +433,16 @@ var Gutter = function(parentEl) {
}).call(Gutter.prototype); }).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; exports.Gutter = Gutter;
}); });

154
plugins/node_modules/ace/lib/ace/layer/lines.js wygenerowano vendored 100644
Wyświetl plik

@ -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<cell.length; i++) {
fragment.appendChild(cell[i].element);
}
this.element.appendChild(fragment);
} else {
this.cells.push(cell);
this.element.appendChild(cell.element);
}
};
this.unshift = function(cell) {
if (cell.length) {
this.cells.unshift.apply(this.cells, cell);
var fragment = dom.createFragment(this.element);
for (var i=0; i<cell.length; i++) {
fragment.appendChild(cell[i].element);
}
if (this.element.firstChild)
this.element.insertBefore(fragment, this.element.firstChild);
else
this.element.appendChild(fragment);
} else {
this.cells.unshift(cell);
this.element.insertAdjacentElement("afterbegin", cell.element);
}
};
this.last = function() {
if (this.cells.length)
return this.cells[this.cells.length-1];
else
return null;
};
this.$cacheCell = function(cell) {
if (!cell)
return;
cell.element.remove();
this.cellCache.push(cell);
};
this.createCell = function(row, config, session, initElement) {
var cell = this.cellCache.pop();
if (!cell) {
var element = dom.createElement("div");
if (initElement)
initElement(element);
this.element.appendChild(element);
cell = {
element: element,
text: "",
row: row
};
}
return cell;
};
}).call(Lines.prototype);
exports.Lines = Lines;
});

Wyświetl plik

@ -54,14 +54,27 @@ var Marker = function(parentEl) {
this.setMarkers = function(markers) { this.setMarkers = function(markers) {
this.markers = markers; this.markers = markers;
}; };
this.elt = function(className, css) {
var x = this.i != -1 && this.element.childNodes[this.i];
if (!x) {
x = document.createElement("div");
this.element.appendChild(x);
this.i = -1;
} else {
this.i++;
}
x.style.cssText = css;
x.className = className;
};
this.update = function(config) { this.update = function(config) {
if (!config) return; if (!config) return;
this.config = config; this.config = config;
this.i = 0;
var html = []; var html;
for (var key in this.markers) { for (var key in this.markers) {
var marker = this.markers[key]; var marker = this.markers[key];
@ -76,9 +89,7 @@ var Marker = function(parentEl) {
range = range.toScreenRange(this.session); range = range.toScreenRange(this.session);
if (marker.renderer) { if (marker.renderer) {
var top = this.$getTop(range.start.row, config); var top = this.$getTop(range.start.row, config);
var left = this.$padding + (this.session.$bidiHandler.isBidiRow(range.start.row) var left = this.$padding + range.start.column * config.characterWidth;
? this.session.$bidiHandler.getPosLeft(range.start.column)
: range.start.column * config.characterWidth);
marker.renderer(html, range, left, top, config); marker.renderer(html, range, left, top, config);
} else if (marker.type == "fullLine") { } else if (marker.type == "fullLine") {
this.drawFullLineMarker(html, range, marker.clazz, config); this.drawFullLineMarker(html, range, marker.clazz, config);
@ -90,14 +101,13 @@ var Marker = function(parentEl) {
else else
this.drawMultiLineMarker(html, range, marker.clazz, config); this.drawMultiLineMarker(html, range, marker.clazz, config);
} else { } else {
if (this.session.$bidiHandler.isBidiRow(range.start.row)) { this.drawSingleLineMarker(html, range, marker.clazz + " ace_start" + " ace_br15", config);
this.drawBidiSingleLineMarker(html, range, marker.clazz + " ace_start" + " ace_br15", config);
} else {
this.drawSingleLineMarker(html, range, marker.clazz + " ace_start" + " ace_br15", config);
}
} }
} }
this.element.innerHTML = html.join(""); if (this.i !=-1) {
while (this.i < this.element.childElementCount)
this.element.removeChild(this.element.lastChild);
}
}; };
this.$getTop = function(row, layerConfig) { this.$getTop = function(row, layerConfig) {
@ -116,7 +126,6 @@ var Marker = function(parentEl) {
var prev = 0; var prev = 0;
var curr = 0; var curr = 0;
var next = session.getScreenLastRowColumn(row); var next = session.getScreenLastRowColumn(row);
var clazzModified = null;
var lineRange = new Range(row, range.start.column, row, curr); var lineRange = new Range(row, range.start.column, row, curr);
for (; row <= end; row++) { for (; row <= end; row++) {
lineRange.start.row = lineRange.end.row = row; lineRange.start.row = lineRange.end.row = row;
@ -125,16 +134,10 @@ var Marker = function(parentEl) {
prev = curr; prev = curr;
curr = next; curr = next;
next = row + 1 < end ? session.getScreenLastRowColumn(row + 1) : row == end ? 0 : range.end.column; next = row + 1 < end ? session.getScreenLastRowColumn(row + 1) : row == end ? 0 : range.end.column;
clazzModified = clazz + (row == start ? " ace_start" : "") + " ace_br" this.drawSingleLineMarker(stringBuilder, lineRange,
+ getBorderClass(row == start || row == start + 1 && range.start.column, prev < curr, curr > next, row == end); clazz + (row == start ? " ace_start" : "") + " ace_br"
+ getBorderClass(row == start || row == start + 1 && range.start.column, prev < curr, curr > next, row == end),
if (this.session.$bidiHandler.isBidiRow(row)) { layerConfig, row == end ? 0 : 1, extraStyle);
this.drawBidiSingleLineMarker(stringBuilder, lineRange, clazzModified,
layerConfig, row == end ? 0 : 1, extraStyle);
} else {
this.drawSingleLineMarker(stringBuilder, lineRange, clazzModified,
layerConfig, row == end ? 0 : 1, extraStyle);
}
} }
}; };
@ -142,43 +145,28 @@ var Marker = function(parentEl) {
this.drawMultiLineMarker = function(stringBuilder, range, clazz, config, extraStyle) { this.drawMultiLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {
// from selection start to the end of the line // from selection start to the end of the line
var padding = this.$padding; 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 || ""; extraStyle = extraStyle || "";
if (this.session.$bidiHandler.isBidiRow(range.start.row)) {
var range1 = range.clone(); this.elt(
range1.end.row = range1.start.row; clazz + " ace_br1 ace_start",
range1.end.column = this.session.getLine(range1.start.row).length; "height:"+ height+ "px;"+ "right:0;"+ "top:"+top+ "px;left:"+ left+ "px;" + (extraStyle || "")
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(
"<div class='", clazz, " ace_br1 ace_start' style='",
"height:", height, "px;",
"right:0;",
"top:", top, "px;",
"left:", left, "px;", extraStyle, "'></div>"
);
}
// from start of the last line to the selection end // from start of the last line to the selection end
if (this.session.$bidiHandler.isBidiRow(range.end.row)) { top = this.$getTop(range.end.row, config);
var range1 = range.clone(); var width = range.end.column * config.characterWidth;
range1.start.row = range1.end.row;
range1.start.column = 0; this.elt(
this.drawBidiSingleLineMarker(stringBuilder, range1, clazz + " ace_br12", config, null, extraStyle); clazz + " ace_br12",
} else { "height:"+ height+ "px;"+
var width = range.end.column * config.characterWidth; "width:"+ width+ "px;"+
height = config.lineHeight; "top:"+ top+ "px;"+
top = this.$getTop(range.end.row, config); "left:"+ padding+ "px;"+ (extraStyle || "")
stringBuilder.push( );
"<div class='", clazz, " ace_br12' style='",
"height:", height, "px;",
"width:", width, "px;",
"top:", top, "px;",
"left:", padding, "px;", extraStyle, "'></div>"
);
}
// all the complete lines // all the complete lines
height = (range.end.row - range.start.row - 1) * config.lineHeight; height = (range.end.row - range.start.row - 1) * config.lineHeight;
if (height <= 0) if (height <= 0)
@ -187,12 +175,12 @@ var Marker = function(parentEl) {
var radiusClass = (range.start.column ? 1 : 0) | (range.end.column ? 0 : 8); var radiusClass = (range.start.column ? 1 : 0) | (range.end.column ? 0 : 8);
stringBuilder.push( this.elt(
"<div class='", clazz, (radiusClass ? " ace_br" + radiusClass : ""), "' style='", clazz + (radiusClass ? " ace_br" + radiusClass : ""),
"height:", height, "px;", "height:"+ height+ "px;"+
"right:0;", "right:0;"+
"top:", top, "px;", "top:"+ top+ "px;"+
"left:", padding, "px;", extraStyle, "'></div>" "left:"+ padding+ "px;"+ (extraStyle || "")
); );
}; };
@ -204,42 +192,26 @@ var Marker = function(parentEl) {
var top = this.$getTop(range.start.row, config); var top = this.$getTop(range.start.row, config);
var left = this.$padding + range.start.column * config.characterWidth; var left = this.$padding + range.start.column * config.characterWidth;
stringBuilder.push( this.elt(
"<div class='", clazz, "' style='", clazz,
"height:", height, "px;", "height:"+ height+ "px;"+
"width:", width, "px;", "width:"+ width+ "px;"+
"top:", top, "px;", "top:"+ top+ "px;"+
"left:", left, "px;", extraStyle || "", "'></div>" "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(
"<div class='", clazz, "' style='",
"height:", height, "px;",
"width:", selection.width + (extraLength || 0), "px;",
"top:", top, "px;",
"left:", padding + selection.left, "px;", extraStyle || "", "'></div>"
);
});
};
this.drawFullLineMarker = function(stringBuilder, range, clazz, config, extraStyle) { this.drawFullLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {
var top = this.$getTop(range.start.row, config); var top = this.$getTop(range.start.row, config);
var height = config.lineHeight; var height = config.lineHeight;
if (range.start.row != range.end.row) if (range.start.row != range.end.row)
height += this.$getTop(range.end.row, config) - top; height += this.$getTop(range.end.row, config) - top;
stringBuilder.push( this.elt(
"<div class='", clazz, "' style='", clazz,
"height:", height, "px;", "height:"+ height+ "px;"+
"top:", top, "px;", "top:"+ top+ "px;"+
"left:0;right:0;", extraStyle || "", "'></div>" "left:0;right:0;"+ (extraStyle || "")
); );
}; };
@ -247,11 +219,11 @@ var Marker = function(parentEl) {
var top = this.$getTop(range.start.row, config); var top = this.$getTop(range.start.row, config);
var height = config.lineHeight; var height = config.lineHeight;
stringBuilder.push( this.elt(
"<div class='", clazz, "' style='", clazz,
"height:", height, "px;", "height:"+ height+ "px;"+
"top:", top, "px;", "top:"+ top+ "px;"+
"left:0;right:0;", extraStyle || "", "'></div>" "left:0;right:0;"+ (extraStyle || "")
); );
}; };
@ -259,4 +231,4 @@ var Marker = function(parentEl) {
exports.Marker = Marker; exports.Marker = Marker;
}); });

Wyświetl plik

@ -34,14 +34,16 @@ define(function(require, exports, module) {
var oop = require("../lib/oop"); var oop = require("../lib/oop");
var dom = require("../lib/dom"); var dom = require("../lib/dom");
var lang = require("../lib/lang"); var lang = require("../lib/lang");
var useragent = require("../lib/useragent"); var Lines = require("./lines").Lines;
var EventEmitter = require("../lib/event_emitter").EventEmitter; var EventEmitter = require("../lib/event_emitter").EventEmitter;
var Text = function(parentEl) { 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"; this.element.className = "ace_layer ace_text-layer";
parentEl.appendChild(this.element); parentEl.appendChild(this.element);
this.$updateEolChar = this.$updateEolChar.bind(this); this.$updateEolChar = this.$updateEolChar.bind(this);
this.$lines = new Lines(this.element);
}; };
(function() { (function() {
@ -69,7 +71,7 @@ var Text = function(parentEl) {
this.setPadding = function(padding) { this.setPadding = function(padding) {
this.$padding = padding; this.$padding = padding;
this.element.style.padding = "0 " + padding + "px"; this.element.style.margin = "0 " + padding + "px";
}; };
this.getLineHeight = function() { this.getLineHeight = function() {
@ -128,11 +130,12 @@ var Text = function(parentEl) {
var tabStr = this.$tabStrings = [0]; var tabStr = this.$tabStrings = [0];
for (var i = 1; i < tabSize + 1; i++) { for (var i = 1; i < tabSize + 1; i++) {
if (this.showInvisibles) { if (this.showInvisibles) {
tabStr.push("<span class='ace_invisible ace_invisible_tab'>" var span = this.dom.createElement("span");
+ lang.stringRepeat(this.TAB_CHAR, i) span.className = "ace_invisible ace_invisible_tab";
+ "</span>"); span.textContent = lang.stringRepeat(this.TAB_CHAR, i);
tabStr.push(span);
} else { } else {
tabStr.push(lang.stringRepeat(" ", i)); tabStr.push(this.dom.createTextNode(lang.stringRepeat(" ", i), this.element));
} }
} }
if (this.displayIndentGuides) { if (this.displayIndentGuides) {
@ -146,13 +149,20 @@ var Text = function(parentEl) {
tabClass = " ace_invisible_tab"; tabClass = " ace_invisible_tab";
var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize); var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize);
var tabContent = lang.stringRepeat(this.TAB_CHAR, this.tabSize); var tabContent = lang.stringRepeat(this.TAB_CHAR, this.tabSize);
} else{ } else {
var spaceContent = lang.stringRepeat(" ", this.tabSize); var spaceContent = lang.stringRepeat(" ", this.tabSize);
var tabContent = spaceContent; var tabContent = spaceContent;
} }
this.$tabStrings[" "] = "<span class='" + className + spaceClass + "'>" + spaceContent + "</span>"; var span = this.dom.createElement("span");
this.$tabStrings["\t"] = "<span class='" + className + tabClass + "'>" + tabContent + "</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. // the line to updated wrapped in the meantime.
if (this.config.lastRow != config.lastRow || if (this.config.lastRow != config.lastRow ||
this.config.firstRow != config.firstRow) { this.config.firstRow != config.firstRow) {
this.scrollLines(config); return this.update(config);
} }
this.config = config; this.config = config;
var first = Math.max(firstRow, config.firstRow); var first = Math.max(firstRow, config.firstRow);
@ -199,12 +210,11 @@ var Text = function(parentEl) {
var lineElement = lineElements[lineElementsIdx++]; var lineElement = lineElements[lineElementsIdx++];
if (lineElement) { if (lineElement) {
var html = []; this.dom.removeChildren(lineElement);
this.$renderLine( 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.style.height = (config.lineHeight * this.session.getRowLength(row)) + "px";
lineElement.innerHTML = html.join("");
} }
row++; row++;
} }
@ -214,37 +224,45 @@ var Text = function(parentEl) {
var oldConfig = this.config; var oldConfig = this.config;
this.config = 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) if (!oldConfig || oldConfig.lastRow < config.firstRow)
return this.update(config); return this.update(config);
if (config.lastRow < oldConfig.firstRow) if (config.lastRow < oldConfig.firstRow)
return this.update(config); return this.update(config);
var el = this.element;
if (oldConfig.firstRow < config.firstRow) if (oldConfig.firstRow < config.firstRow)
for (var row=this.session.getFoldedRowCount(oldConfig.firstRow, config.firstRow - 1); row>0; row--) 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) if (oldConfig.lastRow > config.lastRow)
for (var row=this.session.getFoldedRowCount(config.lastRow + 1, oldConfig.lastRow); row>0; row--) 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) { if (config.firstRow < oldConfig.firstRow) {
var fragment = this.$renderLinesFragment(config, config.firstRow, oldConfig.firstRow - 1); this.$lines.unshift(this.$renderLinesFragment(config, config.firstRow, oldConfig.firstRow - 1));
if (el.firstChild)
el.insertBefore(fragment, el.firstChild);
else
el.appendChild(fragment);
} }
if (config.lastRow > oldConfig.lastRow) { if (config.lastRow > oldConfig.lastRow) {
var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow); this.$lines.push(this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow));
el.appendChild(fragment);
} }
}; };
this.$renderLinesFragment = function(config, firstRow, lastRow) { this.$renderLinesFragment = function(config, firstRow, lastRow) {
var fragment = this.element.ownerDocument.createDocumentFragment(); var fragment = [];
var row = firstRow; var row = firstRow;
var foldLine = this.session.getNextFoldLine(row); var foldLine = this.session.getNextFoldLine(row);
var foldStart = foldLine ? foldLine.start.row : Infinity; var foldStart = foldLine ? foldLine.start.row : Infinity;
@ -258,23 +276,23 @@ var Text = function(parentEl) {
if (row > lastRow) if (row > lastRow)
break; 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 // Get the tokens per line as there might be some lines in between
// beeing folded. // 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()) { if (this.$useLineGroups()) {
container.className = 'ace_line_group'; lineEl.className = "ace_line_group";
fragment.appendChild(container);
container.style.height = config.lineHeight * this.session.getRowLength(row) + "px";
} else { } else {
while(container.firstChild) lineEl.className = "ace_line";
fragment.appendChild(container.firstChild);
} }
fragment.push(line);
row++; row++;
} }
@ -282,35 +300,18 @@ var Text = function(parentEl) {
}; };
this.update = function(config) { this.update = function(config) {
this.$lines.moveContainer(config);
this.config = config; this.config = config;
var html = []; var firstRow = config.firstRow;
var firstRow = config.firstRow, lastRow = config.lastRow; var lastRow = config.lastRow;
var row = firstRow; var lines = this.$lines;
var foldLine = this.session.getNextFoldLine(row); while (lines.getLength())
var foldStart = foldLine ? foldLine.start.row : Infinity; lines.pop();
while (true) { lines.push(this.$renderLinesFragment(config, firstRow, lastRow));
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("<div class='ace_line_group' style='height:", config.lineHeight*this.session.getRowLength(row), "px'>");
this.$renderLine(html, row, false, row == foldStart ? foldLine : false);
if (this.$useLineGroups())
html.push("</div>"); // end the line group
row++;
}
this.element.innerHTML = html.join("");
}; };
this.$textToken = { this.$textToken = {
@ -319,110 +320,154 @@ var Text = function(parentEl) {
"lparen": true "lparen": true
}; };
this.$renderToken = function(stringBuilder, screenColumn, token, value) { this.$renderToken = function(parent, screenColumn, token, value) {
var self = this; 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 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 replaceFunc = function(c, a, b, tabIdx, idx4) {
if (a) { var valueFragment = this.dom.createFragment(this.element);
return self.showInvisibles
? "<span class='ace_invisible ace_invisible_space'>" + lang.stringRepeat(self.SPACE_CHAR, c.length) + "</span>" var m;
: c; var i = 0;
} else if (c == "&") { while (m = re.exec(value)) {
return "&#38;"; var tab = m[1];
} else if (c == "<") { var simpleSpace = m[2];
return "&#60;"; var controlCharacter = m[3];
} else if (c == ">") { var cjkSpace = m[4];
// normally escaping this is not needed, but xml documents throw error when setting innerHTML to ]]> var cjk = m[5];
return "&#62;";
} else if (c == "\t") { if (!self.showInvisibles && simpleSpace)
var tabSize = self.session.getScreenTabSize(screenColumn + tabIdx); 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; screenColumn += tabSize - 1;
return self.$tabStrings[tabSize]; } else if (simpleSpace) {
} else if (c == "\u3000") { 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 // 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 : ""; var space = self.showInvisibles ? self.SPACE_CHAR : "";
screenColumn += 1; screenColumn += 1;
return "<span class='" + classToUse + "' style='width:" +
(self.config.characterWidth * 2) + var span = this.dom.createElement("span");
"px'>" + space + "</span>"; span.style.width = (self.config.characterWidth * 2) + "px";
} else if (b) { span.className = self.showInvisibles ? "ace_cjk ace_invisible ace_invisible_space" : "ace_cjk";
return "<span class='ace_invisible ace_invisible_space ace_invalid'>" + self.SPACE_CHAR + "</span>"; span.textContent = self.showInvisibles ? self.SPACE_CHAR : "";
} else { valueFragment.appendChild(span);
} else if (cjk) {
screenColumn += 1; screenColumn += 1;
return "<span class='ace_cjk' style='width:" + var span = dom.createElement("span");
(self.config.characterWidth * 2) + span.style.width = (self.config.characterWidth * 2) + "px";
"px'>" + c + "</span>"; 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]) { if (!this.$textToken[token.type]) {
var classes = "ace_" + token.type.replace(/\./g, " ace_"); var classes = "ace_" + token.type.replace(/\./g, " ace_");
var style = ""; var span = this.dom.createElement("span");
if (token.type == "fold") if (token.type == "fold")
style = " style='width:" + (token.value.length * this.config.characterWidth) + "px;' "; span.style.width = (token.value.length * this.config.characterWidth) + "px";
stringBuilder.push("<span class='", classes, "'", style, ">", output, "</span>");
span.className = classes;
span.appendChild(valueFragment);
parent.appendChild(span);
} }
else { else {
stringBuilder.push(output); parent.appendChild(valueFragment);
} }
return screenColumn + value.length; return screenColumn + value.length;
}; };
this.renderIndentGuide = function(stringBuilder, value, max) { this.renderIndentGuide = function(parent, value, max) {
var cols = value.search(this.$indentGuideRe); var cols = value.search(this.$indentGuideRe);
if (cols <= 0 || cols >= max) if (cols <= 0 || cols >= max)
return value; return value;
if (value[0] == " ") { if (value[0] == " ") {
cols -= cols % this.tabSize; cols -= cols % this.tabSize;
stringBuilder.push(lang.stringRepeat(this.$tabStrings[" "], cols/this.tabSize)); var count = cols/this.tabSize;
for (var i=0; i<count; i++) {
parent.appendChild(this.$tabStrings[" "].cloneNode(true));
}
return value.substr(cols); return value.substr(cols);
} else if (value[0] == "\t") { } else if (value[0] == "\t") {
stringBuilder.push(lang.stringRepeat(this.$tabStrings["\t"], cols)); for (var i=0; i<cols; i++) {
parent.appendChild(this.$tabStrings["\t"].cloneNode(true));
}
return value.substr(cols); return value.substr(cols);
} }
return value; return value;
}; };
this.$renderWrappedLine = function(stringBuilder, tokens, splits, onlyContents) { this.$createLineElement = function(parent) {
var lineEl = this.dom.createElement("div");
lineEl.className = "ace_line";
lineEl.style.height = this.config.lineHeight + "px";
return lineEl;
};
this.$renderWrappedLine = function(parent, tokens, splits) {
var chars = 0; var chars = 0;
var split = 0; var split = 0;
var splitChars = splits[0]; var splitChars = splits[0];
var screenColumn = 0; var screenColumn = 0;
var lineEl = this.$createLineElement();
parent.appendChild(lineEl);
for (var i = 0; i < tokens.length; i++) { for (var i = 0; i < tokens.length; i++) {
var token = tokens[i]; var token = tokens[i];
var value = token.value; var value = token.value;
if (i == 0 && this.displayIndentGuides) { if (i == 0 && this.displayIndentGuides) {
chars = value.length; chars = value.length;
value = this.renderIndentGuide(stringBuilder, value, splitChars); value = this.renderIndentGuide(lineEl, value, splitChars);
if (!value) if (!value)
continue; continue;
chars -= value.length; chars -= value.length;
} }
if (chars + value.length < splitChars) { if (chars + value.length < splitChars) {
screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); screenColumn = this.$renderToken(lineEl, screenColumn, token, value);
chars += value.length; chars += value.length;
} else { } else {
while (chars + value.length >= splitChars) { while (chars + value.length >= splitChars) {
screenColumn = this.$renderToken( screenColumn = this.$renderToken(
stringBuilder, screenColumn, lineEl, screenColumn,
token, value.substring(0, splitChars - chars) token, value.substring(0, splitChars - chars)
); );
value = value.substring(splitChars - chars); value = value.substring(splitChars - chars);
chars = splitChars; chars = splitChars;
if (!onlyContents) { lineEl = this.$createLineElement();
stringBuilder.push("</div>", parent.appendChild(lineEl);
"<div class='ace_line' style='height:",
this.config.lineHeight, "px'>"
);
}
stringBuilder.push(lang.stringRepeat("\xa0", splits.indent)); lineEl.appendChild(this.dom.createTextNode(lang.stringRepeat("\xa0", splits.indent), this.element));
split ++; split ++;
screenColumn = 0; screenColumn = 0;
@ -431,40 +476,45 @@ var Text = function(parentEl) {
if (value.length != 0) { if (value.length != 0) {
chars += value.length; chars += value.length;
screenColumn = this.$renderToken( 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 screenColumn = 0;
var token = tokens[0]; var token = tokens[0];
var value = token.value; var value = token.value;
if (this.displayIndentGuides) if (this.displayIndentGuides)
value = this.renderIndentGuide(stringBuilder, value); value = this.renderIndentGuide(parent, value);
if (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++) { for (var i = 1; i < tokens.length; i++) {
token = tokens[i]; token = tokens[i];
value = token.value; value = token.value;
if (screenColumn + value.length > this.MAX_LINE_LENGTH) if (screenColumn + value.length > this.MAX_LINE_LENGTH)
return this.$renderOverflowMessage(stringBuilder, screenColumn, token, value); return this.$renderOverflowMessage(parent, screenColumn, token, value);
screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); screenColumn = this.$renderToken(parent, screenColumn, token, value);
} }
}; };
this.$renderOverflowMessage = function(stringBuilder, screenColumn, token, value) { this.$renderOverflowMessage = function(parent, screenColumn, token, value) {
this.$renderToken(stringBuilder, screenColumn, token, this.$renderToken(parent, screenColumn, token,
value.slice(0, this.MAX_LINE_LENGTH - screenColumn)); value.slice(0, this.MAX_LINE_LENGTH - screenColumn));
stringBuilder.push(
"<span style='position:absolute;right:0' class='ace_inline_button ace_keyword ace_toggle_wrap'>&lt;click to see more...&gt;</span>" 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 = "<click to see more...>";
parent.appendChild(overflowEl);
}; };
// row is either first row of foldline or not in fold // 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) if (!foldLine && foldLine != false)
foldLine = this.session.getFoldLine(row); foldLine = this.session.getFoldLine(row);
@ -473,36 +523,35 @@ var Text = function(parentEl) {
else else
var tokens = this.session.getTokens(row); var tokens = this.session.getTokens(row);
var lastLineEl = parent;
if (!onlyContents) {
stringBuilder.push(
"<div class='ace_line' style='height:",
this.config.lineHeight * (
this.$useLineGroups() ? 1 :this.session.getRowLength(row)
), "px'>"
);
}
if (tokens.length) { if (tokens.length) {
var splits = this.session.getRowSplitData(row); var splits = this.session.getRowSplitData(row);
if (splits && splits.length) if (splits && splits.length) {
this.$renderWrappedLine(stringBuilder, tokens, splits, onlyContents); this.$renderWrappedLine(parent, tokens, splits);
else var lastLineEl = parent.lastChild;
this.$renderSimpleLine(stringBuilder, tokens); } 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) if (foldLine)
row = foldLine.end.row; row = foldLine.end.row;
stringBuilder.push( var invisibleEl = this.dom.createElement("span");
"<span class='ace_invisible ace_invisible_eol'>", invisibleEl.className = "ace_invisible ace_invisible_eol";
row == this.session.getLength() - 1 ? this.EOF_CHAR : this.EOL_CHAR, invisibleEl.textContent = row == this.session.getLength() - 1 ? this.EOF_CHAR : this.EOL_CHAR;
"</span>"
); lastLineEl.appendChild(invisibleEl);
} }
if (!onlyContents)
stringBuilder.push("</div>");
}; };
this.$getFoldLineTokens = function(row, foldLine) { this.$getFoldLineTokens = function(row, foldLine) {

Wyświetl plik

@ -40,6 +40,7 @@ var assert = require("../test/assertions");
var EditSession = require("../edit_session").EditSession; var EditSession = require("../edit_session").EditSession;
var TextLayer = require("./text").Text; var TextLayer = require("./text").Text;
var JavaScriptMode = require("../mode/javascript").Mode; var JavaScriptMode = require("../mode/javascript").Mode;
var dom = require("../lib/dom");
module.exports = { module.exports = {
@ -60,61 +61,63 @@ module.exports = {
this.textLayer.$computeTabString(); this.textLayer.$computeTabString();
// row with hard tabs // row with hard tabs
var stringBuilder = []; var parent1 = dom.createElement("div");
this.textLayer.$renderLine(stringBuilder, 0); this.textLayer.$renderLine(parent1, 0);
// row with soft tabs // row with soft tabs
var stringBuilder2 = []; var parent2 = dom.createElement("div");
this.textLayer.$renderLine(stringBuilder2, 1); this.textLayer.$renderLine(parent2, 1);
assert.equal(stringBuilder.join(""), stringBuilder2.join("")); assert.equal(parent1.innerHTML, parent2.innerHTML);
}, },
"test rendering width of ideographic space (U+3000)" : function() { "test rendering width of ideographic space (U+3000)" : function() {
this.session.setValue("\u3000"); this.session.setValue("\u3000");
var stringBuilder = []; var parent = dom.createElement("div");
this.textLayer.$renderLine(stringBuilder, 0, true); this.textLayer.$renderLine(parent, 0);
assert.equal(stringBuilder.join(""), "<span class='ace_cjk' style='width:20px'></span>"); assert.domNode(parent, ["div", {}, ["span", {class: "ace_cjk", style: "width: 20px;"}]]);
this.textLayer.setShowInvisibles(true); this.textLayer.setShowInvisibles(true);
var stringBuilder = []; var parent = dom.createElement("div");
this.textLayer.$renderLine(stringBuilder, 0, true); this.textLayer.$renderLine(parent, 0);
assert.equal( assert.domNode(parent, ["div", {},
stringBuilder.join(""), ["span", {class: "ace_cjk ace_invisible ace_invisible_space", style: "width: 20px;"}, this.textLayer.SPACE_CHAR],
"<span class='ace_cjk ace_invisible ace_invisible_space' style='width:20px'>" + this.textLayer.SPACE_CHAR + "</span>" ["span", {class: "ace_invisible ace_invisible_eol"}, "\xB6"]
+ "<span class='ace_invisible ace_invisible_eol'>\xB6</span>" ]);
);
}, },
"test rendering of indent guides" : function() { "test rendering of indent guides" : function() {
var textLayer = this.textLayer; var textLayer = this.textLayer;
var EOL = "<span class='ace_invisible ace_invisible_eol'>" + textLayer.EOL_CHAR + "</span>"; var EOL = "<span class=\"ace_invisible ace_invisible_eol\">" + textLayer.EOL_CHAR + "</span>";
var SPACE = function(i) {return Array(i+1).join(" ");}; var SPACE = function(i) {return Array(i+1).join(" ");};
var DOT = function(i) {return Array(i+1).join(textLayer.SPACE_CHAR);}; var DOT = function(i) {return Array(i+1).join(textLayer.SPACE_CHAR);};
var TAB = function(i) {return Array(i+1).join(textLayer.TAB_CHAR);}; var TAB = function(i) {return Array(i+1).join(textLayer.TAB_CHAR);};
function testRender(results) { function testRender(results) {
for (var i = results.length; i--; ) { for (var i = results.length; i--; ) {
var stringBuilder = []; var parent = dom.createElement("div");
textLayer.$renderLine(stringBuilder, i, true); textLayer.$renderLine(parent, i);
assert.equal(stringBuilder.join(""), results[i]);
assert.equal(parent.innerHTML, results[i]);
} }
} }
this.session.setValue(" \n\t\tf\n "); this.session.setValue(" \n\t\tf\n ");
testRender([ testRender([
"<span class='ace_indent-guide'>" + SPACE(4) + "</span>" + SPACE(2), "<span class=\"ace_indent-guide\">" + SPACE(4) + "</span>" + SPACE(2),
"<span class='ace_indent-guide'>" + SPACE(4) + "</span>" + SPACE(4) + "<span class='ace_identifier'>f</span>", "<span class=\"ace_indent-guide\">" + SPACE(4) + "</span>" + SPACE(4) + "<span class=\"ace_identifier\">f</span>",
SPACE(3) SPACE(3)
]); ]);
this.textLayer.setShowInvisibles(true); this.textLayer.setShowInvisibles(true);
testRender([ testRender([
"<span class='ace_indent-guide ace_invisible ace_invisible_space'>" + DOT(4) + "</span><span class='ace_invisible ace_invisible_space'>" + DOT(2) + "</span>" + EOL, "<span class=\"ace_indent-guide ace_invisible ace_invisible_space\">" + DOT(4) + "</span><span class=\"ace_invisible ace_invisible_space\">" + DOT(2) + "</span>" + EOL,
"<span class='ace_indent-guide ace_invisible ace_invisible_tab'>" + TAB(4) + "</span><span class='ace_invisible ace_invisible_tab'>" + TAB(4) + "</span><span class='ace_identifier'>f</span>" + EOL "<span class=\"ace_indent-guide ace_invisible ace_invisible_tab\">" + TAB(4) + "</span><span class=\"ace_invisible ace_invisible_tab\">" + TAB(4) + "</span><span class=\"ace_identifier\">f</span>" + EOL
]); ]);
this.textLayer.setDisplayIndentGuides(false); this.textLayer.setDisplayIndentGuides(false);
testRender([ testRender([
"<span class='ace_invisible ace_invisible_space'>" + DOT(6) + "</span>" + EOL, "<span class=\"ace_invisible ace_invisible_space\">" + DOT(6) + "</span>" + EOL,
"<span class='ace_invisible ace_invisible_tab'>" + TAB(4) + "</span><span class='ace_invisible ace_invisible_tab'>" + TAB(4) + "</span><span class='ace_identifier'>f</span>" + EOL "<span class=\"ace_invisible ace_invisible_tab\">" + TAB(4) + "</span><span class=\"ace_invisible ace_invisible_tab\">" + TAB(4) + "</span><span class=\"ace_identifier\">f</span>" + EOL
]); ]);
} }
}; };

Wyświetl plik

@ -31,6 +31,7 @@
define(function(require, exports, module) { define(function(require, exports, module) {
"use strict"; "use strict";
var useragent = require("./useragent");
var XHTML_NS = "http://www.w3.org/1999/xhtml"; var XHTML_NS = "http://www.w3.org/1999/xhtml";
exports.buildDom = function buildDom(arr, parent, refs) { exports.buildDom = function buildDom(arr, parent, refs) {
@ -90,6 +91,20 @@ exports.createElement = function(tag, ns) {
document.createElement(tag); 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) { exports.hasCssClass = function(el, name) {
var classes = (el.className + "").split(/\s+/g); var classes = (el.className + "").split(/\s+/g);
return classes.indexOf(name) !== -1; return classes.indexOf(name) !== -1;
@ -183,6 +198,9 @@ exports.importCssString = function importCssString(cssText, id, container) {
root.appendChild(style); root.appendChild(style);
}; };
exports.importCssStylsheet = function(uri, doc) {
exports.buildDom(["link", {rel: "stylesheet", href: uri}], exports.getDocumentHead(doc));
};
exports.scrollbarWidth = function(document) { exports.scrollbarWidth = function(document) {
var inner = exports.createElement("ace_inner"); var inner = exports.createElement("ace_inner");
inner.style.width = "100%"; inner.style.width = "100%";
@ -228,4 +246,44 @@ exports.computedStyle = function(element, style) {
return window.getComputedStyle(element, "") || {}; 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";
};
}
}); });

Wyświetl plik

@ -364,7 +364,6 @@ exports.addCommandKeyListener = function(el, callback) {
} }
}; };
function resetPressedKeys() { function resetPressedKeys() {
// console.log("resetting")
pressedKeys = Object.create(null); pressedKeys = Object.create(null);
} }
@ -372,18 +371,42 @@ if (typeof window == "object" && window.postMessage && !useragent.isOldIE) {
var postMessageId = 1; var postMessageId = 1;
exports.nextTick = function(callback, win) { exports.nextTick = function(callback, win) {
win = win || window; win = win || window;
var messageName = "zero-timeout-message-" + postMessageId; var messageName = "zero-timeout-message-" + (postMessageId++);
exports.addListener(win, "message", function listener(e) {
var listener = function(e) {
if (e.data == messageName) { if (e.data == messageName) {
exports.stopPropagation(e); exports.stopPropagation(e);
exports.removeListener(win, "message", listener); exports.removeListener(win, "message", listener);
callback(); callback();
} }
}); };
exports.addListener(win, "message", listener);
win.postMessage(messageName, "*"); 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 exports.nextFrame = typeof window == "object" && (window.requestAnimationFrame
|| window.mozRequestAnimationFrame || window.mozRequestAnimationFrame

Wyświetl plik

@ -109,7 +109,6 @@ EventEmitter.removeDefaultHandler = function(eventName, callback) {
var disabled = handlers._disabled_[eventName]; var disabled = handlers._disabled_[eventName];
if (handlers[eventName] == callback) { if (handlers[eventName] == callback) {
var old = handlers[eventName];
if (disabled) if (disabled)
this.setDefaultHandler(eventName, disabled.pop()); this.setDefaultHandler(eventName, disabled.pop());
} else if (disabled) { } else if (disabled) {

Wyświetl plik

@ -34,8 +34,6 @@ For more information about SproutCore, visit http://www.sproutcore.com
define(function(require, exports, module) { define(function(require, exports, module) {
"use strict"; "use strict";
require("./fixoldbrowsers");
var oop = require("./oop"); var oop = require("./oop");
/* /*

Wyświetl plik

@ -88,6 +88,37 @@ var JavaHighlightRules = function() {
}, { }, {
token : "constant.language.boolean", token : "constant.language.boolean",
regex : "(?:true|false)\\b" 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, token : keywordMapper,
// TODO: Unicode escape sequences // TODO: Unicode escape sequences
@ -118,8 +149,10 @@ var JavaHighlightRules = function() {
] ]
}; };
this.embedRules(DocCommentHighlightRules, "doc-", this.embedRules(DocCommentHighlightRules, "doc-",
[ DocCommentHighlightRules.getEndRule("start") ]); [ DocCommentHighlightRules.getEndRule("start") ]);
this.normalizeRules();
}; };
oop.inherits(JavaHighlightRules, TextHighlightRules); oop.inherits(JavaHighlightRules, TextHighlightRules);

Wyświetl plik

@ -1002,6 +1002,9 @@ var PhpLangHighlightRules = function() {
}, { }, {
token : "keyword.operator", token : "keyword.operator",
regex : "::|!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|!=|!==|<=|>=|=>|<<=|>>=|>>>=|<>|<|>|\\.=|=|!|&&|\\|\\||\\?\\:|\\*=|/=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)" regex : "::|!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|!=|!==|<=|>=|=>|<<=|>>=|>>>=|<>|<|>|\\.=|=|!|&&|\\|\\||\\?\\:|\\*=|/=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
}, {
token : "punctuation.operator",
regex : /[,;]/
}, { }, {
token : "paren.lparen", token : "paren.lparen",
regex : "[[({]" regex : "[[({]"

Wyświetl plik

@ -31,8 +31,6 @@
define(function(require, exports, module) { define(function(require, exports, module) {
"use strict"; "use strict";
var dom = require("../lib/dom");
var event = require("../lib/event");
var useragent = require("../lib/useragent"); var useragent = require("../lib/useragent");
var DRAG_OFFSET = 0; // pixels var DRAG_OFFSET = 0; // pixels

Wyświetl plik

@ -216,7 +216,7 @@ var MouseHandler = function(editor) {
config.defineOptions(MouseHandler.prototype, "mouseHandler", { config.defineOptions(MouseHandler.prototype, "mouseHandler", {
scrollSpeed: {initialValue: 2}, scrollSpeed: {initialValue: 2},
dragDelay: {initialValue: 150}, dragDelay: {initialValue: (useragent.isMac ? 150 : 0)},
dragEnabled: {initialValue: true}, dragEnabled: {initialValue: true},
focusTimeout: {initialValue: 0}, focusTimeout: {initialValue: 0},
tooltipFollowsMouse: {initialValue: true} tooltipFollowsMouse: {initialValue: true}

Wyświetl plik

@ -36,8 +36,9 @@ if (typeof process !== "undefined") {
define(function(require, exports, module) { define(function(require, exports, module) {
"use strict"; "use strict";
require("../multi_select");
var Editor = require("../editor").Editor; var Editor = require("../editor").Editor;
var MockRenderer = require("../test/mockrenderer").MockRenderer; var VirtualRenderer = require("../virtual_renderer").VirtualRenderer;
var assert = require("../test/assertions"); var assert = require("../test/assertions");
var MouseEvent = function(type, opts){ var MouseEvent = function(type, opts){
var e = document.createEvent("MouseEvents"); var e = document.createEvent("MouseEvents");
@ -53,20 +54,77 @@ var MouseEvent = function(type, opts){
module.exports = { module.exports = {
setUp : function(next) { setUp : function(next) {
this.editor = new Editor(new MockRenderer()); this.editor = new Editor(new VirtualRenderer());
this.editor.setValue("Juhu kinners!"); 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(); next();
}, },
"test: double tap. issue #956" : function() { "test: double tap. issue #956" : function() {
// mouse up fired immediately after mouse down // 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(); var target = this.editor.renderer.getMouseEventTarget();
target.dispatchEvent(MouseEvent("down", {x: 1, y: 1})); target.dispatchEvent(MouseEvent("down", {x: pos.pageX, y: pos.pageY}));
target.dispatchEvent(MouseEvent("up", {x: 1, y: 1})); target.dispatchEvent(MouseEvent("up", {x: pos.pageX, y: pos.pageY}));
target.dispatchEvent(MouseEvent("down", {x: 1, y: 1, detail: 2})); target.dispatchEvent(MouseEvent("down", {x: pos.pageX, y: pos.pageY, detail: 2}));
target.dispatchEvent(MouseEvent("up", {x: 1, y: 1, detail: 2})); target.dispatchEvent(MouseEvent("up", {x: pos.pageX, y: pos.pageY, detail: 2}));
assert.equal(this.editor.getSelectedText(), "Juhu"); 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);
} }
}; };

Wyświetl plik

@ -173,6 +173,7 @@ function onMouseDown(e) {
screenCursor = {row: -1, column: -1}; screenCursor = {row: -1, column: -1};
var onMouseSelectionEnd = function(e) { var onMouseSelectionEnd = function(e) {
blockSelect();
clearInterval(timerId); clearInterval(timerId);
editor.removeSelectionMarkers(rectSel); editor.removeSelectionMarkers(rectSel);
if (!rectSel.length) if (!rectSel.length)

Wyświetl plik

@ -560,6 +560,8 @@ var Editor = require("./editor").Editor;
if (pos.row != anchor.row if (pos.row != anchor.row
|| this.session.$clipPositionToDocument(pos.row, pos.column).column != anchor.column) || this.session.$clipPositionToDocument(pos.row, pos.column).column != anchor.column)
this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange()); this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange());
else
this.multiSelect.mergeOverlappingRanges();
} }
}; };

Wyświetl plik

@ -275,6 +275,31 @@ module.exports = {
doc.markUndoGroup(); doc.markUndoGroup();
editor.execCommand("undo"); editor.execCommand("undo");
assert.equal('l1\nl2\nl3', editor.getValue()); 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);
} }
}; };

Wyświetl plik

@ -181,46 +181,89 @@ var RangeList = function() {
}; };
this.$onChange = function(delta) { this.$onChange = function(delta) {
if (delta.action == "insert"){ var start = delta.start;
var start = delta.start; var end = delta.end;
var end = delta.end;
} else {
var end = delta.start;
var start = delta.end;
}
var startRow = start.row; var startRow = start.row;
var endRow = end.row; var endRow = end.row;
var lineDif = endRow - startRow;
var colDiff = -start.column + end.column;
var ranges = this.ranges; var ranges = this.ranges;
for (var i = 0, n = ranges.length; i < n; i++) { for (var i = 0, n = ranges.length; i < n; i++) {
var r = ranges[i]; var r = ranges[i];
if (r.end.row < startRow) if (r.end.row >= startRow)
continue;
if (r.start.row > startRow)
break; break;
}
if (r.start.row == startRow && r.start.column >= start.column ) {
if (r.start.column == start.column && this.$insertRight) { if (delta.action == "insert") {
// do nothing var lineDif = endRow - startRow;
} else { var colDiff = -start.column + end.column;
r.start.column += colDiff; for (; i < n; i++) {
r.start.row += lineDif; 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) { } else {
if (r.end.column == start.column && this.$insertRight) { var lineDif = startRow - endRow;
continue; 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.start.row < endRow || r.start.row == endRow && r.start.column <= end.colum) {
if (r.end.column > r.start.column && r.end.column == ranges[i+1].start.column) r.start.row = startRow;
r.end.column -= colDiff; 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;
} }
} }

Wyświetl plik

@ -50,22 +50,23 @@ var RenderLoop = function(onRender, win) {
(function() { (function() {
this.schedule = function(change) { this.schedule = function(change) {
//this.onRender(change);
//return;
this.changes = this.changes | change; this.changes = this.changes | change;
if (!this.pending && this.changes) { if (this.changes) {
this.pending = true;
var _self = this; var _self = this;
event.nextFrame(function() {
_self.pending = false; event.nextFrame(function(ts) {
var changes; var changes = _self.changes;
while (changes = _self.changes) {
if (changes) {
event.blockIdle(100);
_self.changes = 0; _self.changes = 0;
_self.onRender(changes); _self.onRender(changes);
} }
}, this.window);
if (_self.changes)
_self.schedule();
});
} }
}; };

Wyświetl plik

@ -33,17 +33,17 @@
*/ */
(function() { (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) { define(function (require, exports, module) {
"use strict"; "use strict";
if (globalRequire && globalRequire.nodeRequire) { if (globalRequire && globalRequire.nodeRequire) {
module.exports = globalRequire.nodeRequire(require.toUrl("./text_build")); module.exports = globalRequire.nodeRequire(require.toUrl("./text_build"));
} else { } else {
exports.load = function(name, req, onLoad, config) { exports.load = function(name, req, onLoad, config) {
require("../lib/net").get(req.toUrl(name), onLoad); require("../lib/net").get(req.toUrl(name), onLoad);
}; };
} }

Wyświetl plik

@ -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;
};

Wyświetl plik

@ -211,6 +211,7 @@ var Selection = function(session) {
this.$setSelection = function(anchorRow, anchorColumn, cursorRow, cursorColumn) { this.$setSelection = function(anchorRow, anchorColumn, cursorRow, cursorColumn) {
var wasEmpty = this.$isEmpty; var wasEmpty = this.$isEmpty;
var wasMultiselect = this.inMultiSelectMode;
this.$silent = true; this.$silent = true;
this.$cursorChanged = this.$anchorChanged = false; this.$cursorChanged = this.$anchorChanged = false;
this.anchor.setPosition(anchorRow, anchorColumn); this.anchor.setPosition(anchorRow, anchorColumn);
@ -219,7 +220,7 @@ var Selection = function(session) {
this.$silent = false; this.$silent = false;
if (this.$cursorChanged) if (this.$cursorChanged)
this._emit("changeCursor"); this._emit("changeCursor");
if (this.$cursorChanged || this.$anchorChanged) if (this.$cursorChanged || this.$anchorChanged || wasEmpty != this.$isEmpty || wasMultiselect)
this._emit("changeSelection"); this._emit("changeSelection");
}; };

Wyświetl plik

@ -507,6 +507,18 @@ module.exports = {
assert.equal(nCursor, 2); assert.equal(nCursor, 2);
assert.equal(nSelection, 3); assert.equal(nSelection, 3);
assert.ok(selection.isEqual(data)); 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() { "test setRange inside fold": function() {

Wyświetl plik

@ -47,10 +47,34 @@ assert.notOk = function(value) {
assert.equal(value, false); assert.equal(value, false);
}; };
exports.jsonEquals = function(foundJson, expectedJson) { assert.jsonEquals = function(foundJson, expectedJson) {
assert.equal(JSON.stringify(foundJson), JSON.stringify(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; module.exports = assert;
}); });

Wyświetl plik

@ -1,10 +1,373 @@
define(function(require, exports, module) {
"use strict"; "use strict";
var jsdom = require('jsdom/').jsdom; var CHAR_HEIGHT = 10;
var doc = jsdom("<html><head></head><body></body></html>"); var CHAR_WIDTH = 6;
var WINDOW_HEIGHT = 768;
var WINDOW_WIDTH = 1024;
global.document = doc; function Style() {
global.window = doc.defaultView;
global.self = doc.self; }
global.navigator = doc.navigator; Style.prototype.__defineGetter__("cssText", function() {
global.location = doc.location; 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.localName + ">";
});
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;
});

Wyświetl plik

@ -277,6 +277,10 @@ var UndoManager = function() {
this.isClean = this.isAtBookmark; this.isClean = this.isAtBookmark;
this.markClean = this.bookmark; 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); }).call(UndoManager.prototype);
function rearrangeUndoStack(stack, pos) { function rearrangeUndoStack(stack, pos) {
@ -558,20 +562,23 @@ function moveDeltasByOne(redoStack, d) {
d = cloneDelta(d); d = cloneDelta(d);
for (var j = redoStack.length; j--;) { for (var j = redoStack.length; j--;) {
var deltaSet = redoStack[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 x = deltaSet[i];
var xformed = xform(x, d); var xformed = xform(x, d);
d = xformed[0]; d = xformed[0];
if (xformed.length != 2) { if (xformed.length != 2) {
if (xformed[2]) { if (xformed[2]) {
redoStack.splice(i + 1, 1, xformed[1], xformed[2]); deltaSet.splice(i + 1, 1, xformed[1], xformed[2]);
i++; i++;
} else if (!xformed[1]) { } else if (!xformed[1]) {
redoStack.splice(i, 1); deltaSet.splice(i, 1);
i--; i--;
} }
} }
} }
if (!deltaSet.length) {
redoStack.splice(j, 1);
}
} }
return redoStack; return redoStack;
} }

Wyświetl plik

@ -44,19 +44,20 @@ var EditSession = require("./edit_session").EditSession;
var MockRenderer = require("./test/mockrenderer").MockRenderer; var MockRenderer = require("./test/mockrenderer").MockRenderer;
var UndoManager = require("./undomanager").UndoManager; var UndoManager = require("./undomanager").UndoManager;
var editor; var editor, session, undoManager;
module.exports = { module.exports = {
name: "ACE undoManager.js", 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() { "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.setValue("012345-012345-012345");
session.insert({row: 0, column: 0}, "xx"); session.insert({row: 0, column: 0}, "xx");
session.markUndoGroup(); session.markUndoGroup();
@ -66,9 +67,9 @@ module.exports = {
session.markUndoGroup(); session.markUndoGroup();
editor.undo(); editor.undo();
editor.undo(); editor.undo();
var rev = session.getUndoManager().startNewGroup(); var rev = undoManager.startNewGroup();
session.insert({row: 0, column: 5}, "z\nz"); session.insert({row: 0, column: 5}, "z\nz");
session.getUndoManager().markIgnored(rev); undoManager.markIgnored(rev);
// editor.undo() // editor.undo()
editor.redo(); editor.redo();
editor.redo(); editor.redo();
@ -84,11 +85,6 @@ module.exports = {
assert.equal(val1, val2); assert.equal(val1, val2);
}, },
"test: conflicting deletes": function() { "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.setValue("012345\nabcdefg\nxyz");
session.remove(new Range(0, 2, 0, 4)); session.remove(new Range(0, 2, 0, 4));
assert.equal(session.getLine(0), "0145"); assert.equal(session.getLine(0), "0145");
@ -101,6 +97,208 @@ module.exports = {
assert.equal(session.getLine(0), "05"); assert.equal(session.getLine(0), "05");
editor.undo(); editor.undo();
assert.equal(session.getLine(0), "012345"); 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');
} }
}; };

Wyświetl plik

@ -34,7 +34,6 @@ define(function(require, exports, module) {
var oop = require("./lib/oop"); var oop = require("./lib/oop");
var dom = require("./lib/dom"); var dom = require("./lib/dom");
var config = require("./config"); var config = require("./config");
var useragent = require("./lib/useragent");
var GutterLayer = require("./layer/gutter").Gutter; var GutterLayer = require("./layer/gutter").Gutter;
var MarkerLayer = require("./layer/marker").Marker; var MarkerLayer = require("./layer/marker").Marker;
var TextLayer = require("./layer/text").Text; var TextLayer = require("./layer/text").Text;
@ -68,6 +67,7 @@ var VirtualRenderer = function(container, theme) {
this.container = container || dom.createElement("div"); this.container = container || dom.createElement("div");
dom.addCssClass(this.container, "ace_editor"); dom.addCssClass(this.container, "ace_editor");
if (dom.HI_DPI) dom.addCssClass(this.container, "ace_hidpi");
this.setTheme(theme); this.setTheme(theme);
@ -78,6 +78,7 @@ var VirtualRenderer = function(container, theme) {
this.scroller = dom.createElement("div"); this.scroller = dom.createElement("div");
this.scroller.className = "ace_scroller"; this.scroller.className = "ace_scroller";
this.container.appendChild(this.scroller); this.container.appendChild(this.scroller);
this.content = dom.createElement("div"); this.content = dom.createElement("div");
@ -238,7 +239,7 @@ var VirtualRenderer = function(container, theme) {
return; return;
this.$loop.schedule(this.CHANGE_FULL); this.$loop.schedule(this.CHANGE_FULL);
// this.session.$setFontMetrics(this.$fontMetrics); this.session.$setFontMetrics(this.$fontMetrics);
this.scrollBarH.scrollLeft = this.scrollBarV.scrollTop = null; this.scrollBarH.scrollLeft = this.scrollBarV.scrollTop = null;
this.onChangeNewLineMode = this.onChangeNewLineMode.bind(this); this.onChangeNewLineMode = this.onChangeNewLineMode.bind(this);
@ -405,18 +406,20 @@ var VirtualRenderer = function(container, theme) {
this.gutterWidth = gutterWidth; this.gutterWidth = gutterWidth;
this.scrollBarH.element.style.left = dom.setStyle(this.scrollBarH.element.style, "left", gutterWidth + "px");
this.scroller.style.left = gutterWidth + "px"; dom.setStyle(this.scroller.style, "left", gutterWidth + "px");
size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBarV.getWidth()); size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBarV.getWidth());
this.scrollBarH.element.style.right = var right = this.scrollBarV.getWidth() + "px";
this.scroller.style.right = this.scrollBarV.getWidth() + "px"; dom.setStyle(this.scrollBarH.element.style, "right", right);
this.scroller.style.bottom = this.scrollBarH.getHeight() + "px"; dom.setStyle(this.scroller.style, "right", right);
dom.setStyle(this.scroller.style, "bottom", this.scrollBarH.getHeight());
// this.scrollBarH.element.style.setWidth(size.scrollerWidth); // 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; changes |= this.CHANGE_FULL;
}
} }
size.$dirty = !width || !height; size.$dirty = !width || !height;
@ -427,8 +430,8 @@ var VirtualRenderer = function(container, theme) {
return changes; return changes;
}; };
this.onGutterResize = function() { this.onGutterResize = function(width) {
var gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0; var gutterWidth = this.$showGutter ? width : 0;
if (gutterWidth != this.gutterWidth) if (gutterWidth != this.gutterWidth)
this.$changes |= this.$updateCachedSize(true, gutterWidth, this.$size.width, this.$size.height); 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); this.$loop.schedule(this.CHANGE_FULL);
} else { } else {
this.$computeLayerConfig(); this.$computeLayerConfig();
this.$loop.schedule(this.CHANGE_MARKER);
} }
}; };
@ -559,19 +561,6 @@ var VirtualRenderer = function(container, theme) {
return this.getOption("highlightGutterLine"); 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() { this.$updatePrintMargin = function() {
if (!this.$showPrintMargin && !this.$printMarginEl) if (!this.$showPrintMargin && !this.$printMarginEl)
return; return;
@ -625,9 +614,11 @@ var VirtualRenderer = function(container, theme) {
this.$moveTextAreaToCursor = function() { this.$moveTextAreaToCursor = function() {
var style = this.textarea.style; var style = this.textarea.style;
if (!this.$keepTextAreaAtCursor) { if (!this.$keepTextAreaAtCursor) {
style.left = -100 + "px"; dom.translate(this.textarea, -100, 0);
return; return;
} }
if (!this.$cursorLayer.$pixelPos)
return;
var config = this.layerConfig; var config = this.layerConfig;
var posTop = this.$cursorLayer.$pixelPos.top; var posTop = this.$cursorLayer.$pixelPos.top;
var posLeft = this.$cursorLayer.$pixelPos.left; var posLeft = this.$cursorLayer.$pixelPos.left;
@ -635,7 +626,7 @@ var VirtualRenderer = function(container, theme) {
var h = this.lineHeight; var h = this.lineHeight;
if (posTop < 0 || posTop > config.height - h) { if (posTop < 0 || posTop > config.height - h) {
style.top = style.left = "0"; dom.translate(this.textarea, 0, 0);
return; return;
} }
@ -650,10 +641,9 @@ var VirtualRenderer = function(container, theme) {
posLeft = this.$size.scrollerWidth - w; posLeft = this.$size.scrollerWidth - w;
posLeft += this.gutterWidth; posLeft += this.gutterWidth;
style.height = h + "px"; dom.setStyle(style, "height", h + "px");
style.width = w + "px"; dom.setStyle(style, "width", w + "px");
style.left = Math.min(posLeft, this.$size.scrollerWidth - w) + "px"; dom.translate(this.textarea, Math.min(posLeft, this.$size.scrollerWidth - w), Math.min(posTop, this.$size.height - h));
style.top = Math.min(posTop, this.$size.height - h) + "px";
}; };
/** /**
@ -836,15 +826,20 @@ var VirtualRenderer = function(container, theme) {
this.$updateScrollBarV(); this.$updateScrollBarV();
if (changes & this.CHANGE_H_SCROLL) if (changes & this.CHANGE_H_SCROLL)
this.$updateScrollBarH(); this.$updateScrollBarH();
this.$gutterLayer.element.style.marginTop = (-config.offset) + "px";
this.content.style.marginTop = (-config.offset) + "px"; dom.translate(this.$gutter, 0, -config.offset);
this.content.style.width = config.width + 2 * this.$padding + "px"; dom.translate(this.content, -this.scrollLeft, -config.offset);
this.content.style.height = config.minHeight + "px";
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 // horizontal scrolling
if (changes & this.CHANGE_H_SCROLL) { 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"; 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.$markerFront.update(config);
this.$cursorLayer.update(config); this.$cursorLayer.update(config);
this.$moveTextAreaToCursor(); this.$moveTextAreaToCursor();
this.$highlightGutterLine && this.$updateGutterLineHighlight();
this._signal("afterRender"); this._signal("afterRender");
return; return;
} }
@ -869,12 +863,15 @@ var VirtualRenderer = function(container, theme) {
else else
this.$textLayer.scrollLines(config); this.$textLayer.scrollLines(config);
if (this.$showGutter) if (this.$showGutter) {
this.$gutterLayer.update(config); if (changes & this.CHANGE_GUTTER)
this.$gutterLayer.update(config);
else
this.$gutterLayer.scrollLines(config);
}
this.$markerBack.update(config); this.$markerBack.update(config);
this.$markerFront.update(config); this.$markerFront.update(config);
this.$cursorLayer.update(config); this.$cursorLayer.update(config);
this.$highlightGutterLine && this.$updateGutterLineHighlight();
this.$moveTextAreaToCursor(); this.$moveTextAreaToCursor();
this._signal("afterRender"); this._signal("afterRender");
return; return;
@ -893,11 +890,14 @@ var VirtualRenderer = function(container, theme) {
if (this.$showGutter) if (this.$showGutter)
this.$gutterLayer.update(config); this.$gutterLayer.update(config);
} }
else if (changes & this.CHANGE_CURSOR) {
if (this.$highlightGutterLine)
this.$gutterLayer.updateLineHighlight(config);
}
if (changes & this.CHANGE_CURSOR) { if (changes & this.CHANGE_CURSOR) {
this.$cursorLayer.update(config); this.$cursorLayer.update(config);
this.$moveTextAreaToCursor(); this.$moveTextAreaToCursor();
this.$highlightGutterLine && this.$updateGutterLineHighlight();
} }
if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT)) { if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT)) {
@ -922,7 +922,9 @@ var VirtualRenderer = function(container, theme) {
desiredHeight += this.scrollBarH.getHeight(); desiredHeight += this.scrollBarH.getHeight();
if (this.$maxPixelHeight && desiredHeight > this.$maxPixelHeight) if (this.$maxPixelHeight && desiredHeight > 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 || if (desiredHeight != this.desiredHeight ||
this.$size.height != this.desiredHeight || vScroll != this.$vScroll) { this.$size.height != this.desiredHeight || vScroll != this.$vScroll) {
@ -1442,7 +1444,7 @@ var VirtualRenderer = function(container, theme) {
var offset = offsetX / this.characterWidth; var offset = offsetX / this.characterWidth;
var col = this.$blockCursor ? Math.floor(offset) : Math.round(offset); 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); return this.session.screenToDocumentPosition(row, Math.max(col, 0), offsetX);
}; };
@ -1615,8 +1617,7 @@ var VirtualRenderer = function(container, theme) {
}; };
this.setCursorStyle = function(style) { this.setCursorStyle = function(style) {
if (this.scroller.style.cursor != style) dom.setStyle(this.scroller.style, "cursor", style);
this.scroller.style.cursor = style;
}; };
/** /**
@ -1624,7 +1625,7 @@ var VirtualRenderer = function(container, theme) {
* *
**/ **/
this.setMouseCursor = function(cursorStyle) { this.setMouseCursor = function(cursorStyle) {
this.scroller.style.cursor = cursorStyle; dom.setStyle(this.scroller.style, "cursor", cursorStyle);
}; };
this.attachToShadowRoot = function() { this.attachToShadowRoot = function() {
@ -1688,13 +1689,6 @@ config.defineOptions(VirtualRenderer.prototype, "renderer", {
set: function(show) {this.$gutterLayer.setShowFoldWidgets(show);}, set: function(show) {this.$gutterLayer.setShowFoldWidgets(show);},
initialValue: true initialValue: true
}, },
showLineNumbers: {
set: function(show) {
this.$gutterLayer.setShowLineNumbers(show);
this.$loop.schedule(this.CHANGE_GUTTER);
},
initialValue: true
},
displayIndentGuides: { displayIndentGuides: {
set: function(show) { set: function(show) {
if (this.$textLayer.setDisplayIndentGuides(show)) if (this.$textLayer.setDisplayIndentGuides(show))
@ -1704,20 +1698,10 @@ config.defineOptions(VirtualRenderer.prototype, "renderer", {
}, },
highlightGutterLine: { highlightGutterLine: {
set: function(shouldHighlight) { set: function(shouldHighlight) {
if (!this.$gutterLineHighlight) { this.$gutterLayer.setHighlightGutterLine(shouldHighlight);
this.$gutterLineHighlight = dom.createElement("div"); this.$loop.schedule(this.CHANGE_GUTTER);
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();
}, },
initialValue: false, initialValue: true
value: true
}, },
hScrollBarAlwaysVisible: { hScrollBarAlwaysVisible: {
set: function(val) { set: function(val) {
@ -1733,7 +1717,7 @@ config.defineOptions(VirtualRenderer.prototype, "renderer", {
}, },
initialValue: false initialValue: false
}, },
fontSize: { fontSize: {
set: function(size) { set: function(size) {
if (typeof size == "number") if (typeof size == "number")
size = size + "px"; size = size + "px";

Wyświetl plik

@ -43,9 +43,10 @@ var assert = require("./test/assertions");
require("./ext/error_marker"); require("./ext/error_marker");
function setScreenPosition(node, rect) { function setScreenPosition(node, rect) {
node.getBoundingClientRect = function() { node.style.left = rect[0] + "px";
return { left: rect[0], top: rect[1], width: rect[2], height: rect[3] }; node.style.top = rect[1] + "px";
}; node.style.width = rect[2] + "px";
node.style.height = rect[3] + "px";
} }
var editor = null; var editor = null;
@ -147,8 +148,6 @@ module.exports = {
editor.renderer.setScrollMargin(10, 10); editor.renderer.setScrollMargin(10, 10);
editor.setValue("\n\n"); editor.setValue("\n\n");
editor.setValue("\n\n\n\n"); editor.setValue("\n\n\n\n");
if (editor.container.offsetWidth == undefined)
return done(); // jsdom
editor.renderer.once("afterRender", function() { editor.renderer.once("afterRender", function() {
setTimeout(function() { setTimeout(function() {
done(); done();
@ -162,6 +161,11 @@ module.exports = {
editor.execCommand(editor.commands.byName.goToNextError); editor.execCommand(editor.commands.byName.goToNextError);
assert.position(editor.getCursorPosition(), 1, 2); assert.position(editor.getCursorPosition(), 1, 2);
assert.ok(editor.session.lineWidgets[1]); assert.ok(editor.session.lineWidgets[1]);
},
"test resize": function() {
editor.setValue("Juhu kinners!");
editor.resize(true);
} }
// change tab size after setDocument (for text layer) // change tab size after setDocument (for text layer)