Bug 1627175 - part 54: Merge `HTMLEditor::Get(First|Last)EditableLeaf()` into `HTMLEditUtils::Get(First|Last)LeafContent()` r=m_kato

The different points are, whether it checks in a given element or not, and
whether it ignores non-editable content.  Therefore, this patch adds new
`LeafNodeType` and new ancestor limiter argument.

The new flag is not handled in the other methods which take `LeafNodeType`
because there is no test.

Differential Revision: https://phabricator.services.mozilla.com/D115123
This commit is contained in:
Masayuki Nakano 2021-05-17 08:01:38 +00:00
Родитель d6eec3ae11
Коммит 249be2b40e
5 изменённых файлов: 65 добавлений и 53 удалений

Просмотреть файл

@ -568,12 +568,25 @@ class HTMLEditUtils final {
// If there is a non-editable element if and only if scanning from editable
// node, return it too.
LeafNodeOrNonEditableNode,
// Ignore non-editable content at walking the tree.
OnlyEditableLeafNode,
};
using LeafNodeTypes = EnumSet<LeafNodeType>;
static nsIContent* GetLastLeafContent(nsINode& aNode,
const LeafNodeTypes& aLeafNodeTypes) {
for (nsIContent* content = aNode.GetLastChild(); content;
content = content->GetLastChild()) {
static nsIContent* GetLastLeafContent(
nsINode& aNode, const LeafNodeTypes& aLeafNodeTypes,
const Element* aAncestorLimiter = nullptr) {
MOZ_ASSERT_IF(
aLeafNodeTypes.contains(LeafNodeType::OnlyEditableLeafNode),
!aLeafNodeTypes.contains(LeafNodeType::LeafNodeOrNonEditableNode));
for (nsIContent* content = aNode.GetLastChild(); content;) {
if (aLeafNodeTypes.contains(LeafNodeType::OnlyEditableLeafNode) &&
!EditorUtils::IsEditableContent(*content,
EditorUtils::EditorType::HTML)) {
content = HTMLEditUtils::GetPreviousContent(
*content, {WalkTreeOption::IgnoreNonEditableNode},
aAncestorLimiter);
continue;
}
if (aLeafNodeTypes.contains(LeafNodeType::LeafNodeOrChildBlock) &&
HTMLEditUtils::IsBlockElement(*content)) {
return content;
@ -585,6 +598,7 @@ class HTMLEditUtils final {
aNode.IsEditable() && !content->IsEditable()) {
return content;
}
content = content->GetLastChild();
}
return nullptr;
}
@ -594,10 +608,21 @@ class HTMLEditUtils final {
* on aLeafNodeTypes whether this scans into a block child or treat block as a
* leaf.
*/
static nsIContent* GetFirstLeafContent(const nsINode& aNode,
const LeafNodeTypes& aLeafNodeTypes) {
for (nsIContent* content = aNode.GetFirstChild(); content;
content = content->GetFirstChild()) {
static nsIContent* GetFirstLeafContent(
const nsINode& aNode, const LeafNodeTypes& aLeafNodeTypes,
const Element* aAncestorLimiter = nullptr) {
MOZ_ASSERT_IF(
aLeafNodeTypes.contains(LeafNodeType::OnlyEditableLeafNode),
!aLeafNodeTypes.contains(LeafNodeType::LeafNodeOrNonEditableNode));
for (nsIContent* content = aNode.GetFirstChild(); content;) {
if (aLeafNodeTypes.contains(LeafNodeType::OnlyEditableLeafNode) &&
!EditorUtils::IsEditableContent(*content,
EditorUtils::EditorType::HTML)) {
content = HTMLEditUtils::GetNextContent(
*content, {WalkTreeOption::IgnoreNonEditableNode},
aAncestorLimiter);
continue;
}
if (aLeafNodeTypes.contains(LeafNodeType::LeafNodeOrChildBlock) &&
HTMLEditUtils::IsBlockElement(*content)) {
return content;
@ -609,6 +634,7 @@ class HTMLEditUtils final {
aNode.IsEditable() && !content->IsEditable()) {
return content;
}
content = content->GetFirstChild();
}
return nullptr;
}
@ -632,6 +658,10 @@ class HTMLEditUtils final {
const nsIContent& aStartContent, const nsIContent& aCurrentBlock,
const LeafNodeTypes& aLeafNodeTypes,
const Element* aAncestorLimiter = nullptr) {
MOZ_ASSERT_IF(
aLeafNodeTypes.contains(LeafNodeType::OnlyEditableLeafNode),
!aLeafNodeTypes.contains(LeafNodeType::LeafNodeOrNonEditableNode));
if (&aStartContent == aAncestorLimiter) {
return nullptr;
}
@ -691,6 +721,11 @@ class HTMLEditUtils final {
const nsIContent& aCurrentBlock, const LeafNodeTypes& aLeafNodeTypes,
const Element* aAncestorLimiter = nullptr) {
MOZ_ASSERT(aStartPoint.IsSet());
MOZ_ASSERT_IF(
aLeafNodeTypes.contains(LeafNodeType::OnlyEditableLeafNode),
!aLeafNodeTypes.contains(LeafNodeType::LeafNodeOrNonEditableNode));
NS_ASSERTION(!aLeafNodeTypes.contains(LeafNodeType::OnlyEditableLeafNode),
"Not implemented yet");
if (!aStartPoint.IsInContentNode()) {
return nullptr;
@ -759,6 +794,12 @@ class HTMLEditUtils final {
const nsIContent& aStartContent, const nsIContent& aCurrentBlock,
const LeafNodeTypes& aLeafNodeTypes,
const Element* aAncestorLimiter = nullptr) {
MOZ_ASSERT_IF(
aLeafNodeTypes.contains(LeafNodeType::OnlyEditableLeafNode),
!aLeafNodeTypes.contains(LeafNodeType::LeafNodeOrNonEditableNode));
NS_ASSERTION(!aLeafNodeTypes.contains(LeafNodeType::OnlyEditableLeafNode),
"Not implemented yet");
if (&aStartContent == aAncestorLimiter) {
return nullptr;
}
@ -818,6 +859,11 @@ class HTMLEditUtils final {
const nsIContent& aCurrentBlock, const LeafNodeTypes& aLeafNodeTypes,
const Element* aAncestorLimiter = nullptr) {
MOZ_ASSERT(aStartPoint.IsSet());
MOZ_ASSERT_IF(
aLeafNodeTypes.contains(LeafNodeType::OnlyEditableLeafNode),
!aLeafNodeTypes.contains(LeafNodeType::LeafNodeOrNonEditableNode));
NS_ASSERTION(!aLeafNodeTypes.contains(LeafNodeType::OnlyEditableLeafNode),
"Not implemented yet");
if (!aStartPoint.IsInContentNode()) {
return nullptr;

Просмотреть файл

@ -4932,42 +4932,6 @@ nsresult HTMLEditor::DeleteSelectionAndPrepareToCreateNode() {
return error.StealNSResult();
}
nsIContent* HTMLEditor::GetFirstEditableLeaf(nsINode& aNode) const {
Element* editingHost = GetActiveEditingHost();
if (NS_WARN_IF(!editingHost) ||
editingHost->IsInclusiveDescendantOf(&aNode)) {
return nullptr;
}
nsIContent* child =
HTMLEditUtils::GetFirstLeafContent(aNode, {LeafNodeType::OnlyLeafNode});
while (child && (!EditorUtils::IsEditableContent(*child, EditorType::HTML) ||
child->HasChildren())) {
child = HTMLEditUtils::GetNextContent(
*child, {WalkTreeOption::IgnoreNonEditableNode},
aNode.IsElement() ? aNode.AsElement() : editingHost);
}
return child;
}
nsIContent* HTMLEditor::GetLastEditableLeaf(nsINode& aNode) const {
Element* editingHost = GetActiveEditingHost();
if (NS_WARN_IF(!editingHost) ||
editingHost->IsInclusiveDescendantOf(&aNode)) {
return nullptr;
}
nsIContent* child =
HTMLEditUtils::GetLastLeafContent(aNode, {LeafNodeType::OnlyLeafNode});
while (child && (!EditorUtils::IsEditableContent(*child, EditorType::HTML) ||
child->HasChildren())) {
child = HTMLEditUtils::GetPreviousContent(
*child, {WalkTreeOption::IgnoreNonEditableNode},
aNode.IsElement() ? aNode.AsElement() : editingHost);
}
return child;
}
bool HTMLEditor::IsEmpty() const {
if (mPaddingBRElementForEmptyEditor) {
return true;

Просмотреть файл

@ -917,9 +917,6 @@ class HTMLEditor final : public TextEditor,
SplitAncestorStyledInlineElementsAt(const EditorDOMPoint& aPointToSplit,
nsAtom* aProperty, nsAtom* aAttribute);
nsIContent* GetFirstEditableLeaf(nsINode& aNode) const;
nsIContent* GetLastEditableLeaf(nsINode& aNode) const;
[[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult GetInlinePropertyBase(
nsAtom& aHTMLProperty, nsAtom* aAttribute, const nsAString* aValue,
bool* aFirst, bool* aAny, bool* aAll, nsAString* outValue) const;

Просмотреть файл

@ -82,6 +82,7 @@ class nsISupports;
namespace mozilla {
using namespace dom;
using LeafNodeType = HTMLEditUtils::LeafNodeType;
#define kInsertCookie "_moz_Insert Here_moz_"
@ -353,8 +354,9 @@ HTMLEditor::HTMLWithContextInserter::GetNewCaretPointAfterInsertingHTML(
// but don't cross tables
nsIContent* containerContent = nullptr;
if (!HTMLEditUtils::IsTable(aLastInsertedPoint.GetChild())) {
containerContent =
mHTMLEditor.GetLastEditableLeaf(*aLastInsertedPoint.GetChild());
containerContent = HTMLEditUtils::GetLastLeafContent(
*aLastInsertedPoint.GetChild(), {LeafNodeType::OnlyEditableLeafNode},
aLastInsertedPoint.GetChild()->GetAsElementOrParentElement());
if (containerContent) {
Element* mostDistantInclusiveAncestorTableElement = nullptr;
for (Element* maybeTableElement =

Просмотреть файл

@ -48,6 +48,7 @@ namespace mozilla {
using namespace dom;
using EmptyCheckOption = HTMLEditUtils::EmptyCheckOption;
using InvisibleWhiteSpaces = HTMLEditUtils::InvisibleWhiteSpaces;
using LeafNodeType = HTMLEditUtils::LeafNodeType;
using StyleDifference = HTMLEditUtils::StyleDifference;
using TableBoundary = HTMLEditUtils::TableBoundary;
using WalkTreeOption = HTMLEditUtils::WalkTreeOption;
@ -2434,13 +2435,15 @@ bool HTMLEditor::AutoDeleteRangesHandler::AutoBlockElementsJoiner::
// First find the adjacent node in the block
if (aDirectionAndAmount == nsIEditor::ePrevious) {
mLeafContentInOtherBlock =
aHTMLEditor.GetLastEditableLeaf(aOtherBlockElement);
mLeafContentInOtherBlock = HTMLEditUtils::GetLastLeafContent(
aOtherBlockElement, {LeafNodeType::OnlyEditableLeafNode},
&aOtherBlockElement);
mLeftContent = mLeafContentInOtherBlock;
mRightContent = aCaretPoint.GetContainerAsContent();
} else {
mLeafContentInOtherBlock =
aHTMLEditor.GetFirstEditableLeaf(aOtherBlockElement);
mLeafContentInOtherBlock = HTMLEditUtils::GetFirstLeafContent(
aOtherBlockElement, {LeafNodeType::OnlyEditableLeafNode},
&aOtherBlockElement);
mLeftContent = aCaretPoint.GetContainerAsContent();
mRightContent = mLeafContentInOtherBlock;
}