mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 772796 - Handle newlines correctly when joining <div> and <pre>. r=roc
This commit is contained in:
parent
1e118e16a6
commit
8bcd1fb8a3
@ -5614,6 +5614,27 @@ nsHTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode* aNode,
|
||||
if (mHTMLEditor->IsVisBreak(nextNode->AsDOMNode())) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for newlines in pre-formatted text nodes.
|
||||
bool isPRE;
|
||||
mHTMLEditor->IsPreformatted(nextNode->AsDOMNode(), &isPRE);
|
||||
if (isPRE) {
|
||||
nsCOMPtr<nsIDOMText> textNode = do_QueryInterface(nextNode);
|
||||
if (textNode) {
|
||||
nsAutoString tempString;
|
||||
textNode->GetData(tempString);
|
||||
int32_t newlinePos = tempString.FindChar(nsCRT::LF);
|
||||
if (newlinePos >= 0) {
|
||||
if ((uint32_t)newlinePos + 1 == tempString.Length()) {
|
||||
// No need for special processing if the newline is at the end.
|
||||
break;
|
||||
}
|
||||
*outNode = nextNode->AsDOMNode();
|
||||
*outOffset = newlinePos + 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_ENSURE_TRUE(mHTMLEditor, /* void */);
|
||||
nextNode = mHTMLEditor->GetNextHTMLNode(node, offset, true);
|
||||
}
|
||||
@ -5781,6 +5802,29 @@ nsHTMLEditRules::GetNodesForOperation(nsTArray<nsRefPtr<nsRange>>& aArrayOfRange
|
||||
int32_t rangeCount = aArrayOfRanges.Length();
|
||||
nsresult res = NS_OK;
|
||||
|
||||
// Split text nodes. This is necessary, since GetPromotedPoint() may return a
|
||||
// range ending in a text node in case where part of a pre-formatted
|
||||
// elements needs to be moved.
|
||||
for (int32_t i = 0; i < rangeCount; i++) {
|
||||
nsRefPtr<nsRange> r = aArrayOfRanges[i];
|
||||
nsCOMPtr<nsIContent> endParent = do_QueryInterface(r->GetEndParent());
|
||||
|
||||
if (mHTMLEditor->IsTextNode(endParent)) {
|
||||
int32_t offset = r->EndOffset();
|
||||
|
||||
// Split the text node.
|
||||
nsCOMPtr<nsIDOMNode> tempNode;
|
||||
res = mHTMLEditor->SplitNode(endParent->AsDOMNode(), offset,
|
||||
getter_AddRefs(tempNode));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
// Correct the range.
|
||||
// The new end parent becomes the parent node of the text.
|
||||
nsCOMPtr<nsIContent> newParent = endParent->GetParent();
|
||||
r->SetEnd(newParent, newParent->IndexOf(endParent));
|
||||
}
|
||||
}
|
||||
|
||||
// Bust up any inlines that cross our range endpoints, but only if we are
|
||||
// allowed to touch content.
|
||||
|
||||
|
@ -130,6 +130,7 @@ skip-if = toolkit == 'android' || e10s
|
||||
[test_bug757371.html]
|
||||
[test_bug757771.html]
|
||||
[test_bug767684.html]
|
||||
[test_bug772796.html]
|
||||
[test_bug773262.html]
|
||||
[test_bug780035.html]
|
||||
[test_bug787432.html]
|
||||
|
218
editor/libeditor/tests/test_bug772796.html
Normal file
218
editor/libeditor/tests/test_bug772796.html
Normal file
@ -0,0 +1,218 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=772796
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 772796</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style> .pre { white-space: pre } </style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=772796">Mozilla Bug 772796</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
|
||||
<div id="editable" contenteditable></div>
|
||||
|
||||
<pre id="test">
|
||||
|
||||
<script type="application/javascript">
|
||||
var tests = [
|
||||
/*00*/[ "<div>test</div><pre>foobar\nbaz</pre>", "<div>testfoobar\n</div><pre>baz</pre>" ],
|
||||
/*01*/[ "<div>test</div><pre><b>foobar\nbaz</b></pre>", "<div>testfoobar\n</div><pre><b>baz</b></pre>" ],
|
||||
/*02*/[ "<div>test</div><pre><b>foo</b>bar\nbaz</pre>", "<div>test<b>foo</b>bar\n</div><pre>baz</pre>" ],
|
||||
/*03*/[ "<div>test</div><pre><b>foo</b>\nbar</pre>", "<div>test<b>foo</b>\n</div><pre>bar</pre>" ],
|
||||
/*04*/[ "<div>test</div><pre><b>foo\n</b>bar\nbaz</pre>", "<div>testfoo\n</div><pre>bar\nbaz</pre>" ],
|
||||
/* The <br> after the foobar is unfortunate but is behaviour that hasn't changed in bug 772796. */
|
||||
/*05*/[ "<div>test</div><pre>foobar<br>baz</pre>", "<div>testfoobar<br></div><pre>baz</pre>" ],
|
||||
/*06*/[ "<div>test</div><pre><b>foobar<br>baz</b></pre>", "<div>testfoobar<br></div><pre><b>baz</b></pre>" ],
|
||||
|
||||
/*
|
||||
* Some tests with block elements.
|
||||
* Tests 07, 09 and 11 don't use "MoveBlock", they use "JoinNodesSmart".
|
||||
* Test 11 is a pain: <div>foo\bar</div> is be joined to "test", losing the visible line break.
|
||||
*/
|
||||
/*07*/[ "<div>test</div><pre><div>foobar</div>baz</pre>", "<div>testfoobar</div><pre>baz</pre>" ],
|
||||
/*08*/[ "<div>test</div><pre>foobar<div>baz</div></pre>", "<div>testfoobar</div><pre><div>baz</div></pre>" ],
|
||||
/*09*/[ "<div>test</div><pre><div>foobar</div>baz\nfred</pre>", "<div>testfoobar</div><pre>baz\nfred</pre>" ],
|
||||
/*10*/[ "<div>test</div><pre>foobar<div>baz</div>\nfred</pre>", "<div>testfoobar</div><pre><div>baz</div>\nfred</pre>" ],
|
||||
/*11*/[ "<div>test</div><pre><div>foo\nbar</div>baz\nfred</pre>", "<div>testfoo\nbar</div><pre>baz\nfred</pre>" ], // BAD
|
||||
/*12*/[ "<div>test</div><pre>foo<div>bar</div>baz\nfred</pre>", "<div>testfoo</div><pre><div>bar</div>baz\nfred</pre>" ],
|
||||
|
||||
/*
|
||||
* Repeating all tests above with the <pre> on a new line.
|
||||
* We know that backspace doesn't work (bug 1190161). Third argument shows the current outcome.
|
||||
*/
|
||||
/*13*/[ "<div>test</div>\n<pre>foobar\nbaz</pre>", "<div>testfoobar\n</div><pre>baz</pre>",
|
||||
"<div>test</div>foobar\n<pre>baz</pre>" ],
|
||||
/*14*/[ "<div>test</div>\n<pre><b>foobar\nbaz</b></pre>", "<div>testfoobar\n</div><pre><b>baz</b></pre>",
|
||||
"<div>test</div>foobar\n<pre><b>baz</b></pre>" ],
|
||||
/*15*/[ "<div>test</div>\n<pre><b>foo</b>bar\nbaz</pre>", "<div>test<b>foo</b>bar\n</div><pre>baz</pre>",
|
||||
"<div>test</div><b>foo</b>bar\n<pre>baz</pre>" ],
|
||||
/*16*/[ "<div>test</div>\n<pre><b>foo</b>\nbar</pre>", "<div>test<b>foo</b>\n</div><pre>bar</pre>",
|
||||
"<div>test</div><b>foo</b>\n<pre>bar</pre>" ],
|
||||
/*17*/[ "<div>test</div>\n<pre><b>foo\n</b>bar\nbaz</pre>", "<div>testfoo\n</div><pre>bar\nbaz</pre>",
|
||||
"<div>test</div>foo\n<pre>bar\nbaz</pre>" ],
|
||||
/*18*/[ "<div>test</div>\n<pre>foobar<br>baz</pre>", "<div>testfoobar<br></div><pre>baz</pre>",
|
||||
"<div>test</div>foobar<br><pre>baz</pre>" ],
|
||||
/*19*/[ "<div>test</div>\n<pre><b>foobar<br>baz</b></pre>", "<div>testfoobar<br></div><pre><b>baz</b></pre>",
|
||||
"<div>test</div>foobar<br><pre><b>baz</b></pre>" ],
|
||||
/*20*/[ "<div>test</div>\n<pre><div>foobar</div>baz</pre>", "<div>testfoobar</div><pre>baz</pre>",
|
||||
"<div>test</div>foobar<pre>baz</pre>" ],
|
||||
/*21*/[ "<div>test</div>\n<pre>foobar<div>baz</div></pre>", "<div>testfoobar</div><pre><div>baz</div></pre>",
|
||||
"<div>test</div>foobar<pre><div>baz</div></pre>" ],
|
||||
/*22*/[ "<div>test</div>\n<pre><div>foobar</div>baz\nfred</pre>", "<div>testfoobar</div><pre>baz\nfred</pre>",
|
||||
"<div>test</div>foobar<pre>baz\nfred</pre>" ],
|
||||
/*23*/[ "<div>test</div>\n<pre>foobar<div>baz</div>\nfred</pre>", "<div>testfoobar</div><pre><div>baz</div>\nfred</pre>",
|
||||
"<div>test</div>foobar<pre><div>baz</div>\nfred</pre>" ],
|
||||
/*24*/[ "<div>test</div>\n<pre><div>foo\nbar</div>baz\nfred</pre>", "<div>testfoo\nbar</div><pre>baz\nfred</pre>", // BAD
|
||||
"<div>test</div>foo\n<pre><div>bar</div>baz\nfred</pre>" ],
|
||||
/*25*/[ "<div>test</div>\n<pre>foo<div>bar</div>baz\nfred</pre>", "<div>testfoo</div><pre><div>bar</div>baz\nfred</pre>",
|
||||
"<div>test</div>foo<pre><div>bar</div>baz\nfred</pre>" ],
|
||||
|
||||
/* Some tests without <div>. These exercise the MoveBlock "right in left" */
|
||||
/*26*/[ "test<pre>foobar\nbaz</pre>", "testfoobar\n<pre>baz</pre>" ],
|
||||
/*27*/[ "test<pre><b>foobar\nbaz</b></pre>", "testfoobar\n<pre><b>baz</b></pre>" ],
|
||||
/*28*/[ "test<pre><b>foo</b>bar\nbaz</pre>", "test<b>foo</b>bar\n<pre>baz</pre>" ],
|
||||
/*29*/[ "test<pre><b>foo</b>\nbar</pre>", "test<b>foo</b>\n<pre>bar</pre>" ],
|
||||
/*30*/[ "test<pre><b>foo\n</b>bar\nbaz</pre>", "testfoo\n<pre>bar\nbaz</pre>" ],
|
||||
/*31*/[ "test<pre>foobar<br>baz</pre>", "testfoobar<br><pre>baz</pre>" ],
|
||||
/*32*/[ "test<pre><b>foobar<br>baz</b></pre>", "testfoobar<br><pre><b>baz</b></pre>" ],
|
||||
/*33*/[ "test<pre><div>foobar</div>baz</pre>", "testfoobar<pre>baz</pre>" ],
|
||||
/*34*/[ "test<pre>foobar<div>baz</div></pre>", "testfoobar<pre><div>baz</div></pre>" ],
|
||||
/*35*/[ "test<pre><div>foobar</div>baz\nfred</pre>", "testfoobar<pre>baz\nfred</pre>" ],
|
||||
/*36*/[ "test<pre>foobar<div>baz</div>\nfred</pre>", "testfoobar<pre><div>baz</div>\nfred</pre>" ],
|
||||
/*37*/[ "test<pre><div>foo\nbar</div>baz\nfred</pre>", "testfoo\n<pre><div>bar</div>baz\nfred</pre>" ],
|
||||
/*38*/[ "test<pre>foo<div>bar</div>baz\nfred</pre>", "testfoo<pre><div>bar</div>baz\nfred</pre>" ],
|
||||
|
||||
/*
|
||||
* Some tests with <span class="pre">. Again 07, 09 and 11 use "JoinNodesSmart".
|
||||
* All these exercise MoveBlock "left in right". The "right" is the surrounding "contenteditable" div.
|
||||
*/
|
||||
/*39-00*/[ "<div>test</div><span class=\"pre\">foobar\nbaz</span>", "<div>testfoobar\n</div><span class=\"pre\">baz</span>" ],
|
||||
/*40-01*/[ "<div>test</div><span class=\"pre\"><b>foobar\nbaz</b></span>", "<div>testfoobar\n</div><span class=\"pre\"><b>baz</b></span>" ],
|
||||
/*41-02*/[ "<div>test</div><span class=\"pre\"><b>foo</b>bar\nbaz</span>", "<div>test<b>foo</b>bar\n</div><span class=\"pre\">baz</span>" ],
|
||||
/*42-03*/[ "<div>test</div><span class=\"pre\"><b>foo</b>\nbar</span>", "<div>test<b>foo</b>\n</div><span class=\"pre\">bar</span>" ],
|
||||
/*43-04*/[ "<div>test</div><span class=\"pre\"><b>foo\n</b>bar\nbaz</span>", "<div>testfoo\n</div><span class=\"pre\">bar\nbaz</span>" ],
|
||||
/*44-05*/[ "<div>test</div><span class=\"pre\">foobar<br>baz</span>", "<div>testfoobar<br></div><span class=\"pre\">baz</span>" ],
|
||||
/*45-06*/[ "<div>test</div><span class=\"pre\"><b>foobar<br>baz</b></span>", "<div>testfoobar<br></div><span class=\"pre\"><b>baz</b></span>" ],
|
||||
/*46-07*/[ "<div>test</div><span class=\"pre\"><div>foobar</div>baz</span>", "<div>testfoobar</div><span class=\"pre\">baz</span>" ],
|
||||
/*47-08*/[ "<div>test</div><span class=\"pre\">foobar<div>baz</div></span>", "<div>testfoobar</div><span class=\"pre\"><div>baz</div></span>" ],
|
||||
/*48-09*/[ "<div>test</div><span class=\"pre\"><div>foobar</div>baz\nfred</span>", "<div>testfoobar</div><span class=\"pre\">baz\nfred</span>" ],
|
||||
/*49-10*/[ "<div>test</div><span class=\"pre\">foobar<div>baz</div>\nfred</span>", "<div>testfoobar</div><span class=\"pre\"><div>baz</div>\nfred</span>" ],
|
||||
/*50-11*/[ "<div>test</div><span class=\"pre\"><div>foo\nbar</div>baz\nfred</span>", "<div>testfoo\nbar</div><span class=\"pre\">baz\nfred</span>" ], // BAD
|
||||
/*51-12*/[ "<div>test</div><span class=\"pre\">foo<div>bar</div>baz\nfred</span>", "<div>testfoo</div><span class=\"pre\"><div>bar</div>baz\nfred</span>" ],
|
||||
|
||||
/* Some tests with <div class="pre">. */
|
||||
/*
|
||||
* The results are pretty ugly, since joining two <divs> sadly carrys the properties of the right to the left,
|
||||
* but not in all cases: 07, 09, 11 are actually right. All cases use "JoinNodesSmart".
|
||||
* Here we merely document the ugly behaviour. See bug 1191875 for more information.
|
||||
*/
|
||||
/*52-00*/[ "<div>test</div><div class=\"pre\">foobar\nbaz</div>", "<div class=\"pre\">testfoobar\nbaz</div>" ],
|
||||
/*53-01*/[ "<div>test</div><div class=\"pre\"><b>foobar\nbaz</b></div>", "<div class=\"pre\">test<b>foobar\nbaz</b></div>" ],
|
||||
/*54-02*/[ "<div>test</div><div class=\"pre\"><b>foo</b>bar\nbaz</div>", "<div class=\"pre\">test<b>foo</b>bar\nbaz</div>" ],
|
||||
/*55-03*/[ "<div>test</div><div class=\"pre\"><b>foo</b>\nbar</div>", "<div class=\"pre\">test<b>foo</b>\nbar</div>" ],
|
||||
/*56-04*/[ "<div>test</div><div class=\"pre\"><b>foo\n</b>bar\nbaz</div>", "<div class=\"pre\">test<b>foo\n</b>bar\nbaz</div>" ],
|
||||
/*57-05*/[ "<div>test</div><div class=\"pre\">foobar<br>baz</div>", "<div class=\"pre\">testfoobar<br>baz</div>" ],
|
||||
/*58-06*/[ "<div>test</div><div class=\"pre\"><b>foobar<br>baz</b></div>", "<div class=\"pre\">test<b>foobar<br>baz</b></div>" ],
|
||||
/*59-07*/[ "<div>test</div><div class=\"pre\"><div>foobar</div>baz</div>", "<div>testfoobar</div><div class=\"pre\">baz</div>" ],
|
||||
/*60-08*/[ "<div>test</div><div class=\"pre\">foobar<div>baz</div></div>", "<div class=\"pre\">testfoobar<div>baz</div></div>" ],
|
||||
/*61-09*/[ "<div>test</div><div class=\"pre\"><div>foobar</div>baz\nfred</div>", "<div>testfoobar</div><div class=\"pre\">baz\nfred</div>" ],
|
||||
/*62-10*/[ "<div>test</div><div class=\"pre\">foobar<div>baz</div>\nfred</div>", "<div class=\"pre\">testfoobar<div>baz</div>\nfred</div>" ],
|
||||
/*63-11*/[ "<div>test</div><div class=\"pre\"><div>foo\nbar</div>baz\nfred</div>", "<div>testfoo\nbar</div><div class=\"pre\">baz\nfred</div>" ], // BAD
|
||||
/*64-12*/[ "<div>test</div><div class=\"pre\">foo<div>bar</div>baz\nfred</div>", "<div class=\"pre\">testfoo<div>bar</div>baz\nfred</div>" ],
|
||||
|
||||
/* Some tests with lists. These exercise the MoveBlock "left in right". */
|
||||
/*65*/[ "<ul><pre><li>test</li>foobar\nbaz</pre></ul>", "<ul><pre><li>testfoobar\n</li>baz</pre></ul>" ],
|
||||
/*66*/[ "<ul><pre><li>test</li><b>foobar\nbaz</b></pre></ul>", "<ul><pre><li>testfoobar\n</li><b>baz</b></pre></ul>" ],
|
||||
/*67*/[ "<ul><pre><li>test</li><b>foo</b>bar\nbaz</pre></ul>", "<ul><pre><li>test<b>foo</b>bar\n</li>baz</pre></ul>" ],
|
||||
/*68*/[ "<ul><pre><li>test</li><b>foo</b>\nbar</pre></ul>", "<ul><pre><li>test<b>foo</b>\n</li>bar</pre></ul>" ],
|
||||
/*69*/[ "<ul><pre><li>test</li><b>foo\n</b>bar\nbaz</pre></ul>", "<ul><pre><li>testfoo\n</li>bar\nbaz</pre></ul>" ],
|
||||
|
||||
// Last not least, a simple edge case test.
|
||||
/*70*/[ "<div>test</div><pre>foobar\n</pre>baz", "<div>testfoobar\n</div>baz" ],
|
||||
];
|
||||
|
||||
/** Test for Bug 772796 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
SimpleTest.waitForFocus(function() {
|
||||
|
||||
var sel = window.getSelection();
|
||||
var theEdit = document.getElementById("editable");
|
||||
var testName;
|
||||
var theDiv;
|
||||
|
||||
for (i = 0; i < tests.length; i++) {
|
||||
// for (i = 1; i < 2; i++) {
|
||||
testName = "test" + i.toString();
|
||||
dump (testName+"\n");
|
||||
dump (tests[i][0]+"\n");
|
||||
|
||||
/* Set up the selection. */
|
||||
theEdit.innerHTML = "<div id=\"" + testName + "\">" + tests[i][0] + "</div>";
|
||||
theDiv = document.getElementById(testName);
|
||||
theDiv.focus();
|
||||
sel.collapse(theDiv, 0);
|
||||
synthesizeMouse(theDiv, 100, 2, {}); /* click behind and down */
|
||||
|
||||
/** First round: Forward delete. **/
|
||||
synthesizeKey("VK_DELETE", {});
|
||||
is(theDiv.innerHTML, tests[i][1], "delete(collapsed): inner HTML for " + testName);
|
||||
|
||||
/* Set up the selection. */
|
||||
theEdit.innerHTML = "<div id=\"" + testName + "\">" + tests[i][0] + "</div>";
|
||||
theDiv = document.getElementById(testName);
|
||||
theDiv.focus();
|
||||
sel.collapse(theDiv, 0);
|
||||
synthesizeMouse(theDiv, 100, 2, {}); /* click behind and down */
|
||||
|
||||
/** Second round: Backspace. **/
|
||||
synthesizeKey("VK_RIGHT", {});
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
if (tests[i].length == 2) {
|
||||
is(theDiv.innerHTML, tests[i][1], "backspace: inner HTML for " + testName);
|
||||
} else {
|
||||
todo_is(theDiv.innerHTML, tests[i][1], "backspace(should be): inner HTML for " + testName);
|
||||
is(theDiv.innerHTML, tests[i][2], "backspace(currently is): inner HTML for " + testName);
|
||||
}
|
||||
|
||||
/* Set up the selection. */
|
||||
theEdit.innerHTML = "<div id=\"" + testName + "\">" + tests[i][0] + "</div>";
|
||||
theDiv = document.getElementById(testName);
|
||||
theDiv.focus();
|
||||
sel.collapse(theDiv, 0);
|
||||
synthesizeMouse(theDiv, 100, 2, {}); /* click behind and down */
|
||||
|
||||
/** Third round: Delete with non-collapsed selection. **/
|
||||
synthesizeKey("VK_LEFT", {});
|
||||
/* Strangely enough we need to hit "right arrow" three times to select two characters. */
|
||||
synthesizeKey("VK_RIGHT", {shiftKey:true});
|
||||
synthesizeKey("VK_RIGHT", {shiftKey:true});
|
||||
synthesizeKey("VK_RIGHT", {shiftKey:true});
|
||||
synthesizeKey("VK_DELETE", {});
|
||||
|
||||
/* We always expect to the delete the "tf" in "testfoo". */
|
||||
var expected = tests[i][1].replace("testfoo", "tesoo")
|
||||
.replace("test<b>foo", "tes<b>oo")
|
||||
.replace("test<span class=\"pre\">foo", "tes<span class=\"pre\">oo")
|
||||
.replace("test<span class=\"pre\"><b>foo", "tes<span class=\"pre\"><b>oo");
|
||||
is(theDiv.innerHTML, expected, "delete(non-collapsed): inner HTML for " + testName);
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user