Bug 1851951 - Make HTMLEditUtils::GetElementOfImmediateBlockBoundary ignore invisible text node r=m_kato

Without this patch, the following test newly fails:
```
/editing/other/insertparagraph-with-white-space-style.tentative.html?white-space=nowrap&command=insertText
  FAIL <div contenteditable style="white-space:nowrap; display:inline">abc[]</div> (defaultparagraphseparator: div) - assert_equals: A <br> should be inserted at end expected "abc<br><br>" but got "abc<br>"
  FAIL <div contenteditable style="white-space:nowrap; display:inline">abc[]</div> (defaultparagraphseparator: p) - assert_equals: A <br> should be inserted at end expected "abc<br><br>" but got "abc<br>"
```

The reasons is, the inlined editing host is at end of the `<body>`, therefore,
even though the editing host itself is `inline`, it needs a padding `<br>` to
make it the new line visible.

However, `HTMLEditUtils::GetElementOfImmediateBlockBoundary` does not return
`<body>` because the editing host is followed by `<script>` which has
a text node which is not white-spaces only.  Therefore,
`HTMLEditUtils::IsVisibleBRElement` considers the `<br>` element at end of the
editing host is "visible".

Differential Revision: https://phabricator.services.mozilla.com/D188599
This commit is contained in:
Masayuki Nakano 2023-09-27 03:01:26 +00:00
parent 09514edd73
commit ba6d410ac6
2 changed files with 37 additions and 3 deletions

View File

@ -297,6 +297,26 @@ bool HTMLEditUtils::IsInlineContent(const nsIContent& aContent,
styleDisplay->IsRubyDisplayType();
}
bool HTMLEditUtils::IsInclusiveAncestorCSSDisplayNone(
const nsIContent& aContent) {
if (NS_WARN_IF(!aContent.IsInComposedDoc())) {
return true;
}
for (const Element* element :
aContent.InclusiveFlatTreeAncestorsOfType<Element>()) {
RefPtr<const ComputedStyle> elementStyle =
nsComputedDOMStyle::GetComputedStyleNoFlush(element);
if (NS_WARN_IF(!elementStyle)) {
continue;
}
const nsStyleDisplay* styleDisplay = elementStyle->StyleDisplay();
if (MOZ_UNLIKELY(styleDisplay->mDisplay == StyleDisplay::None)) {
return true;
}
}
return false;
}
bool HTMLEditUtils::IsVisibleElementEvenIfLeafNode(const nsIContent& aContent) {
if (!aContent.IsElement()) {
return false;
@ -687,13 +707,22 @@ Element* HTMLEditUtils::GetElementOfImmediateBlockBoundary(
continue;
}
Text* textNode = Text::FromNode(nextContent);
if (NS_WARN_IF(!textNode)) {
continue; // XXX Is this possible?
switch (nextContent->NodeType()) {
case nsINode::TEXT_NODE:
case nsINode::CDATA_SECTION_NODE:
break;
default:
continue;
}
Text* textNode = Text::FromNode(nextContent);
MOZ_ASSERT(textNode);
if (!textNode->TextLength()) {
continue; // empty invisible text node, keep scanning next one.
}
if (HTMLEditUtils::IsInclusiveAncestorCSSDisplayNone(*textNode)) {
continue; // Styled as invisible.
}
if (!textNode->TextIsOnlyWhitespace()) {
return nullptr; // found a visible text node.
}

View File

@ -427,6 +427,11 @@ class HTMLEditUtils final {
return !HTMLEditUtils::IsVisibleBRElement(aBRElement);
}
/**
* Return true if `display` of inclusive ancestor of aContent is `none`.
*/
static bool IsInclusiveAncestorCSSDisplayNone(const nsIContent& aContent);
/**
* IsVisiblePreformattedNewLine() and IsInvisiblePreformattedNewLine() return
* true if the point is preformatted linefeed and it's visible or invisible.