More refactoring
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Wed, 18 May 2011 13:03:04 -0600
changeset 142 8773fac2c993
parent 141 5dd7f3cb4cc6
child 143 e5f970cd0727
More refactoring
editcommands.html
implementation.js
source.html
--- a/editcommands.html	Tue May 17 15:06:07 2011 -0600
+++ b/editcommands.html	Wed May 18 13:03:04 2011 -0600
@@ -27,7 +27,7 @@
 <body class=draft>
 <div class=head id=head>
 <h1>HTML Editing Commands</h1>
-<h2 class="no-num no-toc" id=work-in-progress-&mdash;-last-update-17-may-2011>Work in Progress &mdash; Last Update 17 May 2011</h2>
+<h2 class="no-num no-toc" id=work-in-progress-&mdash;-last-update-18-may-2011>Work in Progress &mdash; Last Update 18 May 2011</h2>
 <dl>
  <dt>Editor
  <dd>Aryeh Gregor &lt;ayg+spec@aryeh.name&gt;
@@ -247,37 +247,8 @@
 </ol>
 
 <p>To remove a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> <var title="">node</var> while <dfn id=preserving-its-descendants>preserving its
-descendants</dfn>:
-
-<ol>
-  <li>Let <var title="">children</var> be a list of <var title="">node</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>children</a>.
-
-  <li>If <var title="">node</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is null, remove all of <var title="">node</var>'s
-  <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>children</a> from <var title="">node</var>, then return <var title="">children</var>.
-
-  <li><a href=#remove-extraneous-line-breaks>Remove extraneous line breaks</a> from <var title="">node</var>.
-
-  <li>If <var title="">node</var> is not an <a href=#inline-node>inline node</a>, and its first
-  <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> and <code class=external data-anolis-spec=domcore title=dom-Node-previousSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-previoussibling>previousSibling</a></code> are both <a href=#inline-node title="inline node">inline
-  nodes</a>, and the first <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">node</var> is not a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>,
-  call <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement("br")</a></code> on the
-  <code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">node</var>, and insert the result into
-  <var title="">node</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> immediately before <var title="">node</var>.
-
-  <li>While <var title="">node</var> has <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>children</a>, insert the first <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of
-  <var title="">node</var> into <var title="">node</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> immediately before
-  <var title="">node</var>, <a href=#preserving-ranges>preserving ranges</a>.
-
-  <li>If <var title="">node</var> is not an <a href=#inline-node>inline node</a>, and its
-  <code class=external data-anolis-spec=domcore title=dom-Node-previousSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-previoussibling>previousSibling</a></code> and <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> are both <a href=#inline-node title="inline
-  node">inline nodes</a> but neither is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, call <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement("br")</a></code> on the
-  <code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">node</var>, and insert the result into
-  <var title="">node</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> immediately before <var title="">node</var>.
-
-  <li>Remove <var title="">node</var> from its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
-
-  <li>Return <var title="">children</var>.
-</ol>
+descendants</dfn>, <a href=#split-the-parent>split the parent</a> of <var title="">node</var>'s
+<a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>children</a>.
 
 <p>To <dfn id=split-the-parent>split the parent</dfn> of a list <var title="">node list</var> of consecutive
 <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-sibling title=concept-tree-sibling>sibling</a> <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>nodes</a>:
@@ -289,9 +260,26 @@
   <li>If <var title="">original parent</var> is not <a href=#editable>editable</a> or its
   <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is null, do nothing and abort these steps.
 
-  <li>If the <code class=external data-anolis-spec=domcore title=dom-Node-previousSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-previoussibling>previousSibling</a></code> of the first member of <var title="">node list</var> is
-  not null, and the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of the last member of <var title="">node list</var>
-  is null:
+  <li>If the first <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">original parent</var> is in <var title="">node
+  list</var>, <a href=#remove-extraneous-line-breaks-before>remove extraneous line breaks before</a> <var title="">original
+  parent</var>.
+
+  <li>If the last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">original parent</var> is in <var title="">node
+  list</var>:
+
+  <ol>
+    <li><a href=#remove-extraneous-line-breaks-after>Remove extraneous line breaks after</a> <var title="">original
+    parent</var>.
+
+    <li>If <var title="">original parent</var>'s last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> and <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> are
+    both <a href=#inline-node title="inline node">inline nodes</a>, call <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement("br")</a></code> on the
+    <code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">original parent</var>, then insert the result
+    into the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">original parent</var> immediately after
+    <var title="">original parent</var>.
+  </ol>
+
+  <li>If the first <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">original parent</var> is not in <var title="">node
+  list</var>, but its last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> is:
 
   <div class=XXX>
   <p>We insert things after the parent.  This is bad, because it will cause
@@ -314,13 +302,6 @@
   </div>
 
   <ol>
-    <li>If the last member of <var title="">node list</var> and the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of
-    <var title="">original parent</var> are both <a href=#inline-node title="inline node">inline
-    nodes</a>, call <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement("br")</a></code> on the
-    <code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">original parent</var>, then insert the result
-    into the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">original parent</var> immediately after
-    <var title="">original parent</var>.
-
     <li>For each <var title="">node</var> in <var title="">node list</var>, <em>in reverse
     order</em>, insert <var title="">node</var> into the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">original
     parent</var> immediately after <var title="">original parent</var>, <a href=#preserving-ranges>preserving
@@ -329,8 +310,8 @@
     <li>Abort these steps.
   </ol>
 
-  <li>If the <code class=external data-anolis-spec=domcore title=dom-Node-previousSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-previoussibling>previousSibling</a></code> of the first member of <var title="">node list</var> is
-  not null:
+  <li>If the first <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">original parent</var> is not in <var title="">node
+  list</var>:
 
   <ol>
     <li>Let <var title="">cloned parent</var> be the result of calling <code class=external data-anolis-spec=domcore title=dom-Node-cloneNode><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-clonenode>cloneNode(false)</a></code>
@@ -362,6 +343,9 @@
   <li>For each <var title="">node</var> in <var title="">node list</var>, insert <var title="">node</var>
   into the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">original parent</var> immediately before
   <var title="">original parent</var>, <a href=#preserving-ranges>preserving ranges</a>.
+
+  <li>If <var title="">original parent</var> has no <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>children</a>, remove it from its
+  <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
 </ol>
 
 <p>To <dfn id=wrap>wrap</dfn> a list <var title="">node list</var> of consecutive <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-sibling title=concept-tree-sibling>sibling</a>
@@ -372,65 +356,57 @@
   <li>If <var title="">node list</var> is empty, or the first member of <var title="">node
   list</var> is not <a href=#editable>editable</a>, return null and abort these steps.
 
-  <li>Let <var title="">original parent</var> be the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of the first member of
-  <var title="">node list</var>.
-
   <li>If the <code class=external data-anolis-spec=domcore title=dom-Node-previousSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-previoussibling>previousSibling</a></code> of the first member of <var title="">node list</var>
-  is <a href=#editable>editable</a> and meets the <a href=#sibling-criteria>sibling criteria</a>:
-
-  <ol>
-    <li>For each <var title="">node</var> in <var title="">node list</var>, append
-    <var title="">node</var> as the last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of its <code class=external data-anolis-spec=domcore title=dom-Node-previousSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-previoussibling>previousSibling</a></code>,
-    <a href=#preserving-ranges>preserving ranges</a>.
-
-    <li>If <var title="">original parent</var> is <a href=#editable>editable</a> and has no
-    <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>children</a>, remove it from its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
-
-    <li>Return the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of the first member of <var title="">node list</var> and
-    abort these steps.
-  </ol>
-
-  <li>If the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of the last member of <var title="">node list</var> is
-  <a href=#editable>editable</a> and meets the <a href=#sibling-criteria>sibling criteria</a>:
+  is <a href=#editable>editable</a> and meets the <a href=#sibling-criteria>sibling criteria</a>, let
+  <var title="">new parent</var> be the <code class=external data-anolis-spec=domcore title=dom-Node-previousSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-previoussibling>previousSibling</a></code> of the first member of
+  <var title="">node list</var>.
+
+  <li>Otherwise, if the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of the last member of <var title="">node
+  list</var> is <a href=#editable>editable</a> and meets the <a href=#sibling-criteria>sibling
+  criteria</a>, let <var title="">new parent</var> be the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of the last
+  member of <var title="">node list</var>.
+
+  <li>Otherwise, run the <a href=#new-parent-instructions>new parent instructions</a>, and let <var title="">new
+  parent</var> be the result.
+
+  <li>If <var title="">new parent</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is null:
 
   <ol>
-    <li>For each <var title="">node</var> in <var title="">node list</var>, <em>in reverse
-    order</em>, insert <var title="">node</var> as the first <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of its
-    <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code>, <a href=#preserving-ranges>preserving ranges</a>.
-
-    <li>If <var title="">original parent</var> is <a href=#editable>editable</a> and has no
-    <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>children</a>, remove it from its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
-
-    <li>Return the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of the first member of <var title="">node list</var> and
-    abort these steps.
+    <li>If <var title="">new parent</var> cannot be the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of
+    the first member of <var title="">node list</var>, <a href=#split-the-parent>split the parent</a> of
+    <var title="">node list</var>.
+
+    <p class=XXX>"Cannot be the child" needs to be defined.
+
+    <li>Insert <var title="">new parent</var> into the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of the first member of
+    <var title="">node list</var> immediately before the first member of <var title="">node
+    list</var>.
   </ol>
 
-  <li>Run the <a href=#new-parent-instructions>new parent instructions</a>, and let <var title="">new
-  parent</var> be the result.
-
-  <li>If <var title="">new parent</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is null, and <var title="">new parent</var>
-  cannot be the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of the first member of <var title="">node
-  list</var>, <a href=#split-the-parent>split the parent</a> of <var title="">node list</var>.
-
-  <p class=XXX>"Cannot be the child" needs to be defined.
-
-  <li>If <var title="">new parent</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is null, insert <var title="">new
-  parent</var> into the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of the first member of <var title="">node list</var>
-  immediately before the first member of <var title="">node list</var>.
-
-  <li>For each <var title="">node</var> in <var title="">node list</var>, append <var title="">node</var>
-  as the last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">new parent</var>, <a href=#preserving-ranges>preserving
-  ranges</a>.
+  <li>Let <var title="">original parent</var> be the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of the first member of
+  <var title="">node list</var>.
+
+  <li>If <var title="">new parent</var> is before the first member of <var title="">node
+  list</var> in <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#tree-order>tree order</a>, then for each <var title="">node</var> in <var title="">node
+  list</var>, append <var title="">node</var> as the last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">new
+  parent</var>, <a href=#preserving-ranges>preserving ranges</a>.
+
+  <li>Otherwise, for each <var title="">node</var> in <var title="">node list</var>, <em>in
+  reverse order</em>, insert <var title="">node</var> as the first <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">new
+  parent</var>, <a href=#preserving-ranges>preserving ranges</a>.
+
+  <li><a href=#remove-extraneous-line-breaks-from>Remove extraneous line breaks from</a> <var title="">new parent</var>.
 
   <li>If <var title="">original parent</var> is <a href=#editable>editable</a> and has no
   <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>children</a>, remove it from its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
-
-  <li><a href=#remove-extraneous-line-breaks>Remove extraneous line breaks</a> from <var title="">new parent</var>.
+  <!-- This could happen if the new parent instructions returned a node whose
+  parent wasn't null. -->
 
   <li>Return <var title="">new parent</var>.
 </ol>
 
-<p>To <dfn id=remove-extraneous-line-breaks>remove extraneous line breaks</dfn> from a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> <var title="">node</var>:
+<p>To <dfn id=remove-extraneous-line-breaks-before>remove extraneous line breaks before</dfn> a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a>
+<var title="">node</var>:
 
 <ol>
   <li>If <var title="">node</var> is not an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>, or it is an <a href=#inline-node>inline
@@ -440,6 +416,14 @@
   <code class=external data-anolis-spec=domcore title=dom-Node-previousSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-previoussibling>previousSibling</a></code> of the <code class=external data-anolis-spec=domcore title=dom-Node-previousSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-previoussibling>previousSibling</a></code> of <var title="">node</var> is an
   <a href=#inline-node>inline node</a> that is not a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, remove the <code class=external data-anolis-spec=domcore title=dom-Node-previousSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-previoussibling>previousSibling</a></code>
   of <var title="">node</var> from its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+</ol>
+
+<p>To <dfn id=remove-extraneous-line-breaks-after>remove extraneous line breaks after</dfn> a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a>
+<var title="">node</var>:
+
+<ol>
+  <li>If <var title="">node</var> is not an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>, or it is an <a href=#inline-node>inline
+  node</a>, do nothing and abort these steps.
 
   <li>If <var title="">node</var> has at least two <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>children</a>, and its last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a>
   is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, and its second-to-last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> is an <a href=#inline-node>inline node</a>
@@ -447,6 +431,10 @@
   <var title="">node</var>.
 </ol>
 
+<p>To <dfn id=remove-extraneous-line-breaks-from>remove extraneous line breaks from</dfn> a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a>, first
+<a href=#remove-extraneous-line-breaks-before>remove extraneous line breaks before</a> it, then <a href=#remove-extraneous-line-breaks-after>remove
+extraneous line breaks after</a> it.
+
 <p>An <dfn id=editing-host>editing host</dfn> is a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> that is either an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code> with
 a <code class=external data-anolis-spec=html title=attr-contenteditable><a href=http://www.whatwg.org/html/#attr-contenteditable>contenteditable</a></code>
 attribute set to the true state, or a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#document>Document</a></code> whose <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/html/#designmode>designMode</a></code> is enabled.
--- a/implementation.js	Tue May 17 15:06:07 2011 -0600
+++ b/implementation.js	Wed May 18 13:03:04 2011 -0600
@@ -57,6 +57,20 @@
 	return isAncestor(ancestor, descendant);
 }
 
+/**
+ * Returns true if node1 is before node2 in tree order, false otherwise.
+ */
+function isBefore(node1, node2) {
+	return Boolean(node1.compareDocumentPosition(node2) & Node.DOCUMENT_POSITION_FOLLOWING);
+}
+
+/**
+ * Returns true if node1 is after node2 in tree order, false otherwise.
+ */
+function isAfter(node1, node2) {
+	return Boolean(node1.compareDocumentPosition(node2) & Node.DOCUMENT_POSITION_PRECEDING);
+}
+
 function convertProperty(property) {
 	// Special-case for now
 	var map = {
@@ -387,56 +401,10 @@
 	return replacementElement;
 }
 
+// "To remove a node node while preserving its descendants, split the parent of
+// node's children."
 function removePreservingDescendants(node) {
-	// "Let children be a list of node's children."
-	var children = [].slice.call(node.childNodes);
-
-	// "If node's parent is null, remove all of node's children from node, then
-	// return children."
-	if (!node.parentNode) {
-		while (node.hasChildNodes()) {
-			node.removeChild(node.firstChild);
-		}
-		return children;
-	}
-
-	// "Remove extraneous line breaks from node."
-	removeExtraneousLineBreaks(node);
-
-	// "If node is not an inline node, and its first child and previousSibling
-	// are both inline nodes, and the first child of node is not a br, call
-	// createElement("br") on the ownerDocument of node, and insert the result
-	// into node's parent immediately before node."
-	if (!isInlineNode(node)
-	&& isInlineNode(node.firstChild)
-	&& isInlineNode(node.previousSibling)
-	&& !isHtmlElement(node.firstChild, "BR")) {
-		node.parentNode.insertBefore(node.ownerDocument.createElement("br"), node);
-	}
-
-	// "While node has children, insert the first child of node into node's
-	// parent immediately before node, preserving ranges."
-	while (node.hasChildNodes()) {
-		movePreservingRanges(node.firstChild, node.parentNode, getNodeIndex(node));
-	}
-
-	// "If node is not an inline node, and its previousSibling and nextSibling
-	// are both inline nodes but neither is a br, call createElement("br") on
-	// the ownerDocument of node, and insert the result into node's parent
-	// immediately before node."
-	if (!isInlineNode(node)
-	&& isInlineNode(node.previousSibling)
-	&& isInlineNode(node.nextSibling)
-	&& !isHtmlElement(node.previousSibling, "BR")
-	&& !isHtmlElement(node.nextSibling, "BR")) {
-		node.parentNode.insertBefore(node.ownerDocument.createElement("br"), node);
-	}
-
-	// "Remove node from its parent."
-	node.parentNode.removeChild(node);
-
-	// "Return children."
-	return children;
+	splitParent([].slice.call(node.childNodes));
 }
 
 function splitParent(nodeList) {
@@ -450,19 +418,31 @@
 		return;
 	}
 
-	// "If the previousSibling of the first member of node list is not null,
-	// and the nextSibling of the last member of node list is null:"
-	if (nodeList[0].previousSibling
-	&& !nodeList[nodeList.length - 1].nextSibling) {
-		// "If the last member of node list and the nextSibling of original
-		// parent are both inline nodes, call createElement("br") on the
-		// ownerDocument of original parent, then insert the result into the
-		// parent of original parent immediately after original parent."
-		if (isInlineNode(nodeList[nodeList.length - 1])
+	// "If the first child of original parent is in node list, remove
+	// extraneous line breaks before original parent."
+	if (nodeList.indexOf(originalParent.firstChild) != -1) {
+		removeExtraneousLineBreaksBefore(originalParent);
+	}
+
+	// "If the last child of original parent is in node list:"
+	if (nodeList.indexOf(originalParent.lastChild) != -1) {
+		// "Remove extraneous line breaks after original parent."
+		removeExtraneousLineBreaksAfter(originalParent);
+
+		// "If original parent's last child and nextSibling are both inline
+		// nodes, call createElement("br") on the ownerDocument of original
+		// parent, then insert the result into the parent of original parent
+		// immediately after original parent."
+		if (isInlineNode(originalParent.lastChild)
 		&& isInlineNode(originalParent.nextSibling)) {
 			originalParent.parentNode.insertBefore(originalParent.ownerDocument.createElement("br"), originalParent.nextSibling);
 		}
-
+	}
+
+	// "If the first child of original parent is not in node list, but its last
+	// child is:"
+	if (nodeList.indexOf(originalParent.firstChild) == -1
+	&& nodeList.indexOf(originalParent.lastChild) != -1) {
 		// "For each node in node list, in reverse order, insert node into the
 		// parent of original parent immediately after original parent,
 		// preserving ranges."
@@ -474,8 +454,8 @@
 		return;
 	}
 
-	// "If the previousSibling of the first member of node list is not null:"
-	if (nodeList[0].previousSibling) {
+	// "If the first child of original parent is not in node list:"
+	if (nodeList.indexOf(originalParent.firstChild) == -1) {
 		// "Let cloned parent be the result of calling cloneNode(false) on
 		// original parent."
 		var clonedParent = originalParent.cloneNode(false);
@@ -506,6 +486,11 @@
 	for (var i = 0; i < nodeList.length; i++) {
 		movePreservingRanges(nodeList[i], originalParent.parentNode, getNodeIndex(originalParent));
 	}
+
+	// "If original parent has no children, remove it from its parent."
+	if (!originalParent.hasChildNodes()) {
+		originalParent.parentNode.removeChild(originalParent);
+	}
 }
 
 function wrap(nodeList, siblingCriteria, newParentInstructions) {
@@ -516,94 +501,75 @@
 		return null;
 	}
 
-	// "Let original parent be the parent of the first member of node list."
-	var originalParent = nodeList[0].parentNode;
-
 	// "If the previousSibling of the first member of node list is editable and
-	// meets the sibling criteria:"
+	// meets the sibling criteria, let new parent be the previousSibling of the
+	// first member of node list."
+	var newParent;
 	if (isEditable(nodeList[0].previousSibling)
 	&& siblingCriteria(nodeList[0].previousSibling)) {
-		// "For each node in node list, append node as the last child of its
-		// previousSibling, preserving ranges."
-		for (var i = 0; i < nodeList.length; i++) {
-			movePreservingRanges(nodeList[i], nodeList[i].previousSibling, -1);
-		}
-
-		// "If original parent is editable and has no children, remove it from
-		// its parent."
-		if (isEditable(originalParent)
-		&& !originalParent.hasChildNodes()) {
-			originalParent.parentNode.removeChild(originalParent);
-		}
-
-		// "Return the parent of the first member of node list and abort these
-		// steps."
-		return nodeList[0].parentNode;
+		newParent = nodeList[0].previousSibling;
+
+	// "Otherwise, if the nextSibling of the last member of node list is
+	// editable and meets the sibling criteria, let new parent be the
+	// nextSibling of the last member of node list."
+	} else if (isEditable(nodeList[nodeList.length - 1].nextSibling)
+	&& siblingCriteria(nodeList[nodeList.length - 1].nextSibling)) {
+		newParent = nodeList[nodeList.length - 1].nextSibling;
+
+	// "Otherwise, run the new parent instructions, and let new parent be the
+	// result."
+	} else {
+		newParent = newParentInstructions();
 	}
 
-	// "If the nextSibling of the last member of node list is editable and
-	// meets the sibling criteria:"
-	if (isEditable(nodeList[nodeList.length - 1].nextSibling)
-	&& siblingCriteria(nodeList[nodeList.length - 1].nextSibling)) {
-		// "For each node in node list, in reverse order, insert node as the
-		// first child of its nextSibling, preserving ranges."
-		for (var i = nodeList.length - 1; i >= 0; i--) {
-			movePreservingRanges(nodeList[i], nodeList[i].nextSibling, 0);
+	// "If new parent's parent is null:"
+	if (!newParent.parentNode) {
+		// "If new parent cannot be the child of the parent of the first member
+		// of node list, split the parent of node list."
+		//
+		// Hack for now, as usual.  Don't use this for inline elements!
+		if (isHtmlElement(nodeList[0].parentNode, "P")) {
+			splitParent(nodeList);
 		}
 
-		// "If original parent is editable and has no children, remove it from
-		// its parent."
-		if (isEditable(originalParent)
-		&& !originalParent.hasChildNodes()) {
-			originalParent.parentNode.removeChild(originalParent);
-		}
-
-		// "Return the parent of the first member of node list and abort these
-		// steps."
-		return nodeList[0].parentNode;
-	}
-
-	// "Run the new parent instructions, and let new parent be the result."
-	var newParent = newParentInstructions();
-
-	// "If new parent's parent is null, and new parent cannot be the child of
-	// the parent of the first member of node list, split the parent of node
-	// list."
-	//
-	// Hack for now, as usual.  Don't use this for inline elements!
-	if (!newParent.parentNode
-	&& isHtmlElement(nodeList[0].parentNode, "P")) {
-		splitParent(nodeList);
-	}
-
-	// "If new parent's parent is null, insert new parent into the parent of
-	// the first member of node list immediately before the first member of
-	// node list."
-	if (!newParent.parentNode) {
+		// "Insert new parent into the parent of the first member of node list
+		// immediately before the first member of node list."
 		nodeList[0].parentNode.insertBefore(newParent, nodeList[0]);
 	}
 
-	// "For each node in node list, append node as the last child of new
+	// "Let original parent be the parent of the first member of node list."
+	var originalParent = nodeList[0].parentNode;
+
+	// "If new parent is before the first member of node list in tree order,
+	// then for each node in node list, append node as the last child of new
 	// parent, preserving ranges."
-	for (var i = 0; i < nodeList.length; i++) {
-		movePreservingRanges(nodeList[i], newParent, -1);
+	if (isBefore(newParent, nodeList[0])) {
+		for (var i = 0; i < nodeList.length; i++) {
+			movePreservingRanges(nodeList[i], newParent, -1);
+		}
+
+	// "Otherwise, for each node in node list, in reverse order, insert node as
+	// the first child of new parent, preserving ranges."
+	} else {
+		for (var i = nodeList.length - 1; i >= 0; i--) {
+			movePreservingRanges(nodeList[i], newParent, 0);
+		}
 	}
 
+	// "Remove extraneous line breaks from new parent."
+	removeExtraneousLineBreaksFrom(newParent);
+
 	// "If original parent is editable and has no children, remove it from its
 	// parent."
-	if (isEditable(originalParent)
-	&& !originalParent.hasChildNodes()) {
+	if (isEditable(originalParent) && !originalParent.hasChildNodes()) {
 		originalParent.parentNode.removeChild(originalParent);
 	}
 
-	// "Remove extraneous line breaks from new parent."
-	removeExtraneousLineBreaks(newParent);
-
 	// "Return new parent."
 	return newParent;
 }
 
-function removeExtraneousLineBreaks(node) {
+function removeExtraneousLineBreaksBefore(node) {
 	// "If node is not an Element, or it is an inline node, do nothing and
 	// abort these steps."
 	if (!node
@@ -620,6 +586,16 @@
 	&& !isHtmlElement(node.previousSibling.previousSibling, "BR")) {
 		node.parentNode.removeChild(node.previousSibling);
 	}
+}
+
+function removeExtraneousLineBreaksAfter(node) {
+	// "If node is not an Element, or it is an inline node, do nothing and
+	// abort these steps."
+	if (!node
+	|| node.nodeType != Node.ELEMENT_NODE
+	|| isInlineNode(node)) {
+		return;
+	}
 
 	// "If node has at least two children, and its last child is a br, and its
 	// second-to-last child is an inline node that is not a br, remove the last
@@ -632,6 +608,13 @@
 	}
 }
 
+// "To remove extraneous line breaks from a node, first remove extraneous line
+// breaks before it, then remove extraneous line breaks after it."
+function removeExtraneousLineBreaksFrom(node) {
+	removeExtraneousLineBreaksBefore(node);
+	removeExtraneousLineBreaksAfter(node);
+}
+
 // "An editing host is a node that is either an Element with a contenteditable
 // attribute set to the true state, or a Document whose designMode is enabled."
 function isEditingHost(node) {
--- a/source.html	Tue May 17 15:06:07 2011 -0600
+++ b/source.html	Wed May 18 13:03:04 2011 -0600
@@ -236,40 +236,8 @@
 </ol>
 
 <p>To remove a [[node]] <var>node</var> while <dfn>preserving its
-descendants</dfn>:
-
-<ol>
-  <li>Let <var>children</var> be a list of <var>node</var>'s [[children]].
-
-  <li>If <var>node</var>'s [[parent]] is null, remove all of <var>node</var>'s
-  [[children]] from <var>node</var>, then return <var>children</var>.
-
-  <li><span>Remove extraneous line breaks</span> from <var>node</var>.
-
-  <li>If <var>node</var> is not an <span>inline node</span>, and its first
-  [[child]] and [[previoussibling]] are both <span title="inline node">inline
-  nodes</span>, and the first [[child]] of <var>node</var> is not a [[br]],
-  call <code data-anolis-spec=domcore
-  title=dom-Document-createElement>createElement("br")</code> on the
-  [[ownerdocument]] of <var>node</var>, and insert the result into
-  <var>node</var>'s [[parent]] immediately before <var>node</var>.
-
-  <li>While <var>node</var> has [[children]], insert the first [[child]] of
-  <var>node</var> into <var>node</var>'s [[parent]] immediately before
-  <var>node</var>, <span>preserving ranges</span>.
-
-  <li>If <var>node</var> is not an <span>inline node</span>, and its
-  [[previoussibling]] and [[nextsibling]] are both <span title="inline
-  node">inline nodes</span> but neither is a [[br]], call <code
-  data-anolis-spec=domcore
-  title=dom-Document-createElement>createElement("br")</code> on the
-  [[ownerdocument]] of <var>node</var>, and insert the result into
-  <var>node</var>'s [[parent]] immediately before <var>node</var>.
-
-  <li>Remove <var>node</var> from its [[parent]].
-
-  <li>Return <var>children</var>.
-</ol>
+descendants</dfn>, <span>split the parent</span> of <var>node</var>'s
+[[children]].
 
 <p>To <dfn>split the parent</dfn> of a list <var>node list</var> of consecutive
 [[sibling]] [[nodes]]:
@@ -281,9 +249,28 @@
   <li>If <var>original parent</var> is not <span>editable</span> or its
   [[parent]] is null, do nothing and abort these steps.
 
-  <li>If the [[previoussibling]] of the first member of <var>node list</var> is
-  not null, and the [[nextsibling]] of the last member of <var>node list</var>
-  is null:
+  <li>If the first [[child]] of <var>original parent</var> is in <var>node
+  list</var>, <span>remove extraneous line breaks before</span> <var>original
+  parent</var>.
+
+  <li>If the last [[child]] of <var>original parent</var> is in <var>node
+  list</var>:
+
+  <ol>
+    <li><span>Remove extraneous line breaks after</span> <var>original
+    parent</var>.
+
+    <li>If <var>original parent</var>'s last [[child]] and [[nextsibling]] are
+    both <span title="inline node">inline nodes</span>, call <code
+    data-anolis-spec=domcore
+    title=dom-Document-createElement>createElement("br")</code> on the
+    [[ownerdocument]] of <var>original parent</var>, then insert the result
+    into the [[parent]] of <var>original parent</var> immediately after
+    <var>original parent</var>.
+  </ol>
+
+  <li>If the first [[child]] of <var>original parent</var> is not in <var>node
+  list</var>, but its last [[child]] is:
 
   <div class=XXX>
   <p>We insert things after the parent.  This is bad, because it will cause
@@ -306,14 +293,6 @@
   </div>
 
   <ol>
-    <li>If the last member of <var>node list</var> and the [[nextsibling]] of
-    <var>original parent</var> are both <span title="inline node">inline
-    nodes</span>, call <code data-anolis-spec=domcore
-    title=dom-Document-createElement>createElement("br")</code> on the
-    [[ownerdocument]] of <var>original parent</var>, then insert the result
-    into the [[parent]] of <var>original parent</var> immediately after
-    <var>original parent</var>.
-
     <li>For each <var>node</var> in <var>node list</var>, <em>in reverse
     order</em>, insert <var>node</var> into the [[parent]] of <var>original
     parent</var> immediately after <var>original parent</var>, <span>preserving
@@ -322,8 +301,8 @@
     <li>Abort these steps.
   </ol>
 
-  <li>If the [[previoussibling]] of the first member of <var>node list</var> is
-  not null:
+  <li>If the first [[child]] of <var>original parent</var> is not in <var>node
+  list</var>:
 
   <ol>
     <li>Let <var>cloned parent</var> be the result of calling <code
@@ -357,6 +336,9 @@
   <li>For each <var>node</var> in <var>node list</var>, insert <var>node</var>
   into the [[parent]] of <var>original parent</var> immediately before
   <var>original parent</var>, <span>preserving ranges</span>.
+
+  <li>If <var>original parent</var> has no [[children]], remove it from its
+  [[parent]].
 </ol>
 
 <p>To <dfn>wrap</dfn> a list <var>node list</var> of consecutive [[sibling]]
@@ -367,65 +349,57 @@
   <li>If <var>node list</var> is empty, or the first member of <var>node
   list</var> is not <span>editable</span>, return null and abort these steps.
 
-  <li>Let <var>original parent</var> be the [[parent]] of the first member of
-  <var>node list</var>.
-
   <li>If the [[previoussibling]] of the first member of <var>node list</var>
-  is <span>editable</span> and meets the <span>sibling criteria</span>:
-
-  <ol>
-    <li>For each <var>node</var> in <var>node list</var>, append
-    <var>node</var> as the last [[child]] of its [[previoussibling]],
-    <span>preserving ranges</span>.
-
-    <li>If <var>original parent</var> is <span>editable</span> and has no
-    [[children]], remove it from its [[parent]].
-
-    <li>Return the [[parent]] of the first member of <var>node list</var> and
-    abort these steps.
-  </ol>
-
-  <li>If the [[nextsibling]] of the last member of <var>node list</var> is
-  <span>editable</span> and meets the <span>sibling criteria</span>:
+  is <span>editable</span> and meets the <span>sibling criteria</span>, let
+  <var>new parent</var> be the [[previoussibling]] of the first member of
+  <var>node list</var>.
+
+  <li>Otherwise, if the [[nextsibling]] of the last member of <var>node
+  list</var> is <span>editable</span> and meets the <span>sibling
+  criteria</span>, let <var>new parent</var> be the [[nextsibling]] of the last
+  member of <var>node list</var>.
+
+  <li>Otherwise, run the <span>new parent instructions</span>, and let <var>new
+  parent</var> be the result.
+
+  <li>If <var>new parent</var>'s [[parent]] is null:
 
   <ol>
-    <li>For each <var>node</var> in <var>node list</var>, <em>in reverse
-    order</em>, insert <var>node</var> as the first [[child]] of its
-    [[nextsibling]], <span>preserving ranges</span>.
-
-    <li>If <var>original parent</var> is <span>editable</span> and has no
-    [[children]], remove it from its [[parent]].
-
-    <li>Return the [[parent]] of the first member of <var>node list</var> and
-    abort these steps.
+    <li>If <var>new parent</var> cannot be the [[child]] of the [[parent]] of
+    the first member of <var>node list</var>, <span>split the parent</span> of
+    <var>node list</var>.
+
+    <p class=XXX>"Cannot be the child" needs to be defined.
+
+    <li>Insert <var>new parent</var> into the [[parent]] of the first member of
+    <var>node list</var> immediately before the first member of <var>node
+    list</var>.
   </ol>
 
-  <li>Run the <span>new parent instructions</span>, and let <var>new
-  parent</var> be the result.
-
-  <li>If <var>new parent</var>'s [[parent]] is null, and <var>new parent</var>
-  cannot be the [[child]] of the [[parent]] of the first member of <var>node
-  list</var>, <span>split the parent</span> of <var>node list</var>.
-
-  <p class=XXX>"Cannot be the child" needs to be defined.
-
-  <li>If <var>new parent</var>'s [[parent]] is null, insert <var>new
-  parent</var> into the [[parent]] of the first member of <var>node list</var>
-  immediately before the first member of <var>node list</var>.
-
-  <li>For each <var>node</var> in <var>node list</var>, append <var>node</var>
-  as the last [[child]] of <var>new parent</var>, <span>preserving
-  ranges</span>.
+  <li>Let <var>original parent</var> be the [[parent]] of the first member of
+  <var>node list</var>.
+
+  <li>If <var>new parent</var> is before the first member of <var>node
+  list</var> in [[treeorder]], then for each <var>node</var> in <var>node
+  list</var>, append <var>node</var> as the last [[child]] of <var>new
+  parent</var>, <span>preserving ranges</span>.
+
+  <li>Otherwise, for each <var>node</var> in <var>node list</var>, <em>in
+  reverse order</em>, insert <var>node</var> as the first [[child]] of <var>new
+  parent</var>, <span>preserving ranges</span>.
+
+  <li><span>Remove extraneous line breaks from</span> <var>new parent</var>.
 
   <li>If <var>original parent</var> is <span>editable</span> and has no
   [[children]], remove it from its [[parent]].
-
-  <li><span>Remove extraneous line breaks</span> from <var>new parent</var>.
+  <!-- This could happen if the new parent instructions returned a node whose
+  parent wasn't null. -->
 
   <li>Return <var>new parent</var>.
 </ol>
 
-<p>To <dfn>remove extraneous line breaks</dfn> from a [[node]] <var>node</var>:
+<p>To <dfn>remove extraneous line breaks before</dfn> a [[node]]
+<var>node</var>:
 
 <ol>
   <li>If <var>node</var> is not an [[element]], or it is an <span>inline
@@ -435,6 +409,14 @@
   [[previoussibling]] of the [[previoussibling]] of <var>node</var> is an
   <span>inline node</span> that is not a [[br]], remove the [[previoussibling]]
   of <var>node</var> from its [[parent]].
+</ol>
+
+<p>To <dfn>remove extraneous line breaks after</dfn> a [[node]]
+<var>node</var>:
+
+<ol>
+  <li>If <var>node</var> is not an [[element]], or it is an <span>inline
+  node</span>, do nothing and abort these steps.
 
   <li>If <var>node</var> has at least two [[children]], and its last [[child]]
   is a [[br]], and its second-to-last [[child]] is an <span>inline node</span>
@@ -442,6 +424,10 @@
   <var>node</var>.
 </ol>
 
+<p>To <dfn>remove extraneous line breaks from</dfn> a [[node]], first
+<span>remove extraneous line breaks before</span> it, then <span>remove
+extraneous line breaks after</span> it.
+
 <p>An <dfn>editing host</dfn> is a [[node]] that is either an [[element]] with
 a <code data-anolis-spec=html title=attr-contenteditable>contenteditable</code>
 attribute set to the true state, or a [[document]] whose <code