Bug 1649980 - part 2: Move WSRunScanner::GetEditableBlockParentOrTopmotEditableInlineContent() to HTMLEditUtils r=m_kato

Depends on D82693

Differential Revision: https://phabricator.services.mozilla.com/D82694
This commit is contained in:
Masayuki Nakano 2020-07-10 12:38:56 +00:00
parent 7121f0a1fb
commit 444700f8d1
5 changed files with 87 additions and 44 deletions

View File

@ -5,11 +5,12 @@
#include "HTMLEditUtils.h"
#include "CSSEditUtils.h" // for CSSEditUtils
#include "mozilla/ArrayUtils.h" // for ArrayLength
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc.
#include "mozilla/EditAction.h" // for EditAction
#include "mozilla/EditorBase.h" // for EditorBase
#include "CSSEditUtils.h" // for CSSEditUtils
#include "mozilla/ArrayUtils.h" // for ArrayLength
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc.
#include "mozilla/EditAction.h" // for EditAction
#include "mozilla/EditorBase.h" // for EditorBase, EditorType
#include "mozilla/EditorUtils.h" // for EditorUtils
#include "mozilla/dom/HTMLAnchorElement.h"
#include "mozilla/dom/Element.h" // for Element, nsINode
#include "nsAString.h" // for nsAString::IsEmpty
@ -27,6 +28,8 @@
namespace mozilla {
using EditorType = EditorBase::EditorType;
bool HTMLEditUtils::CanContentsBeJoined(const nsIContent& aLeftContent,
const nsIContent& aRightContent,
StyleDifference aStyleDifference) {
@ -654,6 +657,24 @@ bool HTMLEditUtils::IsSingleLineContainer(nsINode& aNode) {
aNode.IsAnyOfHTMLElements(nsGkAtoms::li, nsGkAtoms::dt, nsGkAtoms::dd);
}
// static
Element*
HTMLEditUtils::GetInclusiveAncestorEditableBlockElementOrInlineEditingHost(
nsIContent& aContent) {
MOZ_ASSERT(EditorUtils::IsEditableContent(aContent, EditorType::HTML));
Element* maybeInlineEditingHost = nullptr;
for (Element* element : aContent.InclusiveAncestorsOfType<Element>()) {
if (!EditorUtils::IsEditableContent(*element, EditorType::HTML)) {
return maybeInlineEditingHost;
}
if (HTMLEditUtils::IsBlockElement(*element)) {
return element;
}
maybeInlineEditingHost = element;
}
return maybeInlineEditingHost;
}
// static
Element* HTMLEditUtils::GetClosestAncestorAnyListElement(
const nsIContent& aContent) {

View File

@ -528,6 +528,13 @@ class HTMLEditUtils final {
return GetAncestorBlockElement(aContent, aAncestorLimiter);
}
/**
* GetInclusiveAncestorEditableBlockElementOrInlineEditingHost() returns
* inclusive block ancestor element of aContent. If aContent is in inline
* editing host, returns the editing host instead.
*/
static Element* GetInclusiveAncestorEditableBlockElementOrInlineEditingHost(
nsIContent& aContent);
/**
* GetClosestAncestorTableElement() returns the nearest inclusive ancestor
* <table> element of aContent.

View File

@ -800,30 +800,6 @@ nsresult WSRunObject::NormalizeWhiteSpacesAround(
// protected methods
//--------------------------------------------------------------------------------------------
nsIContent* WSRunScanner::GetEditableBlockParentOrTopmotEditableInlineContent(
nsIContent* aContent) const {
if (NS_WARN_IF(!aContent)) {
return nullptr;
}
NS_ASSERTION(EditorUtils::IsEditableContent(*aContent, EditorType::HTML),
"Given content is not editable");
// XXX What should we do if scan range crosses block boundary? Currently,
// it's not collapsed only when inserting composition string so that
// it's possible but shouldn't occur actually.
nsIContent* editableBlockParentOrTopmotEditableInlineContent = nullptr;
for (nsIContent* content : aContent->InclusiveAncestorsOfType<nsIContent>()) {
if (!EditorUtils::IsEditableContent(*content, EditorType::HTML)) {
break;
}
editableBlockParentOrTopmotEditableInlineContent = content;
if (HTMLEditUtils::IsBlockElement(
*editableBlockParentOrTopmotEditableInlineContent)) {
break;
}
}
return editableBlockParentOrTopmotEditableInlineContent;
}
nsresult WSRunScanner::GetWSNodes() {
// collect up an array of nodes that are contiguous with the insertion point
// and which contain only white-space. Stop if you reach non-ws text or a new
@ -837,9 +813,21 @@ nsresult WSRunScanner::GetWSNodes() {
// direct child of Document node.
return NS_ERROR_FAILURE;
}
// XXX What should we do if scan range crosses block boundary? Currently,
// it's not collapsed only when inserting composition string so that
// it's possible but shouldn't occur actually.
NS_ASSERTION(
EditorUtils::IsEditableContent(*scanStartContent, EditorType::HTML),
"Given content is not editable");
NS_ASSERTION(scanStartContent->GetAsElementOrParentElement(),
"Given content is not an element and an orphan node");
nsIContent* editableBlockParentOrTopmotEditableInlineContent =
GetEditableBlockParentOrTopmotEditableInlineContent(scanStartContent);
if (NS_WARN_IF(!editableBlockParentOrTopmotEditableInlineContent)) {
EditorUtils::IsEditableContent(*scanStartContent, EditorType::HTML)
? HTMLEditUtils::
GetInclusiveAncestorEditableBlockElementOrInlineEditingHost(
*scanStartContent)
: nullptr;
if (!editableBlockParentOrTopmotEditableInlineContent) {
// Meaning that the container of `mScanStartPoint` is not editable.
editableBlockParentOrTopmotEditableInlineContent = scanStartContent;
}
@ -1548,9 +1536,20 @@ EditorDOMPointInText WSRunScanner::GetInclusiveNextEditableCharPoint(
return EditorDOMPointInText();
}
NS_ASSERTION(EditorUtils::IsEditableContent(
*mScanStartPoint.ContainerAsContent(), EditorType::HTML),
"Given content is not editable");
NS_ASSERTION(
mScanStartPoint.ContainerAsContent()->GetAsElementOrParentElement(),
"Given content is not an element and an orphan node");
nsIContent* editableBlockParentOrTopmotEditableInlineContent =
GetEditableBlockParentOrTopmotEditableInlineContent(
mScanStartPoint.ContainerAsContent());
mScanStartPoint.ContainerAsContent() &&
EditorUtils::IsEditableContent(
*mScanStartPoint.ContainerAsContent(), EditorType::HTML)
? HTMLEditUtils::
GetInclusiveAncestorEditableBlockElementOrInlineEditingHost(
*mScanStartPoint.ContainerAsContent())
: nullptr;
if (NS_WARN_IF(!editableBlockParentOrTopmotEditableInlineContent)) {
// Meaning that the container of `mScanStartPoint` is not editable.
editableBlockParentOrTopmotEditableInlineContent =
@ -1616,9 +1615,20 @@ EditorDOMPointInText WSRunScanner::GetPreviousEditableCharPoint(
return EditorDOMPointInText();
}
NS_ASSERTION(EditorUtils::IsEditableContent(
*mScanStartPoint.ContainerAsContent(), EditorType::HTML),
"Given content is not editable");
NS_ASSERTION(
mScanStartPoint.ContainerAsContent()->GetAsElementOrParentElement(),
"Given content is not an element and an orphan node");
nsIContent* editableBlockParentOrTopmotEditableInlineContent =
GetEditableBlockParentOrTopmotEditableInlineContent(
mScanStartPoint.ContainerAsContent());
mScanStartPoint.ContainerAsContent() &&
EditorUtils::IsEditableContent(
*mScanStartPoint.ContainerAsContent(), EditorType::HTML)
? HTMLEditUtils::
GetInclusiveAncestorEditableBlockElementOrInlineEditingHost(
*mScanStartPoint.ContainerAsContent())
: nullptr;
if (NS_WARN_IF(!editableBlockParentOrTopmotEditableInlineContent)) {
// Meaning that the container of `mScanStartPoint` is not editable.
editableBlockParentOrTopmotEditableInlineContent =
@ -1874,9 +1884,20 @@ nsresult WSRunObject::NormalizeWhiteSpacesAtEndOf(
bool insertBRElement = HTMLEditUtils::IsBlockElement(
*mScanStartPoint.ContainerAsContent());
if (!insertBRElement) {
NS_ASSERTION(
EditorUtils::IsEditableContent(
*mScanStartPoint.ContainerAsContent(), EditorType::HTML),
"Given content is not editable");
NS_ASSERTION(mScanStartPoint.ContainerAsContent()
->GetAsElementOrParentElement(),
"Given content is not an element and an orphan node");
nsIContent* blockParentOrTopmostEditableInlineContent =
GetEditableBlockParentOrTopmotEditableInlineContent(
mScanStartPoint.ContainerAsContent());
EditorUtils::IsEditableContent(
*mScanStartPoint.ContainerAsContent(), EditorType::HTML)
? HTMLEditUtils::
GetInclusiveAncestorEditableBlockElementOrInlineEditingHost(
*mScanStartPoint.ContainerAsContent())
: nullptr;
insertBRElement = blockParentOrTopmostEditableInlineContent &&
HTMLEditUtils::IsBlockElement(
*blockParentOrTopmostEditableInlineContent);

View File

@ -577,13 +577,6 @@ class MOZ_STACK_CLASS WSRunScanner {
nsresult GetWSNodes();
/**
* Return a current block element for aContent or a topmost editable inline
* element if aContent is not in editable block element.
*/
nsIContent* GetEditableBlockParentOrTopmotEditableInlineContent(
nsIContent* aContent) const;
EditorDOMPointInText GetPreviousCharPointFromPointInText(
const EditorDOMPointInText& aPoint) const;

View File

@ -24,6 +24,7 @@ function checks(msg) {
}
SimpleTest.waitForExplicitFinish();
SimpleTest.expectAssertions(3); // Detect odd orphan editable node in `WSRunScanner::GetWSNodes()`
SimpleTest.waitForFocus(function() {
// Put selection after the "y" and backspace
reset();