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