зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1627175 - part 55: Move `HTMLEditor::IsEmptyInlineNode()` and `HTMLEditor::IsEmptyOneHardLine()` to `HTMLEditUtils` r=m_kato
Differential Revision: https://phabricator.services.mozilla.com/D115164
This commit is contained in:
Родитель
38e52dd665
Коммит
b6ea40871b
|
@ -85,8 +85,8 @@ class EditorDOMPointBase final {
|
|||
: mParent(nullptr), mChild(nullptr), mIsChildInitialized(false) {}
|
||||
|
||||
template <typename ContainerType>
|
||||
EditorDOMPointBase(ContainerType* aContainer, int32_t aOffset)
|
||||
: mParent(aContainer),
|
||||
EditorDOMPointBase(const ContainerType* aContainer, int32_t aOffset)
|
||||
: mParent(const_cast<ContainerType*>(aContainer)),
|
||||
mChild(nullptr),
|
||||
mOffset(mozilla::Some(aOffset)),
|
||||
mIsChildInitialized(false) {
|
||||
|
|
|
@ -2527,7 +2527,8 @@ EditActionResult HTMLEditor::ChangeSelectedHardLinesToList(
|
|||
bool bOnlyBreaks = true;
|
||||
for (auto& content : arrayOfContents) {
|
||||
// if content is not a Break or empty inline, we're done
|
||||
if (!content->IsHTMLElement(nsGkAtoms::br) && !IsEmptyInlineNode(content)) {
|
||||
if (!content->IsHTMLElement(nsGkAtoms::br) &&
|
||||
!HTMLEditUtils::IsEmptyInlineContent(content)) {
|
||||
bOnlyBreaks = false;
|
||||
break;
|
||||
}
|
||||
|
@ -2647,7 +2648,8 @@ EditActionResult HTMLEditor::ChangeSelectedHardLinesToList(
|
|||
// list item element.
|
||||
// If current node is an empty inline node, just delete it.
|
||||
if (EditorUtils::IsEditableContent(content, EditorType::HTML) &&
|
||||
(content->IsHTMLElement(nsGkAtoms::br) || IsEmptyInlineNode(content))) {
|
||||
(content->IsHTMLElement(nsGkAtoms::br) ||
|
||||
HTMLEditUtils::IsEmptyInlineContent(content))) {
|
||||
nsresult rv = DeleteNodeWithTransaction(*content);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return EditActionResult(NS_ERROR_EDITOR_DESTROYED);
|
||||
|
@ -3097,7 +3099,7 @@ nsresult HTMLEditor::FormatBlockContainerWithTransaction(nsAtom& blockType) {
|
|||
// If there is no visible and editable nodes in the edit targets, make an
|
||||
// empty block.
|
||||
// XXX Isn't this odd if there are only non-editable visible nodes?
|
||||
if (IsEmptyOneHardLine(arrayOfContents)) {
|
||||
if (HTMLEditUtils::IsEmptyOneHardLine(arrayOfContents)) {
|
||||
const nsRange* firstRange = SelectionRef().GetRangeAt(0);
|
||||
if (NS_WARN_IF(!firstRange)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -3555,7 +3557,7 @@ nsresult HTMLEditor::HandleCSSIndentAtSelectionInternal() {
|
|||
// If there is no visible and editable nodes in the edit targets, make an
|
||||
// empty block.
|
||||
// XXX Isn't this odd if there are only non-editable visible nodes?
|
||||
if (IsEmptyOneHardLine(arrayOfContents)) {
|
||||
if (HTMLEditUtils::IsEmptyOneHardLine(arrayOfContents)) {
|
||||
// get selection location
|
||||
const nsRange* firstRange = SelectionRef().GetRangeAt(0);
|
||||
if (NS_WARN_IF(!firstRange)) {
|
||||
|
@ -3776,7 +3778,7 @@ nsresult HTMLEditor::HandleHTMLIndentAtSelectionInternal() {
|
|||
// If there is no visible and editable nodes in the edit targets, make an
|
||||
// empty block.
|
||||
// XXX Isn't this odd if there are only non-editable visible nodes?
|
||||
if (IsEmptyOneHardLine(arrayOfContents)) {
|
||||
if (HTMLEditUtils::IsEmptyOneHardLine(arrayOfContents)) {
|
||||
const nsRange* firstRange = SelectionRef().GetRangeAt(0);
|
||||
if (NS_WARN_IF(!firstRange)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -9365,7 +9367,7 @@ nsresult HTMLEditor::MoveSelectedContentsToDivElementToMakeItAbsolutePosition(
|
|||
// If there is no visible and editable nodes in the edit targets, make an
|
||||
// empty block.
|
||||
// XXX Isn't this odd if there are only non-editable visible nodes?
|
||||
if (IsEmptyOneHardLine(arrayOfContents)) {
|
||||
if (HTMLEditUtils::IsEmptyOneHardLine(arrayOfContents)) {
|
||||
const nsRange* firstRange = SelectionRef().GetRangeAt(0);
|
||||
if (NS_WARN_IF(!firstRange)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -204,7 +204,7 @@ bool HTMLEditUtils::IsHeader(nsINode& aNode) {
|
|||
/**
|
||||
* IsListItem() returns true if aNode is an html list item.
|
||||
*/
|
||||
bool HTMLEditUtils::IsListItem(nsINode* aNode) {
|
||||
bool HTMLEditUtils::IsListItem(const nsINode* aNode) {
|
||||
MOZ_ASSERT(aNode);
|
||||
return aNode->IsAnyOfHTMLElements(nsGkAtoms::li, nsGkAtoms::dd,
|
||||
nsGkAtoms::dt);
|
||||
|
@ -248,7 +248,7 @@ bool HTMLEditUtils::IsTableRow(nsINode* aNode) {
|
|||
/**
|
||||
* IsTableCell() returns true if aNode is an html td or th.
|
||||
*/
|
||||
bool HTMLEditUtils::IsTableCell(nsINode* aNode) {
|
||||
bool HTMLEditUtils::IsTableCell(const nsINode* aNode) {
|
||||
MOZ_ASSERT(aNode);
|
||||
return aNode->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th);
|
||||
}
|
||||
|
@ -302,7 +302,7 @@ bool HTMLEditUtils::IsLink(nsINode* aNode) {
|
|||
return !tmpText.IsEmpty();
|
||||
}
|
||||
|
||||
bool HTMLEditUtils::IsNamedAnchor(nsINode* aNode) {
|
||||
bool HTMLEditUtils::IsNamedAnchor(const nsINode* aNode) {
|
||||
MOZ_ASSERT(aNode);
|
||||
if (!aNode->IsHTMLElement(nsGkAtoms::a)) {
|
||||
return false;
|
||||
|
@ -350,7 +350,7 @@ bool HTMLEditUtils::IsMailCite(nsINode* aNode) {
|
|||
/**
|
||||
* IsFormWidget() returns true if aNode is a form widget of some kind.
|
||||
*/
|
||||
bool HTMLEditUtils::IsFormWidget(nsINode* aNode) {
|
||||
bool HTMLEditUtils::IsFormWidget(const nsINode* aNode) {
|
||||
MOZ_ASSERT(aNode);
|
||||
return aNode->IsAnyOfHTMLElements(nsGkAtoms::textarea, nsGkAtoms::select,
|
||||
nsGkAtoms::button, nsGkAtoms::output,
|
||||
|
@ -366,13 +366,13 @@ bool HTMLEditUtils::SupportsAlignAttr(nsINode& aNode) {
|
|||
nsGkAtoms::h4, nsGkAtoms::h5, nsGkAtoms::h6);
|
||||
}
|
||||
|
||||
bool HTMLEditUtils::IsVisibleTextNode(Text& aText,
|
||||
Element* aEditingHost /* = nullptr */) {
|
||||
bool HTMLEditUtils::IsVisibleTextNode(
|
||||
const Text& aText, const Element* aEditingHost /* = nullptr */) {
|
||||
if (!aText.TextDataLength()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aText.TextIsOnlyWhitespace()) {
|
||||
if (!const_cast<Text&>(aText).TextIsOnlyWhitespace()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -388,7 +388,7 @@ bool HTMLEditUtils::IsVisibleTextNode(Text& aText,
|
|||
}
|
||||
|
||||
bool HTMLEditUtils::IsInVisibleTextFrames(nsPresContext* aPresContext,
|
||||
Text& aText) {
|
||||
const Text& aText) {
|
||||
MOZ_ASSERT(aPresContext);
|
||||
|
||||
nsIFrame* frame = aText.GetPrimaryFrame();
|
||||
|
@ -417,7 +417,7 @@ bool HTMLEditUtils::IsInVisibleTextFrames(nsPresContext* aPresContext,
|
|||
// bug 46209.)
|
||||
bool isVisible = false;
|
||||
rv = selectionController->CheckVisibilityContent(
|
||||
&aText, 0, aText.TextDataLength(), &isVisible);
|
||||
const_cast<Text*>(&aText), 0, aText.TextDataLength(), &isVisible);
|
||||
NS_WARNING_ASSERTION(
|
||||
NS_SUCCEEDED(rv),
|
||||
"nsISelectionController::CheckVisibilityContent() failed");
|
||||
|
@ -489,7 +489,8 @@ bool HTMLEditUtils::IsVisibleBRElement(
|
|||
.ReachedBlockBoundary();
|
||||
}
|
||||
|
||||
bool HTMLEditUtils::IsEmptyNode(nsPresContext* aPresContext, nsINode& aNode,
|
||||
bool HTMLEditUtils::IsEmptyNode(nsPresContext* aPresContext,
|
||||
const nsINode& aNode,
|
||||
const EmptyCheckOptions& aOptions /* = {} */,
|
||||
bool* aSeenBR /* = nullptr */) {
|
||||
MOZ_ASSERT_IF(aOptions.contains(EmptyCheckOption::SafeToAskLayout),
|
||||
|
@ -506,7 +507,7 @@ bool HTMLEditUtils::IsEmptyNode(nsPresContext* aPresContext, nsINode& aNode,
|
|||
*aNode.AsContent())
|
||||
: nullptr;
|
||||
|
||||
if (Text* text = Text::FromNode(&aNode)) {
|
||||
if (const Text* text = Text::FromNode(&aNode)) {
|
||||
return aOptions.contains(EmptyCheckOption::SafeToAskLayout)
|
||||
? !IsInVisibleTextFrames(aPresContext, *text)
|
||||
: !IsVisibleTextNode(*text, maybeParentBlockElement);
|
||||
|
|
|
@ -120,21 +120,21 @@ class HTMLEditUtils final {
|
|||
static bool IsFormatNode(nsINode* aNode);
|
||||
static bool IsNodeThatCanOutdent(nsINode* aNode);
|
||||
static bool IsHeader(nsINode& aNode);
|
||||
static bool IsListItem(nsINode* aNode);
|
||||
static bool IsListItem(const nsINode* aNode);
|
||||
static bool IsTable(nsINode* aNode);
|
||||
static bool IsTableRow(nsINode* aNode);
|
||||
static bool IsAnyTableElement(nsINode* aNode);
|
||||
static bool IsAnyTableElementButNotTable(nsINode* aNode);
|
||||
static bool IsTableCell(nsINode* node);
|
||||
static bool IsTableCell(const nsINode* aNode);
|
||||
static bool IsTableCellOrCaption(nsINode& aNode);
|
||||
static bool IsAnyListElement(nsINode* aNode);
|
||||
static bool IsPre(nsINode* aNode);
|
||||
static bool IsImage(nsINode* aNode);
|
||||
static bool IsLink(nsINode* aNode);
|
||||
static bool IsNamedAnchor(nsINode* aNode);
|
||||
static bool IsNamedAnchor(const nsINode* aNode);
|
||||
static bool IsMozDiv(nsINode* aNode);
|
||||
static bool IsMailCite(nsINode* aNode);
|
||||
static bool IsFormWidget(nsINode* aNode);
|
||||
static bool IsFormWidget(const nsINode* aNode);
|
||||
static bool SupportsAlignAttr(nsINode& aNode);
|
||||
|
||||
static bool CanNodeContain(const nsINode& aParent, const nsIContent& aChild) {
|
||||
|
@ -252,15 +252,15 @@ class HTMLEditUtils final {
|
|||
* But if you call this a lot, please specify proper editing host (or parent
|
||||
* block) for the performance.
|
||||
*/
|
||||
static bool IsVisibleTextNode(dom::Text& aText,
|
||||
Element* aEditingHost = nullptr);
|
||||
static bool IsVisibleTextNode(const dom::Text& aText,
|
||||
const Element* aEditingHost = nullptr);
|
||||
|
||||
/**
|
||||
* IsInVisibleTextFrames() returns true if all text in aText is in visible
|
||||
* text frames. Callers have to guarantee that there is no pending reflow.
|
||||
*/
|
||||
static bool IsInVisibleTextFrames(nsPresContext* aPresContext,
|
||||
dom::Text& aText);
|
||||
const dom::Text& aText);
|
||||
|
||||
/**
|
||||
* IsVisibleBRElement() and IsInvisibleBRElement() return true if aContent is
|
||||
|
@ -298,16 +298,59 @@ class HTMLEditUtils final {
|
|||
SafeToAskLayout,
|
||||
};
|
||||
using EmptyCheckOptions = EnumSet<EmptyCheckOption, uint32_t>;
|
||||
static bool IsEmptyNode(nsPresContext* aPresContext, nsINode& aNode,
|
||||
static bool IsEmptyNode(nsPresContext* aPresContext, const nsINode& aNode,
|
||||
const EmptyCheckOptions& aOptions = {},
|
||||
bool* aSeenBR = nullptr);
|
||||
static bool IsEmptyNode(nsINode& aNode,
|
||||
static bool IsEmptyNode(const nsINode& aNode,
|
||||
const EmptyCheckOptions& aOptions = {},
|
||||
bool* aSeenBR = nullptr) {
|
||||
MOZ_ASSERT(!aOptions.contains(EmptyCheckOption::SafeToAskLayout));
|
||||
return IsEmptyNode(nullptr, aNode, aOptions, aSeenBR);
|
||||
}
|
||||
|
||||
/**
|
||||
* IsEmptyInlineContent() returns true if aContent is an inline node and it
|
||||
* does not have meaningful content.
|
||||
*/
|
||||
static bool IsEmptyInlineContent(const nsIContent& aContent) {
|
||||
return HTMLEditUtils::IsInlineElement(aContent) &&
|
||||
HTMLEditUtils::IsContainerNode(aContent) &&
|
||||
HTMLEditUtils::IsEmptyNode(
|
||||
aContent, {EmptyCheckOption::TreatSingleBRElementAsVisible});
|
||||
}
|
||||
|
||||
/**
|
||||
* IsEmptyOneHardLine() returns true if aArrayOfContents does not represent
|
||||
* 2 or more lines and have meaningful content.
|
||||
*/
|
||||
static bool IsEmptyOneHardLine(
|
||||
nsTArray<OwningNonNull<nsIContent>>& aArrayOfContents) {
|
||||
if (NS_WARN_IF(aArrayOfContents.IsEmpty())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool brElementHasFound = false;
|
||||
for (OwningNonNull<nsIContent>& content : aArrayOfContents) {
|
||||
if (!EditorUtils::IsEditableContent(content,
|
||||
EditorUtils::EditorType::HTML)) {
|
||||
continue;
|
||||
}
|
||||
if (content->IsHTMLElement(nsGkAtoms::br)) {
|
||||
// If there are 2 or more `<br>` elements, it's not empty line since
|
||||
// there may be only one `<br>` element in a hard line.
|
||||
if (brElementHasFound) {
|
||||
return false;
|
||||
}
|
||||
brElementHasFound = true;
|
||||
continue;
|
||||
}
|
||||
if (!HTMLEditUtils::IsEmptyInlineContent(content)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* IsPointAtEdgeOfLink() returns true if aPoint is at start or end of a
|
||||
* link.
|
||||
|
|
|
@ -899,17 +899,6 @@ NS_IMETHODIMP HTMLEditor::NodeIsBlock(nsINode* aNode, bool* aIsBlock) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
bool HTMLEditor::IsEmptyInlineNode(nsIContent& aContent) const {
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
if (!HTMLEditUtils::IsInlineElement(aContent) ||
|
||||
!HTMLEditUtils::IsContainerNode(aContent)) {
|
||||
return false;
|
||||
}
|
||||
return HTMLEditUtils::IsEmptyNode(
|
||||
aContent, {EmptyCheckOption::TreatSingleBRElementAsVisible});
|
||||
}
|
||||
|
||||
/**
|
||||
* IsNextCharInNodeWhiteSpace() checks the adjacent content in the same node to
|
||||
* see if following selection is white-space or nbsp.
|
||||
|
|
|
@ -1442,43 +1442,6 @@ class HTMLEditor final : public TextEditor,
|
|||
[[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
|
||||
MaybeExtendSelectionToHardLineEdgesForBlockEditAction();
|
||||
|
||||
/**
|
||||
* IsEmptyInlineNode() returns true if aContent is an inline node and it does
|
||||
* not have meaningful content.
|
||||
*/
|
||||
bool IsEmptyInlineNode(nsIContent& aContent) const;
|
||||
|
||||
/**
|
||||
* IsEmptyOneHardLine() returns true if aArrayOfContents does not represent
|
||||
* 2 or more lines and have meaningful content.
|
||||
*/
|
||||
bool IsEmptyOneHardLine(
|
||||
nsTArray<OwningNonNull<nsIContent>>& aArrayOfContents) const {
|
||||
if (NS_WARN_IF(aArrayOfContents.IsEmpty())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool brElementHasFound = false;
|
||||
for (OwningNonNull<nsIContent>& content : aArrayOfContents) {
|
||||
if (!EditorUtils::IsEditableContent(content, EditorType::HTML)) {
|
||||
continue;
|
||||
}
|
||||
if (content->IsHTMLElement(nsGkAtoms::br)) {
|
||||
// If there are 2 or more `<br>` elements, it's not empty line since
|
||||
// there may be only one `<br>` element in a hard line.
|
||||
if (brElementHasFound) {
|
||||
return false;
|
||||
}
|
||||
brElementHasFound = true;
|
||||
continue;
|
||||
}
|
||||
if (!IsEmptyInlineNode(content)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* MaybeSplitAncestorsForInsertWithTransaction() does nothing if container of
|
||||
* aStartOfDeepestRightNode can have an element whose tag name is aTag.
|
||||
|
|
|
@ -283,10 +283,10 @@ class MOZ_STACK_CLASS WSRunScanner final {
|
|||
using WSType = WSScanResult::WSType;
|
||||
|
||||
template <typename EditorDOMPointType>
|
||||
WSRunScanner(dom::Element* aEditingHost,
|
||||
WSRunScanner(const dom::Element* aEditingHost,
|
||||
const EditorDOMPointType& aScanStartPoint)
|
||||
: mScanStartPoint(aScanStartPoint),
|
||||
mEditingHost(aEditingHost),
|
||||
mEditingHost(const_cast<dom::Element*>(aEditingHost)),
|
||||
mTextFragmentDataAtStart(mScanStartPoint, mEditingHost) {}
|
||||
|
||||
// ScanNextVisibleNodeOrBlockBoundaryForwardFrom() returns the first visible
|
||||
|
@ -298,7 +298,8 @@ class MOZ_STACK_CLASS WSRunScanner final {
|
|||
const EditorDOMPointBase<PT, CT>& aPoint) const;
|
||||
template <typename PT, typename CT>
|
||||
static WSScanResult ScanNextVisibleNodeOrBlockBoundary(
|
||||
dom::Element* aEditingHost, const EditorDOMPointBase<PT, CT>& aPoint) {
|
||||
const dom::Element* aEditingHost,
|
||||
const EditorDOMPointBase<PT, CT>& aPoint) {
|
||||
return WSRunScanner(aEditingHost, aPoint)
|
||||
.ScanNextVisibleNodeOrBlockBoundaryFrom(aPoint);
|
||||
}
|
||||
|
@ -312,7 +313,8 @@ class MOZ_STACK_CLASS WSRunScanner final {
|
|||
const EditorDOMPointBase<PT, CT>& aPoint) const;
|
||||
template <typename PT, typename CT>
|
||||
static WSScanResult ScanPreviousVisibleNodeOrBlockBoundary(
|
||||
dom::Element* aEditingHost, const EditorDOMPointBase<PT, CT>& aPoint) {
|
||||
const dom::Element* aEditingHost,
|
||||
const EditorDOMPointBase<PT, CT>& aPoint) {
|
||||
return WSRunScanner(aEditingHost, aPoint)
|
||||
.ScanPreviousVisibleNodeOrBlockBoundaryFrom(aPoint);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче