diff --git a/editor/libeditor/HTMLEditUtils.h b/editor/libeditor/HTMLEditUtils.h
index d10a481d5851..46e1c1c91bbb 100644
--- a/editor/libeditor/HTMLEditUtils.h
+++ b/editor/libeditor/HTMLEditUtils.h
@@ -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;
- 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;
diff --git a/editor/libeditor/HTMLEditor.cpp b/editor/libeditor/HTMLEditor.cpp
index c7a6c8c244e6..9245065ab9ff 100644
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -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;
diff --git a/editor/libeditor/HTMLEditor.h b/editor/libeditor/HTMLEditor.h
index c80d9d5cde8b..e383a81cc78f 100644
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -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;
diff --git a/editor/libeditor/HTMLEditorDataTransfer.cpp b/editor/libeditor/HTMLEditorDataTransfer.cpp
index a79c62ce998e..1dc922c9381f 100644
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -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 =
diff --git a/editor/libeditor/HTMLEditorDeleteHandler.cpp b/editor/libeditor/HTMLEditorDeleteHandler.cpp
index 5f9cb6809be8..80131656fdb2 100644
--- a/editor/libeditor/HTMLEditorDeleteHandler.cpp
+++ b/editor/libeditor/HTMLEditorDeleteHandler.cpp
@@ -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;
}