Bug 1747008 - Make HTMLEditor::OnEndHandlingTopLevelEditSubActionInternal stop stripping empty inline elements if they may be inserted intentionally r=m_kato

Starting from bug 1730429, we strip empty inline elements at caret for
compatibility with Blink/WebKit.  However, we should not do it for the elements
which are intentionally inserted (from `inserthtml` command, paste and DnD).

All the cases are handled by `HTMLEditor::HTMLWithContextInserter` so that
it should prevent the new clean up with `TopLevelEditSubActionData`.

Note that `inserthtml` command handling of Blink is really odd.  It inserts
the empty inline elements of the adding testcases into different place so that
Chrome does not pass the new tests.  However, it does not make sense and I
believe that it's out of scope of this bug.

Differential Revision: https://phabricator.services.mozilla.com/D135195
This commit is contained in:
Masayuki Nakano 2022-01-07 03:08:41 +00:00
parent 467ced7327
commit acff628112
4 changed files with 27 additions and 3 deletions

View file

@ -866,6 +866,11 @@ class EditorBase : public nsIEditor,
// set to true.
bool mDidNormalizeWhitespaces;
// Set to true by default. If somebody inserts an HTML fragment
// intentionally, inline elements shouldn't be cleaned up later. In the
// case this is set to false.
bool mNeedsToCleanUpEmptyInlineElements;
/**
* The following methods modifies some data of this struct and
* `EditSubActionData` struct. Currently, these are required only
@ -913,6 +918,7 @@ class EditorBase : public nsIEditor,
mDidDeleteEmptyParentBlocks = false;
mRestoreContentEditableCount = false;
mDidNormalizeWhitespaces = false;
mNeedsToCleanUpEmptyInlineElements = true;
}
/**

View file

@ -632,9 +632,10 @@ nsresult HTMLEditor::OnEndHandlingTopLevelEditSubActionInternal() {
}
// If the selection is in empty inline HTML elements, we should delete
// them.
if (mPlaceholderBatch && SelectionRef().IsCollapsed() &&
SelectionRef().GetFocusNode()) {
// them unless it's inserted intentionally.
if (mPlaceholderBatch &&
TopLevelEditSubActionDataRef().mNeedsToCleanUpEmptyInlineElements &&
SelectionRef().IsCollapsed() && SelectionRef().GetFocusNode()) {
RefPtr<Element> mostDistantEmptyInlineAncestor = nullptr;
for (Element* ancestor :
SelectionRef().GetFocusNode()->InclusiveAncestorsOfType<Element>()) {

View file

@ -744,6 +744,9 @@ nsresult HTMLEditor::HTMLWithContextInserter::Run(
return lastInsertedPoint.inspectErr();
}
mHTMLEditor.TopLevelEditSubActionDataRef()
.mNeedsToCleanUpEmptyInlineElements = false;
if (!lastInsertedPoint.inspect().IsSet()) {
return NS_OK;
}

View file

@ -571,4 +571,18 @@ var browserTests = [
"<pre contenteditable=\"false\"><span contenteditable=\"\">abc<br></span></pre>"],
[true],
{"inserthtml":[false,false,"",false,false,""]}],
// Empty inline elements shouldn't be deleted if they are inserted intentionally
["<div>a[]b</div>",
[["inserthtml","<span></span>"]],
["<div>a<span></span>b</div>",
"<div>a<span></span>b<br></div>"],
[true],
{"inserthtml":[false,false,"",false,false,""]}],
["<div>a[]c</div>",
[["inserthtml","<span class=\"s1\"></span>b<span class=\"s2\"></span>"]],
["<div>a<span class=\"s1\"></span>b<span class=\"s2\"></span>c</div>",
"<div>a<span class=\"s1\"></span>b<span class=\"s2\"></span>c<br></div>"],
[true],
{"inserthtml":[false,false,"",false,false,""]}],
]