Commit f8d20922 authored by enrica@apple.com's avatar enrica@apple.com

Source/WebCore: Repeated copy and paste-in-place operation results in increasingly verbose HTML.

<rdar://problem/8690506>
https://bugs.webkit.org/show_bug.cgi?id=56874
        
Reviewed by Darin Adler.

When we calculate the style to apply at the insertion point we compare the initial
style at the insertion point against the style calculated at the span we wrap the
copied markup fragment with. We could end up with a series of unnecessary spans
to remove the initial style that simply grow our markup.
The consists in moving the insertion point outside any inline element that could
affect the fragment being inserted when we are not pasting and matching the style.

Test: editing/pasteboard/paste-text-with-style.html

* editing/ReplaceSelectionCommand.cpp:
(WebCore::isInlineNodeWithStyle): Added.
(WebCore::ReplaceSelectionCommand::doApply): Added logic to change the insertion
point according to the new rules.

LayoutTests: Repeated copy and paste-in-place operation results in increasingly verbose HTML.
<rdar://problem/8690506>
https://bugs.webkit.org/show_bug.cgi?id=56874

Reviewed by Darin Adler.

* editing/pasteboard/paste-text-with-style-expected.txt: Added.
* editing/pasteboard/paste-text-with-style.html: Added.
The following are new results for existing tests that now produce
a different markup.
* platform/mac/editing/pasteboard/5065605-expected.txt:
* platform/mac/editing/pasteboard/display-block-on-spans-expected.txt:
* platform/mac/editing/pasteboard/paste-text-011-expected.txt:
* platform/mac/editing/pasteboard/paste-text-at-tabspan-001-expected.txt:
* platform/mac/editing/pasteboard/paste-text-at-tabspan-002-expected.txt:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@81887 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent d30b8bc3
2011-03-24 Enrica Casucci <enrica@apple.com>
Reviewed by Darin Adler.
Repeated copy and paste-in-place operation results in increasingly verbose HTML.
<rdar://problem/8690506>
https://bugs.webkit.org/show_bug.cgi?id=56874
* editing/pasteboard/paste-text-with-style-expected.txt: Added.
* editing/pasteboard/paste-text-with-style.html: Added.
The following are new results for existing tests that now produce
a different markup.
* platform/mac/editing/pasteboard/5065605-expected.txt:
* platform/mac/editing/pasteboard/display-block-on-spans-expected.txt:
* platform/mac/editing/pasteboard/paste-text-011-expected.txt:
* platform/mac/editing/pasteboard/paste-text-at-tabspan-001-expected.txt:
* platform/mac/editing/pasteboard/paste-text-at-tabspan-002-expected.txt:
2011-03-24 Adam Roben <aroben@apple.com> 2011-03-24 Adam Roben <aroben@apple.com>
Add some flaky tests to the mac-wk2 and win-wk2 Skipped files Add some flaky tests to the mac-wk2 and win-wk2 Skipped files
......
EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 5 of DIV > BODY > HTML > #document
EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document toDOMRange:range from 0 of #text > I > B > DIV > BODY > HTML > #document to 9 of #text > FONT > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 0 of #text > I > B > DIV > BODY > HTML > #document to 9 of #text > FONT > DIV > DIV > BODY > HTML > #document givenAction:WebViewInsertActionPasted
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 9 of #text > FONT > DIV > DIV > BODY > HTML > #document to 9 of #text > FONT > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidEndEditing:WebViewDidEndEditingNotification
Markup before:
| "
"
| <b>
| <i>
| "<#selection-caret>hello bold and italic"
| <div>
| <i>
| "hello italic"
| <div>
| <font>
| color="#ff0000"
| "hello red"
| "
"
Markup after:
| <b>
| <i>
| "hello bold and italic"
| <div>
| <i>
| "hello italic"
| <div>
| <font>
| color="#ff0000"
| "hello red<#selection-caret>"
| "
"
<!DOCTYPE html>
<html>
<head>
<style>
.editing {
border: 2px solid red;
font-size: 24px;
}
.explanation {
border: 2px solid blue;
padding: 12px;
font-size: 24px;
margin-bottom: 24px;
}
.scenario { margin-bottom: 16px;}
.scenario:first-line { font-weight: bold; margin-bottom: 16px;}
.expected-results:first-line { font-weight: bold }
</style>
<script src=../editing.js></script>
<script src="../../resources/dump-as-markup.js"></script>
<script>
if (window.layoutTestController)
layoutTestController.dumpAsText();
function editingTest() {
Markup.dump('test', 'Markup before');
selectAllCommand();
copyCommand();
pasteCommand();
Markup.dump('test', 'Markup after');
}
</script>
<title>Editing Test</title>
</head>
<body>
<div class="explanation">
<div class="scenario">
Tests:
<br>
Fix for this bug:
<a href="https://bugs.webkit.org/show_bug.cgi?id=56874">&lt;https://bugs.webkit.org/show_bug.cgi?id=56874&gt;</a> Repeated copy and paste-in-place operation results in increasingly verbose HTML.
</div>
<div class="expected-results">
Expected Results:
<br>
The markup before and after should be identical.
</div>
</div>
<div contenteditable id="test" class="editing">
<b><i>hello bold and italic</i></b><div><i>hello italic</I></div><div><font color="#ff0000">hello red</font></div>
</div>
<script>
runEditingTest();
</script>
</body>
</html>
...@@ -18,16 +18,11 @@ layer at (0,0) size 800x600 ...@@ -18,16 +18,11 @@ layer at (0,0) size 800x600
RenderBlock {DIV} at (0,36) size 784x36 RenderBlock {DIV} at (0,36) size 784x36
RenderBlock (anonymous) at (0,0) size 784x18 RenderBlock (anonymous) at (0,0) size 784x18
RenderInline {FONT} at (0,0) size 148x18 [color=#FF0000] RenderInline {FONT} at (0,0) size 148x18 [color=#FF0000]
RenderInline {SPAN} at (0,0) size 148x18 [color=#000000] RenderText {#text} at (0,0) size 148x18
RenderInline {FONT} at (0,0) size 148x18 [color=#FF0000] text run at (0,0) width 148: "This text should be red."
RenderText {#text} at (0,0) size 148x18 RenderBlock {DIV} at (0,18) size 784x18
text run at (0,0) width 148: "This text should be red." RenderInline {FONT} at (0,0) size 148x18 [color=#FF0000]
RenderBlock (anonymous) at (0,18) size 784x18 [color=#FF0000] RenderText {#text} at (0,0) size 148x18
RenderBlock {DIV} at (0,0) size 784x18 [color=#000000] text run at (0,0) width 148: "This text should be red."
RenderInline {FONT} at (0,0) size 148x18 [color=#FF0000]
RenderText {#text} at (0,0) size 148x18
text run at (0,0) width 148: "This text should be red."
RenderBlock (anonymous) at (0,36) size 784x0 RenderBlock (anonymous) at (0,36) size 784x0
RenderInline {FONT} at (0,0) size 0x0 [color=#FF0000] caret: position 24 of child 0 {#text} of child 0 {FONT} of child 1 {DIV} of child 2 {DIV} of child 2 {DIV} of body
RenderInline {FONT} at (0,0) size 0x0 [color=#FF0000]
caret: position 24 of child 0 {#text} of child 0 {FONT} of child 1 {DIV} of child 0 {FONT} of child 2 {DIV} of child 2 {DIV} of body
...@@ -5,7 +5,7 @@ EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotificatio ...@@ -5,7 +5,7 @@ EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotificatio
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 0 of #text > B > SPAN > DIV > BODY > HTML > #document to 4 of #text > B > SPAN > DIV > BODY > HTML > #document givenAction:WebViewInsertActionPasted EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 0 of #text > B > SPAN > DIV > BODY > HTML > #document to 4 of #text > B > SPAN > DIV > BODY > HTML > #document givenAction:WebViewInsertActionPasted
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 4 of #text > B > SPAN > B > SPAN > DIV > BODY > HTML > #document to 4 of #text > B > SPAN > B > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 4 of #text > B > SPAN > DIV > BODY > HTML > #document to 4 of #text > B > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
layer at (0,0) size 800x600 layer at (0,0) size 800x600
...@@ -33,11 +33,10 @@ layer at (0,0) size 800x600 ...@@ -33,11 +33,10 @@ layer at (0,0) size 800x600
RenderText {#text} at (0,0) size 137x18 RenderText {#text} at (0,0) size 137x18
text run at (0,0) width 137: "This is a paragraph." text run at (0,0) width 137: "This is a paragraph."
RenderBlock {SPAN} at (0,18) size 784x18 RenderBlock {SPAN} at (0,18) size 784x18
RenderInline {B} at (0,0) size 182x18 RenderInline {B} at (0,0) size 30x18
RenderInline {SPAN} at (0,0) size 30x18 RenderText {#text} at (0,0) size 30x18
RenderInline {B} at (0,0) size 30x18 text run at (0,0) width 30: "This"
RenderText {#text} at (0,0) size 30x18 RenderInline {B} at (0,0) size 152x18
text run at (0,0) width 30: "This"
RenderText {#text} at (30,0) size 152x18 RenderText {#text} at (30,0) size 152x18
text run at (30,0) width 152: " is another paragraph." text run at (30,0) width 152: " is another paragraph."
caret: position 4 of child 0 {#text} of child 0 {B} of child 0 {SPAN} of child 0 {B} of child 2 {SPAN} of child 5 {DIV} of body caret: position 4 of child 0 {#text} of child 0 {B} of child 2 {SPAN} of child 5 {DIV} of body
...@@ -9,7 +9,7 @@ EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotificatio ...@@ -9,7 +9,7 @@ EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotificatio
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 0 of P > BODY > HTML > #document to 0 of P > BODY > HTML > #document givenAction:WebViewInsertActionPasted EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 0 of P > BODY > HTML > #document to 0 of P > BODY > HTML > #document givenAction:WebViewInsertActionPasted
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 5 of #text > B > FONT > P > B > FONT > P > BODY > HTML > #document to 5 of #text > B > FONT > P > B > FONT > P > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 5 of #text > B > FONT > P > FONT > P > BODY > HTML > #document to 5 of #text > B > FONT > P > FONT > P > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
layer at (0,0) size 800x600 layer at (0,0) size 800x600
...@@ -30,7 +30,6 @@ layer at (0,0) size 800x600 ...@@ -30,7 +30,6 @@ layer at (0,0) size 800x600
RenderBlock {P} at (0,74) size 784x58 RenderBlock {P} at (0,74) size 784x58
RenderBlock (anonymous) at (0,0) size 784x0 RenderBlock (anonymous) at (0,0) size 784x0
RenderInline {FONT} at (0,0) size 0x0 RenderInline {FONT} at (0,0) size 0x0
RenderInline {B} at (0,0) size 0x0
RenderBlock (anonymous) at (0,0) size 784x58 RenderBlock (anonymous) at (0,0) size 784x58
RenderBlock {P} at (0,0) size 784x21 RenderBlock {P} at (0,0) size 784x21
RenderInline {FONT} at (0,0) size 55x20 RenderInline {FONT} at (0,0) size 55x20
...@@ -44,7 +43,5 @@ layer at (0,0) size 800x600 ...@@ -44,7 +43,5 @@ layer at (0,0) size 800x600
text run at (0,0) width 55: "there" text run at (0,0) width 55: "there"
RenderBlock (anonymous) at (0,74) size 784x0 RenderBlock (anonymous) at (0,74) size 784x0
RenderInline {FONT} at (0,0) size 0x0 RenderInline {FONT} at (0,0) size 0x0
RenderInline {B} at (0,0) size 0x0
RenderInline {FONT} at (0,0) size 0x0 RenderInline {FONT} at (0,0) size 0x0
RenderInline {B} at (0,0) size 0x0 caret: position 5 of child 0 {#text} of child 0 {B} of child 0 {FONT} of child 1 {P} of child 0 {FONT} of child 4 {P} of body
caret: position 5 of child 0 {#text} of child 0 {B} of child 0 {FONT} of child 1 {P} of child 0 {B} of child 0 {FONT} of child 4 {P} of body
...@@ -4,11 +4,11 @@ EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotificatio ...@@ -4,11 +4,11 @@ EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotificatio
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 1 of #text > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > DIV > BODY > HTML > #document givenAction:WebViewInsertActionPasted EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 1 of #text > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > DIV > BODY > HTML > #document givenAction:WebViewInsertActionPasted
EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > DIV > BODY > HTML > #document toDOMRange:range from 1 of #text > SPAN > SPAN > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > SPAN > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > DIV > BODY > HTML > #document toDOMRange:range from 1 of #text > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > SPAN > SPAN > SPAN > DIV > BODY > HTML > #document to 2 of #text > SPAN > SPAN > SPAN > DIV > BODY > HTML > #document toDOMRange:range from 2 of #text > SPAN > SPAN > SPAN > DIV > BODY > HTML > #document to 2 of #text > SPAN > SPAN > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > SPAN > DIV > BODY > HTML > #document to 2 of #text > SPAN > DIV > BODY > HTML > #document toDOMRange:range from 2 of #text > SPAN > DIV > BODY > HTML > #document to 2 of #text > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
layer at (0,0) size 800x600 layer at (0,0) size 800x600
...@@ -20,13 +20,12 @@ layer at (0,0) size 800x600 ...@@ -20,13 +20,12 @@ layer at (0,0) size 800x600
RenderInline {SPAN} at (0,0) size 155x28 RenderInline {SPAN} at (0,0) size 155x28
RenderText {#text} at (14,14) size 11x28 RenderText {#text} at (14,14) size 11x28
text run at (14,14) width 11: "a" text run at (14,14) width 11: "a"
RenderInline {SPAN} at (0,0) size 133x28 RenderText {#text} at (25,14) size 23x28
RenderInline {SPAN} at (0,0) size 23x28 text run at (25,14) width 23: "ax"
RenderText {#text} at (25,14) size 23x28 RenderInline {SPAN} at (0,0) size 110x28
text run at (25,14) width 23: "ax"
RenderText {#text} at (48,14) size 110x28 RenderText {#text} at (48,14) size 110x28
text run at (48,14) width 110: "\x{9}\x{9}\x{9}" text run at (48,14) width 110: "\x{9}\x{9}\x{9}"
RenderText {#text} at (158,14) size 11x28 RenderText {#text} at (158,14) size 11x28
text run at (158,14) width 11: "z" text run at (158,14) width 11: "z"
RenderText {#text} at (0,0) size 0x0 RenderText {#text} at (0,0) size 0x0
caret: position 2 of child 0 {#text} of child 0 {SPAN} of child 1 {SPAN} of child 1 {SPAN} of child 1 {DIV} of body caret: position 2 of child 1 {#text} of child 1 {SPAN} of child 1 {DIV} of body
...@@ -6,11 +6,11 @@ EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotificatio ...@@ -6,11 +6,11 @@ EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotificatio
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 1 of #text > SPAN > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > SPAN > DIV > BODY > HTML > #document givenAction:WebViewInsertActionPasted EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 1 of #text > SPAN > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > SPAN > DIV > BODY > HTML > #document givenAction:WebViewInsertActionPasted
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > SPAN > SPAN > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > SPAN > SPAN > DIV > BODY > HTML > #document toDOMRange:range from 1 of #text > SPAN > SPAN > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > SPAN > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > DIV > BODY > HTML > #document toDOMRange:range from 1 of #text > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > SPAN > SPAN > SPAN > DIV > BODY > HTML > #document to 2 of #text > SPAN > SPAN > SPAN > DIV > BODY > HTML > #document toDOMRange:range from 2 of #text > SPAN > SPAN > SPAN > DIV > BODY > HTML > #document to 2 of #text > SPAN > SPAN > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > SPAN > DIV > BODY > HTML > #document to 2 of #text > SPAN > DIV > BODY > HTML > #document toDOMRange:range from 2 of #text > SPAN > DIV > BODY > HTML > #document to 2 of #text > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
layer at (0,0) size 800x600 layer at (0,0) size 800x600
...@@ -25,13 +25,12 @@ layer at (0,0) size 800x600 ...@@ -25,13 +25,12 @@ layer at (0,0) size 800x600
RenderInline {SPAN} at (0,0) size 37x28 RenderInline {SPAN} at (0,0) size 37x28
RenderText {#text} at (25,14) size 37x28 RenderText {#text} at (25,14) size 37x28
text run at (25,14) width 37: "\x{9}" text run at (25,14) width 37: "\x{9}"
RenderInline {SPAN} at (0,0) size 96x28 RenderText {#text} at (62,14) size 23x28
RenderInline {SPAN} at (0,0) size 23x28 text run at (62,14) width 23: "ax"
RenderText {#text} at (62,14) size 23x28 RenderInline {SPAN} at (0,0) size 73x28
text run at (62,14) width 23: "ax"
RenderText {#text} at (85,14) size 73x28 RenderText {#text} at (85,14) size 73x28
text run at (85,14) width 73: "\x{9}\x{9}" text run at (85,14) width 73: "\x{9}\x{9}"
RenderText {#text} at (158,14) size 11x28 RenderText {#text} at (158,14) size 11x28
text run at (158,14) width 11: "z" text run at (158,14) width 11: "z"
RenderText {#text} at (0,0) size 0x0 RenderText {#text} at (0,0) size 0x0
caret: position 2 of child 0 {#text} of child 0 {SPAN} of child 2 {SPAN} of child 1 {SPAN} of child 1 {DIV} of body caret: position 2 of child 2 {#text} of child 1 {SPAN} of child 1 {DIV} of body
2011-03-24 Enrica Casucci <enrica@apple.com>
Reviewed by Darin Adler.
Repeated copy and paste-in-place operation results in increasingly verbose HTML.
<rdar://problem/8690506>
https://bugs.webkit.org/show_bug.cgi?id=56874
When we calculate the style to apply at the insertion point we compare the initial
style at the insertion point against the style calculated at the span we wrap the
copied markup fragment with. We could end up with a series of unnecessary spans
to remove the initial style that simply grow our markup.
The consists in moving the insertion point outside any inline element that could
affect the fragment being inserted when we are not pasting and matching the style.
Test: editing/pasteboard/paste-text-with-style.html
* editing/ReplaceSelectionCommand.cpp:
(WebCore::isInlineNodeWithStyle): Added.
(WebCore::ReplaceSelectionCommand::doApply): Added logic to change the insertion
point according to the new rules.
2011-03-24 Benjamin Poulain <benjamin.poulain@nokia.com> 2011-03-24 Benjamin Poulain <benjamin.poulain@nokia.com>
Reviewed by Kenneth Rohde Christiansen. Reviewed by Kenneth Rohde Christiansen.
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include "HTMLInputElement.h" #include "HTMLInputElement.h"
#include "HTMLInterchange.h" #include "HTMLInterchange.h"
#include "HTMLNames.h" #include "HTMLNames.h"
#include "NodeList.h"
#include "SelectionController.h" #include "SelectionController.h"
#include "SmartReplace.h" #include "SmartReplace.h"
#include "TextIterator.h" #include "TextIterator.h"
...@@ -776,6 +777,34 @@ static Node* enclosingInline(Node* node) ...@@ -776,6 +777,34 @@ static Node* enclosingInline(Node* node)
return node; return node;
} }
static bool isInlineNodeWithStyle(const Node* node)
{
// We don't want to skip over any block elements.
if (!node->renderer() || !node->renderer()->isInline())
return false;
if (!node->isHTMLElement())
return false;
// We can skip over elements whose class attribute is
// one of our internal classes.
const HTMLElement* element = static_cast<const HTMLElement*>(node);
AtomicString classAttributeValue = element->getAttribute(classAttr);
if (classAttributeValue == AppleStyleSpanClass
|| classAttributeValue == AppleTabSpanClass
|| classAttributeValue == AppleConvertedSpace
|| classAttributeValue == ApplePasteAsQuotation)
return true;
// We can skip inline elements that don't have attributes or whose only
// attribute is the style attribute.
const NamedNodeMap* attributeMap = element->attributeMap();
if (!attributeMap || attributeMap->isEmpty() || (attributeMap->length() == 1 && element->hasAttribute(styleAttr)))
return true;
return false;
}
void ReplaceSelectionCommand::doApply() void ReplaceSelectionCommand::doApply()
{ {
VisibleSelection selection = endingSelection(); VisibleSelection selection = endingSelection();
...@@ -917,6 +946,29 @@ void ReplaceSelectionCommand::doApply() ...@@ -917,6 +946,29 @@ void ReplaceSelectionCommand::doApply()
// outside of preceding tags. // outside of preceding tags.
insertionPos = positionAvoidingPrecedingNodes(insertionPos); insertionPos = positionAvoidingPrecedingNodes(insertionPos);
// If we are not trying to match the destination style we prefer a position
// that is outside inline elements that provide style.
// This way we can produce a less verbose markup.
// We can skip this optimization for fragments not wrapped in one of
// our style spans and for positions inside list items
// since insertAsListItems already does the right thing.
if (!m_matchStyle && !enclosingList(insertionPos.anchorNode()) && isStyleSpan(fragment.firstChild())) {
Node* parentNode = insertionPos.anchorNode()->parentNode();
while (parentNode && parentNode->renderer() && isInlineNodeWithStyle(parentNode)) {
// If we are in the middle of a text node, we need to split it before we can
// move the insertion position.
if (insertionPos.anchorNode()->isTextNode() && insertionPos.anchorType() == Position::PositionIsOffsetInAnchor && insertionPos.offsetInContainerNode() && !insertionPos.atLastEditingPositionForNode())
splitTextNodeContainingElement(static_cast<Text*>(insertionPos.anchorNode()), insertionPos.offsetInContainerNode());
// If the style element has more than one child, we need to split it.
if (parentNode->firstChild()->nextSibling())
splitElement(static_cast<Element*>(parentNode), insertionPos.computeNodeAfterPosition());
insertionPos = positionInParentBeforeNode(parentNode);
parentNode = parentNode->parentNode();
}
}
// FIXME: When pasting rich content we're often prevented from heading down the fast path by style spans. Try // FIXME: When pasting rich content we're often prevented from heading down the fast path by style spans. Try
// again here if they've been removed. // again here if they've been removed.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment