diff --git a/editor/libeditor/HTMLEditSubActionHandler.cpp b/editor/libeditor/HTMLEditSubActionHandler.cpp index 2a409b6884aa..6aafcd8f5a3a 100644 --- a/editor/libeditor/HTMLEditSubActionHandler.cpp +++ b/editor/libeditor/HTMLEditSubActionHandler.cpp @@ -9028,7 +9028,87 @@ nsresult HTMLEditor::GetInlineStyles( MOZ_ASSERT(IsEditActionDataAvailable()); MOZ_ASSERT(aPendingStyleCacheArray.IsEmpty()); - bool useCSS = IsCSSEnabled(); + if (!IsCSSEnabled()) { + // In the HTML styling mode, we should preserve the order of inline styles + // specified with HTML elements, then, we can keep same order as original + // one when we create new elements to apply the styles at new place. + // XXX Currently, we don't preserve all inline parents, therefore, we cannot + // restore all inline elements as-is. Perhaps, we should store all + // inline elements with more details (e.g., all attributes), and store + // same elements. For example, web apps may give style as: + // em { + // font-style: italic; + // } + // em em { + // font-style: normal; + // font-weight: bold; + // } + // but we cannot restore the style as-is. + nsString value; + const bool givenElementIsEditable = + HTMLEditUtils::IsSimplyEditableNode(aElement); + auto NeedToAppend = [&](nsStaticAtom& aTagName, nsStaticAtom* aAttribute) { + if (mPendingStylesToApplyToNewContent->GetStyleState( + aTagName, aAttribute) != PendingStyleState::NotUpdated) { + return false; // The style has already been changed. + } + if (aPendingStyleCacheArray.Contains(aTagName, aAttribute)) { + return false; // Already preserved + } + return true; + }; + for (Element* const inclusiveAncestor : + aElement.InclusiveAncestorsOfType()) { + if (HTMLEditUtils::IsBlockElement(*inclusiveAncestor) || + (givenElementIsEditable && + !HTMLEditUtils::IsSimplyEditableNode(*inclusiveAncestor))) { + break; + } + if (inclusiveAncestor->IsAnyOfHTMLElements( + nsGkAtoms::b, nsGkAtoms::i, nsGkAtoms::u, nsGkAtoms::s, + nsGkAtoms::strike, nsGkAtoms::tt, nsGkAtoms::em, + nsGkAtoms::strong, nsGkAtoms::dfn, nsGkAtoms::code, + nsGkAtoms::samp, nsGkAtoms::var, nsGkAtoms::cite, nsGkAtoms::abbr, + nsGkAtoms::acronym, nsGkAtoms::sub, nsGkAtoms::sup)) { + nsStaticAtom& tagName = const_cast( + *inclusiveAncestor->NodeInfo()->NameAtom()->AsStatic()); + if (NeedToAppend(tagName, nullptr)) { + aPendingStyleCacheArray.AppendElement( + PendingStyleCache(tagName, nullptr, EmptyString())); + } + continue; + } + if (inclusiveAncestor->IsHTMLElement(nsGkAtoms::font)) { + if (NeedToAppend(*nsGkAtoms::font, nsGkAtoms::face)) { + inclusiveAncestor->GetAttr(kNameSpaceID_None, nsGkAtoms::face, value); + if (!value.IsEmpty()) { + aPendingStyleCacheArray.AppendElement( + PendingStyleCache(*nsGkAtoms::font, nsGkAtoms::face, value)); + value.Truncate(); + } + } + if (NeedToAppend(*nsGkAtoms::font, nsGkAtoms::size)) { + inclusiveAncestor->GetAttr(kNameSpaceID_None, nsGkAtoms::size, value); + if (!value.IsEmpty()) { + aPendingStyleCacheArray.AppendElement( + PendingStyleCache(*nsGkAtoms::font, nsGkAtoms::size, value)); + value.Truncate(); + } + } + if (NeedToAppend(*nsGkAtoms::font, nsGkAtoms::color)) { + inclusiveAncestor->GetAttr(kNameSpaceID_None, nsGkAtoms::color, + value); + if (!value.IsEmpty()) { + aPendingStyleCacheArray.AppendElement( + PendingStyleCache(*nsGkAtoms::font, nsGkAtoms::color, value)); + value.Truncate(); + } + } + continue; + } + } + return NS_OK; + } for (nsStaticAtom* property : {nsGkAtoms::b, nsGkAtoms::i, @@ -9067,7 +9147,7 @@ nsresult HTMLEditor::GetInlineStyles( nsString value; // Don't use nsAutoString here because it requires memcpy // at creating new PendingStyleCache instance. // Don't use CSS for , we don't support it usefully (bug 780035) - if (!useCSS || (property == nsGkAtoms::size)) { + if (property == nsGkAtoms::size) { isSet = HTMLEditUtils::IsInlineStyleSetByElement(aElement, style, nullptr, &value); } else if (style.IsCSSEditable(aElement)) { diff --git a/editor/libeditor/PendingStyles.h b/editor/libeditor/PendingStyles.h index 368802f2ee00..e8c5d01057f6 100644 --- a/editor/libeditor/PendingStyles.h +++ b/editor/libeditor/PendingStyles.h @@ -105,8 +105,8 @@ class PendingStyleCache final { class MOZ_STACK_CLASS AutoPendingStyleCacheArray final : public AutoTArray { public: - index_type IndexOf(const nsStaticAtom& aTag, - const nsStaticAtom* aAttribute) const { + [[nodiscard]] index_type IndexOf(const nsStaticAtom& aTag, + const nsStaticAtom* aAttribute) const { for (index_type index = 0; index < Length(); ++index) { const PendingStyleCache& styleCache = ElementAt(index); if (&styleCache.TagRef() == &aTag && @@ -116,6 +116,11 @@ class MOZ_STACK_CLASS AutoPendingStyleCacheArray final } return NoIndex; } + + [[nodiscard]] bool Contains(const nsStaticAtom& aTag, + const nsStaticAtom* aAttribute) const { + return IndexOf(aTag, aAttribute) != NoIndex; + } }; enum class PendingStyleState { diff --git a/testing/web-platform/meta/editing/run/inserttext.html.ini b/testing/web-platform/meta/editing/run/inserttext.html.ini index b654a68d1842..2b5a76cf7b2f 100644 --- a/testing/web-platform/meta/editing/run/inserttext.html.ini +++ b/testing/web-platform/meta/editing/run/inserttext.html.ini @@ -330,9 +330,6 @@ [[["inserttext","d"\],["inserttext","e"\],["inserttext","f"\]\] "
abc{def}ghi
" compare innerHTML] expected: FAIL - [[["inserttext","d"\],["inserttext","e"\],["inserttext","f"\]\] "
abc[def\]ghi
" compare innerHTML] - expected: FAIL - [[["inserttext","d"\],["inserttext","e"\],["inserttext","f"\],["inserttext","g"\]\] "
abc[defg\]hi
" compare innerHTML] expected: FAIL @@ -347,15 +344,3 @@ [[["inserttext","c"\],["inserttext","d"\],["inserttext","e"\]\] "
ab[cde\]fghi
" compare innerHTML] expected: FAIL - - [[["inserttext","d"\],["inserttext","e"\]\] "
abc[de\]fghi
" compare innerHTML] - expected: FAIL - - [[["inserttext","d"\],["inserttext","e"\]\] "
abc{de\]fghi
" compare innerHTML] - expected: FAIL - - [[["inserttext","d"\],["inserttext","e"\]\] "
abc[de\]fghi
" compare innerHTML] - expected: FAIL - - [[["inserttext","d"\],["inserttext","e"\]\] "
abc{de\]fghi
" compare innerHTML] - expected: FAIL diff --git a/testing/web-platform/meta/editing/run/multitest.html.ini b/testing/web-platform/meta/editing/run/multitest.html.ini index 2ef6f09352a6..535ef516c10b 100644 --- a/testing/web-platform/meta/editing/run/multitest.html.ini +++ b/testing/web-platform/meta/editing/run/multitest.html.ini @@ -1144,27 +1144,12 @@ [[["forwarddelete",""\],["inserttext","d"\],["inserttext","e"\],["inserttext","f"\]\] "
abc{def}ghi
" compare innerHTML] expected: FAIL - [[["delete",""\],["inserttext","d"\],["inserttext","e"\],["inserttext","f"\]\] "
abc[def\]ghi
" compare innerHTML] - expected: FAIL - - [[["forwarddelete",""\],["inserttext","d"\],["inserttext","e"\],["inserttext","f"\]\] "
abc[def\]ghi
" compare innerHTML] - expected: FAIL - [[["delete",""\],["inserttext","d"\],["inserttext","e"\],["inserttext","f"\]\] "
abc[def\]ghi
" compare innerHTML] expected: FAIL - [[["forwarddelete",""\],["inserttext","d"\],["inserttext","e"\],["inserttext","f"\]\] "
abc[def\]ghi
" compare innerHTML] - expected: FAIL - - [[["delete",""\],["inserttext","d"\],["inserttext","e"\],["inserttext","f"\]\] "
abc[def\]ghi
" compare innerHTML] - expected: FAIL - [[["forwarddelete",""\],["inserttext","d"\],["inserttext","e"\],["inserttext","f"\]\] "
abc[def\]ghi
" compare innerHTML] expected: FAIL - [[["delete",""\],["inserttext","d"\],["inserttext","e"\],["inserttext","f"\],["inserttext","g"\]\] "
abc[defg\]hi
" compare innerHTML] - expected: FAIL - [[["forwarddelete",""\],["inserttext","d"\],["inserttext","e"\],["inserttext","f"\],["inserttext","g"\]\] "
abc[defg\]hi
" compare innerHTML] expected: FAIL @@ -1183,12 +1168,6 @@ [[["insertparagraph",""\],["inserttext","d"\],["inserttext","e"\],["inserttext","f"\]\] "
abc{def}ghi
" compare innerHTML] expected: FAIL - [[["insertparagraph",""\],["inserttext","d"\],["inserttext","e"\],["inserttext","f"\]\] "
abc[def\]ghi
" compare innerHTML] - expected: FAIL - - [[["insertparagraph",""\],["inserttext","d"\],["inserttext","e"\],["inserttext","f"\]\] "
abc[def\]ghi
" compare innerHTML] - expected: FAIL - [[["insertparagraph",""\],["inserttext","d"\],["inserttext","e"\],["inserttext","f"\]\] "
abc[def\]ghi
" compare innerHTML] expected: FAIL @@ -1210,9 +1189,6 @@ [[["forwarddelete",""\],["inserttext","d"\],["inserttext","e"\],["inserttext","f"\]\] "
abc[def\]ghi
" compare innerHTML] expected: FAIL - [[["insertlinebreak",""\],["inserttext","d"\],["inserttext","e"\]\] "
abc[de\]fghi
" compare innerHTML] - expected: FAIL - [[["insertparagraph",""\],["inserttext","d"\],["inserttext","e"\],["inserttext","f"\]\] "
abc[def\]ghi
" compare innerHTML] expected: FAIL @@ -1225,9 +1201,6 @@ [[["forwarddelete",""\],["inserttext","c"\],["inserttext","d"\],["inserttext","e"\]\] "
ab[cde\]fghi
" compare innerHTML] expected: FAIL - [[["insertlinebreak",""\],["inserttext","c"\],["inserttext","d"\],["inserttext","e"\]\] "
ab[cde\]fghi
" compare innerHTML] - expected: FAIL - [[["delete",""\],["inserttext","d"\],["inserttext","e"\]\] "
abc[de\]fghi
" compare innerHTML] expected: FAIL @@ -1240,12 +1213,6 @@ [[["forwarddelete",""\],["inserttext","d"\],["inserttext","e"\]\] "
abc{de\]fghi
" compare innerHTML] expected: FAIL - [[["insertlinebreak",""\],["inserttext","d"\],["inserttext","e"\]\] "
abc[de\]fghi
" compare innerHTML] - expected: FAIL - - [[["insertlinebreak",""\],["inserttext","d"\],["inserttext","e"\]\] "
abc{de\]fghi
" compare innerHTML] - expected: FAIL - [[["delete",""\],["inserttext","d"\],["inserttext","e"\]\] "
abc[de\]fghi
" compare innerHTML] expected: FAIL @@ -1257,9 +1224,3 @@ [[["forwarddelete",""\],["inserttext","d"\],["inserttext","e"\]\] "
abc{de\]fghi
" compare innerHTML] expected: FAIL - - [[["insertlinebreak",""\],["inserttext","d"\],["inserttext","e"\]\] "
abc[de\]fghi
" compare innerHTML] - expected: FAIL - - [[["insertlinebreak",""\],["inserttext","d"\],["inserttext","e"\]\] "
abc{de\]fghi
" compare innerHTML] - expected: FAIL diff --git a/testing/web-platform/tests/editing/data/multitest.js b/testing/web-platform/tests/editing/data/multitest.js index b1259afcbf61..135f133ebc34 100644 --- a/testing/web-platform/tests/editing/data/multitest.js +++ b/testing/web-platform/tests/editing/data/multitest.js @@ -2481,27 +2481,20 @@ var browserTests = [ [["styleWithCSS", "false"],["bold",""],["inserttext","d"]], ["
abcd
", "
abcd
", - "
abcd
", - "
abcd
", - "
abcd
", - "
abcd
"], + "
abcd
"], [true,true,true], {"bold":[false,true,"",false,false,""]}], ["
abc[]
", [["styleWithCSS", "false"],["bold",""],["inserttext","d"]], ["
abcd
", "
abcd
", - "
abcd
", - "
abcd
", - "
abcd
", - "
abcd
"], + "
abcd
"], [true,true,true], {"bold":[false,true,"",false,false,""]}], // In this case, second line text should be keep bold style. ["
abc[]

", [["styleWithCSS", "false"],["bold",""],["inserttext","d"]], - ["
abcd

", - "
abcd

"], + "
abcd

", [true,true,true], {"bold":[false,true,"",false,false,""]}], // Tests putting caret to right paragraph at insert paragraph, and preserve