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

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

@ -4932,42 +4932,6 @@ nsresult HTMLEditor::DeleteSelectionAndPrepareToCreateNode() {
return error.StealNSResult(); 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 { bool HTMLEditor::IsEmpty() const {
if (mPaddingBRElementForEmptyEditor) { if (mPaddingBRElementForEmptyEditor) {
return true; return true;

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

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

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

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

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

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