diff --git a/editor/libeditor/HTMLEditSubActionHandler.cpp b/editor/libeditor/HTMLEditSubActionHandler.cpp
index 2cb79eed4b32..c537444a1a43 100644
--- a/editor/libeditor/HTMLEditSubActionHandler.cpp
+++ b/editor/libeditor/HTMLEditSubActionHandler.cpp
@@ -560,9 +560,9 @@ nsresult HTMLEditor::OnEndHandlingTopLevelEditSubActionInternal() {
case EditSubAction::eInsertText:
case EditSubAction::eInsertTextComingFromIME:
case EditSubAction::eInsertLineBreak:
+ case EditSubAction::eInsertParagraphSeparator:
return !StaticPrefs::
editor_white_space_normalization_blink_compatible();
- case EditSubAction::eInsertParagraphSeparator:
case EditSubAction::ePasteHTMLContent:
case EditSubAction::eInsertHTMLSource:
return true;
@@ -2305,7 +2305,7 @@ HTMLEditor::InsertParagraphSeparatorAsSubAction(const Element& aEditingHost) {
Result HTMLEditor::HandleInsertBRElement(
const EditorDOMPoint& aPointToBreak, const Element& aEditingHost) {
- MOZ_ASSERT(aPointToBreak.IsSet());
+ MOZ_ASSERT(aPointToBreak.IsInContentNode());
MOZ_ASSERT(IsEditActionDataAvailable());
const bool editingHostIsEmpty = HTMLEditUtils::IsEmptyNode(
@@ -2365,6 +2365,8 @@ Result HTMLEditor::HandleInsertBRElement(
RefPtr linkNode =
HTMLEditor::GetLinkElement(pointToBreak.GetContainer());
if (linkNode) {
+ // FIXME: Normalize surrounding white-spaces before splitting the
+ // insertion point here.
Result splitLinkNodeResult =
SplitNodeDeepWithTransaction(
*linkNode, pointToBreak,
@@ -2716,6 +2718,26 @@ Result HTMLEditor::HandleInsertParagraphInMailCiteElement(
return Err(NS_ERROR_FAILURE);
}
+ if (StaticPrefs::editor_white_space_normalization_blink_compatible()) {
+ Result pointToSplitOrError =
+ WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitAt(
+ *this, pointToSplit,
+ {WhiteSpaceVisibilityKeeper::NormalizeOption::
+ StopIfPrecedingWhiteSpacesEndsWithNBP,
+ WhiteSpaceVisibilityKeeper::NormalizeOption::
+ StopIfFollowingWhiteSpacesStartsWithNBSP});
+ if (MOZ_UNLIKELY(pointToSplitOrError.isErr())) {
+ NS_WARNING(
+ "WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitAt() "
+ "failed");
+ return pointToSplitOrError.propagateErr();
+ }
+ pointToSplit = pointToSplitOrError.unwrap();
+ if (NS_WARN_IF(!pointToSplit.IsInContentNode())) {
+ return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
+ }
+ }
+
Result splitResult =
SplitNodeDeepWithTransaction(aMailCiteElement, pointToSplit,
SplitAtEdges::eDoNotCreateEmptyContainer);
@@ -9005,6 +9027,7 @@ Result HTMLEditor::HandleInsertParagraphInParagraph(
if (pointToInsertBR.IsInContentNode() &&
HTMLEditUtils::CanNodeContain(
*pointToInsertBR.ContainerAs(), *nsGkAtoms::br)) {
+ AutoTrackDOMPoint trackPointToSplit(RangeUpdaterRef(), &pointToSplit);
Result insertBRElementResultOrError =
InsertLineBreak(WithTransaction::Yes, LineBreakType::BRElement,
pointToInsertBR);
@@ -9020,6 +9043,10 @@ Result HTMLEditor::HandleInsertParagraphInParagraph(
// SplitParagraphWithTransaction.
insertBRElementResult.IgnoreCaretPointSuggestion();
brElement = &insertBRElementResult->BRElementRef();
+ trackPointToSplit.FlushAndStopTracking();
+ if (NS_WARN_IF(!pointToSplit.IsInContentNodeAndValidInComposedDoc())) {
+ return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
+ }
}
}
} else {
diff --git a/editor/libeditor/HTMLEditor.cpp b/editor/libeditor/HTMLEditor.cpp
index 4365cb885b96..7ae5c78ef675 100644
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -4394,7 +4394,9 @@ Result HTMLEditor::PrepareToInsertLineBreak(
}
Result pointToInsertOrError =
WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitAt(
- *this, aPointToInsert);
+ *this, aPointToInsert,
+ {WhiteSpaceVisibilityKeeper::NormalizeOption::
+ StopIfPrecedingWhiteSpacesEndsWithNBP});
if (NS_WARN_IF(pointToInsertOrError.isErr())) {
return pointToInsertOrError.propagateErr();
}
@@ -4413,7 +4415,9 @@ Result HTMLEditor::PrepareToInsertLineBreak(
Result pointToInsertOrError =
StaticPrefs::editor_white_space_normalization_blink_compatible()
? WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitAt(
- *this, aPointToInsert)
+ *this, aPointToInsert,
+ {WhiteSpaceVisibilityKeeper::NormalizeOption::
+ StopIfPrecedingWhiteSpacesEndsWithNBP})
: aPointToInsert;
if (NS_WARN_IF(pointToInsertOrError.isErr())) {
return pointToInsertOrError.propagateErr();
diff --git a/editor/libeditor/WhiteSpaceVisibilityKeeper.cpp b/editor/libeditor/WhiteSpaceVisibilityKeeper.cpp
index 050bfe14acf9..caa97cc8ba80 100644
--- a/editor/libeditor/WhiteSpaceVisibilityKeeper.cpp
+++ b/editor/libeditor/WhiteSpaceVisibilityKeeper.cpp
@@ -47,7 +47,7 @@ Result
WhiteSpaceVisibilityKeeper::PrepareToSplitBlockElement(
HTMLEditor& aHTMLEditor, const EditorDOMPoint& aPointToSplit,
const Element& aSplittingBlockElement) {
- if (NS_WARN_IF(!aPointToSplit.IsInContentNode()) ||
+ if (NS_WARN_IF(!aPointToSplit.IsInContentNodeAndValidInComposedDoc()) ||
NS_WARN_IF(!HTMLEditUtils::IsSplittableNode(aSplittingBlockElement)) ||
NS_WARN_IF(!EditorUtils::IsEditableContent(
*aPointToSplit.ContainerAs(), EditorType::HTML))) {
@@ -69,7 +69,8 @@ WhiteSpaceVisibilityKeeper::PrepareToSplitBlockElement(
pointToSplit.Set(content);
}
- {
+ // TODO: Delete this block once we ship the new normalizer.
+ if (!StaticPrefs::editor_white_space_normalization_blink_compatible()) {
AutoTrackDOMPoint tracker(aHTMLEditor.RangeUpdaterRef(), &pointToSplit);
nsresult rv = WhiteSpaceVisibilityKeeper::
@@ -84,6 +85,21 @@ WhiteSpaceVisibilityKeeper::PrepareToSplitBlockElement(
"MakeSureToKeepVisibleWhiteSpacesVisibleAfterSplit() failed");
return Err(rv);
}
+ } else {
+ // NOTE: Chrome does not normalize white-spaces at splitting `Text` when
+ // inserting a paragraph at least when the surrounding white-spaces being or
+ // end with an NBSP.
+ Result pointToSplitOrError =
+ WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitAt(
+ aHTMLEditor, pointToSplit,
+ {NormalizeOption::StopIfFollowingWhiteSpacesStartsWithNBSP,
+ NormalizeOption::StopIfPrecedingWhiteSpacesEndsWithNBP});
+ if (MOZ_UNLIKELY(pointToSplitOrError.isErr())) {
+ NS_WARNING(
+ "WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitAt() failed");
+ return pointToSplitOrError.propagateErr();
+ }
+ pointToSplit = pointToSplitOrError.unwrap();
}
if (NS_WARN_IF(!pointToSplit.IsInContentNode()) ||
@@ -821,7 +837,8 @@ Result WhiteSpaceVisibilityKeeper::
// static
Result
WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitTextNodeAt(
- HTMLEditor& aHTMLEditor, const EditorDOMPointInText& aPointToSplit) {
+ HTMLEditor& aHTMLEditor, const EditorDOMPointInText& aPointToSplit,
+ NormalizeOptions aOptions) {
MOZ_ASSERT(aPointToSplit.IsSetAndValid());
MOZ_ASSERT(StaticPrefs::editor_white_space_normalization_blink_compatible());
@@ -855,13 +872,18 @@ WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitTextNodeAt(
const HTMLEditor::ReplaceWhiteSpacesData replacePrecedingWhiteSpacesData =
aPointToSplit.IsStartOfContainer() ||
- // Chrome does not normalize the left `Text` at least when it ends
- // with an NBSP.
- aPointToSplit.IsPreviousCharNBSP()
+ (aOptions.contains(
+ NormalizeOption::StopIfPrecedingWhiteSpacesEndsWithNBP) &&
+ aPointToSplit.IsPreviousCharNBSP())
? HTMLEditor::ReplaceWhiteSpacesData()
: aHTMLEditor.GetPrecedingNormalizedStringToSplitAt(aPointToSplit);
const HTMLEditor::ReplaceWhiteSpacesData replaceFollowingWhiteSpaceData =
- aHTMLEditor.GetFollowingNormalizedStringToSplitAt(aPointToSplit);
+ aPointToSplit.IsEndOfContainer() ||
+ (aOptions.contains(
+ NormalizeOption::StopIfFollowingWhiteSpacesStartsWithNBSP) &&
+ aPointToSplit.IsCharNBSP())
+ ? HTMLEditor::ReplaceWhiteSpacesData()
+ : aHTMLEditor.GetFollowingNormalizedStringToSplitAt(aPointToSplit);
const HTMLEditor::ReplaceWhiteSpacesData replaceWhiteSpacesData =
(replacePrecedingWhiteSpacesData + replaceFollowingWhiteSpaceData)
.GetMinimizedData(*textNode);
@@ -904,7 +926,8 @@ WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitTextNodeAt(
// static
Result
WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitAt(
- HTMLEditor& aHTMLEditor, const EditorDOMPoint& aPointToSplit) {
+ HTMLEditor& aHTMLEditor, const EditorDOMPoint& aPointToSplit,
+ NormalizeOptions aOptions) {
MOZ_ASSERT(aPointToSplit.IsSet());
MOZ_ASSERT(StaticPrefs::editor_white_space_normalization_blink_compatible());
@@ -936,7 +959,7 @@ WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitAt(
if (pointToSplit.IsInTextNode()) {
Result pointToSplitOrError =
WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitTextNodeAt(
- aHTMLEditor, pointToSplit.AsInText());
+ aHTMLEditor, pointToSplit.AsInText(), aOptions);
if (MOZ_UNLIKELY(pointToSplitOrError.isErr())) {
NS_WARNING(
"WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitTextNodeAt() "
@@ -981,11 +1004,9 @@ WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitAt(
textNode->TextDataLength()) {
break;
}
- // Chrome does not normalize preceding `Text` at least when it ends with
- // an NBSP.
- if (textNode->TextDataLength() &&
- textNode->TextFragment().CharAt(textNode->TextLength() - 1u) ==
- HTMLEditUtils::kNBSP) {
+ if (aOptions.contains(
+ NormalizeOption::StopIfPrecedingWhiteSpacesEndsWithNBP) &&
+ textNode->TextFragment().SafeLastChar() == HTMLEditUtils::kNBSP) {
break;
}
precedingTextNodes.AppendElement(*textNode);
@@ -1021,6 +1042,11 @@ WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitAt(
textNode->TextDataLength()) {
break;
}
+ if (aOptions.contains(
+ NormalizeOption::StopIfFollowingWhiteSpacesStartsWithNBSP) &&
+ textNode->TextFragment().SafeFirstChar() == HTMLEditUtils::kNBSP) {
+ break;
+ }
followingTextNodes.AppendElement(*textNode);
if (textNode->TextIsOnlyWhitespace() &&
EditorUtils::IsWhiteSpacePreformatted(*textNode)) {
@@ -1045,7 +1071,7 @@ WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitAt(
for (const auto& textNode : precedingTextNodes) {
Result normalizeWhiteSpacesResultOrError =
WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitTextNodeAt(
- aHTMLEditor, EditorDOMPointInText::AtEndOf(textNode));
+ aHTMLEditor, EditorDOMPointInText::AtEndOf(textNode), aOptions);
if (MOZ_UNLIKELY(normalizeWhiteSpacesResultOrError.isErr())) {
NS_WARNING(
"WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitTextNodeAt() "
@@ -1062,7 +1088,7 @@ WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitAt(
for (const auto& textNode : followingTextNodes) {
Result normalizeWhiteSpacesResultOrError =
WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitTextNodeAt(
- aHTMLEditor, EditorDOMPointInText(textNode, 0u));
+ aHTMLEditor, EditorDOMPointInText(textNode, 0u), aOptions);
if (MOZ_UNLIKELY(normalizeWhiteSpacesResultOrError.isErr())) {
NS_WARNING(
"WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitTextNodeAt() "
@@ -1295,10 +1321,13 @@ WhiteSpaceVisibilityKeeper::InsertLineBreak(
}
}
} else {
+ // Chrome does not normalize preceding white-spaces at least when it ends
+ // with an NBSP.
Result
normalizeSurroundingWhiteSpacesResultOrError =
WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitAt(
- aHTMLEditor, aPointToInsert);
+ aHTMLEditor, aPointToInsert,
+ {NormalizeOption::StopIfPrecedingWhiteSpacesEndsWithNBP});
if (MOZ_UNLIKELY(normalizeSurroundingWhiteSpacesResultOrError.isErr())) {
NS_WARNING(
"WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitAt() failed");
diff --git a/editor/libeditor/WhiteSpaceVisibilityKeeper.h b/editor/libeditor/WhiteSpaceVisibilityKeeper.h
index ebb3035e8c2f..76b2f66ab435 100644
--- a/editor/libeditor/WhiteSpaceVisibilityKeeper.h
+++ b/editor/libeditor/WhiteSpaceVisibilityKeeper.h
@@ -130,6 +130,14 @@ class WhiteSpaceVisibilityKeeper final {
const EditorDOMPoint& aPointToSplit,
const Element& aSplittingBlockElement);
+ enum class NormalizeOption {
+ // If set, don't normalize following white-spaces if starts with an NBSP.
+ StopIfFollowingWhiteSpacesStartsWithNBSP,
+ // If set, don't normalize preceding white-spaces if ends with an NBSP.
+ StopIfPrecedingWhiteSpacesEndsWithNBP,
+ };
+ using NormalizeOptions = EnumSet;
+
/**
* Normalize surrounding white-spaces of aPointToSplit. This may normalize
* 2 `Text` nodes if the point is surrounded by them.
@@ -137,7 +145,8 @@ class WhiteSpaceVisibilityKeeper final {
*/
[[nodiscard]] MOZ_CAN_RUN_SCRIPT static Result
NormalizeWhiteSpacesToSplitAt(HTMLEditor& aHTMLEditor,
- const EditorDOMPoint& aPointToSplit);
+ const EditorDOMPoint& aPointToSplit,
+ NormalizeOptions aOptions);
/**
* MergeFirstLineOfRightBlockElementIntoDescendantLeftBlockElement() merges
@@ -365,7 +374,8 @@ class WhiteSpaceVisibilityKeeper final {
*/
[[nodiscard]] MOZ_CAN_RUN_SCRIPT static Result
NormalizeWhiteSpacesToSplitTextNodeAt(
- HTMLEditor& aHTMLEditor, const EditorDOMPointInText& aPointToSplit);
+ HTMLEditor& aHTMLEditor, const EditorDOMPointInText& aPointToSplit,
+ NormalizeOptions aOptions);
/**
* Delete leading or trailing invisible white-spaces around block boundaries