[evolution/wip/mcrha/webkit-jsc-api] e-editor.js: Correct deletion in blockquote in Plain Text mode
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/wip/mcrha/webkit-jsc-api] e-editor.js: Correct deletion in blockquote in Plain Text mode
- Date: Thu, 16 Apr 2020 14:50:15 +0000 (UTC)
commit 455c106324dafe51a1462ea50af051e0e5c23b7c
Author: Milan Crha <mcrha redhat com>
Date: Thu Apr 16 16:52:50 2020 +0200
e-editor.js: Correct deletion in blockquote in Plain Text mode
data/webkit/e-editor.js | 288 +++++++++++++++++-------------------
src/e-util/test-html-editor-units.c | 80 ++++++++++
2 files changed, 214 insertions(+), 154 deletions(-)
---
diff --git a/data/webkit/e-editor.js b/data/webkit/e-editor.js
index e85a6dcbb5..c3c2d8a7d9 100644
--- a/data/webkit/e-editor.js
+++ b/data/webkit/e-editor.js
@@ -3004,11 +3004,26 @@ EvoEditor.removeEmptyElements = function(tagName)
{
var nodes, node, ii, didRemove = 0;
- nodes = document.querySelectorAll(tagName + ":empty");
+ nodes = document.getElementsByTagName(tagName);
for (ii = nodes.length - 1; ii >= 0; ii--) {
node = nodes[ii];
+ // more than one child element means it's not empty
+ if (node.childElementCount > 1)
+ continue;
+
+ // the first element is not quotation mark
+ if (node.firstElementChild && (node.firstElementChild.tagName != "SPAN" ||
+ node.firstElementChild.className != "-x-evo-quoted"))
+ continue;
+
+ // the text inside is not empty, possibly on either of the two sides of the quotation mark
+ if ((node.firstChild && (node.firstChild.nodeType == node.TEXT_NODE &&
node.firstChild.nodeValue)) ||
+ (node.lastChild && !(node.lastChild === node.firstChild) && (node.lastChild.nodeType ==
node.TEXT_NODE && node.lastChild.nodeValue)))
+ continue;
+
+ // it's either completely empty or it contains only the quotation mark and nothing else
didRemove++;
EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, "removeEmptyElem::" + tagName,
node.parentElement, node.parentElement,
@@ -3056,55 +3071,6 @@ EvoEditor.beforeInputCb = function(inputEvent)
return;
}
-
- if (!selection.isCollapsed) {
- var didRemove = 0;
-
- if (selection.anchorNode && selection.anchorNode.previousSibling &&
- EvoEditor.maybeRemoveQuotationMark(selection.anchorNode.previousSibling))
- didRemove++;
-
- if (selection.focusNode && selection.focusNode.previousSibling &&
- EvoEditor.maybeRemoveQuotationMark(selection.focusNode.previousSibling))
- didRemove++;
-
- if (didRemove) {
- EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, inputEvent.inputType
+ "::selDeletion", selection.anchorNode.parentElement, selection.focusNode.parentElement,
- EvoEditor.CLAIM_CONTENT_FLAG_SAVE_HTML |
EvoEditor.CLAIM_CONTENT_FLAG_USE_PARENT_BLOCK_NODE);
- try {
- var anchorBlockquote = EvoEditor.getParentElement("BLOCKQUOTE",
selection.anchorNode, true);
- var blockquote = EvoEditor.getParentElement("BLOCKQUOTE",
selection.focusNode, true);
-
- selection.deleteFromDocument();
-
- if (blockquote && anchorBlockquote === blockquote &&
blockquote.lastElementChild &&
- (blockquote.lastElementChild.tagName == "DIV" ||
blockquote.lastElementChild.tagName == "PRE") &&
- (!blockquote.lastElementChild.childNodes.length ||
(blockquote.lastElementChild.childNodes.length == 1 &&
- blockquote.lastElementChild.childNodes[0].nodeType ==
blockquote.TEXT_NODE && !blockquote.lastElementChild.childNodes[0].nodeValue))) {
- // keep at least one empty DIV/PRE, when it's at the end of
the BLOCKQUOTE
-
blockquote.lastElementChild.append(document.createElement("BR"));
-
- if
(EvoEditor.requoteNodeParagraph(blockquote.lastElementChild.firstElementChild))
- didRemove++;
- }
- } finally {
- EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_CUSTOM,
inputEvent.inputType + "::selDeletion");
- }
-
- didRemove += EvoEditor.removeEmptyElements("DIV");
- didRemove += EvoEditor.removeEmptyElements("PRE");
-
- EvoUndoRedo.GroupTopRecords(didRemove + 1, inputEvent.inputType +
"::grouped");
- EvoEditor.maybeUpdateFormattingState(EvoEditor.FORCE_MAYBE);
- EvoEditor.EmitContentChanged();
-
- inputEvent.stopImmediatePropagation();
- inputEvent.stopPropagation();
- inputEvent.preventDefault();
-
- return;
- }
- }
}
if (EvoUndoRedo.disabled ||
@@ -3224,149 +3190,163 @@ EvoEditor.AfterInputEvent = function(inputEvent, isWordDelim)
}
// special editing of blockquotes
- if ((inputEvent.inputType.startsWith("insert") || inputEvent.inputType.startsWith("delete")) &&
- selection.isCollapsed && EvoEditor.hasElementWithTagNameAsParent(selection.anchorNode,
"BLOCKQUOTE")) {
- // insertParagraph should split the blockquote into two
- if (isInsertParagraph) {
- var node = selection.anchorNode, childNode = node, parent, removeNode = null;
-
- for (parent = node.parentElement; parent && parent.tagName != "BODY"; parent =
parent.parentElement) {
- if (parent.tagName == "BLOCKQUOTE") {
- childNode = parent;
- }
- }
+ if (selection.isCollapsed && (inputEvent.inputType.startsWith("insert") ||
inputEvent.inputType.startsWith("delete"))) {
+ if (EvoEditor.mode == EvoEditor.MODE_PLAIN_TEXT && inputEvent.inputType.startsWith("delete"))
{
+ var didRemove = 0;
- EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, "blockquoteSplit", childNode,
childNode,
- EvoEditor.CLAIM_CONTENT_FLAG_SAVE_HTML);
+ didRemove += EvoEditor.removeEmptyElements("DIV");
+ didRemove += EvoEditor.removeEmptyElements("PRE");
- try {
- if (node.nodeType == node.ELEMENT_NODE && node.childNodes.length == 1 &&
node.firstChild.tagName == "BR")
- removeNode = node;
- else if (node.nodeType == node.ELEMENT_NODE && node.childNodes.length > 1 &&
node.firstChild.tagName == "BR")
- removeNode = node.firstChild;
+ if (didRemove)
+ EvoUndoRedo.GroupTopRecords(didRemove + 1, inputEvent.inputType +
"::removeEmptyElems");
+ }
- childNode = node;
+ if (EvoEditor.hasElementWithTagNameAsParent(selection.anchorNode, "BLOCKQUOTE")) {
+ // insertParagraph should split the blockquote into two
+ if (isInsertParagraph) {
+ var node = selection.anchorNode, childNode = node, parent, removeNode = null;
for (parent = node.parentElement; parent && parent.tagName != "BODY"; parent
= parent.parentElement) {
if (parent.tagName == "BLOCKQUOTE") {
- childNode = EvoEditor.splitAtChild(parent, childNode);
- parent = childNode;
- } else {
childNode = parent;
}
}
- if (parent) {
- var divNode = document.createElement("DIV");
- divNode.appendChild(document.createElement("BR"));
- parent.insertBefore(divNode, childNode);
- document.getSelection().setPosition(divNode, 0);
- EvoEditor.maybeUpdateParagraphWidth(divNode);
- }
+ EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, "blockquoteSplit",
childNode, childNode,
+ EvoEditor.CLAIM_CONTENT_FLAG_SAVE_HTML);
- while (removeNode && removeNode.tagName != "BODY") {
- node = removeNode.parentElement;
- node.removeChild(removeNode);
+ try {
+ if (node.nodeType == node.ELEMENT_NODE && node.childNodes.length == 1
&& node.firstChild.tagName == "BR")
+ removeNode = node;
+ else if (node.nodeType == node.ELEMENT_NODE && node.childNodes.length
1 && node.firstChild.tagName == "BR")
+ removeNode = node.firstChild;
- if (node.childNodes.length)
- break;
+ childNode = node;
- removeNode = node;
- }
+ for (parent = node.parentElement; parent && parent.tagName != "BODY";
parent = parent.parentElement) {
+ if (parent.tagName == "BLOCKQUOTE") {
+ childNode = EvoEditor.splitAtChild(parent, childNode);
+ parent = childNode;
+ } else {
+ childNode = parent;
+ }
+ }
- if (EvoEditor.mode == EvoEditor.MODE_PLAIN_TEXT) {
- node = document.getSelection().anchorNode;
+ if (parent) {
+ var divNode = document.createElement("DIV");
+ divNode.appendChild(document.createElement("BR"));
+ parent.insertBefore(divNode, childNode);
+ document.getSelection().setPosition(divNode, 0);
+ EvoEditor.maybeUpdateParagraphWidth(divNode);
+ }
+
+ while (removeNode && removeNode.tagName != "BODY") {
+ node = removeNode.parentElement;
+ node.removeChild(removeNode);
- if (node && node.nextElementSibling) {
- var blockquoteLevel = (node.nextElementSibling.tagName ==
"BLOCKQUOTE" ? 1 : 0);
+ if (node.childNodes.length)
+ break;
- EvoEditor.removeQuoteMarks(node.nextElementSibling);
- EvoEditor.convertParagraphs(node.nextElementSibling,
blockquoteLevel,
- EvoEditor.NORMAL_PARAGRAPH_WIDTH - (blockquoteLevel *
2), false);
+ removeNode = node;
}
- if (node && node.previousElementSibling) {
- var blockquoteLevel = (node.previousElementSibling.tagName ==
"BLOCKQUOTE" ? 1 : 0);
+ if (EvoEditor.mode == EvoEditor.MODE_PLAIN_TEXT) {
+ node = document.getSelection().anchorNode;
+
+ if (node && node.nextElementSibling) {
+ var blockquoteLevel =
(node.nextElementSibling.tagName == "BLOCKQUOTE" ? 1 : 0);
+
+ EvoEditor.removeQuoteMarks(node.nextElementSibling);
+ EvoEditor.convertParagraphs(node.nextElementSibling,
blockquoteLevel,
+ EvoEditor.NORMAL_PARAGRAPH_WIDTH -
(blockquoteLevel * 2), false);
+ }
- EvoEditor.removeQuoteMarks(node.previousElementSibling);
- EvoEditor.convertParagraphs(node.previousElementSibling,
blockquoteLevel,
- EvoEditor.NORMAL_PARAGRAPH_WIDTH - (blockquoteLevel *
2), false);
+ if (node && node.previousElementSibling) {
+ var blockquoteLevel =
(node.previousElementSibling.tagName == "BLOCKQUOTE" ? 1 : 0);
+
+
EvoEditor.removeQuoteMarks(node.previousElementSibling);
+
EvoEditor.convertParagraphs(node.previousElementSibling, blockquoteLevel,
+ EvoEditor.NORMAL_PARAGRAPH_WIDTH -
(blockquoteLevel * 2), false);
+ }
}
+ } finally {
+ EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_CUSTOM,
"blockquoteSplit");
+ EvoUndoRedo.GroupTopRecords(2, "insertParagraph::blockquoteSplit");
+ EvoEditor.maybeUpdateFormattingState(EvoEditor.FORCE_MAYBE);
+ EvoEditor.EmitContentChanged();
}
- } finally {
- EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, "blockquoteSplit");
- EvoUndoRedo.GroupTopRecords(2, "insertParagraph::blockquoteSplit");
- EvoEditor.maybeUpdateFormattingState(EvoEditor.FORCE_MAYBE);
- EvoEditor.EmitContentChanged();
- }
- // insertLineBreak should re-quote text in the Plain Text mode
- } else if (inputEvent.inputType == "insertLineBreak") {
- if (EvoEditor.mode == EvoEditor.MODE_PLAIN_TEXT) {
- var selNode = document.getSelection().anchorNode, node = selNode, parent;
+ // insertLineBreak should re-quote text in the Plain Text mode
+ } else if (inputEvent.inputType == "insertLineBreak") {
+ if (EvoEditor.mode == EvoEditor.MODE_PLAIN_TEXT) {
+ var selNode = document.getSelection().anchorNode, node = selNode,
parent;
- while (node && node.tagName != "BODY" && !EvoEditor.IsBlockNode(node)) {
- node = node.parentElement;
- }
+ while (node && node.tagName != "BODY" &&
!EvoEditor.IsBlockNode(node)) {
+ node = node.parentElement;
+ }
- if (node && node.tagName != "BODY" && selNode.previousSibling &&
selNode.previousSibling.nodeValue == "\n") {
- EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, "requote",
node, node,
- EvoEditor.CLAIM_CONTENT_FLAG_SAVE_HTML);
+ if (node && node.tagName != "BODY" && selNode.previousSibling &&
selNode.previousSibling.nodeValue == "\n") {
+ EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_CUSTOM,
"requote", node, node,
+ EvoEditor.CLAIM_CONTENT_FLAG_SAVE_HTML);
- try {
- var blockquoteLevel;
+ try {
+ var blockquoteLevel;
- // the "\n" is replaced with full paragraph
- selNode.parentElement.removeChild(selNode.previousSibling);
+ // the "\n" is replaced with full paragraph
+
selNode.parentElement.removeChild(selNode.previousSibling);
- parent = selNode.parentElement;
+ parent = selNode.parentElement;
- var childNode = selNode;
+ var childNode = selNode;
- while (parent && parent.tagName != "BODY") {
- childNode = EvoEditor.splitAtChild(parent, childNode);
+ while (parent && parent.tagName != "BODY") {
+ childNode = EvoEditor.splitAtChild(parent,
childNode);
- if (childNode === node ||
EvoEditor.IsBlockNode(parent))
- break;
+ if (childNode === node ||
EvoEditor.IsBlockNode(parent))
+ break;
- parent = childNode.parentElement;
- }
+ parent = childNode.parentElement;
+ }
- blockquoteLevel = EvoEditor.getBlockquoteLevel(parent);
+ blockquoteLevel =
EvoEditor.getBlockquoteLevel(parent);
- EvoEditor.quoteParagraph(childNode, blockquoteLevel,
EvoEditor.NORMAL_PARAGRAPH_WIDTH - (2 * blockquoteLevel));
+ EvoEditor.quoteParagraph(childNode, blockquoteLevel,
EvoEditor.NORMAL_PARAGRAPH_WIDTH - (2 * blockquoteLevel));
- document.getSelection().setPosition(childNode, 0);
- } finally {
- EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_CUSTOM,
"requote");
- EvoUndoRedo.GroupTopRecords(2, "insertLineBreak::requote");
- EvoEditor.maybeUpdateFormattingState(EvoEditor.FORCE_MAYBE);
- EvoEditor.EmitContentChanged();
+ document.getSelection().setPosition(childNode, 0);
+ } finally {
+
EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, "requote");
+ EvoUndoRedo.GroupTopRecords(2,
"insertLineBreak::requote");
+
EvoEditor.maybeUpdateFormattingState(EvoEditor.FORCE_MAYBE);
+ EvoEditor.EmitContentChanged();
+ }
}
}
- }
- // it's an insert or delete in the blockquote, which means to recalculate where quotation
marks should be
- } else if (EvoEditor.mode == EvoEditor.MODE_PLAIN_TEXT) {
- var node = document.getSelection().anchorNode;
+ // it's an insert or delete in the blockquote, which means to recalculate where
quotation marks should be
+ } else if (EvoEditor.mode == EvoEditor.MODE_PLAIN_TEXT) {
+ var node = document.getSelection().anchorNode;
- EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_GROUP, "requote::group");
- try {
- var selection = EvoSelection.Store(document);
+ EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_GROUP, "requote::group");
+ try {
+ var selection = EvoSelection.Store(document);
- node = EvoEditor.requoteNodeParagraph(node);
+ EvoEditor.removeEmptyElements("DIV");
+ EvoEditor.removeEmptyElements("PRE");
- if (node && inputEvent.inputType.startsWith("delete")) {
- if (node.nextSiblingElement)
- EvoEditor.requoteNodeParagraph(node.nextSiblingElement);
- if (node.previousSiblingElement)
- EvoEditor.requoteNodeParagraph(node.previousSiblingElement);
- }
+ node = EvoEditor.requoteNodeParagraph(node);
- EvoSelection.Restore(document, selection);
- } finally {
- EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_GROUP, "requote::group");
- EvoUndoRedo.GroupTopRecords(2, inputEvent.inputType + "::requote");
- EvoEditor.maybeUpdateFormattingState(EvoEditor.FORCE_MAYBE);
- EvoEditor.EmitContentChanged();
+ if (node && inputEvent.inputType.startsWith("delete")) {
+ if (node.nextSiblingElement)
+
EvoEditor.requoteNodeParagraph(node.nextSiblingElement);
+ if (node.previousSiblingElement)
+
EvoEditor.requoteNodeParagraph(node.previousSiblingElement);
+ }
+
+ EvoSelection.Restore(document, selection);
+ } finally {
+ EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_GROUP,
"requote::group");
+ EvoUndoRedo.GroupTopRecords(2, inputEvent.inputType + "::requote");
+ EvoEditor.maybeUpdateFormattingState(EvoEditor.FORCE_MAYBE);
+ EvoEditor.EmitContentChanged();
+ }
}
}
}
diff --git a/src/e-util/test-html-editor-units.c b/src/e-util/test-html-editor-units.c
index 04bc9977b5..c738c23aef 100644
--- a/src/e-util/test-html-editor-units.c
+++ b/src/e-util/test-html-editor-units.c
@@ -5926,6 +5926,85 @@ test_delete_quoted_selection (TestFixture *fixture)
g_test_fail ();
}
+static void
+test_delete_quoted_multiselect (TestFixture *fixture)
+{
+ test_utils_set_clipboard_text ("line 1\nline 2\nline 3", FALSE);
+
+ if (!test_utils_run_simple_test (fixture,
+ "mode:html\n"
+ "action:paste-quote\n"
+ "type:X\n"
+ "undo:save\n" /* 1 */
+ "seq:ChcrrSdsD\n",
+ HTML_PREFIX "<blockquote type=\"cite\" " BLOCKQUOTE_STYLE ">"
+ "<div>line 2</div>"
+ "<div>line 3X</div>"
+ "</blockquote>"
+ HTML_SUFFIX,
+ "> line 2\n"
+ "> line 3X\n")) {
+ g_test_fail ();
+ return;
+ }
+
+ if (!test_utils_run_simple_test (fixture,
+ "undo:undo\n"
+ "undo:test\n"
+ "undo:redo\n"
+ "undo:drop:1\n"
+ "seq:Cec\n" /* Go to the end of the document (Ctrl+End) */
+ "type:\\nY\n",
+ HTML_PREFIX "<blockquote type=\"cite\" " BLOCKQUOTE_STYLE ">"
+ "<div>line 2</div>"
+ "<div>line 3X</div>"
+ "</blockquote>"
+ "<div>Y</div>"
+ HTML_SUFFIX,
+ "> line 2\n"
+ "> line 3X\n"
+ "Y\n")) {
+ g_test_fail ();
+ return;
+ }
+
+ test_utils_insert_content (fixture, "<body></body>", E_CONTENT_EDITOR_INSERT_REPLACE_ALL |
E_CONTENT_EDITOR_INSERT_TEXT_HTML);
+
+ if (!test_utils_run_simple_test (fixture,
+ "mode:plain\n"
+ "action:paste-quote\n"
+ "type:X\n"
+ "undo:save\n" /* 1 */
+ "seq:ChcrrSdsD\n",
+ HTML_PREFIX "<blockquote type=\"cite\">"
+ "<div>" QUOTE_SPAN (QUOTE_CHR) "line 2</div>"
+ "<div>" QUOTE_SPAN (QUOTE_CHR) "line 3X</div>"
+ "</blockquote>"
+ HTML_SUFFIX,
+ "> line 2\n"
+ "> line 3X\n")) {
+ g_test_fail ();
+ return;
+ }
+
+ if (!test_utils_run_simple_test (fixture,
+ "undo:undo\n"
+ "undo:test\n"
+ "undo:redo\n"
+ "seq:Cec\n" /* Go to the end of the document (Ctrl+End) */
+ "type:\\nY\n",
+ HTML_PREFIX "<blockquote type=\"cite\">"
+ "<div>" QUOTE_SPAN (QUOTE_CHR) "line 2</div>"
+ "<div>" QUOTE_SPAN (QUOTE_CHR) "line 3X</div>"
+ "</blockquote>"
+ "<div style=\"width: 71ch;\">Y</div>"
+ HTML_SUFFIX,
+ "> line 2\n"
+ "> line 3X\n"
+ "Y\n"))
+ g_test_fail ();
+}
+
static void
test_replace_dialog (TestFixture *fixture)
{
@@ -6525,6 +6604,7 @@ main (gint argc,
test_utils_add_test ("/delete/quoted", test_delete_quoted);
test_utils_add_test ("/delete/after-quoted", test_delete_after_quoted);
test_utils_add_test ("/delete/quoted-selection", test_delete_quoted_selection);
+ test_utils_add_test ("/delete/quoted-multiselect", test_delete_quoted_multiselect);
test_utils_add_test ("/replace/dialog", test_replace_dialog);
test_utils_add_test ("/replace/dialog-all", test_replace_dialog_all);
test_utils_add_test ("/wrap/basic", test_wrap_basic);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]