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 "HTMLEditUtils.h"
#include "CSSEditUtils.h" // for CSSEditUtils #include "CSSEditUtils.h" // for CSSEditUtils
#include "mozilla/ArrayUtils.h" // for ArrayLength #include "mozilla/ArrayUtils.h" // for ArrayLength
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc. #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc.
#include "mozilla/EditAction.h" // for EditAction #include "mozilla/EditAction.h" // for EditAction
#include "mozilla/EditorBase.h" // for EditorBase #include "mozilla/EditorBase.h" // for EditorBase, EditorType
#include "mozilla/EditorUtils.h" // for EditorUtils
#include "mozilla/dom/HTMLAnchorElement.h" #include "mozilla/dom/HTMLAnchorElement.h"
#include "mozilla/dom/Element.h" // for Element, nsINode #include "mozilla/dom/Element.h" // for Element, nsINode
#include "nsAString.h" // for nsAString::IsEmpty #include "nsAString.h" // for nsAString::IsEmpty
@ -27,6 +28,8 @@
namespace mozilla { namespace mozilla {
using EditorType = EditorBase::EditorType;
bool HTMLEditUtils::CanContentsBeJoined(const nsIContent& aLeftContent, bool HTMLEditUtils::CanContentsBeJoined(const nsIContent& aLeftContent,
const nsIContent& aRightContent, const nsIContent& aRightContent,
StyleDifference aStyleDifference) { StyleDifference aStyleDifference) {
@ -654,6 +657,24 @@ bool HTMLEditUtils::IsSingleLineContainer(nsINode& aNode) {
aNode.IsAnyOfHTMLElements(nsGkAtoms::li, nsGkAtoms::dt, nsGkAtoms::dd); 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 // static
Element* HTMLEditUtils::GetClosestAncestorAnyListElement( Element* HTMLEditUtils::GetClosestAncestorAnyListElement(
const nsIContent& aContent) { const nsIContent& aContent) {

View File

@ -528,6 +528,13 @@ class HTMLEditUtils final {
return GetAncestorBlockElement(aContent, aAncestorLimiter); 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 * GetClosestAncestorTableElement() returns the nearest inclusive ancestor
* <table> element of aContent. * <table> element of aContent.

View File

@ -800,30 +800,6 @@ nsresult WSRunObject::NormalizeWhiteSpacesAround(
// protected methods // 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() { nsresult WSRunScanner::GetWSNodes() {
// collect up an array of nodes that are contiguous with the insertion point // 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 // 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. // direct child of Document node.
return NS_ERROR_FAILURE; 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 = nsIContent* editableBlockParentOrTopmotEditableInlineContent =
GetEditableBlockParentOrTopmotEditableInlineContent(scanStartContent); EditorUtils::IsEditableContent(*scanStartContent, EditorType::HTML)
if (NS_WARN_IF(!editableBlockParentOrTopmotEditableInlineContent)) { ? HTMLEditUtils::
GetInclusiveAncestorEditableBlockElementOrInlineEditingHost(
*scanStartContent)
: nullptr;
if (!editableBlockParentOrTopmotEditableInlineContent) {
// Meaning that the container of `mScanStartPoint` is not editable. // Meaning that the container of `mScanStartPoint` is not editable.
editableBlockParentOrTopmotEditableInlineContent = scanStartContent; editableBlockParentOrTopmotEditableInlineContent = scanStartContent;
} }
@ -1548,9 +1536,20 @@ EditorDOMPointInText WSRunScanner::GetInclusiveNextEditableCharPoint(
return EditorDOMPointInText(); 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 = nsIContent* editableBlockParentOrTopmotEditableInlineContent =
GetEditableBlockParentOrTopmotEditableInlineContent( mScanStartPoint.ContainerAsContent() &&
mScanStartPoint.ContainerAsContent()); EditorUtils::IsEditableContent(
*mScanStartPoint.ContainerAsContent(), EditorType::HTML)
? HTMLEditUtils::
GetInclusiveAncestorEditableBlockElementOrInlineEditingHost(
*mScanStartPoint.ContainerAsContent())
: nullptr;
if (NS_WARN_IF(!editableBlockParentOrTopmotEditableInlineContent)) { if (NS_WARN_IF(!editableBlockParentOrTopmotEditableInlineContent)) {
// Meaning that the container of `mScanStartPoint` is not editable. // Meaning that the container of `mScanStartPoint` is not editable.
editableBlockParentOrTopmotEditableInlineContent = editableBlockParentOrTopmotEditableInlineContent =
@ -1616,9 +1615,20 @@ EditorDOMPointInText WSRunScanner::GetPreviousEditableCharPoint(
return EditorDOMPointInText(); 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 = nsIContent* editableBlockParentOrTopmotEditableInlineContent =
GetEditableBlockParentOrTopmotEditableInlineContent( mScanStartPoint.ContainerAsContent() &&
mScanStartPoint.ContainerAsContent()); EditorUtils::IsEditableContent(
*mScanStartPoint.ContainerAsContent(), EditorType::HTML)
? HTMLEditUtils::
GetInclusiveAncestorEditableBlockElementOrInlineEditingHost(
*mScanStartPoint.ContainerAsContent())
: nullptr;
if (NS_WARN_IF(!editableBlockParentOrTopmotEditableInlineContent)) { if (NS_WARN_IF(!editableBlockParentOrTopmotEditableInlineContent)) {
// Meaning that the container of `mScanStartPoint` is not editable. // Meaning that the container of `mScanStartPoint` is not editable.
editableBlockParentOrTopmotEditableInlineContent = editableBlockParentOrTopmotEditableInlineContent =
@ -1874,9 +1884,20 @@ nsresult WSRunObject::NormalizeWhiteSpacesAtEndOf(
bool insertBRElement = HTMLEditUtils::IsBlockElement( bool insertBRElement = HTMLEditUtils::IsBlockElement(
*mScanStartPoint.ContainerAsContent()); *mScanStartPoint.ContainerAsContent());
if (!insertBRElement) { 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 = nsIContent* blockParentOrTopmostEditableInlineContent =
GetEditableBlockParentOrTopmotEditableInlineContent( EditorUtils::IsEditableContent(
mScanStartPoint.ContainerAsContent()); *mScanStartPoint.ContainerAsContent(), EditorType::HTML)
? HTMLEditUtils::
GetInclusiveAncestorEditableBlockElementOrInlineEditingHost(
*mScanStartPoint.ContainerAsContent())
: nullptr;
insertBRElement = blockParentOrTopmostEditableInlineContent && insertBRElement = blockParentOrTopmostEditableInlineContent &&
HTMLEditUtils::IsBlockElement( HTMLEditUtils::IsBlockElement(
*blockParentOrTopmostEditableInlineContent); *blockParentOrTopmostEditableInlineContent);

View File

@ -577,13 +577,6 @@ class MOZ_STACK_CLASS WSRunScanner {
nsresult GetWSNodes(); 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( EditorDOMPointInText GetPreviousCharPointFromPointInText(
const EditorDOMPointInText& aPoint) const; const EditorDOMPointInText& aPoint) const;

View File

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