From e3024452176015df0dc15c3f328c4c2813b0a725 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Thu, 26 Oct 2023 03:45:17 +0000 Subject: [PATCH] Bug 1244437 - part 1: Make `HTMLEditUtils::IsFormatNode` check same tags as Chromium does r=m_kato I realized that our `HTMLEditUtils::IsFormatNode` is not maintained different from the other browsers. Therefore, only we do not check new elements defined after HTML 4.01. This patch aligns the list of the format elements to the others [1]. Then, this also changes some expectations of `editing/run/formatblock.html` to align common behavior of the browsers. Note that we mapped `formatBlock` of `execCommand` to `cmd_paragraphState`, and the XUL command handles `
` in a different path [2] and the behavior is pretty different from the other formatBlock command implementations. Therefore, this patch creates new command for `formatBlock` and makes `HTMLEditor` switch behavior in any places. 1. https://source.chromium.org/chromium/chromium/src/+/ba50f40fc4a203df704dc697d6e72469da8c5019:third_party/WebKit/WebCore/editing/FormatBlockCommand.cpp;l=114-134 2. https://searchfox.org/mozilla-central/rev/6602bdf9fff5020fbc8e248c963ddddf09a77b1b/editor/libeditor/HTMLEditor.cpp#2461-2474 Differential Revision: https://phabricator.services.mozilla.com/D190900 --- dom/base/Document.cpp | 12 +- editor/libeditor/EditorCommands.h | 25 + editor/libeditor/HTMLEditSubActionHandler.cpp | 101 +-- editor/libeditor/HTMLEditUtils.cpp | 10 - editor/libeditor/HTMLEditUtils.h | 101 ++- editor/libeditor/HTMLEditor.cpp | 74 ++- editor/libeditor/HTMLEditor.h | 123 +++- editor/libeditor/HTMLEditorCommands.cpp | 55 +- editor/libeditor/HTMLEditorController.cpp | 2 + editor/libeditor/HTMLEditorState.cpp | 74 ++- .../lib/richtext2/currentStatus.js | 3 - .../meta/editing/run/formatblock.html.ini | 583 +----------------- .../meta/editing/run/multitest.html.ini | 69 --- .../tests/editing/data/formatblock.js | 334 ++++++---- widget/CommandList.h | 3 +- 15 files changed, 669 insertions(+), 900 deletions(-) diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index 35f5c31b8596..c3299a3c2c62 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -4912,10 +4912,10 @@ void Document::EnsureInitializeInternalCommandDataHashtable() { sInternalCommandDataHashtable->InsertOrUpdate( u"formatblock"_ns, InternalCommandData( - "cmd_paragraphState", + "cmd_formatBlock", Command::FormatBlock, ExecCommandParam::String, - ParagraphStateCommand::GetInstance, + FormatBlockStateCommand::GetInstance, CommandOnTextEditor::Disabled)); sInternalCommandDataHashtable->InsertOrUpdate( u"styleWithCSS"_ns, @@ -5114,19 +5114,27 @@ Document::InternalCommandData Document::ConvertToInternalCommand( static const nsStaticAtom* kFormattableBlockTags[] = { // clang-format off nsGkAtoms::address, + nsGkAtoms::article, + nsGkAtoms::aside, nsGkAtoms::blockquote, nsGkAtoms::dd, nsGkAtoms::div, nsGkAtoms::dl, nsGkAtoms::dt, + nsGkAtoms::footer, nsGkAtoms::h1, nsGkAtoms::h2, nsGkAtoms::h3, nsGkAtoms::h4, nsGkAtoms::h5, nsGkAtoms::h6, + nsGkAtoms::header, + nsGkAtoms::hgroup, + nsGkAtoms::main, + nsGkAtoms::nav, nsGkAtoms::p, nsGkAtoms::pre, + nsGkAtoms::section, // clang-format on }; nsAutoString value(nsDependentSubstring(start, end)); diff --git a/editor/libeditor/EditorCommands.h b/editor/libeditor/EditorCommands.h index 73fa8ab36d75..031f9057e6de 100644 --- a/editor/libeditor/EditorCommands.h +++ b/editor/libeditor/EditorCommands.h @@ -237,6 +237,7 @@ class EditorCommand : public nsIControllerCommand { return EditorCommandParamType::None; // ParagraphStateCommand case Command::FormatBlock: + case Command::ParagraphState: return EditorCommandParamType::CString | EditorCommandParamType::String | EditorCommandParamType::StateAttribute; @@ -729,6 +730,30 @@ class MultiStateCommandBase : public EditorCommand { nsIPrincipal* aPrincipal) const = 0; }; +/** + * The command class for Document.execCommand("formatBlock"), + * Document.queryCommandValue("formatBlock") etc. + */ +class FormatBlockStateCommand final : public MultiStateCommandBase { + public: + NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON(FormatBlockStateCommand) + + protected: + FormatBlockStateCommand() = default; + virtual ~FormatBlockStateCommand() = default; + + MOZ_CAN_RUN_SCRIPT nsresult GetCurrentState( + HTMLEditor* aHTMLEditor, nsCommandParams& aParams) const final; + MOZ_CAN_RUN_SCRIPT nsresult SetState(HTMLEditor* aHTMLEditor, + const nsAString& aNewState, + nsIPrincipal* aPrincipal) const final; +}; + +/** + * The command class for the legacy XUL edit command, cmd_paragraphState. + * This command treats only

,

, 

,

,

,

,

,
, + *
as a format node. + */ class ParagraphStateCommand final : public MultiStateCommandBase { public: NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON(ParagraphStateCommand) diff --git a/editor/libeditor/HTMLEditSubActionHandler.cpp b/editor/libeditor/HTMLEditSubActionHandler.cpp index dbcdb30b8c47..930768426895 100644 --- a/editor/libeditor/HTMLEditSubActionHandler.cpp +++ b/editor/libeditor/HTMLEditSubActionHandler.cpp @@ -1993,11 +1993,17 @@ HTMLEditor::InsertParagraphSeparatorAsSubAction(const Element& aEditingHost) { separator != ParagraphSeparator::br) { MOZ_ASSERT(separator == ParagraphSeparator::div || separator == ParagraphSeparator::p); + // FIXME: If there is no splittable block element, the other browsers wrap + // the right nodes into new paragraph, but keep the left node as-is. + // We should follow them to make here simpler and better compatibility. Result, nsresult> suggestBlockElementToPutCaretOrError = FormatBlockContainerWithTransaction( selectionRanges, MOZ_KnownLive(HTMLEditor::ToParagraphSeparatorTagName(separator)), - aEditingHost); + // For keeping the traditional behavior at insertParagraph command, + // let's use the XUL paragraph state command targets even if we're + // handling HTML insertParagraph command. + FormatBlockMode::XULParagraphStateCommand, aEditingHost); if (MOZ_UNLIKELY(suggestBlockElementToPutCaretOrError.isErr())) { NS_WARNING("HTMLEditor::FormatBlockContainerWithTransaction() failed"); return suggestBlockElementToPutCaretOrError.propagateErr(); @@ -4577,8 +4583,8 @@ nsresult HTMLEditor::RemoveListAtSelectionAsSubAction( Result, nsresult> HTMLEditor::FormatBlockContainerWithTransaction( - AutoRangeArray& aSelectionRanges, nsAtom& blockType, - const Element& aEditingHost) { + AutoRangeArray& aSelectionRanges, const nsStaticAtom& aNewFormatTagName, + FormatBlockMode aFormatBlockMode, const Element& aEditingHost) { MOZ_ASSERT(IsTopLevelEditSubActionDataAvailable()); // XXX Why do we do this only when there is only one selection range? @@ -4654,7 +4660,8 @@ HTMLEditor::FormatBlockContainerWithTransaction( auto pointToInsertBlock = aSelectionRanges.GetFirstRangeStartPoint(); - if (&blockType == nsGkAtoms::normal || &blockType == nsGkAtoms::_empty) { + if (&aNewFormatTagName == nsGkAtoms::normal || + &aNewFormatTagName == nsGkAtoms::_empty) { if (!pointToInsertBlock.IsInContentNode()) { NS_WARNING( "HTMLEditor::FormatBlockContainerWithTransaction() couldn't find " @@ -4673,7 +4680,10 @@ HTMLEditor::FormatBlockContainerWithTransaction( "block parent"); return Err(NS_ERROR_FAILURE); } - if (!HTMLEditUtils::IsFormatNode(editableBlockElement)) { + if (editableBlockElement->IsAnyOfHTMLElements( + nsGkAtoms::dd, nsGkAtoms::dl, nsGkAtoms::dt) || + !HTMLEditor::IsFormatElement(aFormatBlockMode, + *editableBlockElement)) { return RefPtr(); } @@ -4743,14 +4753,14 @@ HTMLEditor::FormatBlockContainerWithTransaction( // Make sure we can put a block here. Result createNewBlockElementResult = InsertElementWithSplittingAncestorsWithTransaction( - blockType, pointToInsertBlock, BRElementNextToSplitPoint::Keep, - aEditingHost); + aNewFormatTagName, pointToInsertBlock, + BRElementNextToSplitPoint::Keep, aEditingHost); if (MOZ_UNLIKELY(createNewBlockElementResult.isErr())) { NS_WARNING( nsPrintfCString( "HTMLEditor::InsertElementWithSplittingAncestorsWithTransaction(" "%s) failed", - nsAtomCString(&blockType).get()) + nsAtomCString(&aNewFormatTagName).get()) .get()); return createNewBlockElementResult.propagateErr(); } @@ -4784,7 +4794,7 @@ HTMLEditor::FormatBlockContainerWithTransaction( // Okay, now go through all the nodes and make the right kind of blocks, or // whatever is appropriate. // Note: blockquote is handled a little differently. - if (&blockType == nsGkAtoms::blockquote) { + if (&aNewFormatTagName == nsGkAtoms::blockquote) { Result wrapContentsInBlockquoteElementsResult = WrapContentsInBlockquoteElementsWithTransaction(arrayOfContents, @@ -4799,10 +4809,12 @@ HTMLEditor::FormatBlockContainerWithTransaction( .IgnoreCaretPointSuggestion(); return wrapContentsInBlockquoteElementsResult.unwrap().UnwrapNewNode(); } - if (&blockType == nsGkAtoms::normal || &blockType == nsGkAtoms::_empty) { + if (&aNewFormatTagName == nsGkAtoms::normal || + &aNewFormatTagName == nsGkAtoms::_empty) { Result removeBlockContainerElementsResult = RemoveBlockContainerElementsWithTransaction( - arrayOfContents, BlockInlineCheck::UseHTMLDefaultStyle); + arrayOfContents, aFormatBlockMode, + BlockInlineCheck::UseHTMLDefaultStyle); if (MOZ_UNLIKELY(removeBlockContainerElementsResult.isErr())) { NS_WARNING( "HTMLEditor::RemoveBlockContainerElementsWithTransaction() failed"); @@ -4811,10 +4823,10 @@ HTMLEditor::FormatBlockContainerWithTransaction( return RefPtr(); } Result wrapContentsInBlockElementResult = - CreateOrChangeBlockContainerElement(arrayOfContents, blockType, - aEditingHost); + CreateOrChangeFormatContainerElement(arrayOfContents, aNewFormatTagName, + aFormatBlockMode, aEditingHost); if (MOZ_UNLIKELY(wrapContentsInBlockElementResult.isErr())) { - NS_WARNING("HTMLEditor::CreateOrChangeBlockContainerElement() failed"); + NS_WARNING("HTMLEditor::CreateOrChangeFormatContainerElement() failed"); return wrapContentsInBlockElementResult.propagateErr(); } wrapContentsInBlockElementResult.inspect().IgnoreCaretPointSuggestion(); @@ -9008,7 +9020,7 @@ HTMLEditor::WrapContentsInBlockquoteElementsWithTransaction( Result HTMLEditor::RemoveBlockContainerElementsWithTransaction( const nsTArray>& aArrayOfContents, - BlockInlineCheck aBlockInlineCheck) { + FormatBlockMode aFormatBlockMode, BlockInlineCheck aBlockInlineCheck) { MOZ_ASSERT(IsEditActionDataAvailable()); // Intent of this routine is to be used for converting to/from headers, @@ -9018,8 +9030,10 @@ HTMLEditor::RemoveBlockContainerElementsWithTransaction( nsCOMPtr firstContent, lastContent; EditorDOMPoint pointToPutCaret; for (const auto& content : aArrayOfContents) { - // If curNode is an
,

, , or

, remove it.
-    if (HTMLEditUtils::IsFormatNode(content)) {
+    // If the current node is a format element, remove it.
+    if (!content->IsAnyOfHTMLElements(nsGkAtoms::dd, nsGkAtoms::dl,
+                                      nsGkAtoms::dt) &&
+        HTMLEditor::IsFormatElement(aFormatBlockMode, content)) {
       // Process any partial progress saved
       if (blockElement) {
         Result unwrapBlockElementResult =
@@ -9079,8 +9093,8 @@ HTMLEditor::RemoveBlockContainerElementsWithTransaction(
       AutoTArray, 24> childContents;
       HTMLEditUtils::CollectAllChildren(*content, childContents);
       Result removeBlockContainerElementsResult =
-          RemoveBlockContainerElementsWithTransaction(childContents,
-                                                      aBlockInlineCheck);
+          RemoveBlockContainerElementsWithTransaction(
+              childContents, aFormatBlockMode, aBlockInlineCheck);
       if (MOZ_UNLIKELY(removeBlockContainerElementsResult.isErr())) {
         NS_WARNING(
             "HTMLEditor::RemoveBlockContainerElementsWithTransaction() failed");
@@ -9120,7 +9134,10 @@ HTMLEditor::RemoveBlockContainerElementsWithTransaction(
       blockElement = HTMLEditUtils::GetAncestorElement(
           content, HTMLEditUtils::ClosestEditableBlockElement,
           aBlockInlineCheck);
-      if (!blockElement || !HTMLEditUtils::IsFormatNode(blockElement) ||
+      if (!blockElement ||
+          blockElement->IsAnyOfHTMLElements(nsGkAtoms::dd, nsGkAtoms::dl,
+                                            nsGkAtoms::dt) ||
+          !HTMLEditor::IsFormatElement(aFormatBlockMode, *blockElement) ||
           !HTMLEditUtils::IsRemovableNode(*blockElement)) {
         // Not a block kind that we care about.
         blockElement = nullptr;
@@ -9167,8 +9184,9 @@ HTMLEditor::RemoveBlockContainerElementsWithTransaction(
 }
 
 Result
-HTMLEditor::CreateOrChangeBlockContainerElement(
-    nsTArray>& aArrayOfContents, nsAtom& aBlockTag,
+HTMLEditor::CreateOrChangeFormatContainerElement(
+    nsTArray>& aArrayOfContents,
+    const nsStaticAtom& aNewFormatTagName, FormatBlockMode aFormatBlockMode,
     const Element& aEditingHost) {
   MOZ_ASSERT(IsTopLevelEditSubActionDataAvailable());
 
@@ -9189,7 +9207,7 @@ HTMLEditor::CreateOrChangeBlockContainerElement(
     }
 
     // Is it already the right kind of block, or an uneditable block?
-    if (content->IsHTMLElement(&aBlockTag) ||
+    if (content->IsHTMLElement(&aNewFormatTagName) ||
         (!EditorUtils::IsEditableContent(content, EditorType::HTML) &&
          HTMLEditUtils::IsBlockElement(
              content, BlockInlineCheck::UseHTMLDefaultStyle))) {
@@ -9203,12 +9221,14 @@ HTMLEditor::CreateOrChangeBlockContainerElement(
     // new block of correct type.
     // XXX: pre can't hold everything the others can
     if (HTMLEditUtils::IsMozDiv(content) ||
-        HTMLEditUtils::IsFormatNode(content)) {
+        (!content->IsAnyOfHTMLElements(nsGkAtoms::dd, nsGkAtoms::dl,
+                                       nsGkAtoms::dt) &&
+         HTMLEditor::IsFormatElement(aFormatBlockMode, content))) {
       // Forget any previous block used for previous inline nodes
       curBlock = nullptr;
       Result replaceWithNewBlockElementResult =
           ReplaceContainerAndCloneAttributesWithTransaction(
-              MOZ_KnownLive(*content->AsElement()), aBlockTag);
+              MOZ_KnownLive(*content->AsElement()), aNewFormatTagName);
       if (MOZ_UNLIKELY(replaceWithNewBlockElementResult.isErr())) {
         NS_WARNING(
             "EditorBase::ReplaceContainerAndCloneAttributesWithTransaction() "
@@ -9242,11 +9262,12 @@ HTMLEditor::CreateOrChangeBlockContainerElement(
       HTMLEditUtils::CollectAllChildren(*content, childContents);
       if (!childContents.IsEmpty()) {
         Result wrapChildrenInBlockElementResult =
-            CreateOrChangeBlockContainerElement(childContents, aBlockTag,
-                                                aEditingHost);
+            CreateOrChangeFormatContainerElement(
+                childContents, aNewFormatTagName, aFormatBlockMode,
+                aEditingHost);
         if (MOZ_UNLIKELY(wrapChildrenInBlockElementResult.isErr())) {
           NS_WARNING(
-              "HTMLEditor::CreateOrChangeBlockContainerElement() failed");
+              "HTMLEditor::CreateOrChangeFormatContainerElement() failed");
           return wrapChildrenInBlockElementResult;
         }
         CreateElementResult unwrappedWrapChildrenInBlockElementResult =
@@ -9263,14 +9284,14 @@ HTMLEditor::CreateOrChangeBlockContainerElement(
       // Make sure we can put a block here
       Result createNewBlockElementResult =
           InsertElementWithSplittingAncestorsWithTransaction(
-              aBlockTag, atContent, BRElementNextToSplitPoint::Keep,
+              aNewFormatTagName, atContent, BRElementNextToSplitPoint::Keep,
               aEditingHost);
       if (MOZ_UNLIKELY(createNewBlockElementResult.isErr())) {
         NS_WARNING(
             nsPrintfCString(
                 "HTMLEditor::"
                 "InsertElementWithSplittingAncestorsWithTransaction(%s) failed",
-                nsAtomCString(&aBlockTag).get())
+                nsAtomCString(&aNewFormatTagName).get())
                 .get());
         return createNewBlockElementResult;
       }
@@ -9304,14 +9325,14 @@ HTMLEditor::CreateOrChangeBlockContainerElement(
       // block for it.
       Result createNewBlockElementResult =
           InsertElementWithSplittingAncestorsWithTransaction(
-              aBlockTag, atContent, BRElementNextToSplitPoint::Keep,
+              aNewFormatTagName, atContent, BRElementNextToSplitPoint::Keep,
               aEditingHost);
       if (MOZ_UNLIKELY(createNewBlockElementResult.isErr())) {
         NS_WARNING(
             nsPrintfCString(
                 "HTMLEditor::"
                 "InsertElementWithSplittingAncestorsWithTransaction(%s) failed",
-                nsAtomCString(&aBlockTag).get())
+                nsAtomCString(&aNewFormatTagName).get())
                 .get());
         return createNewBlockElementResult;
       }
@@ -9348,7 +9369,7 @@ HTMLEditor::CreateOrChangeBlockContainerElement(
       // added here if that should change
       //
       // If content is a non editable, drop it if we are going to 
.
-      if (&aBlockTag == nsGkAtoms::pre &&
+      if (&aNewFormatTagName == nsGkAtoms::pre &&
           !EditorUtils::IsEditableContent(content, EditorType::HTML)) {
         // Do nothing to this block
         continue;
@@ -9358,13 +9379,13 @@ HTMLEditor::CreateOrChangeBlockContainerElement(
       if (!curBlock) {
         Result createNewBlockElementResult =
             InsertElementWithSplittingAncestorsWithTransaction(
-                aBlockTag, atContent, BRElementNextToSplitPoint::Keep,
+                aNewFormatTagName, atContent, BRElementNextToSplitPoint::Keep,
                 aEditingHost);
         if (MOZ_UNLIKELY(createNewBlockElementResult.isErr())) {
           NS_WARNING(nsPrintfCString("HTMLEditor::"
-                                     "InsertElementWithSplittingAncestorsWithTr"
-                                     "ansaction(%s) failed",
-                                     nsAtomCString(&aBlockTag).get())
+                                     "InsertElementWithSplittingAncestorsWith"
+                                     "Transaction(%s) failed",
+                                     nsAtomCString(&aNewFormatTagName).get())
                          .get());
           return createNewBlockElementResult;
         }
@@ -9414,7 +9435,7 @@ HTMLEditor::CreateOrChangeBlockContainerElement(
 
 Result
 HTMLEditor::MaybeSplitAncestorsForInsertWithTransaction(
-    nsAtom& aTag, const EditorDOMPoint& aStartOfDeepestRightNode,
+    const nsAtom& aTag, const EditorDOMPoint& aStartOfDeepestRightNode,
     const Element& aEditingHost) {
   MOZ_ASSERT(IsEditActionDataAvailable());
 
@@ -9465,7 +9486,7 @@ HTMLEditor::MaybeSplitAncestorsForInsertWithTransaction(
 
 Result
 HTMLEditor::InsertElementWithSplittingAncestorsWithTransaction(
-    nsAtom& aTagName, const EditorDOMPoint& aPointToInsert,
+    const nsAtom& aTagName, const EditorDOMPoint& aPointToInsert,
     BRElementNextToSplitPoint aBRElementNextToSplitPoint,
     const Element& aEditingHost,
     const InitializeInsertingElement& aInitializer) {
@@ -10382,7 +10403,7 @@ nsresult HTMLEditor::RemoveEmptyNodesIn(const EditorDOMRange& aRange) {
             // Only consider certain nodes to be empty for purposes of removal
             return true;
           }
-          if (HTMLEditUtils::IsFormatNode(content) ||
+          if (HTMLEditUtils::IsFormatElementForFormatBlockCommand(*content) ||
               HTMLEditUtils::IsListItem(content) ||
               content->IsHTMLElement(nsGkAtoms::blockquote)) {
             // These node types are candidates if selection is not in them.  If
diff --git a/editor/libeditor/HTMLEditUtils.cpp b/editor/libeditor/HTMLEditUtils.cpp
index 8fac3e757b35..bc61d817269f 100644
--- a/editor/libeditor/HTMLEditUtils.cpp
+++ b/editor/libeditor/HTMLEditUtils.cpp
@@ -403,16 +403,6 @@ bool HTMLEditUtils::IsRemovableInlineStyleElement(Element& aElement) {
   return tagName.LowerCaseEqualsASCII("blink");
 }
 
-/**
- * IsFormatNode() returns true if aNode is a format node.
- */
-bool HTMLEditUtils::IsFormatNode(const nsINode* aNode) {
-  MOZ_ASSERT(aNode);
-  return aNode->IsAnyOfHTMLElements(
-      nsGkAtoms::p, nsGkAtoms::pre, nsGkAtoms::h1, nsGkAtoms::h2, nsGkAtoms::h3,
-      nsGkAtoms::h4, nsGkAtoms::h5, nsGkAtoms::h6, nsGkAtoms::address);
-}
-
 /**
  * IsNodeThatCanOutdent() returns true if aNode is a list, list item or
  * blockquote.
diff --git a/editor/libeditor/HTMLEditUtils.h b/editor/libeditor/HTMLEditUtils.h
index d2c1b305dfd2..1482a1d2b03d 100644
--- a/editor/libeditor/HTMLEditUtils.h
+++ b/editor/libeditor/HTMLEditUtils.h
@@ -213,7 +213,90 @@ class HTMLEditUtils final {
    * styles.
    */
   static bool IsRemovableInlineStyleElement(Element& aElement);
-  static bool IsFormatNode(const nsINode* aNode);
+
+  /**
+   * Return true if aTagName is one of the format element name of
+   * Document.execCommand("formatBlock").
+   */
+  [[nodiscard]] static bool IsFormatTagForFormatBlockCommand(
+      const nsStaticAtom& aTagName) {
+    return
+        // clang-format off
+        &aTagName == nsGkAtoms::address ||
+        &aTagName == nsGkAtoms::article ||
+        &aTagName == nsGkAtoms::aside ||
+        &aTagName == nsGkAtoms::blockquote ||
+        &aTagName == nsGkAtoms::dd ||
+        &aTagName == nsGkAtoms::div ||
+        &aTagName == nsGkAtoms::dl ||
+        &aTagName == nsGkAtoms::dt ||
+        &aTagName == nsGkAtoms::footer ||
+        &aTagName == nsGkAtoms::h1 ||
+        &aTagName == nsGkAtoms::h2 ||
+        &aTagName == nsGkAtoms::h3 ||
+        &aTagName == nsGkAtoms::h4 ||
+        &aTagName == nsGkAtoms::h5 ||
+        &aTagName == nsGkAtoms::h6 ||
+        &aTagName == nsGkAtoms::header ||
+        &aTagName == nsGkAtoms::hgroup ||
+        &aTagName == nsGkAtoms::main ||
+        &aTagName == nsGkAtoms::nav ||
+        &aTagName == nsGkAtoms::p ||
+        &aTagName == nsGkAtoms::pre ||
+        &aTagName == nsGkAtoms::section;
+    // clang-format on
+  }
+
+  /**
+   * Return true if aContent is a format element of
+   * Document.execCommand("formatBlock").
+   */
+  [[nodiscard]] static bool IsFormatElementForFormatBlockCommand(
+      const nsIContent& aContent) {
+    if (!aContent.IsHTMLElement() ||
+        !aContent.NodeInfo()->NameAtom()->IsStatic()) {
+      return false;
+    }
+    const nsStaticAtom* tagName = aContent.NodeInfo()->NameAtom()->AsStatic();
+    return IsFormatTagForFormatBlockCommand(*tagName);
+  }
+
+  /**
+   * Return true if aTagName is one of the format element name of
+   * cmd_paragraphState.
+   */
+  [[nodiscard]] static bool IsFormatTagForParagraphStateCommand(
+      const nsStaticAtom& aTagName) {
+    return
+        // clang-format off
+        &aTagName == nsGkAtoms::address ||
+        &aTagName == nsGkAtoms::dd ||
+        &aTagName == nsGkAtoms::dl ||
+        &aTagName == nsGkAtoms::dt ||
+        &aTagName == nsGkAtoms::h1 ||
+        &aTagName == nsGkAtoms::h2 ||
+        &aTagName == nsGkAtoms::h3 ||
+        &aTagName == nsGkAtoms::h4 ||
+        &aTagName == nsGkAtoms::h5 ||
+        &aTagName == nsGkAtoms::h6 ||
+        &aTagName == nsGkAtoms::p ||
+        &aTagName == nsGkAtoms::pre;
+    // clang-format on
+  }
+
+  /**
+   * Return true if aContent is a format element of cmd_paragraphState.
+   */
+  [[nodiscard]] static bool IsFormatElementForParagraphStateCommand(
+      const nsIContent& aContent) {
+    if (!aContent.IsHTMLElement() ||
+        !aContent.NodeInfo()->NameAtom()->IsStatic()) {
+      return false;
+    }
+    const nsStaticAtom* tagName = aContent.NodeInfo()->NameAtom()->AsStatic();
+    return IsFormatTagForParagraphStateCommand(*tagName);
+  }
+
   static bool IsNodeThatCanOutdent(nsINode* aNode);
   static bool IsHeader(nsINode& aNode);
   static bool IsListItem(const nsINode* aNode);
@@ -243,7 +326,8 @@ class HTMLEditUtils final {
     return false;
   }
 
-  static bool CanNodeContain(const nsINode& aParent, nsAtom& aChildNodeName) {
+  static bool CanNodeContain(const nsINode& aParent,
+                             const nsAtom& aChildNodeName) {
     switch (aParent.NodeType()) {
       case nsINode::ELEMENT_NODE:
       case nsINode::DOCUMENT_FRAGMENT_NODE:
@@ -253,7 +337,7 @@ class HTMLEditUtils final {
     return false;
   }
 
-  static bool CanNodeContain(nsAtom& aParentNodeName,
+  static bool CanNodeContain(const nsAtom& aParentNodeName,
                              const nsIContent& aChild) {
     switch (aChild.NodeType()) {
       case nsINode::TEXT_NODE:
@@ -269,7 +353,8 @@ class HTMLEditUtils final {
 
   // XXX Only this overload does not check the node type.  Therefore, only this
   //     handle Document and ProcessingInstructionTagName.
-  static bool CanNodeContain(nsAtom& aParentNodeName, nsAtom& aChildNodeName) {
+  static bool CanNodeContain(const nsAtom& aParentNodeName,
+                             const nsAtom& aChildNodeName) {
     nsHTMLTag childTagEnum;
     if (&aChildNodeName == nsGkAtoms::textTagName) {
       childTagEnum = eHTMLTag_text;
@@ -277,10 +362,12 @@ class HTMLEditUtils final {
                &aChildNodeName == nsGkAtoms::cdataTagName) {
       childTagEnum = eHTMLTag_comment;
     } else {
-      childTagEnum = nsHTMLTags::AtomTagToId(&aChildNodeName);
+      childTagEnum =
+          nsHTMLTags::AtomTagToId(const_cast(&aChildNodeName));
     }
 
-    nsHTMLTag parentTagEnum = nsHTMLTags::AtomTagToId(&aParentNodeName);
+    nsHTMLTag parentTagEnum =
+        nsHTMLTags::AtomTagToId(const_cast(&aParentNodeName));
     return HTMLEditUtils::CanNodeContain(parentTagEnum, childTagEnum);
   }
 
@@ -313,7 +400,7 @@ class HTMLEditUtils final {
    */
   template 
   static EditorDOMPoint GetInsertionPointInInclusiveAncestor(
-      nsAtom& aTagName, const EditorDOMPointType& aPoint,
+      const nsAtom& aTagName, const EditorDOMPointType& aPoint,
       const Element* aAncestorLimit = nullptr) {
     if (MOZ_UNLIKELY(!aPoint.IsInContentNode())) {
       return EditorDOMPoint();
diff --git a/editor/libeditor/HTMLEditor.cpp b/editor/libeditor/HTMLEditor.cpp
index 5ab11770444d..5dfa65bd9a78 100644
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -2437,7 +2437,53 @@ nsresult HTMLEditor::ClearSelection() {
   return error.StealNSResult();
 }
 
-nsresult HTMLEditor::SetParagraphFormatAsAction(
+nsresult HTMLEditor::FormatBlockAsAction(const nsAString& aParagraphFormat,
+                                         nsIPrincipal* aPrincipal) {
+  AutoEditActionDataSetter editActionData(
+      *this, EditAction::eInsertBlockElement, aPrincipal);
+  nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
+  if (NS_FAILED(rv)) {
+    NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,
+                         "CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
+    return EditorBase::ToGenericNSResult(rv);
+  }
+
+  if (NS_WARN_IF(aParagraphFormat.IsEmpty())) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  RefPtr tagName = NS_Atomize(aParagraphFormat);
+  MOZ_ASSERT(tagName);
+  if (NS_WARN_IF(!tagName->IsStatic()) ||
+      NS_WARN_IF(!HTMLEditUtils::IsFormatTagForFormatBlockCommand(
+          *tagName->AsStatic()))) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  if (tagName == nsGkAtoms::dd || tagName == nsGkAtoms::dt) {
+    // MOZ_KnownLive(tagName->AsStatic()) because nsStaticAtom instances live
+    // while the process is running.
+    Result result =
+        MakeOrChangeListAndListItemAsSubAction(
+            MOZ_KnownLive(*tagName->AsStatic()), u""_ns,
+            SelectAllOfCurrentList::No);
+    if (MOZ_UNLIKELY(result.isErr())) {
+      NS_WARNING(
+          "HTMLEditor::MakeOrChangeListAndListItemAsSubAction("
+          "SelectAllOfCurrentList::No) failed");
+      return EditorBase::ToGenericNSResult(result.unwrapErr());
+    }
+    return NS_OK;
+  }
+
+  rv = FormatBlockContainerAsSubAction(MOZ_KnownLive(*tagName->AsStatic()),
+                                       FormatBlockMode::HTMLFormatBlockCommand);
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                       "HTMLEditor::FormatBlockContainerAsSubAction() failed");
+  return EditorBase::ToGenericNSResult(rv);
+}
+
+nsresult HTMLEditor::SetParagraphStateAsAction(
     const nsAString& aParagraphFormat, nsIPrincipal* aPrincipal) {
   AutoEditActionDataSetter editActionData(
       *this, EditAction::eInsertBlockElement, aPrincipal);
@@ -2458,6 +2504,9 @@ nsresult HTMLEditor::SetParagraphFormatAsAction(
   ToLowerCase(lowerCaseTagName);
   RefPtr tagName = NS_Atomize(lowerCaseTagName);
   MOZ_ASSERT(tagName);
+  if (NS_WARN_IF(!tagName->IsStatic())) {
+    return NS_ERROR_INVALID_ARG;
+  }
   if (tagName == nsGkAtoms::dd || tagName == nsGkAtoms::dt) {
     // MOZ_KnownLive(tagName->AsStatic()) because nsStaticAtom instances live
     // while the process is running.
@@ -2474,12 +2523,23 @@ nsresult HTMLEditor::SetParagraphFormatAsAction(
     return NS_OK;
   }
 
-  rv = FormatBlockContainerAsSubAction(*tagName);
+  rv = FormatBlockContainerAsSubAction(
+      MOZ_KnownLive(*tagName->AsStatic()),
+      FormatBlockMode::XULParagraphStateCommand);
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                        "HTMLEditor::FormatBlockContainerAsSubAction() failed");
   return EditorBase::ToGenericNSResult(rv);
 }
 
+// static
+bool HTMLEditor::IsFormatElement(FormatBlockMode aFormatBlockMode,
+                                 const nsIContent& aContent) {
+  // FYI: Optimize for HTML command because it may run too many times.
+  return MOZ_LIKELY(aFormatBlockMode == FormatBlockMode::HTMLFormatBlockCommand)
+             ? HTMLEditUtils::IsFormatElementForFormatBlockCommand(aContent)
+             : HTMLEditUtils::IsFormatElementForParagraphStateCommand(aContent);
+}
+
 NS_IMETHODIMP HTMLEditor::GetParagraphState(bool* aMixed,
                                             nsAString& aFirstParagraphState) {
   if (NS_WARN_IF(!aMixed)) {
@@ -2490,7 +2550,8 @@ NS_IMETHODIMP HTMLEditor::GetParagraphState(bool* aMixed,
   }
 
   ErrorResult error;
-  ParagraphStateAtSelection paragraphState(*this, error);
+  ParagraphStateAtSelection paragraphState(
+      *this, FormatBlockMode::XULParagraphStateCommand, error);
   if (error.Failed()) {
     NS_WARNING("ParagraphStateAtSelection failed");
     return error.StealNSResult();
@@ -2902,7 +2963,8 @@ nsresult HTMLEditor::RemoveListAsAction(const nsAString& aListType,
   return rv;
 }
 
-nsresult HTMLEditor::FormatBlockContainerAsSubAction(nsAtom& aTagName) {
+nsresult HTMLEditor::FormatBlockContainerAsSubAction(
+    const nsStaticAtom& aTagName, FormatBlockMode aFormatBlockMode) {
   MOZ_ASSERT(IsEditActionDataAvailable());
 
   if (NS_WARN_IF(!mInitSucceeded)) {
@@ -2976,7 +3038,7 @@ nsresult HTMLEditor::FormatBlockContainerAsSubAction(nsAtom& aTagName) {
   AutoRangeArray selectionRanges(SelectionRef());
   Result, nsresult> suggestBlockElementToPutCaretOrError =
       FormatBlockContainerWithTransaction(selectionRanges, aTagName,
-                                          *editingHost);
+                                          aFormatBlockMode, *editingHost);
   if (suggestBlockElementToPutCaretOrError.isErr()) {
     NS_WARNING("HTMLEditor::FormatBlockContainerWithTransaction() failed");
     return suggestBlockElementToPutCaretOrError.unwrapErr();
@@ -3429,7 +3491,7 @@ already_AddRefed HTMLEditor::GetSelectedElement(const nsAtom* aTagName,
 }
 
 Result HTMLEditor::CreateAndInsertElement(
-    WithTransaction aWithTransaction, nsAtom& aTagName,
+    WithTransaction aWithTransaction, const nsAtom& aTagName,
     const EditorDOMPoint& aPointToInsert,
     const InitializeInsertingElement& aInitializer) {
   MOZ_ASSERT(IsEditActionDataAvailable());
diff --git a/editor/libeditor/HTMLEditor.h b/editor/libeditor/HTMLEditor.h
index bf48bbe6313c..cf7929e37e6b 100644
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -26,6 +26,7 @@
 #include "nsIHTMLEditor.h"
 #include "nsIHTMLInlineTableEditor.h"
 #include "nsIHTMLObjectResizer.h"
+#include "nsIPrincipal.h"
 #include "nsITableEditor.h"
 #include "nsPoint.h"
 #include "nsStubMutationObserver.h"
@@ -299,7 +300,26 @@ class HTMLEditor final : public EditorBase,
   MOZ_CAN_RUN_SCRIPT nsresult
   OutdentAsAction(nsIPrincipal* aPrincipal = nullptr);
 
-  MOZ_CAN_RUN_SCRIPT nsresult SetParagraphFormatAsAction(
+  /**
+   * The Document.execCommand("formatBlock") handler.
+   *
+   * @param aParagraphFormat    Must not be an empty string, and the value must
+   *                            be one of address, article, aside, blockquote,
+   *                            div, footer, h1, h2, h3, h4, h5, h6, header,
+   *                            hgroup, main, nav, p, pre, selection, dt or dd.
+   */
+  MOZ_CAN_RUN_SCRIPT nsresult FormatBlockAsAction(
+      const nsAString& aParagraphFormat, nsIPrincipal* aPrincipal = nullptr);
+
+  /**
+   * The cmd_paragraphState command handler.
+   *
+   * @param aParagraphFormat    Can be empty string.  If this is empty string,
+   *                            this removes ancestor format elements.
+   *                            Otherwise, the value must be one of p, pre,
+   *                            h1, h2, h3, h4, h5, h6, address, dt or dl.
+   */
+  MOZ_CAN_RUN_SCRIPT nsresult SetParagraphStateAsAction(
       const nsAString& aParagraphFormat, nsIPrincipal* aPrincipal = nullptr);
 
   MOZ_CAN_RUN_SCRIPT nsresult AlignAsAction(const nsAString& aAlignType,
@@ -1344,7 +1364,7 @@ class HTMLEditor final : public EditorBase,
    */
   [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result
   CreateAndInsertElement(
-      WithTransaction aWithTransaction, nsAtom& aTagName,
+      WithTransaction aWithTransaction, const nsAtom& aTagName,
       const EditorDOMPoint& aPointToInsert,
       const InitializeInsertingElement& aInitializer = DoNothingForNewElement);
 
@@ -1401,7 +1421,7 @@ class HTMLEditor final : public EditorBase,
    */
   [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result
   MaybeSplitAncestorsForInsertWithTransaction(
-      nsAtom& aTag, const EditorDOMPoint& aStartOfDeepestRightNode,
+      const nsAtom& aTag, const EditorDOMPoint& aStartOfDeepestRightNode,
       const Element& aEditingHost);
 
   /**
@@ -1430,7 +1450,7 @@ class HTMLEditor final : public EditorBase,
   enum class BRElementNextToSplitPoint { Keep, Delete };
   [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result
   InsertElementWithSplittingAncestorsWithTransaction(
-      nsAtom& aTagName, const EditorDOMPoint& aPointToInsert,
+      const nsAtom& aTagName, const EditorDOMPoint& aPointToInsert,
       BRElementNextToSplitPoint aBRElementNextToSplitPoint,
       const Element& aEditingHost,
       const InitializeInsertingElement& aInitializer = DoNothingForNewElement);
@@ -1497,6 +1517,25 @@ class HTMLEditor final : public EditorBase,
       const nsTArray>& aArrayOfContents,
       const Element& aEditingHost);
 
+  /**
+   * Our traditional formatBlock was same as XUL cmd_paragraphState command.
+   * However, the behavior is pretty different from the others and aligning
+   * the XUL command behavior may break Thunderbird a lot because it handles
+   * 
in a special path and
(generic block element) is not + * treated as a format node and these things may be used for designing + * current roles of the elements in the email composer of Thunderbird. + * Therefore, we create a new mode for HTMLFormatBlockCommand to align + * the behavior to the others but does not harm Thunderbird. + */ + enum class FormatBlockMode { + // Document.execCommand("formatBlock"). Cannot set new format to "normal" + // nor "". So, the paths to handle these ones are not used in this mode. + HTMLFormatBlockCommand, + // cmd_paragraphState. Can set new format to "normal" or "" to remove + // ancestor format blocks. + XULParagraphStateCommand, + }; + /** * RemoveBlockContainerElementsWithTransaction() removes all format blocks, * table related element, etc in aArrayOfContents from the DOM tree. If @@ -1505,36 +1544,44 @@ class HTMLEditor final : public EditorBase, * If aArrayOfContents has a table related element,
  • ,
    or *
    , it will be removed and its contents will be moved to where it was. * + * @param aFormatBlockMode Whether HTML formatBlock command or XUL + * paragraphState command. + * * @return A suggest point to put caret if succeeded, but it may be * unset if there is no suggestion. */ [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result RemoveBlockContainerElementsWithTransaction( const nsTArray>& aArrayOfContents, - BlockInlineCheck aBlockInlineCheck); + FormatBlockMode aFormatBlockMode, BlockInlineCheck aBlockInlineCheck); /** - * CreateOrChangeBlockContainerElement() formats all nodes in aArrayOfContents - * with block elements whose name is aBlockTag. + * CreateOrChangeFormatContainerElement() formats all nodes in + * aArrayOfContents with block elements whose name is aNewFormatTagName. + * * If aArrayOfContents has an inline element, a block element is created and * the inline element and following inline elements are moved into the new * block element. - * If aArrayOfContents has
    elements, they'll be removed from the DOM - * tree and new block element will be created when there are some remaining - * inline elements. - * If aArrayOfContents has a block element, this calls itself with children - * of the block element. Then, new block element will be created when there - * are some remaining inline elements. + * If aArrayOfContents has
    elements, they'll be removed from the DOM tree + * and new block element will be created when there are some remaining inline + * elements. + * If aArrayOfContents has a block element, this calls itself with children of + * the block element. Then, new block element will be created when there are + * some remaining inline elements. * * @param aArrayOfContents Must be descendants of a node. - * @param aBlockTag The element name of new block elements. + * @param aNewFormatTagName The element name of new block elements. + * @param aFormatBlockMode The replacing block element target type is for + * whether HTML formatBLock command or XUL + * paragraphState command. * @param aEditingHost The editing host. * @return The latest created new block element and a * suggest point to put caret. */ [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result - CreateOrChangeBlockContainerElement( - nsTArray>& aArrayOfContents, nsAtom& aBlockTag, + CreateOrChangeFormatContainerElement( + nsTArray>& aArrayOfContents, + const nsStaticAtom& aNewFormatTagName, FormatBlockMode aFormatBlockMode, const Element& aEditingHost); /** @@ -1545,22 +1592,25 @@ class HTMLEditor final : public EditorBase, * @param aSelectionRanges The ranges which are cloned by selection or * updated from it with doing something before * calling this. - * @param aBlockType New block tag name. - * If nsGkAtoms::normal or nsGkAtoms::_empty, - * RemoveBlockContainerElementsWithTransaction() will be - * called. - * If nsGkAtoms::blockquote, - * WrapContentsInBlockquoteElementsWithTransaction() will - * be called. - * Otherwise, CreateOrChangeBlockContainerElement() will be - * called. + * @param aNewFormatTagName New block tag name. + * If nsGkAtoms::normal or nsGkAtoms::_empty, + * RemoveBlockContainerElementsWithTransaction() + * will be called. + * If nsGkAtoms::blockquote, + * WrapContentsInBlockquoteElementsWithTransaction() + * will be called. + * Otherwise, CreateOrChangeBlockContainerElement() + * will be called. + * @param aFormatBlockMode Whether HTML formatBlock command or XUL + * paragraphState command. * @param aEditingHost The editing host. * @return If selection should be finally collapsed in a * created block element, this returns the element. */ [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result, nsresult> FormatBlockContainerWithTransaction(AutoRangeArray& aSelectionRanges, - nsAtom& aBlockType, + const nsStaticAtom& aNewFormatTagName, + FormatBlockMode aFormatBlockMode, const Element& aEditingHost); /** @@ -1698,6 +1748,9 @@ class HTMLEditor final : public EditorBase, class AutoListElementCreator; + [[nodiscard]] static bool IsFormatElement(FormatBlockMode aFormatBlockMode, + const nsIContent& aContent); + /** * MakeOrChangeListAndListItemAsSubAction() handles create list commands with * current selection. If @@ -3866,8 +3919,11 @@ class HTMLEditor final : public EditorBase, * * @param aTagName A block level element name. Must NOT be * nsGkAtoms::dt nor nsGkAtoms::dd. + * @param aFormatBlockMode Whether HTML formatBlock command or XUL + * paragraphState command. */ - MOZ_CAN_RUN_SCRIPT nsresult FormatBlockContainerAsSubAction(nsAtom& aTagName); + MOZ_CAN_RUN_SCRIPT nsresult FormatBlockContainerAsSubAction( + const nsStaticAtom& aTagName, FormatBlockMode aFormatBlockMode); /** * Increase/decrease the font size of selection. @@ -4629,8 +4685,15 @@ class MOZ_STACK_CLASS AlignStateAtSelection final { */ class MOZ_STACK_CLASS ParagraphStateAtSelection final { public: + using FormatBlockMode = HTMLEditor::FormatBlockMode; + ParagraphStateAtSelection() = delete; - ParagraphStateAtSelection(HTMLEditor& aHTMLEditor, ErrorResult& aRv); + /** + * @param aFormatBlockMode Whether HTML formatBlock command or XUL + * paragraphState command. + */ + ParagraphStateAtSelection(HTMLEditor& aHTMLEditor, + FormatBlockMode aFormatBlockMode, ErrorResult& aRv); /** * GetFirstParagraphStateAtSelection() returns: @@ -4663,11 +4726,13 @@ class MOZ_STACK_CLASS ParagraphStateAtSelection final { * @param aArrayOfContents [in/out] Found descendant format blocks * and first inline node in each non-format * block will be appended to this. + * @param aFormatBlockMode Whether HTML formatBlock command or XUL + * paragraphState command. * @param aNonFormatBlockElement Must be a non-format block element. */ static void AppendDescendantFormatNodesAndFirstInlineNode( nsTArray>& aArrayOfContents, - dom::Element& aNonFormatBlockElement); + FormatBlockMode aFormatBlockMode, dom::Element& aNonFormatBlockElement); /** * CollectEditableFormatNodesInSelection() collects only editable nodes diff --git a/editor/libeditor/HTMLEditorCommands.cpp b/editor/libeditor/HTMLEditorCommands.cpp index b8af794c09a7..1864299a3a4c 100644 --- a/editor/libeditor/HTMLEditorCommands.cpp +++ b/editor/libeditor/HTMLEditorCommands.cpp @@ -336,7 +336,7 @@ nsresult ListItemCommand::ToggleState(nsStaticAtom& aTagName, // XXX Note: This actually doesn't work for "LI", // but we currently don't use this for non DL lists anyway. // Problem: won't this replace any current block paragraph style? - nsresult rv = aHTMLEditor.SetParagraphFormatAsAction( + nsresult rv = aHTMLEditor.SetParagraphStateAsAction( nsDependentAtomString(&aTagName), aPrincipal); NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "HTMLEditor::SetParagraphFormatAsAction() failed"); @@ -511,6 +511,50 @@ nsresult MultiStateCommandBase::GetCommandStateParams( return rv; } +/***************************************************************************** + * mozilla::FormatBlockStateCommand + *****************************************************************************/ + +StaticRefPtr FormatBlockStateCommand::sInstance; + +nsresult FormatBlockStateCommand::GetCurrentState( + HTMLEditor* aHTMLEditor, nsCommandParams& aParams) const { + if (NS_WARN_IF(!aHTMLEditor)) { + return NS_ERROR_INVALID_ARG; + } + + ErrorResult error; + ParagraphStateAtSelection state( + *aHTMLEditor, + ParagraphStateAtSelection::FormatBlockMode::HTMLFormatBlockCommand, + error); + if (error.Failed()) { + NS_WARNING("ParagraphStateAtSelection failed"); + return error.StealNSResult(); + } + aParams.SetBool(STATE_MIXED, state.IsMixed()); + if (NS_WARN_IF(!state.GetFirstParagraphStateAtSelection())) { + aParams.SetCString(STATE_ATTRIBUTE, ""_ns); + } else { + nsCString paragraphState; // Don't use `nsAutoCString` for avoiding copy. + state.GetFirstParagraphStateAtSelection()->ToUTF8String(paragraphState); + aParams.SetCString(STATE_ATTRIBUTE, paragraphState); + } + return NS_OK; +} + +nsresult FormatBlockStateCommand::SetState(HTMLEditor* aHTMLEditor, + const nsAString& aNewState, + nsIPrincipal* aPrincipal) const { + if (NS_WARN_IF(!aHTMLEditor) || NS_WARN_IF(aNewState.IsEmpty())) { + return NS_ERROR_INVALID_ARG; + } + nsresult rv = aHTMLEditor->FormatBlockAsAction(aNewState, aPrincipal); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), + "HTMLEditor::FormatBlockAsAction() failed"); + return rv; +} + /***************************************************************************** * mozilla::ParagraphStateCommand *****************************************************************************/ @@ -524,7 +568,10 @@ nsresult ParagraphStateCommand::GetCurrentState( } ErrorResult error; - ParagraphStateAtSelection state(*aHTMLEditor, error); + ParagraphStateAtSelection state( + *aHTMLEditor, + ParagraphStateAtSelection::FormatBlockMode::XULParagraphStateCommand, + error); if (error.Failed()) { NS_WARNING("ParagraphStateAtSelection failed"); return error.StealNSResult(); @@ -547,9 +594,9 @@ nsresult ParagraphStateCommand::SetState(HTMLEditor* aHTMLEditor, if (NS_WARN_IF(!aHTMLEditor)) { return NS_ERROR_INVALID_ARG; } - nsresult rv = aHTMLEditor->SetParagraphFormatAsAction(aNewState, aPrincipal); + nsresult rv = aHTMLEditor->SetParagraphStateAsAction(aNewState, aPrincipal); NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), - "HTMLEditor::SetParagraphFormatAsAction() failed"); + "HTMLEditor::SetParagraphStateAsAction() failed"); return rv; } diff --git a/editor/libeditor/HTMLEditorController.cpp b/editor/libeditor/HTMLEditorController.cpp index 19cd6c9c90cc..ea795b920bb2 100644 --- a/editor/libeditor/HTMLEditorController.cpp +++ b/editor/libeditor/HTMLEditorController.cpp @@ -82,6 +82,7 @@ nsresult HTMLEditorController::RegisterHTMLEditorCommands( NS_REGISTER_COMMAND(RemoveListCommand, "cmd_removeList"); // format stuff + NS_REGISTER_COMMAND(FormatBlockStateCommand, "cmd_formatBlock"); NS_REGISTER_COMMAND(ParagraphStateCommand, "cmd_paragraphState"); NS_REGISTER_COMMAND(FontFaceStateCommand, "cmd_fontFace"); NS_REGISTER_COMMAND(FontSizeStateCommand, "cmd_fontSize"); @@ -122,6 +123,7 @@ void HTMLEditorController::Shutdown() { ListCommand::Shutdown(); ListItemCommand::Shutdown(); RemoveListCommand::Shutdown(); + FormatBlockStateCommand::Shutdown(); ParagraphStateCommand::Shutdown(); FontFaceStateCommand::Shutdown(); FontSizeStateCommand::Shutdown(); diff --git a/editor/libeditor/HTMLEditorState.cpp b/editor/libeditor/HTMLEditorState.cpp index aa747133ac5f..d86b28d499f6 100644 --- a/editor/libeditor/HTMLEditorState.cpp +++ b/editor/libeditor/HTMLEditorState.cpp @@ -442,8 +442,9 @@ AlignStateAtSelection::AlignStateAtSelection(HTMLEditor& aHTMLEditor, * ParagraphStateAtSelection ****************************************************************************/ -ParagraphStateAtSelection::ParagraphStateAtSelection(HTMLEditor& aHTMLEditor, - ErrorResult& aRv) { +ParagraphStateAtSelection::ParagraphStateAtSelection( + HTMLEditor& aHTMLEditor, FormatBlockMode aFormatBlockMode, + ErrorResult& aRv) { if (NS_WARN_IF(aHTMLEditor.Destroyed())) { aRv = EditorBase::ToGenericNSResult(NS_ERROR_EDITOR_DESTROYED); return; @@ -464,19 +465,26 @@ ParagraphStateAtSelection::ParagraphStateAtSelection(HTMLEditor& aHTMLEditor, return; } - Element* editingHostOrRoot = aHTMLEditor.ComputeEditingHost(); - if (!editingHostOrRoot) { - // This is not a handler of editing command so that if there is no active - // editing host, let's use the or document element instead. - editingHostOrRoot = aHTMLEditor.GetRoot(); - if (!editingHostOrRoot) { - return; + if (MOZ_UNLIKELY(!aHTMLEditor.SelectionRef().RangeCount())) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + + const Element* const editingHostOrBodyOrDocumentElement = [&]() -> Element* { + if (Element* editingHost = aHTMLEditor.ComputeEditingHost()) { + return editingHost; } + return aHTMLEditor.GetRoot(); + }(); + if (!editingHostOrBodyOrDocumentElement || + !HTMLEditUtils::IsSimplyEditableNode( + *editingHostOrBodyOrDocumentElement)) { + return; } AutoTArray, 64> arrayOfContents; nsresult rv = CollectEditableFormatNodesInSelection( - aHTMLEditor, *editingHostOrRoot, arrayOfContents); + aHTMLEditor, *editingHostOrBodyOrDocumentElement, arrayOfContents); if (NS_FAILED(rv)) { NS_WARNING( "ParagraphStateAtSelection::CollectEditableFormatNodesInSelection() " @@ -492,7 +500,9 @@ ParagraphStateAtSelection::ParagraphStateAtSelection(HTMLEditor& aHTMLEditor, OwningNonNull& content = arrayOfContents[index]; if (HTMLEditUtils::IsBlockElement(content, BlockInlineCheck::UseHTMLDefaultStyle) && - !HTMLEditUtils::IsFormatNode(content)) { + (content->IsAnyOfHTMLElements(nsGkAtoms::dd, nsGkAtoms::dl, + nsGkAtoms::dt) || + !HTMLEditor::IsFormatElement(aFormatBlockMode, content))) { // XXX This RemoveObject() call has already been commented out and // the above comment explained we're trying to replace non-format // block nodes in the array. According to the following blocks and @@ -500,7 +510,7 @@ ParagraphStateAtSelection::ParagraphStateAtSelection(HTMLEditor& aHTMLEditor, // non-format block with descendants format blocks makes sense. // arrayOfContents.RemoveObject(node); ParagraphStateAtSelection::AppendDescendantFormatNodesAndFirstInlineNode( - arrayOfContents, *content->AsElement()); + arrayOfContents, aFormatBlockMode, *content->AsElement()); } } @@ -510,21 +520,20 @@ ParagraphStateAtSelection::ParagraphStateAtSelection(HTMLEditor& aHTMLEditor, const auto atCaret = aHTMLEditor.GetFirstSelectionStartPoint(); if (NS_WARN_IF(!atCaret.IsInContentNode())) { + MOZ_ASSERT(false, + "We've already checked whether there is a selection range, " + "but we have no range right now."); aRv.Throw(NS_ERROR_FAILURE); return; } arrayOfContents.AppendElement(*atCaret.ContainerAs()); } - dom::Element* bodyOrDocumentElement = aHTMLEditor.GetRoot(); - if (NS_WARN_IF(!bodyOrDocumentElement)) { - aRv.Throw(NS_ERROR_FAILURE); - return; - } - for (auto& content : Reversed(arrayOfContents)) { nsAtom* paragraphStateOfNode = nsGkAtoms::_empty; - if (HTMLEditUtils::IsFormatNode(content)) { + if (!content->IsAnyOfHTMLElements(nsGkAtoms::dd, nsGkAtoms::dl, + nsGkAtoms::dt) && + HTMLEditor::IsFormatElement(aFormatBlockMode, content)) { MOZ_ASSERT(content->NodeInfo()->NameAtom()); paragraphStateOfNode = content->NodeInfo()->NameAtom(); } @@ -536,16 +545,17 @@ ParagraphStateAtSelection::ParagraphStateAtSelection(HTMLEditor& aHTMLEditor, } // If we meet an inline node, let's get its parent format. else { - for (nsINode* parentNode = content->GetParentNode(); parentNode; - parentNode = parentNode->GetParentNode()) { + for (Element* parentElement : content->AncestorsOfType()) { // If we reach `HTMLDocument.body` or `Document.documentElement`, // there is no format. - if (parentNode == bodyOrDocumentElement) { + if (parentElement == editingHostOrBodyOrDocumentElement) { break; } - if (HTMLEditUtils::IsFormatNode(parentNode)) { - MOZ_ASSERT(parentNode->NodeInfo()->NameAtom()); - paragraphStateOfNode = parentNode->NodeInfo()->NameAtom(); + if (!parentElement->IsAnyOfHTMLElements(nsGkAtoms::dd, nsGkAtoms::dl, + nsGkAtoms::dt) && + HTMLEditor::IsFormatElement(aFormatBlockMode, *parentElement)) { + MOZ_ASSERT(parentElement->NodeInfo()->NameAtom()); + paragraphStateOfNode = parentElement->NodeInfo()->NameAtom(); break; } } @@ -567,10 +577,13 @@ ParagraphStateAtSelection::ParagraphStateAtSelection(HTMLEditor& aHTMLEditor, // static void ParagraphStateAtSelection::AppendDescendantFormatNodesAndFirstInlineNode( nsTArray>& aArrayOfContents, - dom::Element& aNonFormatBlockElement) { + FormatBlockMode aFormatBlockMode, dom::Element& aNonFormatBlockElement) { MOZ_ASSERT(HTMLEditUtils::IsBlockElement( aNonFormatBlockElement, BlockInlineCheck::UseHTMLDefaultStyle)); - MOZ_ASSERT(!HTMLEditUtils::IsFormatNode(&aNonFormatBlockElement)); + MOZ_ASSERT( + aNonFormatBlockElement.IsAnyOfHTMLElements(nsGkAtoms::dd, nsGkAtoms::dl, + nsGkAtoms::dt) || + !HTMLEditor::IsFormatElement(aFormatBlockMode, aNonFormatBlockElement)); // We only need to place any one inline inside this node onto // the list. They are all the same for purposes of determining @@ -581,12 +594,15 @@ void ParagraphStateAtSelection::AppendDescendantFormatNodesAndFirstInlineNode( childContent; childContent = childContent->GetNextSibling()) { const bool isBlock = HTMLEditUtils::IsBlockElement( *childContent, BlockInlineCheck::UseHTMLDefaultStyle); - const bool isFormat = HTMLEditUtils::IsFormatNode(childContent); + const bool isFormat = + !childContent->IsAnyOfHTMLElements(nsGkAtoms::dd, nsGkAtoms::dl, + nsGkAtoms::dt) && + HTMLEditor::IsFormatElement(aFormatBlockMode, *childContent); // If the child is a non-format block element, let's check its children // recursively. if (isBlock && !isFormat) { ParagraphStateAtSelection::AppendDescendantFormatNodesAndFirstInlineNode( - aArrayOfContents, *childContent->AsElement()); + aArrayOfContents, aFormatBlockMode, *childContent->AsElement()); continue; } diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/currentStatus.js b/editor/libeditor/tests/browserscope/lib/richtext2/currentStatus.js index 578807492dae..6b833248cd74 100644 --- a/editor/libeditor/tests/browserscope/lib/richtext2/currentStatus.js +++ b/editor/libeditor/tests/browserscope/lib/richtext2/currentStatus.js @@ -410,9 +410,6 @@ const knownFailures = { "QV-Proposed-I_MYI-1-SI-dM": true, "QV-Proposed-I_MYI-1-SI-body": true, "QV-Proposed-I_MYI-1-SI-div": true, - "QV-Proposed-FB_BQ-1_SC-dM": true, - "QV-Proposed-FB_BQ-1_SC-body": true, - "QV-Proposed-FB_BQ-1_SC-div": true, "QV-Proposed-FB_H1-H2-1_SL-dM": true, "QV-Proposed-FB_H1-H2-1_SL-body": true, "QV-Proposed-FB_H1-H2-1_SL-div": true, diff --git a/testing/web-platform/meta/editing/run/formatblock.html.ini b/testing/web-platform/meta/editing/run/formatblock.html.ini index 273840313c9b..c676a5f03d0c 100644 --- a/testing/web-platform/meta/editing/run/formatblock.html.ini +++ b/testing/web-platform/meta/editing/run/formatblock.html.ini @@ -1,180 +1,36 @@ [formatblock.html?1-1000] expected: if (os == "android") and fission: [OK, TIMEOUT] - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "foo[\]bar

    extra" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "foo[\]bar

    extra" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "foo{}bar

    extra" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "foo{}bar

    extra" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "foo[\]bar

    extra" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "foo[\]bar

    extra" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "foo[bar\]baz

    extra" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "foo[bar\]baz

    extra" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "foo\]bar[baz

    extra" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "foo\]bar[baz

    extra" queryCommandValue("formatblock") after] - expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "{

    foo

    }" compare innerHTML] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "{

    foo

    }" queryCommandValue("formatblock") after] - expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "{

    foo

    }" compare innerHTML] expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "{

    foo

    }" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "foo[barbaz\]qozquz

    extra" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "foo[barbaz\]qozquz

    extra" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "
    foob[a\]rbaz
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    foob[a\]rbaz
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    foobarbaz
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    foobarbaz
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    foobarbaz
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    foobarbaz
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    foobarbaz
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    foobarbaz
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    foobarbaz
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    foobarbaz
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "{
    foobarbaz
    }" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "{
    foobarbaz
    }" queryCommandValue("formatblock") after] - expected: FAIL - - [[["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "

    [foobar\]

    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "

    [foobar\]

    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "

    [foobar\]

    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "

    [foobar\]

    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "

    [foobar\]

    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "

    [foobar\]

    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "

    [foobar\]

    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "

    [foobar\]

    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "

    [foobar\]

    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "

    [foobar\]

    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foo\]
    bar
    " compare innerHTML] expected: FAIL [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foo\]
    bar
    " queryCommandValue("formatblock") before] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foo\]
    bar
    " queryCommandValue("formatblock") after] - expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foo\]
    bar
    " compare innerHTML] expected: FAIL [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foo\]
    bar
    " queryCommandValue("formatblock") before] expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foo\]
    bar
    " queryCommandValue("formatblock") after] - expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    foo
    [bar\]
    " compare innerHTML] expected: FAIL [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    foo
    [bar\]
    " queryCommandValue("formatblock") before] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    foo
    [bar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    foo
    [bar\]
    " compare innerHTML] expected: FAIL [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    foo
    [bar\]
    " queryCommandValue("formatblock") before] expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    foo
    [bar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foo
    bar\]
    " compare innerHTML] expected: FAIL @@ -199,51 +55,6 @@ [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foo
    bar\]
    " queryCommandValue("formatblock") after] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    1. [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    1. [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    • [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    • [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "[foobar\]" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "[foobar\]" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "[foobar\]" queryCommandValue("formatblock") after] - expected: FAIL - [formatblock.html?1001-2000] expected: @@ -254,36 +65,12 @@ [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "[foobar\]" queryCommandValue("defaultparagraphseparator") before] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "[foobar\]" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "[foobar\]" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "[foobar\]" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "[foobar\]" queryCommandValue("formatblock") after] - expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "{

    foo

    }" compare innerHTML] expected: FAIL [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "{

    foo

    }" compare innerHTML] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "

    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "

    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "

    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "

    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "

    [foo\]
    bar
    " compare innerHTML] expected: FAIL @@ -348,267 +135,69 @@ [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "

    [foobar\]" queryCommandValue("formatblock") after] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "

    [foobar\]" compare innerHTML] - expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "

    [foobar\]" queryCommandValue("defaultparagraphseparator") before] expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "

    [foobar\]" compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "

    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "

    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "

    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "

    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["formatblock","
    "\]\] "
    [foo\]

    extra": execCommand("formatblock", false, "

    ") return value] - expected: FAIL - [[["formatblock","
    "\]\] "
    [foo\]

    extra" compare innerHTML] expected: FAIL - [[["formatblock","

    "\]\] "

    [foo\]

    bar

    extra": execCommand("formatblock", false, "

    ") return value] - expected: FAIL - [[["formatblock","
    "\]\] "

    [foo\]

    bar

    extra" compare innerHTML] expected: FAIL - [[["formatblock","

    "\]\] "[foo\]
    bar

    extra": execCommand("formatblock", false, "

    ") return value] - expected: FAIL - - [[["formatblock","
    "\]\] "[foo\]
    bar

    extra" compare innerHTML] - expected: FAIL - [[["formatblock","

    "\]\] "

    [foo

    bar\]

    baz": execCommand("formatblock", false, "

    ") return value] expected: FAIL [[["formatblock","
    "\]\] "

    [foo

    bar\]

    baz" compare innerHTML] expected: FAIL - [[["formatblock","

    "\]\] "
    [foo\]
    ": execCommand("formatblock", false, "
    ") return value] - expected: FAIL - [[["formatblock","
    "\]\] "
    [foo\]
    " compare innerHTML] expected: FAIL - [[["formatblock","
    "\]\] "

    [foo\]

    ": execCommand("formatblock", false, "
    ") return value] - expected: FAIL - [[["formatblock","
    "\]\] "

    [foo\]

    " compare innerHTML] expected: FAIL - [[["formatblock","
    "\]\] "

    [foo\]

    bar

    baz

    ": execCommand("formatblock", false, "
    ") return value] - expected: FAIL - [[["formatblock","
    "\]\] "

    [foo\]

    bar

    baz

    " compare innerHTML] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["formatblock","
    "\]\] "
    [foobar\]
    ": execCommand("formatblock", false, "
    ") return value] - expected: FAIL - [[["formatblock","
    "\]\] "
    [foobar\]
    " compare innerHTML] expected: FAIL - [[["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foobar\]
    " compare innerHTML] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] expected: FAIL [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " compare innerHTML] expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] expected: FAIL - [[["formatblock",""\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["formatblock",""\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - [[["formatblock","
    "\]\] "
    [foobar\]
    ": execCommand("formatblock", false, "
    ") return value] expected: FAIL [[["formatblock","
    "\]\] "
    [foobar\]
    " compare innerHTML] expected: FAIL - [[["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - [[["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] expected: FAIL [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foobar\]
    " compare innerHTML] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] expected: FAIL [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " compare innerHTML] expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "
    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "
    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "
    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "
    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "
    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "
    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "
    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "
    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

    "\]\] "
    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
    "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["formatblock",""\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["formatblock",""\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["formatblock","
  • "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") before] - expected: FAIL - - [[["formatblock","
  • "\]\] "
    [foobar\]
    " queryCommandValue("formatblock") after] - expected: FAIL - - [[["formatblock","
      "\]\] "
      [foobar\]
      " queryCommandValue("formatblock") before] - expected: FAIL - - [[["formatblock","
        "\]\] "
        [foobar\]
        " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
        "\]\] "
        [foobar\]
        " compare innerHTML] - expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
        "\]\] "
        [foobar\]
        " queryCommandValue("defaultparagraphseparator") before] expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
        "\]\] "
        [foobar\]
        " queryCommandValue("formatblock") before] - expected: FAIL - - [[["formatblock","
          "\]\] "
          [foobar\]
          " queryCommandValue("formatblock") before] - expected: FAIL - - [[["formatblock","
            "\]\] "
            [foobar\]
            " queryCommandValue("formatblock") after] - expected: FAIL - - [[["formatblock",""\]\] "
            [foobar\]
            " queryCommandValue("formatblock") before] - expected: FAIL - - [[["formatblock",""\]\] "
            [foobar\]
            " queryCommandValue("formatblock") after] - expected: FAIL - - [[["formatblock","
            "\]\] "

            [foobar\]

            ": execCommand("formatblock", false, "
            ") return value] - expected: FAIL - [[["formatblock","
            "\]\] "

            [foobar\]

            " compare innerHTML] expected: FAIL @@ -633,6 +222,9 @@ [[["defaultparagraphseparator","p"\],["formatblock","
            "\]\] "

            [foobar\]

            " queryCommandValue("formatblock") after] expected: FAIL + [[["formatblock","
            "\]\] "

            [foo\]

            " queryCommandValue("formatblock") before] + expected: FAIL + [formatblock.html?3001-4000] expected: @@ -640,15 +232,6 @@ [[["defaultparagraphseparator","div"\],["formatblock","
            "\]\] "

            [foobar\]

            " queryCommandValue("formatblock") after] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
            "\]\] "

            [foo

            bar\]" compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "

            [foo

            bar\]" compare innerHTML] - expected: FAIL - - [[["formatblock","

            "\]\] "

            [foo

            bar\]": execCommand("formatblock", false, "

            ") return value] - expected: FAIL - [[["formatblock","
            "\]\] "

            [foo

            bar\]" compare innerHTML] expected: FAIL @@ -658,12 +241,6 @@ [[["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "

            [foo

            bar\]" queryCommandValue("formatblock") after] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","

            "\]\] "

            [foo

            bar\]" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "

            [foo

            bar\]" queryCommandValue("formatblock") after] - expected: FAIL - [[["formatblock","

            "\]\] "

            [foo

            bar\]": execCommand("formatblock", false, "

            ") return value] expected: FAIL @@ -679,66 +256,9 @@ [[["defaultparagraphseparator","p"\],["formatblock","
            "\]\] "

            [foo

            bar\]" queryCommandValue("formatblock") after] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","

            "\]\] "

            [foo

            bar\]" compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "

            [foo

            bar\]" compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

            "\]\] "

            [foo

            bar\]" compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "

            [foo

            bar\]" compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

            "\]\] "

            [foo

            bar\]" compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "

            [foo

            bar\]" compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

            "\]\] "

            [foo

            bar\]" compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "

            [foo

            bar\]" compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

            "\]\] "

            [foo

            bar\]" compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "

            [foo

            bar\]" compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

            "\]\] "

            [foo

            bar\]" compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "

            [foo

            bar\]" compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","

            "\]\] "

            [foo

            bar\]" compare innerHTML] - expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "

            [foo

            bar\]" compare innerHTML] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","p"\]\] "

            [foobar\]
            " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","p"\]\] "
            [foobar\]
            " queryCommandValue("formatblock") before] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","p"\]\] "
            [foobar\]
            " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","p"\]\] "
            [foobar\]
            " queryCommandValue("formatblock") before] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
            "\]\] "
            1. [foo\]
            2. bar
            " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
            "\]\] "
            1. [foo\]
            2. bar
            " queryCommandValue("formatblock") after] - expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","

            "\]\] "

            foo
            [bar\]

            " compare innerHTML] expected: FAIL @@ -839,114 +359,30 @@ [[["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "

            [foo

            bar\]

            " queryCommandValue("formatblock") before] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","

            "\]\] "

            [foo\]" compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "

            [foo\]" compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
            "\]\] "[foo\]" compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
            "\]\] "[foo\]" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
            "\]\] "[foo\]" compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
            "\]\] "[foo\]" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
            "\]\] "
            1. [foo\]
            " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
            "\]\] "
            1. [foo\]
            " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
            "\]\] "
            1. [foo\]
            " compare innerHTML] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
            "\]\] "
            1. [foo\]
            " queryCommandValue("formatblock") after] - expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
            "\]\] "
            [foo\]
            " compare innerHTML] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
            "\]\] "
            [foo\]
            " queryCommandValue("formatblock") after] - expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
            "\]\] "
            [foo\]
            " compare innerHTML] expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
            "\]\] "
            [foo\]
            " queryCommandValue("formatblock") after] - expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
            "\]\] "

            [foo

            bar\]

            " queryCommandValue("formatblock") before] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
            "\]\] "

            [foo

            bar\]

            " queryCommandValue("formatblock") after] - expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
            "\]\] "

            [foo

            bar\]

            " queryCommandValue("formatblock") before] expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
            "\]\] "

            [foo

            bar\]

            " queryCommandValue("formatblock") after] - expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
            "\]\] "

            [foo

            bar\]

            " queryCommandValue("formatblock") before] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
            "\]\] "

            [foo

            bar\]

            " queryCommandValue("formatblock") after] - expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
            "\]\] "

            [foo

            bar\]

            " queryCommandValue("formatblock") before] expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
            "\]\] "

            [foo

            bar\]

            " queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","div"\],["formatblock","
            "\]\] "
            [foo
            bar\]" queryCommandIndeterm("formatblock") before] - expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
            "\]\] "
            [foo
            bar\]" queryCommandValue("formatblock") before] expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","
            "\]\] "
            [foo
            bar\]" queryCommandValue("formatblock") after] - expected: FAIL - - [[["defaultparagraphseparator","p"\],["formatblock","
            "\]\] "
            [foo
            bar\]" queryCommandIndeterm("formatblock") before] - expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
            "\]\] "
            [foo
            bar\]" queryCommandValue("formatblock") before] expected: FAIL - [[["defaultparagraphseparator","p"\],["formatblock","
            "\]\] "
            [foo
            bar\]" queryCommandValue("formatblock") after] - expected: FAIL - - [[["stylewithcss","true"\],["defaultparagraphseparator","div"\],["formatblock","

            "\]\] "

            [foo\]
            " compare innerHTML] - expected: FAIL - - [[["stylewithcss","true"\],["defaultparagraphseparator","div"\],["formatblock","

            "\]\] "

            [foo\]
            " queryCommandValue("formatblock") before] - expected: FAIL - - [[["stylewithcss","false"\],["defaultparagraphseparator","div"\],["formatblock","

            "\]\] "

            [foo\]
            " compare innerHTML] - expected: FAIL - - [[["stylewithcss","false"\],["defaultparagraphseparator","div"\],["formatblock","

            "\]\] "

            [foo\]
            " queryCommandValue("formatblock") before] - expected: FAIL - - [[["stylewithcss","true"\],["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "

            [foo\]
            " compare innerHTML] - expected: FAIL - - [[["stylewithcss","true"\],["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "

            [foo\]
            " queryCommandValue("formatblock") before] - expected: FAIL - - [[["stylewithcss","false"\],["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "

            [foo\]
            " compare innerHTML] - expected: FAIL - - [[["stylewithcss","false"\],["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "

            [foo\]
            " queryCommandValue("formatblock") before] - expected: FAIL - [[["defaultparagraphseparator","div"\],["formatblock","

            "\]\] "{

            foo

            ba\]r" compare innerHTML] expected: FAIL @@ -959,17 +395,20 @@ [[["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "{

            foo

            ba\]r" queryCommandValue("formatblock") before] expected: FAIL - [[["formatblock","p"\]\] "

            [foo\]

            " queryCommandValue("formatblock") before] + [[["defaultparagraphseparator","div"\],["formatblock","

            "\]\] "

            [foo

            bar\]

            " compare innerHTML] expected: FAIL - [[["formatblock","p"\]\] "

            [foo\]

            " queryCommandValue("formatblock") after] + [[["defaultparagraphseparator","div"\],["formatblock","

            "\]\] "

            [foo

            bar\]

            " queryCommandIndeterm("formatblock") before] expected: FAIL - [[["formatblock","div"\]\] "

            [foo\]

            " queryCommandValue("formatblock") before] + [[["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "

            [foo

            bar\]

            " compare innerHTML] expected: FAIL - [[["formatblock","div"\]\] "

            [foo\]

            " queryCommandValue("formatblock") after] + [[["defaultparagraphseparator","p"\],["formatblock","

            "\]\] "

            [foo

            bar\]

            " queryCommandIndeterm("formatblock") before] expected: FAIL - [[["formatblock","div"\]\] "
            [foo\]
            " queryCommandValue("formatblock") after] + [[["defaultparagraphseparator","div"\],["formatblock","
            "\]\] "
            [foo\]
            " queryCommandValue("formatblock") before] + expected: FAIL + + [[["defaultparagraphseparator","p"\],["formatblock","
            "\]\] "
            [foo\]
            " queryCommandValue("formatblock") before] 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 2a7ddab5a189..92a1c39928cb 100644 --- a/testing/web-platform/meta/editing/run/multitest.html.ini +++ b/testing/web-platform/meta/editing/run/multitest.html.ini @@ -1,12 +1,6 @@ [multitest.html?1-1000] expected: if (os == "android") and fission: [OK, TIMEOUT] - [[["bold",""\],["formatblock","
            "\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - - [[["bold",""\],["formatblock","
            "\],["inserttext","a"\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - [[["bold",""\],["inserthtml","abcd"\]\] "foo[\]bar" queryCommandState("bold") after] expected: FAIL @@ -46,12 +40,6 @@ [[["bold",""\],["justifyright",""\],["inserttext","a"\]\] "foo[\]bar" compare innerHTML] expected: FAIL - [[["italic",""\],["formatblock","
            "\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - - [[["italic",""\],["formatblock","
            "\],["inserttext","a"\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - [[["italic",""\],["inserthtml","abcd"\]\] "foo[\]bar" queryCommandState("italic") after] expected: FAIL @@ -101,15 +89,9 @@ [[["strikethrough",""\],["delete",""\],["inserttext","a"\]\] "foo[\]bar" compare innerHTML] expected: FAIL - [[["strikethrough",""\],["formatblock","
            "\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - [[["strikethrough",""\],["formatblock","
            "\],["inserttext","a"\]\] "foo[\]bar" compare innerHTML] expected: FAIL - [[["strikethrough",""\],["formatblock","
            "\],["inserttext","a"\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - [[["strikethrough",""\],["forwarddelete",""\],["inserttext","a"\]\] "foo[\]bar" compare innerHTML] expected: FAIL @@ -176,9 +158,6 @@ [[["subscript",""\],["delete",""\],["inserttext","a"\]\] "foo[\]bar" compare innerHTML] expected: FAIL - [[["subscript",""\],["formatblock","
            "\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - [multitest.html?2001-3000] expected: @@ -234,12 +213,6 @@ [[["superscript",""\],["delete",""\],["inserttext","a"\]\] "foo[\]bar" compare innerHTML] expected: FAIL - [[["superscript",""\],["formatblock","
            "\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - - [[["superscript",""\],["formatblock","
            "\],["inserttext","a"\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - [[["superscript",""\],["forwarddelete",""\],["inserttext","a"\]\] "foo[\]bar" compare innerHTML] expected: FAIL @@ -286,12 +259,6 @@ [[["superscript",""\],["justifyright",""\],["inserttext","a"\]\] "foo[\]bar" compare innerHTML] expected: FAIL - [[["underline",""\],["formatblock","
            "\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - - [[["underline",""\],["formatblock","
            "\],["inserttext","a"\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - [[["underline",""\],["inserthtml","abcd"\]\] "foo[\]bar" queryCommandState("underline") after] expected: FAIL @@ -343,15 +310,9 @@ [[["backcolor","#00FFFF"\],["formatblock","
            "\]\] "foo[\]bar" queryCommandValue("backcolor") after] expected: FAIL - [[["backcolor","#00FFFF"\],["formatblock","
            "\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - [[["backcolor","#00FFFF"\],["formatblock","
            "\],["inserttext","a"\]\] "foo[\]bar" queryCommandValue("backcolor") after] expected: FAIL - [[["backcolor","#00FFFF"\],["formatblock","
            "\],["inserttext","a"\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - [[["backcolor","#00FFFF"\],["forwarddelete",""\]\] "foo[\]bar" queryCommandValue("backcolor") after] expected: FAIL @@ -479,15 +440,9 @@ [[["createlink","http://www.google.com/"\],["delete",""\],["inserttext","a"\]\] "foo[\]bar" compare innerHTML] expected: FAIL - [[["createlink","http://www.google.com/"\],["formatblock","
            "\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - [[["createlink","http://www.google.com/"\],["formatblock","
            "\],["inserttext","a"\]\] "foo[\]bar" compare innerHTML] expected: FAIL - [[["createlink","http://www.google.com/"\],["formatblock","
            "\],["inserttext","a"\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - [[["createlink","http://www.google.com/"\],["forwarddelete",""\],["inserttext","a"\]\] "foo[\]bar" compare innerHTML] expected: FAIL @@ -549,12 +504,6 @@ [[["createlink","http://www.google.com/"\],["outdent",""\],["inserttext","a"\]\] "foo[\]bar" compare innerHTML] expected: FAIL - [[["fontname","sans-serif"\],["formatblock","
            "\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - - [[["fontname","sans-serif"\],["formatblock","
            "\],["inserttext","a"\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - [[["fontname","sans-serif"\],["inserthtml","abcd"\]\] "foo[\]bar" queryCommandValue("fontname") after] expected: FAIL @@ -606,15 +555,9 @@ [[["fontsize","4"\],["formatblock","
            "\]\] "foo[\]bar" queryCommandValue("fontsize") before] expected: FAIL - [[["fontsize","4"\],["formatblock","
            "\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - [[["fontsize","4"\],["formatblock","
            "\],["inserttext","a"\]\] "foo[\]bar" queryCommandValue("fontsize") before] expected: FAIL - [[["fontsize","4"\],["formatblock","
            "\],["inserttext","a"\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - [[["fontsize","4"\],["forwarddelete",""\]\] "foo[\]bar" queryCommandValue("fontsize") before] expected: FAIL @@ -742,12 +685,6 @@ [[["fontsize","4"\],["outdent",""\],["inserttext","a"\]\] "foo[\]bar" queryCommandValue("fontsize") before] expected: FAIL - [[["forecolor","#0000FF"\],["formatblock","
            "\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - - [[["forecolor","#0000FF"\],["formatblock","
            "\],["inserttext","a"\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - [[["forecolor","#0000FF"\],["inserthtml","abcd"\]\] "foo[\]bar" queryCommandValue("forecolor") after] expected: FAIL @@ -803,15 +740,9 @@ [[["hilitecolor","#00FFFF"\],["formatblock","
            "\]\] "foo[\]bar" queryCommandValue("hilitecolor") after] expected: FAIL - [[["hilitecolor","#00FFFF"\],["formatblock","
            "\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - [[["hilitecolor","#00FFFF"\],["formatblock","
            "\],["inserttext","a"\]\] "foo[\]bar" queryCommandValue("hilitecolor") after] expected: FAIL - [[["hilitecolor","#00FFFF"\],["formatblock","
            "\],["inserttext","a"\]\] "foo[\]bar" queryCommandValue("formatblock") after] - expected: FAIL - [[["hilitecolor","#00FFFF"\],["forwarddelete",""\]\] "foo[\]bar" queryCommandValue("hilitecolor") after] expected: FAIL diff --git a/testing/web-platform/tests/editing/data/formatblock.js b/testing/web-platform/tests/editing/data/formatblock.js index 64e0d11d5948..1d9db464907e 100644 --- a/testing/web-platform/tests/editing/data/formatblock.js +++ b/testing/web-platform/tests/editing/data/formatblock.js @@ -147,14 +147,14 @@ var browserTests = [ {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"p",false,false,"div"]}], ["
            [foobar]
            ", [["defaultparagraphseparator","div"],["formatblock","
            "]], - "
            [foobar]
            ", + "
            [foobar]
            ", [true,true], - {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"",false,false,"div"]}], + {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"blockquote",false,false,"div"]}], ["
            [foobar]
            ", [["defaultparagraphseparator","p"],["formatblock","
            "]], - "
            [foobar]
            ", + "
            [foobar]
            ", [true,true], - {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"",false,false,"div"]}], + {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"blockquote",false,false,"div"]}], ["

            [foobar]

            ", [["defaultparagraphseparator","div"],["formatblock","
            "]], "
            [foobar]
            ", @@ -287,14 +287,14 @@ var browserTests = [ {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"pre",false,false,"div"]}], ["
            [foobar]
            ", [["defaultparagraphseparator","div"],["formatblock","
            "]], - "
            [foobar]
            ", + "
            [foobar]
            ", [true,true], - {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"",false,false,"div"]}], + {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"article",false,false,"div"]}], ["
            [foobar]
            ", [["defaultparagraphseparator","p"],["formatblock","
            "]], - "
            [foobar]
            ", + "
            [foobar]
            ", [true,true], - {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"",false,false,"div"]}], + {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"article",false,false,"div"]}], ["[foobar]", [["defaultparagraphseparator","div"],["formatblock","
            "]], "
            [foobar]
            ", @@ -482,14 +482,14 @@ var browserTests = [ {"formatblock":[false,false,"p",false,false,"p"]}], ["
            [foobar]
            ", [["defaultparagraphseparator","div"],["formatblock","

            "]], - "

            [foobar]

            ", + "

            [foobar]

            ", [true,true], - {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"",false,false,"p"]}], + {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"blockquote",false,false,"p"]}], ["
            [foobar]
            ", [["defaultparagraphseparator","p"],["formatblock","

            "]], - "

            [foobar]

            ", + "

            [foobar]

            ", [true,true], - {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"",false,false,"p"]}], + {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"blockquote",false,false,"p"]}], ["

            [foobar]

            ", [["defaultparagraphseparator","div"],["formatblock","

            "]], "

            [foobar]

            ", @@ -622,34 +622,34 @@ var browserTests = [ {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"pre",false,false,"p"]}], ["[foobar]", [["defaultparagraphseparator","div"],["formatblock","

            "]], - "

            [foobar]

            ", + "

            [foobar]

            ", [true,true], {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"",false,false,"p"]}], ["[foobar]", [["defaultparagraphseparator","p"],["formatblock","

            "]], - "

            [foobar]

            ", + "

            [foobar]

            ", [true,true], {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"",false,false,"p"]}], ["[foobar]", [["defaultparagraphseparator","div"],["formatblock","

            "]], - "

            [foobar]

            ", + "

            [foobar]

            ", [true,true], {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"",false,false,"p"]}], ["[foobar]", [["defaultparagraphseparator","p"],["formatblock","

            "]], - "

            [foobar]

            ", + "

            [foobar]

            ", [true,true], {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"",false,false,"p"]}], ["
            [foobar]
            ", [["defaultparagraphseparator","div"],["formatblock","

            "]], - "

            [foobar]

            ", + "

            [foobar]

            ", [true,true], - {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"",false,false,"p"]}], + {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"article",false,false,"p"]}], ["
            [foobar]
            ", [["defaultparagraphseparator","p"],["formatblock","

            "]], - "

            [foobar]

            ", + "

            [foobar]

            ", [true,true], - {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"",false,false,"p"]}], + {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"article",false,false,"p"]}], ["[foobar]", [["defaultparagraphseparator","div"],["formatblock","

            "]], "

            [foobar]

            ", @@ -693,43 +693,46 @@ var browserTests = [ ["
            [foo]

            extra", [["formatblock","

            "]], "
            [foo]

            extra

            ", - [false], - {"formatblock":[false,false,"",false,false,""]}], + [true], + {"formatblock":[false,false,"blockquote",false,false,"blockquote"]}], ["

            [foo]

            bar

            extra", [["formatblock","

            "]], - "

            [foo]

            bar

            extra

            ", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + "
            [foo]

            bar

            extra

            ", + [true], + {"formatblock":[false,false,"p",false,false,"blockquote"]}], ["[foo]
            bar

            extra", [["formatblock","

            "]], - "[foo]
            bar

            extra

            ", - [false], - {"formatblock":[false,false,"",false,false,""]}], + "
            [foo]
            bar

            extra

            ", + [true], + {"formatblock":[false,false,"",false,false,"blockquote"]}], ["

            [foo

            bar]

            baz", [["formatblock","

            "]], - "

            [foo

            bar]

            baz

            ", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + [ + "
            [foo
            bar]

            baz

            ", + "
            [foo
            bar]

            baz

            ", + ] + [true], + {"formatblock":[false,false,"",false,false,"blockquote"]}], ["
            [foo]
            ", [["formatblock","
            "]], - "
            [foo]
            ", - [false], - {"formatblock":[false,false,"",false,false,""]}], + "
            [foo]
            ", + [true], + {"formatblock":[false,false,"section",false,false,"blockquote"]}], ["

            [foo]

            ", [["formatblock","
            "]], - "

            [foo]

            ", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + "
            [foo]
            ", + [true], + {"formatblock":[false,false,"p",false,false,"blockquote"]}], ["

            [foo]

            bar

            baz

            ", [["formatblock","
            "]], - "

            [foo]

            bar

            baz

            ", - [false], - {"formatblock":[false,false,"h1",false,false,"h1"]}], + "
            [foo]

            bar

            baz

            ", + [true], + {"formatblock":[false,false,"h1",false,false,"blockquote"]}], ["
            [foo]
            ", [["formatblock","
            "]], - "
            [foo]
            ", - [false], - {"formatblock":[false,false,"",false,false,""]}], + "
            [foo]
            ", + [true], + {"formatblock":[false,false,"section",false,false,"article"]}], ["
            [foobar]
            ", [["defaultparagraphseparator","div"],["formatblock","
            "]], "
            [foobar]
            ", @@ -742,14 +745,14 @@ var browserTests = [ {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"div",false,false,"address"]}], ["
            [foobar]
            ", [["formatblock","
            "]], - "
            [foobar]
            ", - [false], - {"formatblock":[false,false,"div",false,false,"div"]}], + "
            [foobar]
            ", + [true], + {"formatblock":[false,false,"div",false,false,"article"]}], ["
            [foobar]
            ", [["formatblock","
            "]], - "
            [foobar]
            ", - [false], - {"formatblock":[false,false,"div",false,false,"div"]}], + "
            [foobar]
            ", + [true], + {"formatblock":[false,false,"div",false,false,"blockquote"]}], ["
            [foobar]
            ", [["defaultparagraphseparator","div"],["formatblock","
            "]], "
            [foobar]
            ", @@ -882,19 +885,19 @@ var browserTests = [ {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"p",false,false,"address"]}], ["

            [foobar]

            ", [["formatblock","
            "]], - "

            [foobar]

            ", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + "
            [foobar]
            ", + [true], + {"formatblock":[false,false,"p",false,false,"article"]}], ["

            [foobar]

            ", [["formatblock","