Title: [243124] trunk
Revision
243124
Author
[email protected]
Date
2019-03-18 18:56:39 -0700 (Mon, 18 Mar 2019)

Log Message

Smart Insert for paragraphs.
https://bugs.webkit.org/show_bug.cgi?id=194880

Reviewed by Ryosuke Niwa.

Source/WebCore:

Add additional newlines to maintain spacing around paragraphs.

Tests: editing/pasteboard/smart-paste-paragraph-001.html
       editing/pasteboard/smart-paste-paragraph-002.html
       editing/pasteboard/smart-paste-paragraph-003.html
       editing/pasteboard/smart-paste-paragraph-004.html

* dom/Document.cpp:
(WebCore::Document::editingBehavior const):
* dom/Document.h:

Expose editing behaviour through document so that is can be access from the selection commands
and allow the editing behaviour to be used.

* editing/CompositeEditCommand.h:
* editing/EditingBehavior.h:
(WebCore::EditingBehavior::shouldSmartInsertDeleteParagraphs const):

Only have editing insert paragraphs on iOS and in editing elements that support multiple lines.

* editing/ReplaceSelectionCommand.cpp:
(WebCore::ReplaceSelectionCommand::doApply):
(WebCore::ReplaceSelectionCommand::shouldPerformSmartParagraphReplace const):
(WebCore::ReplaceSelectionCommand::addNewLinesForSmartReplace):
* editing/ReplaceSelectionCommand.h:

Add addititional newlines when pasting full paragraphs to maintian two newlines between paragraphs
if that is what the original document had. If there are not multiple lines between paragraphs, do not
add additional new lines.

LayoutTests:

List tests are covered by paste-list-00*.
Table tests are covered by paste-table-00* and paste-into-table-*.

* editing/pasteboard/smart-paste-paragraph-001-expected.txt: Added.
* editing/pasteboard/smart-paste-paragraph-001.html: Added.
* editing/pasteboard/smart-paste-paragraph-002-expected.txt: Added.
* editing/pasteboard/smart-paste-paragraph-002.html: Added.
* editing/pasteboard/smart-paste-paragraph-003-expected.txt: Added.
* editing/pasteboard/smart-paste-paragraph-003.html: Added.
* editing/pasteboard/smart-paste-paragraph-004-expected.txt: Added.
* editing/pasteboard/smart-paste-paragraph-004.html: Added.
* platform/ios-wk2/editing/pasteboard/paste-text-016-expected.txt:
This needed to be rebaselined to match the new behaviour.
* platform/ios/editing/pasteboard/smart-paste-paragraph-001-expected.txt: Added.
* platform/ios/editing/pasteboard/smart-paste-paragraph-002-expected.txt: Added.
* platform/ios/editing/pasteboard/smart-paste-paragraph-003-expected.txt: Added.
* platform/ios/editing/pasteboard/smart-paste-paragraph-004-expected.txt: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (243123 => 243124)


--- trunk/LayoutTests/ChangeLog	2019-03-19 01:55:13 UTC (rev 243123)
+++ trunk/LayoutTests/ChangeLog	2019-03-19 01:56:39 UTC (rev 243124)
@@ -1,3 +1,28 @@
+2019-03-18  Megan Gardner  <[email protected]>
+
+        Smart Insert for paragraphs.
+        https://bugs.webkit.org/show_bug.cgi?id=194880
+
+        Reviewed by Ryosuke Niwa.
+
+        List tests are covered by paste-list-00*.
+        Table tests are covered by paste-table-00* and paste-into-table-*.
+
+        * editing/pasteboard/smart-paste-paragraph-001-expected.txt: Added.
+        * editing/pasteboard/smart-paste-paragraph-001.html: Added.
+        * editing/pasteboard/smart-paste-paragraph-002-expected.txt: Added.
+        * editing/pasteboard/smart-paste-paragraph-002.html: Added.
+        * editing/pasteboard/smart-paste-paragraph-003-expected.txt: Added.
+        * editing/pasteboard/smart-paste-paragraph-003.html: Added.
+        * editing/pasteboard/smart-paste-paragraph-004-expected.txt: Added.
+        * editing/pasteboard/smart-paste-paragraph-004.html: Added.
+        * platform/ios-wk2/editing/pasteboard/paste-text-016-expected.txt:
+        This needed to be rebaselined to match the new behaviour.
+        * platform/ios/editing/pasteboard/smart-paste-paragraph-001-expected.txt: Added.
+        * platform/ios/editing/pasteboard/smart-paste-paragraph-002-expected.txt: Added.
+        * platform/ios/editing/pasteboard/smart-paste-paragraph-003-expected.txt: Added.
+        * platform/ios/editing/pasteboard/smart-paste-paragraph-004-expected.txt: Added.
+
 2019-03-18  Jer Noble  <[email protected]>
 
         Add experimental "alphaChannel" property to VideoConfiguration

Added: trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-001-expected.txt (0 => 243124)


--- trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-001-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-001-expected.txt	2019-03-19 01:56:39 UTC (rev 243124)
@@ -0,0 +1,28 @@
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 7 of DIV > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document toDOMRange:range from 1 of #text > DIV > DIV > BODY > HTML > #document to 5 of #text > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document givenAction:WebViewInsertActionPasted
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 15 of #text > DIV > DIV > BODY > HTML > #document to 15 of #text > DIV > DIV > BODY > HTML > #document toDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+Tests: 
+Smart paste when pasting a paragraph between two paragraphs.
+Expected Results: 
+A newline should be added between the preexisting paragraphs and the paragraph that's pasted. It should like this: 
+Test paragraph. 
+
+Test paragraph. 
+
+Last test paragraph.
+Test paragraph.
+
+Test paragraph.
+
+Last test paragraph.
+execCopyCommand: <div id="test"> Test paragraph. </div> <div><br></div> <div> Last test paragraph. </div>
+execPasteCommand: <div id="test"> Test paragraph. </div> <div><br></div><div>Test paragraph.<br></div><div><br></div> <div> Last test paragraph. </div>

Added: trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-001.html (0 => 243124)


--- trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-001.html	                        (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-001.html	2019-03-19 01:56:39 UTC (rev 243124)
@@ -0,0 +1,68 @@
+<!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>
+</head> 
+<body>
+<div class="explanation">
+<div class="scenario">
+Tests: 
+<br>
+Smart paste when pasting a paragraph between two paragraphs.
+</div>
+<div class="expected-results">
+Expected Results:
+<br>
+A newline should be added between the preexisting paragraphs and the paragraph that's pasted. It should like this:
+<BR>
+Test paragraph.
+<BR>
+<BR>
+Test paragraph.
+<BR>
+<BR>
+Last test paragraph.
+</div>
+</div>
+
+<div contenteditable id="root" class="editing" style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;">
+<div id="test">
+Test paragraph.
+</div>
+<div><br></div>
+<div>
+Last test paragraph.
+</div>
+</div>
+<script src=""
+<script src=""
+<script>
+
+async function editingTest() {
+    internals.settings.setEditingBehavior("ios");
+    await UIHelper.selectWordByDoubleTapOrClick(document.getElementById('test'));
+    extendSelectionForwardByLineBoundaryCommand();
+    copyCommand();
+    moveSelectionForwardByCharacterCommand();
+    moveSelectionForwardByCharacterCommand();
+    pasteCommand();
+}
+
+runDumpAsTextEditingTest(true);
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-002-expected.txt (0 => 243124)


--- trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-002-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-002-expected.txt	2019-03-19 01:56:39 UTC (rev 243124)
@@ -0,0 +1,28 @@
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of PRE > BODY > HTML > #document to 4 of PRE > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of PRE > BODY > HTML > #document to 0 of PRE > BODY > HTML > #document toDOMRange:range from 0 of #text > SPAN > PRE > BODY > HTML > #document to 4 of #text > SPAN > PRE > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 12 of #text > PRE > BODY > HTML > #document to 12 of #text > PRE > BODY > HTML > #document givenAction:WebViewInsertActionPasted
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 3 of PRE > BODY > HTML > #document to 3 of PRE > BODY > HTML > #document toDOMRange:range from 0 of PRE > PRE > BODY > HTML > #document to 0 of PRE > PRE > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+Tests: 
+Smart paste when pasting a paragraph between two paragraphs in a pre element.
+Expected Results: 
+A space should be added between the preexisting word and the word that's pasted. It should like this: 
+Test paragraph. 
+
+Test paragraph. 
+
+Last test paragraph.
+Test paragraph.
+
+Test paragraph.
+
+Last test paragraph.
+execCopyCommand: <span id="test">Test</span> paragraph. <br>Last test paragraph.
+execPasteCommand: <span id="test">Test</span> paragraph. <pre id="root" class="editing" style="word-wrap: break-word;"><span><br></span></pre><pre id="root" class="editing" style="word-wrap: break-word;"><span id="test">Test</span> paragraph.</pre><pre id="root" class="editing" style="word-wrap: break-word;"><br></pre>Last test paragraph.

Added: trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-002.html (0 => 243124)


--- trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-002.html	                        (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-002.html	2019-03-19 01:56:39 UTC (rev 243124)
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html> 
+<head>
+<style>
+.editing { 
+    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>
+</head> 
+<body>
+<div class="explanation">
+<div class="scenario">
+Tests: 
+<br>
+Smart paste when pasting a paragraph between two paragraphs in a pre element.
+</div>
+<div class="expected-results">
+Expected Results:
+<br>
+A space should be added between the preexisting word and the word that's pasted. It should like this:
+<BR>
+Test paragraph.
+<BR>
+<BR>
+Test paragraph.
+<BR>
+<BR>
+Last test paragraph.
+</div>
+</div>
+
+<pre contenteditable id="root" class="editing" style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;">
+<span id="test">Test</span> paragraph.
+<br>Last test paragraph.
+</pre>
+<script src=""
+<script src=""
+<script>
+
+async function editingTest() {
+    internals.settings.setEditingBehavior("ios");
+    await UIHelper.selectWordByDoubleTapOrClick(document.getElementById('test'));
+    extendSelectionForwardByLineBoundaryCommand();
+    copyCommand();
+    moveSelectionForwardByCharacterCommand();
+    moveSelectionForwardByCharacterCommand();
+    pasteCommand();
+}
+
+runDumpAsTextEditingTest(true);
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-003-expected.txt (0 => 243124)


--- trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-003-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-003-expected.txt	2019-03-19 01:56:39 UTC (rev 243124)
@@ -0,0 +1,24 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 3 of BODY > HTML > #document to 3 of BODY > HTML > #document toDOMRange:range from 0 of DIV > #document-fragment to 0 of DIV > #document-fragment affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > #document-fragment to 0 of DIV > #document-fragment toDOMRange:range from 0 of #text > DIV > #document-fragment to 4 of #text > DIV > #document-fragment affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldInsertText:Test paragraph. replacingDOMRange:range from 16 of #text > DIV > #document-fragment to 16 of #text > DIV > #document-fragment givenAction:WebViewInsertActionPasted
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 32 of #text > DIV > #document-fragment to 32 of #text > DIV > #document-fragment toDOMRange:range from 1 of #text > DIV > #document-fragment to 1 of #text > DIV > #document-fragment affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+Tests: 
+Smart paste when pasting a paragraph between two paragraphs in an input element.
+Expected Results: 
+A newline should be added between the preexisting paragraphs and the paragraph that's pasted. It should like this: 
+Test paragraph. 
+
+Test paragraph. 
+
+Last test paragraph.
+
+

Added: trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-003.html (0 => 243124)


--- trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-003.html	                        (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-003.html	2019-03-19 01:56:39 UTC (rev 243124)
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html> 
+<head>
+<style>
+.editing { 
+    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 }
+textarea {
+    width: 300px;
+    height: 200px;
+}
+</style>
+</head> 
+<body>
+<div class="explanation">
+<div class="scenario">
+Tests: 
+<br>
+Smart paste when pasting a paragraph between two paragraphs in an input element.
+</div>
+<div class="expected-results">
+Expected Results:
+<br>
+A newline should be added between the preexisting paragraphs and the paragraph that's pasted. It should like this:
+<BR>
+Test paragraph.
+<BR>
+<BR>
+Test paragraph.
+<BR>
+<BR>
+Last test paragraph.
+</div>
+</div>
+
+<textarea id="test">
+Test paragraph.
+
+Last test paragraph.</textarea>
+<script src=""
+<script src=""
+<script>
+
+async function editingTest() {
+    internals.settings.setEditingBehavior("ios");
+    await UIHelper.selectWordByDoubleTapOrClick(document.getElementById('test'));
+    extendSelectionForwardByLineBoundaryCommand();
+    copyCommand();
+    moveSelectionForwardByCharacterCommand();
+    moveSelectionForwardByCharacterCommand();
+    pasteCommand();
+}
+
+runDumpAsTextEditingTest(true);
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-004-expected.txt (0 => 243124)


--- trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-004-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-004-expected.txt	2019-03-19 01:56:39 UTC (rev 243124)
@@ -0,0 +1,37 @@
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 7 of DIV > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document toDOMRange:range from 1 of #text > DIV > DIV > BODY > HTML > #document to 5 of #text > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document givenAction:WebViewInsertActionPasted
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 15 of #text > DIV > DIV > BODY > HTML > #document to 15 of #text > DIV > DIV > BODY > HTML > #document toDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document givenAction:WebViewInsertActionPasted
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 15 of #text > DIV > DIV > BODY > HTML > #document to 15 of #text > DIV > DIV > BODY > HTML > #document toDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+Tests: 
+Smart paste when pasting a paragraph between two paragraphs.
+Expected Results: 
+A newline should be added between the preexisting paragraphs and the paragraph that's pasted. This should work with multiple pastes. The caret should end up on the next line, thus allowing another paragraph to be pasted on the next line. It should like this: 
+Test paragraph. 
+
+Test paragraph. 
+
+Test paragraph. 
+
+Last test paragraph.
+Test paragraph.
+
+Test paragraph.
+
+Test paragraph.
+
+Last test paragraph.
+execCopyCommand: <div id="test"> Test paragraph. </div> <div><br></div> <div> Last test paragraph. </div>
+execPasteCommand: <div id="test"> Test paragraph. </div> <div><br></div><div>Test paragraph.<br></div><div><br></div> <div> Last test paragraph. </div>
+execPasteCommand: <div id="test"> Test paragraph. </div> <div><br></div><div>Test paragraph.<br></div><div><br></div><div>Test paragraph.<br></div><div><br></div> <div> Last test paragraph. </div>

Added: trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-004.html (0 => 243124)


--- trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-004.html	                        (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/smart-paste-paragraph-004.html	2019-03-19 01:56:39 UTC (rev 243124)
@@ -0,0 +1,72 @@
+<!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>
+</head> 
+<body>
+<div class="explanation">
+<div class="scenario">
+Tests: 
+<br>
+Smart paste when pasting a paragraph between two paragraphs.
+</div>
+<div class="expected-results">
+Expected Results:
+<br>
+A newline should be added between the preexisting paragraphs and the paragraph that's pasted. This should work with multiple pastes. The caret should end up on the next line, thus allowing another paragraph to be pasted on the next line. It should like this:
+<BR>
+Test paragraph.
+<BR>
+<BR>
+Test paragraph.
+<BR>
+<BR>
+Test paragraph.
+<BR>
+<BR>
+Last test paragraph.
+</div>
+</div>
+
+<div contenteditable id="root" class="editing" style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;">
+<div id="test">
+Test paragraph.
+</div>
+<div><br></div>
+<div>
+Last test paragraph.
+</div>
+</div>
+<script src=""
+<script src=""
+<script>
+
+async function editingTest() {
+    internals.settings.setEditingBehavior("ios");
+    await UIHelper.selectWordByDoubleTapOrClick(document.getElementById('test'));
+    extendSelectionForwardByLineBoundaryCommand();
+    copyCommand();
+    moveSelectionForwardByCharacterCommand();
+    moveSelectionForwardByCharacterCommand();
+    pasteCommand();
+    pasteCommand();
+}
+
+runDumpAsTextEditingTest(true);
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/platform/ios/editing/pasteboard/smart-paste-paragraph-001-expected.txt (0 => 243124)


--- trunk/LayoutTests/platform/ios/editing/pasteboard/smart-paste-paragraph-001-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/ios/editing/pasteboard/smart-paste-paragraph-001-expected.txt	2019-03-19 01:56:39 UTC (rev 243124)
@@ -0,0 +1,29 @@
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 7 of DIV > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document toDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document toDOMRange:range from 1 of #text > DIV > DIV > BODY > HTML > #document to 5 of #text > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document givenAction:WebViewInsertActionPasted
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 15 of #text > DIV > DIV > BODY > HTML > #document to 15 of #text > DIV > DIV > BODY > HTML > #document toDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+Tests: 
+Smart paste when pasting a paragraph between two paragraphs.
+Expected Results: 
+A newline should be added between the preexisting paragraphs and the paragraph that's pasted. It should like this: 
+Test paragraph. 
+
+Test paragraph. 
+
+Last test paragraph.
+Test paragraph.
+
+Test paragraph.
+
+Last test paragraph.
+execCopyCommand: <div id="test"> Test paragraph. </div> <div><br></div> <div> Last test paragraph. </div>
+execPasteCommand: <div id="test"> Test paragraph. </div> <div><br></div><div>Test paragraph.<br></div><div><br></div> <div> Last test paragraph. </div>

Added: trunk/LayoutTests/platform/ios/editing/pasteboard/smart-paste-paragraph-002-expected.txt (0 => 243124)


--- trunk/LayoutTests/platform/ios/editing/pasteboard/smart-paste-paragraph-002-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/ios/editing/pasteboard/smart-paste-paragraph-002-expected.txt	2019-03-19 01:56:39 UTC (rev 243124)
@@ -0,0 +1,29 @@
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of PRE > BODY > HTML > #document to 4 of PRE > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of PRE > BODY > HTML > #document to 0 of PRE > BODY > HTML > #document toDOMRange:range from 0 of PRE > BODY > HTML > #document to 0 of PRE > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of PRE > BODY > HTML > #document to 0 of PRE > BODY > HTML > #document toDOMRange:range from 0 of #text > SPAN > PRE > BODY > HTML > #document to 4 of #text > SPAN > PRE > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 12 of #text > PRE > BODY > HTML > #document to 12 of #text > PRE > BODY > HTML > #document givenAction:WebViewInsertActionPasted
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 3 of PRE > BODY > HTML > #document to 3 of PRE > BODY > HTML > #document toDOMRange:range from 0 of PRE > PRE > BODY > HTML > #document to 0 of PRE > PRE > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+Tests: 
+Smart paste when pasting a paragraph between two paragraphs in a pre element.
+Expected Results: 
+A space should be added between the preexisting word and the word that's pasted. It should like this: 
+Test paragraph. 
+
+Test paragraph. 
+
+Last test paragraph.
+Test paragraph.
+
+Test paragraph.
+
+Last test paragraph.
+execCopyCommand: <span id="test">Test</span> paragraph. <br>Last test paragraph.
+execPasteCommand: <span id="test">Test</span> paragraph. <pre id="root" class="editing" style="word-wrap: break-word;"><span><br></span></pre><pre id="root" class="editing" style="word-wrap: break-word;"><span id="test">Test</span> paragraph.</pre><pre id="root" class="editing" style="word-wrap: break-word;"><br></pre>Last test paragraph.

Added: trunk/LayoutTests/platform/ios/editing/pasteboard/smart-paste-paragraph-003-expected.txt (0 => 243124)


--- trunk/LayoutTests/platform/ios/editing/pasteboard/smart-paste-paragraph-003-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/ios/editing/pasteboard/smart-paste-paragraph-003-expected.txt	2019-03-19 01:56:39 UTC (rev 243124)
@@ -0,0 +1,26 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV > #document-fragment to 0 of DIV > #document-fragment affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > #document-fragment to 0 of DIV > #document-fragment toDOMRange:range from 0 of DIV > #document-fragment to 0 of DIV > #document-fragment affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > #document-fragment to 0 of DIV > #document-fragment toDOMRange:range from 0 of #text > DIV > #document-fragment to 4 of #text > DIV > #document-fragment affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldInsertText:Test paragraph. replacingDOMRange:range from 16 of #text > DIV > #document-fragment to 16 of #text > DIV > #document-fragment givenAction:WebViewInsertActionPasted
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 32 of #text > DIV > #document-fragment to 32 of #text > DIV > #document-fragment toDOMRange:range from 1 of #text > DIV > #document-fragment to 1 of #text > DIV > #document-fragment affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+Tests: 
+Smart paste when pasting a paragraph between two paragraphs in an input element.
+Expected Results: 
+A newline should be added between the preexisting paragraphs and the paragraph that's pasted. It should like this: 
+Test paragraph. 
+
+Test paragraph. 
+
+Last test paragraph.
+
+

Added: trunk/LayoutTests/platform/ios/editing/pasteboard/smart-paste-paragraph-004-expected.txt (0 => 243124)


--- trunk/LayoutTests/platform/ios/editing/pasteboard/smart-paste-paragraph-004-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/ios/editing/pasteboard/smart-paste-paragraph-004-expected.txt	2019-03-19 01:56:39 UTC (rev 243124)
@@ -0,0 +1,38 @@
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 7 of DIV > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document toDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document toDOMRange:range from 1 of #text > DIV > DIV > BODY > HTML > #document to 5 of #text > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document givenAction:WebViewInsertActionPasted
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 15 of #text > DIV > DIV > BODY > HTML > #document to 15 of #text > DIV > DIV > BODY > HTML > #document toDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document givenAction:WebViewInsertActionPasted
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 15 of #text > DIV > DIV > BODY > HTML > #document to 15 of #text > DIV > DIV > BODY > HTML > #document toDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+Tests: 
+Smart paste when pasting a paragraph between two paragraphs.
+Expected Results: 
+A newline should be added between the preexisting paragraphs and the paragraph that's pasted. This should work with multiple pastes. The caret should end up on the next line, thus allowing another paragraph to be pasted on the next line. It should like this: 
+Test paragraph. 
+
+Test paragraph. 
+
+Test paragraph. 
+
+Last test paragraph.
+Test paragraph.
+
+Test paragraph.
+
+Test paragraph.
+
+Last test paragraph.
+execCopyCommand: <div id="test"> Test paragraph. </div> <div><br></div> <div> Last test paragraph. </div>
+execPasteCommand: <div id="test"> Test paragraph. </div> <div><br></div><div>Test paragraph.<br></div><div><br></div> <div> Last test paragraph. </div>
+execPasteCommand: <div id="test"> Test paragraph. </div> <div><br></div><div>Test paragraph.<br></div><div><br></div><div>Test paragraph.<br></div><div><br></div> <div> Last test paragraph. </div>

Modified: trunk/LayoutTests/platform/ios-wk2/editing/pasteboard/paste-text-016-expected.txt (243123 => 243124)


--- trunk/LayoutTests/platform/ios-wk2/editing/pasteboard/paste-text-016-expected.txt	2019-03-19 01:55:13 UTC (rev 243123)
+++ trunk/LayoutTests/platform/ios-wk2/editing/pasteboard/paste-text-016-expected.txt	2019-03-19 01:56:39 UTC (rev 243124)
@@ -38,28 +38,30 @@
         RenderText {#text} at (0,20) size 384x19
           text run at (0,20) width 384: "***TEST*** line should be second, following the first line."
       RenderBlock {DIV} at (0,40) size 784x12
-      RenderBlock {DIV} at (0,52) size 784x238
-        RenderBlock {DIV} at (0,0) size 784x238 [border: (2px solid #FF0000)]
+      RenderBlock {DIV} at (0,52) size 784x268
+        RenderBlock {DIV} at (0,0) size 784x268 [border: (2px solid #FF0000)]
           RenderBlock {P} at (14,14) size 756x30
             RenderText {#text} at (0,1) size 316x28
               text run at (0,1) width 316: "Should be first line of document."
             RenderBR {BR} at (315,23) size 1x0
           RenderBlock {P} at (14,44) size 756x30
+            RenderBR {BR} at (0,1) size 0x28
+          RenderBlock {P} at (14,74) size 756x30
             RenderText {#text} at (0,1) size 130x28
               text run at (0,1) width 130: "***TEST***"
-          RenderBlock {DIV} at (14,74) size 756x30
+          RenderBlock {DIV} at (14,104) size 756x30
             RenderBR {BR} at (0,1) size 0x28
-          RenderBlock {P} at (14,104) size 756x30
+          RenderBlock {P} at (14,134) size 756x30
             RenderText {#text} at (0,1) size 127x28
               text run at (0,1) width 127: "Another line."
-          RenderBlock {P} at (14,134) size 756x0
-          RenderBlock (anonymous) at (14,134) size 756x30
-            RenderText {#text} at (0,1) size 6x28
-              text run at (0,1) width 6: " "
           RenderBlock {P} at (14,164) size 756x0
           RenderBlock (anonymous) at (14,164) size 756x30
             RenderText {#text} at (0,1) size 6x28
               text run at (0,1) width 6: " "
-          RenderBlock {P} at (14,194) size 756x30
+          RenderBlock {P} at (14,194) size 756x0
+          RenderBlock (anonymous) at (14,194) size 756x30
+            RenderText {#text} at (0,1) size 6x28
+              text run at (0,1) width 6: " "
+          RenderBlock {P} at (14,224) size 756x30
             RenderBR {BR} at (0,1) size 0x28
-caret: position 0 of child 0 {BR} of child 2 {DIV} of child 1 {DIV} of child 7 {DIV} of body
+caret: position 0 of child 0 {BR} of child 3 {DIV} of child 1 {DIV} of child 7 {DIV} of body

Modified: trunk/Source/WebCore/ChangeLog (243123 => 243124)


--- trunk/Source/WebCore/ChangeLog	2019-03-19 01:55:13 UTC (rev 243123)
+++ trunk/Source/WebCore/ChangeLog	2019-03-19 01:56:39 UTC (rev 243124)
@@ -1,3 +1,40 @@
+2019-03-18  Megan Gardner  <[email protected]>
+
+        Smart Insert for paragraphs.
+        https://bugs.webkit.org/show_bug.cgi?id=194880
+
+        Reviewed by Ryosuke Niwa.
+
+        Add additional newlines to maintain spacing around paragraphs.
+
+        Tests: editing/pasteboard/smart-paste-paragraph-001.html
+               editing/pasteboard/smart-paste-paragraph-002.html
+               editing/pasteboard/smart-paste-paragraph-003.html
+               editing/pasteboard/smart-paste-paragraph-004.html
+
+        * dom/Document.cpp:
+        (WebCore::Document::editingBehavior const):
+        * dom/Document.h:
+
+        Expose editing behaviour through document so that is can be access from the selection commands
+        and allow the editing behaviour to be used.
+
+        * editing/CompositeEditCommand.h:
+        * editing/EditingBehavior.h:
+        (WebCore::EditingBehavior::shouldSmartInsertDeleteParagraphs const):
+
+        Only have editing insert paragraphs on iOS and in editing elements that support multiple lines.
+
+        * editing/ReplaceSelectionCommand.cpp:
+        (WebCore::ReplaceSelectionCommand::doApply):
+        (WebCore::ReplaceSelectionCommand::shouldPerformSmartParagraphReplace const):
+        (WebCore::ReplaceSelectionCommand::addNewLinesForSmartReplace):
+        * editing/ReplaceSelectionCommand.h:
+
+        Add addititional newlines when pasting full paragraphs to maintian two newlines between paragraphs
+        if that is what the original document had. If there are not multiple lines between paragraphs, do not
+        add additional new lines.
+
 2019-03-18  Ryosuke Niwa  <[email protected]>
 
         Reduce the size of Node::deref by eliminating an explicit parentNode check

Modified: trunk/Source/WebCore/dom/Document.cpp (243123 => 243124)


--- trunk/Source/WebCore/dom/Document.cpp	2019-03-19 01:55:13 UTC (rev 243123)
+++ trunk/Source/WebCore/dom/Document.cpp	2019-03-19 01:56:39 UTC (rev 243124)
@@ -7430,6 +7430,11 @@
     updateStyleIfNeeded();
     return fontSelector().fontFaceSet();
 }
+    
+EditingBehavior Document::editingBehavior() const
+{
+    return EditingBehavior { settings().editingBehaviorType() };
+}
 
 float Document::deviceScaleFactor() const
 {

Modified: trunk/Source/WebCore/dom/Document.h (243123 => 243124)


--- trunk/Source/WebCore/dom/Document.h	2019-03-19 01:55:13 UTC (rev 243123)
+++ trunk/Source/WebCore/dom/Document.h	2019-03-19 01:56:39 UTC (rev 243124)
@@ -116,6 +116,7 @@
 class DocumentSharedObjectPool;
 class DocumentTimeline;
 class DocumentType;
+class EditingBehavior;
 class ExtensionStyleSheets;
 class FloatQuad;
 class FloatRect;
@@ -562,6 +563,7 @@
     WEBCORE_EXPORT Page* page() const; // Can be null.
     const Settings& settings() const { return m_settings.get(); }
     Settings& mutableSettings() { return m_settings.get(); }
+    EditingBehavior editingBehavior() const;
 
     const Quirks& quirks() const { return m_quirks; }
 

Modified: trunk/Source/WebCore/editing/CompositeEditCommand.h (243123 => 243124)


--- trunk/Source/WebCore/editing/CompositeEditCommand.h	2019-03-19 01:55:13 UTC (rev 243123)
+++ trunk/Source/WebCore/editing/CompositeEditCommand.h	2019-03-19 01:56:39 UTC (rev 243124)
@@ -152,6 +152,7 @@
     void insertNodeAt(Ref<Node>&&, const Position&);
     void insertNodeAtTabSpanPosition(Ref<Node>&&, const Position&);
     void insertNodeBefore(Ref<Node>&&, Node& refChild, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable);
+    void insertParagraphSeparatorAtPosition(const Position&, bool useDefaultParagraphElement = false, bool pasteBlockqutoeIntoUnquotedArea = false);
     void insertParagraphSeparator(bool useDefaultParagraphElement = false, bool pasteBlockqutoeIntoUnquotedArea = false);
     void insertLineBreak();
     void insertTextIntoNode(Text&, unsigned offset, const String& text);

Modified: trunk/Source/WebCore/editing/EditingBehavior.h (243123 => 243124)


--- trunk/Source/WebCore/editing/EditingBehavior.h	2019-03-19 01:55:13 UTC (rev 243123)
+++ trunk/Source/WebCore/editing/EditingBehavior.h	2019-03-19 01:56:39 UTC (rev 243124)
@@ -98,6 +98,9 @@
     
     // On iOS, when smart delete is on, it is always on, and should do not additional checks (i.e. WordGranularity).
     bool shouldAlwaysSmartDelete() const { return m_type == EditingIOSBehavior; }
+    
+    // On iOS, we should turn on smart insert and delete and newlines around paragraphs to match UIKit behaviour.
+    bool shouldSmartInsertDeleteParagraphs() const { return m_type == EditingIOSBehavior; }
 
 private:
     EditingBehaviorType m_type;

Modified: trunk/Source/WebCore/editing/ReplaceSelectionCommand.cpp (243123 => 243124)


--- trunk/Source/WebCore/editing/ReplaceSelectionCommand.cpp	2019-03-19 01:55:13 UTC (rev 243123)
+++ trunk/Source/WebCore/editing/ReplaceSelectionCommand.cpp	2019-03-19 01:56:39 UTC (rev 243124)
@@ -777,6 +777,11 @@
     fragment.removeNodePreservingChildren(*wrappingStyleSpan);
     return true;
 }
+    
+static bool isBlankLine(VisiblePosition& position)
+{
+    return isStartOfLine(position) && startOfLine(position.next()) != startOfLine(position);
+}
 
 // At copy time, WebKit wraps copied content in a span that contains the source document's 
 // default styles.  If the copied Range inherits any other styles from its ancestors, we put 
@@ -924,6 +929,18 @@
     m_documentFragmentHTMLMarkup = serializeFragment(*m_documentFragment, SerializedNodes::SubtreeIncludingNode);
     return CompositeEditCommand::willApplyCommand();
 }
+    
+static bool hasBlankLineBetweenParagraphs(Position& position)
+{
+    bool reachedBoundaryStart = false;
+    bool reachedBoundaryEnd = false;
+    VisiblePosition visiblePosition(position);
+    VisiblePosition previousPosition = visiblePosition.previous(CannotCrossEditingBoundary, &reachedBoundaryStart);
+    VisiblePosition nextPosition = visiblePosition.next(CannotCrossEditingBoundary, &reachedBoundaryStart);
+    bool hasLineBeforePosition = isEndOfLine(previousPosition);
+    
+    return !reachedBoundaryStart && !reachedBoundaryEnd && isBlankLine(visiblePosition) && hasLineBeforePosition && isStartOfLine(nextPosition);
+}
 
 void ReplaceSelectionCommand::doApply()
 {
@@ -1069,6 +1086,8 @@
     // Paste into run of tabs splits the tab span.
     insertionPos = positionOutsideTabSpan(insertionPos);
 
+    bool hasBlankLinesBetweenParagraphs = hasBlankLineBetweenParagraphs(insertionPos);
+    
     bool handledStyleSpans = handleStyleSpansBeforeInsertion(fragment, insertionPos);
 
     // We're finished if there is nothing to add.
@@ -1120,8 +1139,9 @@
         fragment.removeNode(*refNode);
 
     Node* blockStart = enclosingBlock(insertionPos.deprecatedNode());
-    if ((isListHTMLElement(refNode.get()) || (isLegacyAppleStyleSpan(refNode.get()) && isListHTMLElement(refNode->firstChild())))
-        && blockStart && blockStart->renderer()->isListItem())
+    bool isInsertingIntoList = (isListHTMLElement(refNode.get()) || (isLegacyAppleStyleSpan(refNode.get()) && isListHTMLElement(refNode->firstChild())))
+    && blockStart && blockStart->renderer()->isListItem();
+    if (isInsertingIntoList)
         refNode = insertAsListItems(downcast<HTMLElement>(*refNode), blockStart, insertionPos, insertedNodes);
     else {
         insertNodeAt(*refNode, insertionPos);
@@ -1270,6 +1290,9 @@
     if (shouldPerformSmartReplace())
         addSpacesForSmartReplace();
 
+    if (!isInsertingIntoList && hasBlankLinesBetweenParagraphs && shouldPerformSmartParagraphReplace())
+        addNewLinesForSmartReplace();
+
     // If we are dealing with a fragment created from plain text
     // no style matching is necessary.
     if (plainTextFragment)
@@ -1325,12 +1348,63 @@
 
     return true;
 }
+    
+bool ReplaceSelectionCommand::shouldPerformSmartParagraphReplace() const
+{
+    if (!m_smartReplace)
+        return false;
 
+    if (!document().editingBehavior().shouldSmartInsertDeleteParagraphs())
+        return false;
+
+    return true;
+}
+
 static bool isCharacterSmartReplaceExemptConsideringNonBreakingSpace(UChar32 character, bool previousCharacter)
 {
     return isCharacterSmartReplaceExempt(character == noBreakSpace ? ' ' : character, previousCharacter);
 }
 
+void ReplaceSelectionCommand::addNewLinesForSmartReplace()
+{
+    VisiblePosition startOfInsertedContent = positionAtStartOfInsertedContent();
+    VisiblePosition endOfInsertedContent = positionAtEndOfInsertedContent();
+
+    bool isPastedContentEntireParagraphs = isStartOfParagraph(startOfInsertedContent) && isEndOfParagraph(endOfInsertedContent);
+
+    // If we aren't pasting a paragraph, no need to attempt to insert newlines.
+    if (!isPastedContentEntireParagraphs)
+        return;
+
+    bool reachedBoundaryStart = false;
+    bool reachedBoundaryEnd = false;
+    VisiblePosition positionBeforeStart = startOfInsertedContent.previous(CannotCrossEditingBoundary, &reachedBoundaryStart);
+    VisiblePosition positionAfterEnd = endOfInsertedContent.next(CannotCrossEditingBoundary, &reachedBoundaryEnd);
+
+    if (!reachedBoundaryStart && !reachedBoundaryEnd) {
+        if (!isBlankLine(positionBeforeStart) && !isBlankLine(startOfInsertedContent) && isEndOfLine(positionBeforeStart) && !isEndOfEditableOrNonEditableContent(positionAfterEnd) && !isEndOfEditableOrNonEditableContent(endOfInsertedContent)) {
+            setEndingSelection(startOfInsertedContent);
+            insertParagraphSeparator();
+            auto newStart = endingSelection().visibleStart().previous(CannotCrossEditingBoundary, &reachedBoundaryStart);
+            if (!reachedBoundaryStart)
+                m_startOfInsertedContent = newStart.deepEquivalent();
+        }
+    }
+
+    reachedBoundaryStart = false;
+    reachedBoundaryEnd = false;
+    positionAfterEnd = endOfInsertedContent.next(CannotCrossEditingBoundary, &reachedBoundaryEnd);
+    positionBeforeStart = startOfInsertedContent.previous(CannotCrossEditingBoundary, &reachedBoundaryStart);
+
+    if (!reachedBoundaryEnd && !reachedBoundaryStart) {
+        if (!isBlankLine(positionAfterEnd) && !isBlankLine(endOfInsertedContent) && isStartOfLine(positionAfterEnd) && !isEndOfLine(positionAfterEnd) && !isEndOfEditableOrNonEditableContent(positionAfterEnd)) {
+            setEndingSelection(endOfInsertedContent);
+            insertParagraphSeparator();
+            m_endOfInsertedContent = endingSelection().start();
+        }
+    }
+}
+
 void ReplaceSelectionCommand::addSpacesForSmartReplace()
 {
     VisiblePosition startOfInsertedContent = positionAtStartOfInsertedContent();

Modified: trunk/Source/WebCore/editing/ReplaceSelectionCommand.h (243123 => 243124)


--- trunk/Source/WebCore/editing/ReplaceSelectionCommand.h	2019-03-19 01:55:13 UTC (rev 243123)
+++ trunk/Source/WebCore/editing/ReplaceSelectionCommand.h	2019-03-19 01:56:39 UTC (rev 243124)
@@ -108,7 +108,9 @@
     VisiblePosition positionAtEndOfInsertedContent() const;
 
     bool shouldPerformSmartReplace() const;
+    bool shouldPerformSmartParagraphReplace() const;
     void addSpacesForSmartReplace();
+    void addNewLinesForSmartReplace();
     void completeHTMLReplacement(const Position& lastPositionToSelect);
     void mergeTextNodesAroundPosition(Position&, Position& positionOnlyToBeUpdated);
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to