Bug 677752 - [contentEditable] indent and justify* fail on editable nodes that have only one child; r=ehsan
Issue #1: indent/justify* can create non-valid fragments. When applying a block-level formatting to a text node, Gecko creates a div or blockquote block around the text node and sets the corresponding "align" or "style" attribute. This patch checks that the active editing host can contain such a block-level element. Issue #2: indent/justify* can modify the active editing host. On the first child of the editable element, the selection is extended outside of the active editing host -- which causes a few issues for our test cases. In this patch, this issue is "solved" by modifying `nsHTMLEditRules::GetPromotedPoint' for block-level operations. ** About the tests ** Sorry for the long explanation but I prefer to be as sharp as possible when I have to modify existing unit tests. This patch raises 34 unit test "failures" which are improvements. Two test files are concerned and have been modified accordingly: * test_htmleditor_keyevent_handling * test_richtext2.html One test has been clarified (no real modification): * test_bug414526.html Of course, a specific unit test has been added, see `test_bug677752.html'. ** editor/libeditor/html/tests/test_htmleditor_keyevent_handling.html ** Outdenting now works properly, which results in 4 `FAIL'. * 7372 ERROR TEST-UNEXPECTED-FAIL | non-tabbable HTML editor: Shift+Tab after Tab on UL - got "<ul><li id=\"target\">ul list item</li></ul>", expected "<ul><ul><li id=\"target\">ul list item</li></ul></ul>" * 7379 ERROR TEST-UNEXPECTED-FAIL | non-tabbable HTML editor: Shift+Tab on UL - got "ul list item", expected "<ul><li id=\"target\">ul list item</li></ul>" * 7415 ERROR TEST-UNEXPECTED-FAIL | non-tabbable HTML editor: Shift+Tab after Tab on OL - got "<ol><li id=\"target\">ol list item</li></ol>", expected "<ol><ol><li id=\"target\">ol list item</li></ol></ol>" * 7422 ERROR TEST-UNEXPECTED-FAIL | non-tabbable HTML editor: Shfit+Tab on OL - got "ol list item", expected "<ol><li id=\"target\">ol list item</li></ol>" ** editor/libeditor/html/tests/browserscope/test_richtext2.html ** The 15 tests that now pass result in 15 `FAIL' and 15 `UNEXPECTED_PASS'. Here's an overview of what we had before the patch: * Section A - Apply Formatting Tests: +10 points before patch: 21/31 (Selection: 9/31) after patch: 28/31 (Selection: 12/31) FB:BQ_TEXT-1_SI EXECUTION EXCEPTION FB:BQ_TEXT-1_SI EXECUTION EXCEPTION FB:BQ_BR.BR-1_SM EXECUTION EXCEPTION FB:BQ_BR.BR-1_SM EXECUTION EXCEPTION IND_TEXT-1_SI EXECUTION EXCEPTION IND_TEXT-1_SI EXECUTION EXCEPTION JC_TEXT-1_SC editing host is modified JF_TEXT-1_SC editing host is modified JL_TEXT-1_SC editing host is modified JR_TEXT-1_SC editing host is modified * Section AC - Apply Formatting Tests, using styleWithCSS: +5 points before patch: 7/18 (Selection: 5/18) after patch: 12/18 (Selection: 5/18) IND_TEXT-1_SI editing host is modified JC_TEXT-1_SC editing host is modified JF_TEXT-1_SC editing host is modified JL_TEXT-1_SC editing host is modified JR_TEXT-1_SC editing host is modified ** editor/libeditor/html/tests/test_bug414526.html ** This test has been clarified to get more explicit report messages -- the test themselves haven't been changed. A `todo_is' test has been added. This test is the one that shows that `IsNodeInActiveEditor' can't be modified, and that limiting the range promotion for block-level operations is preferrable.
This commit is contained in:
@@ -3730,7 +3730,11 @@ nsHTMLEditRules::WillCSSIndent(nsISelection *aSelection, PRBool *aCancel, PRBool
|
||||
else {
|
||||
if (!curQuote)
|
||||
{
|
||||
// First, check that our element can contain a div.
|
||||
NS_NAMED_LITERAL_STRING(divquoteType, "div");
|
||||
if (!mEditor->CanContainTag(curParent, divquoteType))
|
||||
return NS_OK; // cancelled
|
||||
|
||||
res = SplitAsNeeded(&divquoteType, address_of(curParent), &offset);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
res = mHTMLEditor->CreateNode(divquoteType, curParent, offset, getter_AddRefs(curQuote));
|
||||
@@ -3957,6 +3961,10 @@ nsHTMLEditRules::WillHTMLIndent(nsISelection *aSelection, PRBool *aCancel, PRBoo
|
||||
|
||||
if (!curQuote)
|
||||
{
|
||||
// First, check that our element can contain a blockquote.
|
||||
if (!mEditor->CanContainTag(curParent, quoteType))
|
||||
return NS_OK; // cancelled
|
||||
|
||||
res = SplitAsNeeded("eType, address_of(curParent), &offset);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
res = mHTMLEditor->CreateNode(quoteType, curParent, offset, getter_AddRefs(curQuote));
|
||||
@@ -4089,10 +4097,10 @@ nsHTMLEditRules::WillOutdent(nsISelection *aSelection, PRBool *aCancel, PRBool *
|
||||
nsCOMPtr<nsIDOMNode> n = curNode;
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
curBlockQuoteIsIndentedWithCSS = PR_FALSE;
|
||||
// keep looking up the hierarchy as long as we don't hit the body or a table element
|
||||
// (other than an entire table)
|
||||
while (!nsTextEditUtils::IsBody(n) &&
|
||||
(nsHTMLEditUtils::IsTable(n) || !nsHTMLEditUtils::IsTableElement(n)))
|
||||
// keep looking up the hierarchy as long as we don't hit the body or the
|
||||
// active editing host or a table element (other than an entire table)
|
||||
while (!nsTextEditUtils::IsBody(n) && mHTMLEditor->IsNodeInActiveEditor(n)
|
||||
&& (nsHTMLEditUtils::IsTable(n) || !nsHTMLEditUtils::IsTableElement(n)))
|
||||
{
|
||||
n->GetParentNode(getter_AddRefs(tmp));
|
||||
if (!tmp) {
|
||||
@@ -4785,7 +4793,11 @@ nsHTMLEditRules::WillAlign(nsISelection *aSelection,
|
||||
// or if this node doesn't go in div we used earlier.
|
||||
if (!curDiv || transitionList[i])
|
||||
{
|
||||
// First, check that our element can contain a div.
|
||||
NS_NAMED_LITERAL_STRING(divType, "div");
|
||||
if (!mEditor->CanContainTag(curParent, divType))
|
||||
return NS_OK; // cancelled
|
||||
|
||||
res = SplitAsNeeded(&divType, address_of(curParent), &offset);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
res = mHTMLEditor->CreateNode(divType, curParent, offset, getter_AddRefs(curDiv));
|
||||
@@ -4795,9 +4807,9 @@ nsHTMLEditRules::WillAlign(nsISelection *aSelection,
|
||||
// set up the alignment on the div
|
||||
nsCOMPtr<nsIDOMElement> divElem = do_QueryInterface(curDiv);
|
||||
res = AlignBlock(divElem, alignType, PR_TRUE);
|
||||
// nsAutoString attr(NS_LITERAL_STRING("align"));
|
||||
// res = mHTMLEditor->SetAttribute(divElem, attr, *alignType);
|
||||
// NS_ENSURE_SUCCESS(res, res);
|
||||
//nsAutoString attr(NS_LITERAL_STRING("align"));
|
||||
//res = mHTMLEditor->SetAttribute(divElem, attr, *alignType);
|
||||
//NS_ENSURE_SUCCESS(res, res);
|
||||
// curDiv is now the correct thing to put curNode in
|
||||
}
|
||||
|
||||
@@ -5598,9 +5610,13 @@ nsHTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode *aNode, PRInt
|
||||
// Don't walk past the editable section. Note that we need to check
|
||||
// before walking up to a parent because we need to return the parent
|
||||
// object, so the parent itself might not be in the editable area, but
|
||||
// it's OK.
|
||||
if (!mHTMLEditor->IsNodeInActiveEditor(node) &&
|
||||
!mHTMLEditor->IsNodeInActiveEditor(parent)) {
|
||||
// it's OK if we're not performing a block-level action.
|
||||
PRBool blockLevelAction = (actionID == nsHTMLEditor::kOpIndent)
|
||||
|| (actionID == nsHTMLEditor::kOpOutdent)
|
||||
|| (actionID == nsHTMLEditor::kOpAlign)
|
||||
|| (actionID == nsHTMLEditor::kOpMakeBasicBlock);
|
||||
if (!mHTMLEditor->IsNodeInActiveEditor(parent) &&
|
||||
(blockLevelAction || !mHTMLEditor->IsNodeInActiveEditor(node))) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -8935,8 +8951,17 @@ nsHTMLEditRules::RelativeChangeIndentationOfElementNode(nsIDOMNode *aNode, PRInt
|
||||
}
|
||||
else {
|
||||
mHTMLEditor->mHTMLCSSUtils->RemoveCSSProperty(element, marginProperty, value, PR_FALSE);
|
||||
if (nsHTMLEditUtils::IsDiv(aNode)) {
|
||||
// we deal with a DIV ; let's see if it is useless and if we can remove it
|
||||
// remove unnecessary DIV blocks:
|
||||
// we could skip this section but that would cause a FAIL in
|
||||
// editor/libeditor/html/tests/browserscope/richtext.html, which expects
|
||||
// to unapply a CSS "indent" (<div style="margin-left: 40px;">) by
|
||||
// removing the DIV container instead of just removing the CSS property.
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
|
||||
if (nsHTMLEditUtils::IsDiv(aNode)
|
||||
&& (node != mHTMLEditor->GetActiveEditingHost())
|
||||
&& mHTMLEditor->IsNodeInActiveEditor(aNode)) {
|
||||
// we deal with an editable DIV;
|
||||
// let's see if it is useless and if we can remove it
|
||||
nsCOMPtr<nsIDOMNamedNodeMap> attributeList;
|
||||
res = element->GetAttributes(getter_AddRefs(attributeList));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
Reference in New Issue
Block a user