Bug 1727479 - Make WhiteSpaceVisibilityKeeper::PrepareToSplitAcrossBlocks() adjust split point if it's in non-splittable node r=m_kato

`Selection` can be collapsed in a non-splittable element like a void element
and data nodes such as a comment node.  In this case, we should split the
parent block at before the void element (Blink almost does so, except
`<embed>`, `<hr>` and `<wbr>`).

Differential Revision: https://phabricator.services.mozilla.com/D123709
This commit is contained in:
Masayuki Nakano
2021-08-27 02:14:15 +00:00
parent 9ad028e86b
commit a776c11c37
7 changed files with 387 additions and 187 deletions

View File

@@ -73,25 +73,59 @@ template WSRunScanner::TextFragmentData::TextFragmentData(
template WSRunScanner::TextFragmentData::TextFragmentData(
const EditorDOMPointInText& aPoint, const Element* aEditingHost);
nsresult WhiteSpaceVisibilityKeeper::PrepareToSplitAcrossBlocks(
HTMLEditor& aHTMLEditor, nsCOMPtr<nsINode>* aSplitNode,
uint32_t* aSplitOffset) {
if (NS_WARN_IF(!aSplitNode) || NS_WARN_IF(!*aSplitNode) ||
NS_WARN_IF(!aSplitOffset)) {
return NS_ERROR_INVALID_ARG;
Result<EditorDOMPoint, nsresult>
WhiteSpaceVisibilityKeeper::PrepareToSplitBlockElement(
HTMLEditor& aHTMLEditor, const EditorDOMPoint& aPointToSplit,
const Element& aSplittingBlockElement) {
if (NS_WARN_IF(!aPointToSplit.IsInContentNode()) ||
NS_WARN_IF(!HTMLEditUtils::IsSplittableNode(aSplittingBlockElement)) ||
NS_WARN_IF(!EditorUtils::IsEditableContent(
*aPointToSplit.ContainerAsContent(), EditorType::HTML))) {
return Err(NS_ERROR_FAILURE);
}
AutoTrackDOMPoint tracker(aHTMLEditor.RangeUpdaterRef(), aSplitNode,
aSplitOffset);
// The container of aPointToSplit may be not splittable, e.g., selection
// may be collapsed **in** a `<br>` element or a comment node. So, look
// for splittable point with climbing the tree up.
EditorDOMPoint pointToSplit(aPointToSplit);
for (nsIContent* content : aPointToSplit.ContainerAsContent()
->InclusiveAncestorsOfType<nsIContent>()) {
if (content == &aSplittingBlockElement) {
break;
}
if (HTMLEditUtils::IsSplittableNode(*content)) {
break;
}
pointToSplit.Set(content);
}
nsresult rv = WhiteSpaceVisibilityKeeper::
MakeSureToKeepVisibleWhiteSpacesVisibleAfterSplit(
aHTMLEditor, EditorDOMPoint(*aSplitNode, *aSplitOffset));
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"WhiteSpaceVisibilityKeeper::"
"MakeSureToKeepVisibleWhiteSpacesVisibleAfterSplit() "
"failed");
return rv;
{
AutoTrackDOMPoint tracker(aHTMLEditor.RangeUpdaterRef(), &pointToSplit);
nsresult rv = WhiteSpaceVisibilityKeeper::
MakeSureToKeepVisibleWhiteSpacesVisibleAfterSplit(aHTMLEditor,
pointToSplit);
if (NS_WARN_IF(aHTMLEditor.Destroyed())) {
return Err(NS_ERROR_EDITOR_DESTROYED);
}
if (NS_FAILED(rv)) {
NS_WARNING(
"WhiteSpaceVisibilityKeeper::"
"MakeSureToKeepVisibleWhiteSpacesVisibleAfterSplit() failed");
return Err(rv);
}
}
if (NS_WARN_IF(!pointToSplit.IsInContentNode()) ||
NS_WARN_IF(!pointToSplit.ContainerAsContent()->IsInclusiveDescendantOf(
&aSplittingBlockElement)) ||
NS_WARN_IF(!HTMLEditUtils::IsSplittableNode(aSplittingBlockElement)) ||
NS_WARN_IF(!HTMLEditUtils::IsSplittableNode(
*pointToSplit.ContainerAsContent()))) {
return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
}
return pointToSplit;
}
// static