summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McLear <john@mclear.co.uk>2015-10-22 16:12:07 +0100
committerJohn McLear <john@mclear.co.uk>2015-10-22 16:12:07 +0100
commit50171a4c3c3a580a3136a9939902cd411775d323 (patch)
tree19c8a7a274aca54364e7834fbe9b53c2ef13c8a7
parent5652adb4eb3dfe3afa0520b0ff95d02bbcf30d70 (diff)
parent5deb06d5891ce9278b74c253fd85741757b25c82 (diff)
downloadetherpad-lite-50171a4c3c3a580a3136a9939902cd411775d323.zip
Merge pull request #2805 from storytouch/indentationSetting
Create setting to control if a new line will be indented or not
-rw-r--r--settings.json.template5
-rw-r--r--src/node/handler/PadMessageHandler.js7
-rw-r--r--src/node/utils/Settings.js5
-rw-r--r--src/static/js/ace2_inner.js40
-rw-r--r--tests/frontend/specs/indentation.js102
5 files changed, 128 insertions, 31 deletions
diff --git a/settings.json.template b/settings.json.template
index 321d21d6..f29bcbc0 100644
--- a/settings.json.template
+++ b/settings.json.template
@@ -135,6 +135,11 @@
// Allow Load Testing tools to hit the Etherpad Instance. Warning this will disable security on the instance.
"loadTest": false,
+ // Disable indentation on new line when previous line ends with some special chars (':', '[', '(', '{')
+ /*
+ "indentationOnNewLine": false,
+ */
+
/* The toolbar buttons configuration.
"toolbar": {
"left": [
diff --git a/src/node/handler/PadMessageHandler.js b/src/node/handler/PadMessageHandler.js
index e72625d0..9481889f 100644
--- a/src/node/handler/PadMessageHandler.js
+++ b/src/node/handler/PadMessageHandler.js
@@ -630,8 +630,8 @@ function handleUserChanges(data, cb)
messageLogger.warn("Dropped message, USER_CHANGES Message has no changeset!");
return cb();
}
- //TODO: this might happen with other messages too => find one place to copy the session
- //and always use the copy. atm a message will be ignored if the session is gone even
+ //TODO: this might happen with other messages too => find one place to copy the session
+ //and always use the copy. atm a message will be ignored if the session is gone even
//if the session was valid when the message arrived in the first place
if(!sessioninfos[client.id])
{
@@ -960,7 +960,7 @@ function handleSwitchToPad(client, message)
roomClients[i].leave(padId);
}
}
-
+
// start up the new pad
createSessionInfo(client, message);
handleClientReady(client, message);
@@ -1231,6 +1231,7 @@ function handleClientReady(client, message)
"plugins": plugins.plugins,
"parts": plugins.parts,
},
+ "indentationOnNewLine": settings.indentationOnNewLine,
"initialChangesets": [] // FIXME: REMOVE THIS SHIT
}
diff --git a/src/node/utils/Settings.js b/src/node/utils/Settings.js
index d03e2a6c..ec327fb6 100644
--- a/src/node/utils/Settings.js
+++ b/src/node/utils/Settings.js
@@ -182,6 +182,11 @@ exports.disableIPlogging = false;
*/
exports.loadTest = false;
+/**
+ * Enable indentation on new lines
+ */
+exports.indentationOnNewLine = true;
+
/*
* log4js appender configuration
*/
diff --git a/src/static/js/ace2_inner.js b/src/static/js/ace2_inner.js
index 00dcd4e9..55a1b5ac 100644
--- a/src/static/js/ace2_inner.js
+++ b/src/static/js/ace2_inner.js
@@ -1894,7 +1894,11 @@ function Ace2Inner(){
var prevLine = rep.lines.prev(thisLine);
var prevLineText = prevLine.text;
var theIndent = /^ *(?:)/.exec(prevLineText)[0];
- if (/[\[\(\:\{]\s*$/.exec(prevLineText)) theIndent += THE_TAB;
+ var shouldIndent = parent.parent.clientVars.indentationOnNewLine;
+ if (shouldIndent && /[\[\(\:\{]\s*$/.exec(prevLineText))
+ {
+ theIndent += THE_TAB;
+ }
var cs = Changeset.builder(rep.lines.totalWidth()).keep(
rep.lines.offsetOfIndex(lineNum), lineNum).insert(
theIndent, [
@@ -2336,7 +2340,7 @@ function Ace2Inner(){
function getAttributeOnSelection(attributeName){
if (!(rep.selStart && rep.selEnd)) return
-
+
var withIt = Changeset.makeAttribsString('+', [
[attributeName, 'true']
], rep.apool);
@@ -2347,14 +2351,14 @@ function Ace2Inner(){
}
return rangeHasAttrib(rep.selStart, rep.selEnd)
-
+
function rangeHasAttrib(selStart, selEnd) {
// if range is collapsed -> no attribs in range
if(selStart[1] == selEnd[1] && selStart[0] == selEnd[0]) return false
-
+
if(selStart[0] != selEnd[0]) { // -> More than one line selected
var hasAttrib = true
-
+
// from selStart to the end of the first line
hasAttrib = hasAttrib && rangeHasAttrib(selStart, [selStart[0], rep.lines.atIndex(selStart[0]).text.length])
@@ -2365,22 +2369,22 @@ function Ace2Inner(){
// for the last, potentially partial, line
hasAttrib = hasAttrib && rangeHasAttrib([selEnd[0], 0], [selEnd[0], selEnd[1]])
-
+
return hasAttrib
}
-
+
// Logic tells us we now have a range on a single line
-
+
var lineNum = selStart[0]
, start = selStart[1]
, end = selEnd[1]
, hasAttrib = true
-
+
// Iterate over attribs on this line
-
+
var opIter = Changeset.opIterator(rep.alines[lineNum])
, indexIntoLine = 0
-
+
while (opIter.hasNext()) {
var op = opIter.next();
var opStartInLine = indexIntoLine;
@@ -2394,11 +2398,11 @@ function Ace2Inner(){
}
indexIntoLine = opEndInLine;
}
-
+
return hasAttrib
}
}
-
+
editorInfo.ace_getAttributeOnSelection = getAttributeOnSelection;
function toggleAttributeOnSelection(attributeName)
@@ -3641,7 +3645,7 @@ function Ace2Inner(){
// Is caret potentially hidden by the chat button?
var myselection = document.getSelection(); // get the current caret selection
var caretOffsetTop = myselection.focusNode.parentNode.offsetTop | myselection.focusNode.offsetTop; // get the carets selection offset in px IE 214
-
+
if(myselection.focusNode.wholeText){ // Is there any content? If not lineHeight will report wrong..
var lineHeight = myselection.focusNode.parentNode.offsetHeight; // line height of populated links
}else{
@@ -3713,13 +3717,13 @@ function Ace2Inner(){
// As ubuntu cannot use Alt F10....
// Focus on the editbar. -- TODO: Move Focus back to previous state (we know it so we can use it)
var firstEditbarElement = parent.parent.$('#editbar').children("ul").first().children().first().children().first().children().first();
- $(this).blur();
+ $(this).blur();
firstEditbarElement.focus();
evt.preventDefault();
}
if ((!specialHandled) && altKey && keyCode == 67 && type === "keydown"){
// Alt c focuses on the Chat window
- $(this).blur();
+ $(this).blur();
parent.parent.chat.show();
parent.parent.$("#chatinput").focus();
evt.preventDefault();
@@ -4961,7 +4965,7 @@ function Ace2Inner(){
// Disabled: https://github.com/ether/etherpad-lite/issues/2546
// Will break OL re-numbering: https://github.com/ether/etherpad-lite/pull/2533
- // $(document).on("cut", handleCut);
+ // $(document).on("cut", handleCut);
$(root).on("blur", handleBlur);
if (browser.msie)
@@ -4972,7 +4976,7 @@ function Ace2Inner(){
// Don't paste on middle click of links
$(root).on("paste", function(e){
- // TODO: this breaks pasting strings into URLS when using
+ // TODO: this breaks pasting strings into URLS when using
// Control C and Control V -- the Event is never available
// here.. :(
if(e.target.a || e.target.localName === "a"){
diff --git a/tests/frontend/specs/indentation.js b/tests/frontend/specs/indentation.js
index 8e851d87..71aafc7a 100644
--- a/tests/frontend/specs/indentation.js
+++ b/tests/frontend/specs/indentation.js
@@ -15,7 +15,7 @@ describe("indentation button", function(){
//select this text element
$firstTextElement.sendkeys('{selectall}');
- if(inner$(window)[0].bowser.firefox || inner$(window)[0].bowser.modernIE){ // if it's a mozilla or IE
+ if(inner$(window)[0].bowser.firefox || inner$(window)[0].bowser.modernIE){ // if it's a mozilla or IE
var evtType = "keypress";
}else{
var evtType = "keydown";
@@ -31,7 +31,7 @@ describe("indentation button", function(){
});
it("indent text with button", function(done){
- var inner$ = helper.padInner$;
+ var inner$ = helper.padInner$;
var chrome$ = helper.padChrome$;
var $indentButton = chrome$(".buttonicon-indent");
@@ -43,7 +43,7 @@ describe("indentation button", function(){
});
it("keeps the indent on enter for the new line", function(done){
- var inner$ = helper.padInner$;
+ var inner$ = helper.padInner$;
var chrome$ = helper.padChrome$;
var $indentButton = chrome$(".buttonicon-indent");
@@ -51,9 +51,9 @@ describe("indentation button", function(){
//type a bit, make a line break and type again
var $firstTextElement = inner$("div span").first();
- $firstTextElement.sendkeys('line 1');
- $firstTextElement.sendkeys('{enter}');
- $firstTextElement.sendkeys('line 2');
+ $firstTextElement.sendkeys('line 1');
+ $firstTextElement.sendkeys('{enter}');
+ $firstTextElement.sendkeys('line 2');
$firstTextElement.sendkeys('{enter}');
helper.waitFor(function(){
@@ -68,13 +68,83 @@ describe("indentation button", function(){
});
});
+ it("indents text with spaces on enter if previous line ends with ':', '[', '(', or '{'", function(done){
+ var inner$ = helper.padInner$;
+ var chrome$ = helper.padChrome$;
+
+ //type a bit, make a line break and type again
+ var $firstTextElement = inner$("div").first();
+ $firstTextElement.sendkeys("line with ':'{enter}");
+ $firstTextElement.sendkeys("line with '['{enter}");
+ $firstTextElement.sendkeys("line with '('{enter}");
+ $firstTextElement.sendkeys("line with '{{}'{enter}");
+
+ helper.waitFor(function(){
+ return inner$("div span").first().text().indexOf("line with '{'") === -1;
+ }).done(function(){
+ // we validate bottom to top for easier implementation
+
+ // curly braces
+ var $lineWithCurlyBraces = inner$("div").first().next().next().next();
+ $lineWithCurlyBraces.sendkeys('{{}');
+ pressEnter(); // cannot use sendkeys('{enter}') here, browser does not read the command properly
+ var $lineAfterCurlyBraces = inner$("div").first().next().next().next().next();
+ expect($lineAfterCurlyBraces.text()).to.match(/\s{4}/); // tab === 4 spaces
+
+ // parenthesis
+ var $lineWithParenthesis = inner$("div").first().next().next();
+ $lineWithParenthesis.sendkeys('(');
+ pressEnter();
+ var $lineAfterParenthesis = inner$("div").first().next().next().next();
+ expect($lineAfterParenthesis.text()).to.match(/\s{4}/);
+
+ // bracket
+ var $lineWithBracket = inner$("div").first().next();
+ $lineWithBracket.sendkeys('[');
+ pressEnter();
+ var $lineAfterBracket = inner$("div").first().next().next();
+ expect($lineAfterBracket.text()).to.match(/\s{4}/);
+
+ // colon
+ var $lineWithColon = inner$("div").first();
+ $lineWithColon.sendkeys(':');
+ pressEnter();
+ var $lineAfterColon = inner$("div").first().next();
+ expect($lineAfterColon.text()).to.match(/\s{4}/);
+
+ done();
+ });
+ });
+
+ it("appends indentation to the indent of previous line if previous line ends with ':', '[', '(', or '{'", function(done){
+ var inner$ = helper.padInner$;
+ var chrome$ = helper.padChrome$;
+
+ //type a bit, make a line break and type again
+ var $firstTextElement = inner$("div").first();
+ $firstTextElement.sendkeys(" line with some indentation and ':'{enter}");
+ $firstTextElement.sendkeys("line 2{enter}");
+
+ helper.waitFor(function(){
+ return inner$("div span").first().text().indexOf("line 2") === -1;
+ }).done(function(){
+ var $lineWithColon = inner$("div").first();
+ $lineWithColon.sendkeys(':');
+ pressEnter();
+ var $lineAfterColon = inner$("div").first().next();
+ expect($lineAfterColon.text()).to.match(/\s{6}/); // previous line indentation + regular tab (4 spaces)
+
+ done();
+ });
+ });
+
/*
it("makes text indented and outdented", function() {
//get the inner iframe
var $inner = testHelper.$getPadInner();
-
+
//get the first text element out of the inner iframe
var firstTextElement = $inner.find("div").first();
@@ -87,7 +157,7 @@ describe("indentation button", function(){
//ace creates a new dom element when you press a button, so just get the first text element again
var newFirstTextElement = $inner.find("div").first();
-
+
// is there a list-indent class element now?
var firstChild = newFirstTextElement.children(":first");
var isUL = firstChild.is('ul');
@@ -160,12 +230,12 @@ describe("indentation button", function(){
/* this test creates the below content, both should have double indentation
line1
line2
-
+
firstTextElement.sendkeys('{rightarrow}'); // simulate a keypress of enter
firstTextElement.sendkeys('{enter}'); // simulate a keypress of enter
firstTextElement.sendkeys('line 1'); // simulate writing the first line
- firstTextElement.sendkeys('{enter}'); // simulate a keypress of enter
+ firstTextElement.sendkeys('{enter}'); // simulate a keypress of enter
firstTextElement.sendkeys('line 2'); // simulate writing the second line
//get the second text element out of the inner iframe
@@ -203,3 +273,15 @@ describe("indentation button", function(){
});*/
});
+
+function pressEnter(){
+ var inner$ = helper.padInner$;
+ if(inner$(window)[0].bowser.firefox || inner$(window)[0].bowser.modernIE){ // if it's a mozilla or IE
+ var evtType = "keypress";
+ }else{
+ var evtType = "keydown";
+ }
+ var e = inner$.Event(evtType);
+ e.keyCode = 13; // enter :|
+ inner$("#innerdocbody").trigger(e);
+}