зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
d6eec3ae11
Коммит
249be2b40e
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче