Bug 1587141 part 2 - Make execCommand("indent") ignore whitespace when looking for sibling list element. r=masayuki

Differential Revision: https://phabricator.services.mozilla.com/D48587

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Mats Palmgren 2019-10-14 17:11:00 +00:00
parent c506e40d11
commit 6aadfc8aaf
6 changed files with 170 additions and 17 deletions

View File

@ -4983,7 +4983,8 @@ nsresult HTMLEditor::IndentListChild(RefPtr<Element>* aCurList,
// Check for whether we should join a list that follows aCurNode.
// We do this if the next element is a list, and the list is of the
// same type (li/ol) as aCurNode was a part it.
if (nsIContent* nextEditableSibling = GetNextHTMLSibling(aCurNode)) {
if (nsIContent* nextEditableSibling =
GetNextHTMLSibling(aCurNode, SkipWhitespace::Yes)) {
if (HTMLEditUtils::IsList(nextEditableSibling) &&
aCurPoint.GetContainer()->NodeInfo()->NameAtom() ==
nextEditableSibling->NodeInfo()->NameAtom() &&
@ -5005,7 +5006,7 @@ nsresult HTMLEditor::IndentListChild(RefPtr<Element>* aCurList,
// We do this if the previous element is a list, and the list is of
// the same type (li/ol) as aCurNode was a part of.
if (nsCOMPtr<nsIContent> previousEditableSibling =
GetPriorHTMLSibling(aCurNode)) {
GetPriorHTMLSibling(aCurNode, SkipWhitespace::Yes)) {
if (HTMLEditUtils::IsList(previousEditableSibling) &&
aCurPoint.GetContainer()->NodeInfo()->NameAtom() ==
previousEditableSibling->NodeInfo()->NameAtom() &&
@ -5026,7 +5027,7 @@ nsresult HTMLEditor::IndentListChild(RefPtr<Element>* aCurList,
// check to see if aCurList is still appropriate. Which it is if
// aCurNode is still right after it in the same list.
nsIContent* previousEditableSibling =
*aCurList ? GetPriorHTMLSibling(aCurNode) : nullptr;
*aCurList ? GetPriorHTMLSibling(aCurNode, SkipWhitespace::Yes) : nullptr;
if (!*aCurList ||
(previousEditableSibling && previousEditableSibling != *aCurList)) {
nsAtom* containerName =

View File

@ -3789,30 +3789,22 @@ nsresult HTMLEditor::RemoveBlockContainerWithTransaction(Element& aElement) {
return NS_OK;
}
/**
* GetPriorHTMLSibling() returns the previous editable sibling, if there is
* one within the parent.
*/
nsIContent* HTMLEditor::GetPriorHTMLSibling(nsINode* aNode) {
nsIContent* HTMLEditor::GetPriorHTMLSibling(nsINode* aNode, SkipWhitespace aSkipWS) {
MOZ_ASSERT(aNode);
nsIContent* node = aNode->GetPreviousSibling();
while (node && !IsEditable(node)) {
while (node && (!IsEditable(node) || SkippableWhitespace(node, aSkipWS))) {
node = node->GetPreviousSibling();
}
return node;
}
/**
* GetNextHTMLSibling() returns the next editable sibling, if there is
* one within the parent.
*/
nsIContent* HTMLEditor::GetNextHTMLSibling(nsINode* aNode) {
nsIContent* HTMLEditor::GetNextHTMLSibling(nsINode* aNode, SkipWhitespace aSkipWS) {
MOZ_ASSERT(aNode);
nsIContent* node = aNode->GetNextSibling();
while (node && !IsEditable(node)) {
while (node && (!IsEditable(node) || SkippableWhitespace(node, aSkipWS))) {
node = node->GetNextSibling();
}

View File

@ -1015,9 +1015,26 @@ class HTMLEditor final : public TextEditor,
SplitAncestorStyledInlineElementsAt(const EditorDOMPoint& aPointToSplit,
nsAtom* aProperty, nsAtom* aAttribute);
nsIContent* GetPriorHTMLSibling(nsINode* aNode);
/**
* GetPriorHTMLSibling() returns the previous editable sibling, if there is
* one within the parent, optionally skipping text nodes that are only
* whitespace.
*/
enum class SkipWhitespace { Yes, No };
nsIContent* GetPriorHTMLSibling(nsINode* aNode, SkipWhitespace = SkipWhitespace::No);
nsIContent* GetNextHTMLSibling(nsINode* aNode);
/**
* GetNextHTMLSibling() returns the next editable sibling, if there is
* one within the parent, optionally skipping text nodes that are only
* whitespace.
*/
nsIContent* GetNextHTMLSibling(nsINode* aNode, SkipWhitespace = SkipWhitespace::No);
// Helper for GetPriorHTMLSibling/GetNextHTMLSibling.
static bool SkippableWhitespace(nsINode* aNode, SkipWhitespace aSkipWS) {
return aSkipWS == SkipWhitespace::Yes &&
aNode->IsText() && aNode->AsText()->TextIsOnlyWhitespace();
}
/**
* GetPreviousHTMLElementOrText*() methods are similar to

View File

@ -0,0 +1,61 @@
<!DOCTYPE HTML>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html><head>
<meta charset="utf-8">
<title>Reference for bug </title>
<style>
html,body {
color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
}
li::before { content: " list-item counter:" counters(list-item,".") " "; }
ol,ul { border:1px solid; margin: 0; }
div > ul { counter-reset: list-item 7; }
</style>
</head>
<body>
<div contenteditable>
<ol start=8>
<li>A</li>
<ol><li class="indent">B</li></ol>
<li>C</li>
</ol>
</div>
<div contenteditable>
<ol start=8>
<li>A</li>
<ol><li class="indent">B</li></ol>
<li>C</li>
</ol>
</div>
<div contenteditable>
<ul>
<li>A</li>
<ul><li class="indent">B</li></ul>
<li>C</li>
</ul>
</div>
<div contenteditable>
<ul>
<li>A</li>
<ul><li class="indent">B</li></ul>
<li>C</li>
</ul>
</div>
<!-- now the same as above without whitespace: -->
<div contenteditable><ol start=8><li>A</li><ol><li class="indent">B</li></ol><li>C</li></ol></div>
<div contenteditable><ol start=8><li>A</li><ol><li class="indent">B</li></ol><li>C</li></ol></div>
<div contenteditable><ul><li>A</li><ul><li class="indent">B</li></ul><li>C</li></ul></div>
<div contenteditable><ul><li>A</li><ul><li class="indent">B</li></ul><li>C</li></ul></div>
</body>
</html>

View File

@ -0,0 +1,81 @@
<!DOCTYPE HTML>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html><head>
<meta charset="utf-8">
<title>Testcase for bug </title>
<style>
html,body {
color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
}
li::before { content: " list-item counter:" counters(list-item,".") " "; }
ol,ul { border:1px solid; margin: 0; }
div > ul { counter-reset: list-item 7; }
</style>
</head>
<body>
<div contenteditable>
<ol start=8>
<li>A</li>
<ol></ol>
<li class="indent">B</li>
<li>C</li>
</ol>
</div>
<div contenteditable>
<ol start=8>
<li>A</li>
<li class="indent">B</li>
<ol></ol>
<li>C</li>
</ol>
</div>
<div contenteditable>
<ul>
<li>A</li>
<ul></ul>
<li class="indent">B</li>
<li>C</li>
</ul>
</div>
<div contenteditable>
<ul>
<li>A</li>
<li class="indent">B</li>
<ul></ul>
<li>C</li>
</ul>
</div>
<!-- now the same as above without whitespace: -->
<div contenteditable><ol start=8><li>A</li><ol></ol><li class="indent">B</li><li>C</li></ol></div>
<div contenteditable><ol start=8><li>A</li><li class="indent">B</li><ol></ol><li>C</li></ol></div>
<div contenteditable><ul><li>A</li><ul></ul><li class="indent">B</li><li>C</li></ul></div>
<div contenteditable><ul><li>A</li><li class="indent">B</li><ul></ul><li>C</li></ul></div>
<script>
function test() {
[...document.querySelectorAll('.indent')].forEach(function(elm) {
var r = document.createRange();
r.setStart(elm.firstChild,0)
r.setEnd(elm.firstChild,0)
window.getSelection().addRange(r);
document.execCommand("indent");
window.getSelection().removeAllRanges();
});
}
test();
document.activeElement.blur();
</script>
</body>
</html>

View File

@ -150,3 +150,4 @@ fuzzy-if(Android,0-1,0-1) needs-focus == 1443902-1.html 1443902-1-ref.html
fuzzy-if(Android,0-1,0-1) needs-focus == 1443902-2.html 1443902-2-ref.html
fuzzy-if(Android,0-1,0-1) needs-focus == 1443902-3.html 1443902-3-ref.html
fuzzy-if(Android,0-1,0-1) needs-focus == 1443902-4.html 1443902-4-ref.html
== exec-command-indent-ws.html exec-command-indent-ws-ref.html