Make "remove preserving descendants" block-only
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Tue, 05 Jul 2011 15:56:37 -0600
changeset 366 0ee7984f8909
parent 365 3ff0ff364e74
child 367 8d6c424b650c
Make "remove preserving descendants" block-only

It was only used in one place in the inline commands, and the
implementation was never actually updated to use it. All the fiddling
it does is only useful for block formatting anyway. This is mostly just
moving code around, but it paves the way for a substantive change:
preserving styles when I split the parent.
editcommands.html
implementation.js
source.html
--- a/editcommands.html	Tue Jul 05 15:42:44 2011 -0600
+++ b/editcommands.html	Tue Jul 05 15:56:37 2011 -0600
@@ -890,144 +890,6 @@
   (<var title="">node</var>, <var title="">offset</var>), true otherwise.
 </ol>
 
-<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>:
-
-<p class=XXX>Pretty much any time we call this algorithm, it can cause trouble
-if the parent had styles, classes, etc.  There's not going to be any general
-way to handle this, but we should at least try to handle the special case of
-inline styles, because Firefox does actually add them to arbitrary elements.
-Also, when splitting out of an inline parent, it might be good to wrap all the
-inline descendants in a clone of the former parent.
-
-<ol>
-  <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="">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 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 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>, and <var title="">original parent</var> <a href=#follows-a-line-break>follows a line break</a>,
-  set <var title="">follows line break</var> to true.  Otherwise, set <var title="">follows line
-  break</var> to false.
-
-  <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>, and <var title="">original parent</var> <a href=#precedes-a-line-break>precedes a line
-  break</a>, set <var title="">precedes line break</var> to true.  Otherwise, set
-  <var title="">precedes line break</var> to false.
-
-  <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
-  them to become part of any ranges that immediately follow.  For instance, if
-  we're hitting "bar" in
-
-  </p><xmp><div><p>foo<p>bar</div>{<p>baz}</xmp>
-
-  <p>it becomes
-
-  </p><xmp><div><p>foo</div>{<p>bar<p>baz}</xmp>
-
-  <p>instead of
-
-  </p><xmp><div><p>foo</div><p>bar{<p>baz}</xmp>
-
-  <p>because of how range mutation rules work.  This doesn't happen if we
-  insert before.  Probably this isn't important enough to try working around,
-  though.
-  </div>
-
-  <ol>
-    <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
-    ranges</a>.
-
-    <li>If <var title="">precedes line break</var> is true, and the last member of
-    <var title="">node list</var> does not <a href=#precedes-a-line-break title="precedes a line break">precede a
-    line break</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 <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a> and
-    insert the result immediately after the last member of <var title="">node
-    list</var>.
-
-    <li><a href=#remove-extraneous-line-breaks-at-the-end-of>Remove extraneous line breaks at the end of</a> <var title="">original
-    parent</var>.
-
-    <li>Abort these steps.
-  </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>:
-
-  <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>
-    on <var title="">original parent</var>.
-
-    <li>If <var title="">original parent</var> has an <code class=external data-anolis-spec=html title="the id attribute"><a href=http://www.whatwg.org/html/#the-id-attribute>id</a></code> attribute, unset it.
-
-    <li>Insert <var title="">cloned 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 <var title="">original
-    parent</var> immediately before <var title="">original parent</var>.
-
-    <li>While 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, append 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> 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="">cloned parent</var>,
-    <a href=#preserving-ranges>preserving ranges</a>.
-  </ol>
-
-  <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>.
-  <!-- Notice that a boundary point that was immediately before the element
-  will now be immediately before its children, just because of the regular
-  range mutation rules, without needing to worry about preserving ranges.
-  Likewise for boundary points immediately after the element, if we wind up
-  removing the element in the final step.  Preserving ranges is only necessary
-  for the sake of boundary points in the element or its descendants. -->
-
-  <li>If <var title="">follows line break</var> is true, and the first member of
-  <var title="">node list</var> does not <a href=#follows-a-line-break title="follows a line break">follow a
-  line break</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 <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a> and
-  insert the result immediately before the first member of <var title="">node
-  list</var>.
-
-  <li>If the last member of <var title="">node list</var> is an <a href=#inline-node>inline node</a>
-  other than 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 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
-  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 <var title="">original parent</var> is not an <a href=#inline-node>inline node</a>,
-  remove 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> from <var title="">original
-  parent</var>.
-
-  <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>:
-
-  <ol>
-    <li>Remove <var title="">original parent</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>If <var title="">precedes line break</var> is true, and the last member of
-    <var title="">node list</var> does not <a href=#precedes-a-line-break title="precedes a line break">precede a
-    line break</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 <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a> and
-    insert the result immediately after the last member of <var title="">node
-    list</var>.
-  </ol>
-
-  <li>Otherwise, <a href=#remove-extraneous-line-breaks-before>remove extraneous line breaks before</a>
-  <var title="">original parent</var>.
-
-  <li>If <var title="">node list</var>'s last member's <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> is null,
-  but 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 not null, <a href=#remove-extraneous-line-breaks-at-the-end-of>remove extraneous line breaks at the
-  end of</a> <var title="">node list</var>'s last member'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>.
-  <!-- The parent might be null if it's a br that we removed in the last step,
-  in which case this step isn't necessary. -->
-</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>, <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>.
-
 
 <h3 id=wrapping-a-list-of-nodes><span class=secno>6.2 </span>Wrapping a list of nodes</h3>
 
@@ -1553,7 +1415,11 @@
   <ol>
     <li>Let <var title="">children</var> 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>children</a> of <var title="">element</var>.
 
-    <li>Remove <var title="">element</var>, <a href=#preserving-its-descendants>preserving its descendants</a>.
+    <li>For each <var title="">child</var> in <var title="">children</var>, insert
+    <var title="">child</var> into <var title="">element</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="">element</var>, <a href=#preserving-ranges>preserving ranges</a>.
+
+    <li>Remove <var title="">element</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>
@@ -3140,6 +3006,144 @@
   of <var title="">node</var>.
 </ol>
 
+<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>:
+
+<p class=XXX>Pretty much any time we call this algorithm, it can cause trouble
+if the parent had styles, classes, etc.  There's not going to be any general
+way to handle this, but we should at least try to handle the special case of
+inline styles, because Firefox does actually add them to arbitrary elements.
+Also, when splitting out of an inline parent, it might be good to wrap all the
+inline descendants in a clone of the former parent.
+
+<ol>
+  <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="">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 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 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>, and <var title="">original parent</var> <a href=#follows-a-line-break>follows a line break</a>,
+  set <var title="">follows line break</var> to true.  Otherwise, set <var title="">follows line
+  break</var> to false.
+
+  <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>, and <var title="">original parent</var> <a href=#precedes-a-line-break>precedes a line
+  break</a>, set <var title="">precedes line break</var> to true.  Otherwise, set
+  <var title="">precedes line break</var> to false.
+
+  <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
+  them to become part of any ranges that immediately follow.  For instance, if
+  we're hitting "bar" in
+
+  </p><xmp><div><p>foo<p>bar</div>{<p>baz}</xmp>
+
+  <p>it becomes
+
+  </p><xmp><div><p>foo</div>{<p>bar<p>baz}</xmp>
+
+  <p>instead of
+
+  </p><xmp><div><p>foo</div><p>bar{<p>baz}</xmp>
+
+  <p>because of how range mutation rules work.  This doesn't happen if we
+  insert before.  Probably this isn't important enough to try working around,
+  though.
+  </div>
+
+  <ol>
+    <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
+    ranges</a>.
+
+    <li>If <var title="">precedes line break</var> is true, and the last member of
+    <var title="">node list</var> does not <a href=#precedes-a-line-break title="precedes a line break">precede a
+    line break</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 <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a> and
+    insert the result immediately after the last member of <var title="">node
+    list</var>.
+
+    <li><a href=#remove-extraneous-line-breaks-at-the-end-of>Remove extraneous line breaks at the end of</a> <var title="">original
+    parent</var>.
+
+    <li>Abort these steps.
+  </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>:
+
+  <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>
+    on <var title="">original parent</var>.
+
+    <li>If <var title="">original parent</var> has an <code class=external data-anolis-spec=html title="the id attribute"><a href=http://www.whatwg.org/html/#the-id-attribute>id</a></code> attribute, unset it.
+
+    <li>Insert <var title="">cloned 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 <var title="">original
+    parent</var> immediately before <var title="">original parent</var>.
+
+    <li>While 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, append 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> 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="">cloned parent</var>,
+    <a href=#preserving-ranges>preserving ranges</a>.
+  </ol>
+
+  <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>.
+  <!-- Notice that a boundary point that was immediately before the element
+  will now be immediately before its children, just because of the regular
+  range mutation rules, without needing to worry about preserving ranges.
+  Likewise for boundary points immediately after the element, if we wind up
+  removing the element in the final step.  Preserving ranges is only necessary
+  for the sake of boundary points in the element or its descendants. -->
+
+  <li>If <var title="">follows line break</var> is true, and the first member of
+  <var title="">node list</var> does not <a href=#follows-a-line-break title="follows a line break">follow a
+  line break</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 <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a> and
+  insert the result immediately before the first member of <var title="">node
+  list</var>.
+
+  <li>If the last member of <var title="">node list</var> is an <a href=#inline-node>inline node</a>
+  other than 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 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
+  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 <var title="">original parent</var> is not an <a href=#inline-node>inline node</a>,
+  remove 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> from <var title="">original
+  parent</var>.
+
+  <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>:
+
+  <ol>
+    <li>Remove <var title="">original parent</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>If <var title="">precedes line break</var> is true, and the last member of
+    <var title="">node list</var> does not <a href=#precedes-a-line-break title="precedes a line break">precede a
+    line break</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 <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a> and
+    insert the result immediately after the last member of <var title="">node
+    list</var>.
+  </ol>
+
+  <li>Otherwise, <a href=#remove-extraneous-line-breaks-before>remove extraneous line breaks before</a>
+  <var title="">original parent</var>.
+
+  <li>If <var title="">node list</var>'s last member's <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> is null,
+  but 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 not null, <a href=#remove-extraneous-line-breaks-at-the-end-of>remove extraneous line breaks at the
+  end of</a> <var title="">node list</var>'s last member'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>.
+  <!-- The parent might be null if it's a br that we removed in the last step,
+  in which case this step isn't necessary. -->
+</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>, <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=indent>indent</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>
 <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>:
 <!--
--- a/implementation.js	Tue Jul 05 15:42:44 2011 -0600
+++ b/implementation.js	Tue Jul 05 15:56:37 2011 -0600
@@ -1141,142 +1141,6 @@
 	return getPosition(newRange.endContainer, newRange.endOffset, node, offset) != "after";
 }
 
-function splitParent(nodeList) {
-	// "Let original parent be the parent of the first member of node list."
-	var originalParent = nodeList[0].parentNode;
-
-	// "If original parent is not editable or its parent is null, do nothing
-	// and abort these steps."
-	if (!isEditable(originalParent)
-	|| !originalParent.parentNode) {
-		return;
-	}
-
-	// "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 first child of original parent is in node list, and original
-	// parent follows a line break, set follows line break to true. Otherwise,
-	// set follows line break to false."
-	var followsLineBreak_ = nodeList.indexOf(originalParent.firstChild) != -1
-		&& followsLineBreak(originalParent);
-
-	// "If the last child of original parent is in node list, and original
-	// parent precedes a line break, set precedes line break to true.
-	// Otherwise, set precedes line break to false."
-	var precedesLineBreak_ = nodeList.indexOf(originalParent.lastChild) != -1
-		&& precedesLineBreak(originalParent);
-
-	// "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."
-		for (var i = nodeList.length - 1; i >= 0; i--) {
-			movePreservingRanges(nodeList[i], originalParent.parentNode, 1 + getNodeIndex(originalParent));
-		}
-
-		// "If precedes line break is true, and the last member of node list
-		// does not precede a line break, call createElement("br") on the
-		// context object and insert the result immediately after the last
-		// member of node list."
-		if (precedesLineBreak_
-		&& !precedesLineBreak(nodeList[nodeList.length - 1])) {
-			nodeList[nodeList.length - 1].parentNode.insertBefore(document.createElement("br"), nodeList[nodeList.length - 1].nextSibling);
-		}
-
-		// "Remove extraneous line breaks at the end of original parent."
-		removeExtraneousLineBreaksAtTheEndOf(originalParent);
-
-		// "Abort these steps."
-		return;
-	}
-
-	// "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);
-
-		// "If original parent has an id attribute, unset it."
-		originalParent.removeAttribute("id");
-
-		// "Insert cloned parent into the parent of original parent immediately
-		// before original parent."
-		originalParent.parentNode.insertBefore(clonedParent, originalParent);
-
-		// "While the previousSibling of the first member of node list is not
-		// null, append the first child of original parent as the last child of
-		// cloned parent, preserving ranges."
-		while (nodeList[0].previousSibling) {
-			movePreservingRanges(originalParent.firstChild, clonedParent, clonedParent.childNodes.length);
-		}
-	}
-
-	// "For each node in node list, insert node into the parent of original
-	// parent immediately before original parent, preserving ranges."
-	for (var i = 0; i < nodeList.length; i++) {
-		movePreservingRanges(nodeList[i], originalParent.parentNode, getNodeIndex(originalParent));
-	}
-
-	// "If follows line break is true, and the first member of node list does
-	// not follow a line break, call createElement("br") on the context object
-	// and insert the result immediately before the first member of node list."
-	if (followsLineBreak_
-	&& !followsLineBreak(nodeList[0])) {
-		nodeList[0].parentNode.insertBefore(document.createElement("br"), nodeList[0]);
-	}
-
-	// "If the last member of node list is an inline node other than a br, and
-	// the first child of original parent is a br, and original parent is not
-	// an inline node, remove the first child of original parent from original
-	// parent."
-	if (isInlineNode(nodeList[nodeList.length - 1])
-	&& !isHtmlElement(nodeList[nodeList.length - 1], "br")
-	&& isHtmlElement(originalParent.firstChild, "br")
-	&& !isInlineNode(originalParent)) {
-		originalParent.removeChild(originalParent.firstChild);
-	}
-
-	// "If original parent has no children:"
-	if (!originalParent.hasChildNodes()) {
-		// "Remove original parent from its parent."
-		originalParent.parentNode.removeChild(originalParent);
-
-		// "If precedes line break is true, and the last member of node list
-		// does not precede a line break, call createElement("br") on the
-		// context object and insert the result immediately after the last
-		// member of node list."
-		if (precedesLineBreak_
-		&& !precedesLineBreak(nodeList[nodeList.length - 1])) {
-			nodeList[nodeList.length - 1].parentNode.insertBefore(document.createElement("br"), nodeList[nodeList.length - 1].nextSibling);
-		}
-
-	// "Otherwise, remove extraneous line breaks before original parent."
-	} else {
-		removeExtraneousLineBreaksBefore(originalParent);
-	}
-
-	// "If node list's last member's nextSibling is null, but its parent is not
-	// null, remove extraneous line breaks at the end of node list's last
-	// member's parent."
-	if (!nodeList[nodeList.length - 1].nextSibling
-	&& nodeList[nodeList.length - 1].parentNode) {
-		removeExtraneousLineBreaksAtTheEndOf(nodeList[nodeList.length - 1].parentNode);
-	}
-}
-
-// "To remove a node node while preserving its descendants, split the parent of
-// node's children."
-function removePreservingDescendants(node) {
-	splitParent([].slice.call(node.childNodes));
-}
-
 //@}
 
 ///// Wrapping a list of nodes /////
@@ -2088,10 +1952,10 @@
 		// "Let children be the children of element."
 		var children = Array.prototype.slice.call(element.childNodes);
 
-		// "While element has children, insert its first child into its parent
-		// immediately before it, preserving ranges."
-		while (element.childNodes.length) {
-			movePreservingRanges(element.firstChild, element.parentNode, getNodeIndex(element));
+		// "For each child in children, insert child into element's parent
+		// immediately before element, preserving ranges."
+		for (var i = 0; i < children.length; i++) {
+			movePreservingRanges(children[i], element.parentNode, getNodeIndex(element));
 		}
 
 		// "Remove element from its parent."
@@ -3489,6 +3353,142 @@
 	}
 }
 
+function splitParent(nodeList) {
+	// "Let original parent be the parent of the first member of node list."
+	var originalParent = nodeList[0].parentNode;
+
+	// "If original parent is not editable or its parent is null, do nothing
+	// and abort these steps."
+	if (!isEditable(originalParent)
+	|| !originalParent.parentNode) {
+		return;
+	}
+
+	// "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 first child of original parent is in node list, and original
+	// parent follows a line break, set follows line break to true. Otherwise,
+	// set follows line break to false."
+	var followsLineBreak_ = nodeList.indexOf(originalParent.firstChild) != -1
+		&& followsLineBreak(originalParent);
+
+	// "If the last child of original parent is in node list, and original
+	// parent precedes a line break, set precedes line break to true.
+	// Otherwise, set precedes line break to false."
+	var precedesLineBreak_ = nodeList.indexOf(originalParent.lastChild) != -1
+		&& precedesLineBreak(originalParent);
+
+	// "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."
+		for (var i = nodeList.length - 1; i >= 0; i--) {
+			movePreservingRanges(nodeList[i], originalParent.parentNode, 1 + getNodeIndex(originalParent));
+		}
+
+		// "If precedes line break is true, and the last member of node list
+		// does not precede a line break, call createElement("br") on the
+		// context object and insert the result immediately after the last
+		// member of node list."
+		if (precedesLineBreak_
+		&& !precedesLineBreak(nodeList[nodeList.length - 1])) {
+			nodeList[nodeList.length - 1].parentNode.insertBefore(document.createElement("br"), nodeList[nodeList.length - 1].nextSibling);
+		}
+
+		// "Remove extraneous line breaks at the end of original parent."
+		removeExtraneousLineBreaksAtTheEndOf(originalParent);
+
+		// "Abort these steps."
+		return;
+	}
+
+	// "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);
+
+		// "If original parent has an id attribute, unset it."
+		originalParent.removeAttribute("id");
+
+		// "Insert cloned parent into the parent of original parent immediately
+		// before original parent."
+		originalParent.parentNode.insertBefore(clonedParent, originalParent);
+
+		// "While the previousSibling of the first member of node list is not
+		// null, append the first child of original parent as the last child of
+		// cloned parent, preserving ranges."
+		while (nodeList[0].previousSibling) {
+			movePreservingRanges(originalParent.firstChild, clonedParent, clonedParent.childNodes.length);
+		}
+	}
+
+	// "For each node in node list, insert node into the parent of original
+	// parent immediately before original parent, preserving ranges."
+	for (var i = 0; i < nodeList.length; i++) {
+		movePreservingRanges(nodeList[i], originalParent.parentNode, getNodeIndex(originalParent));
+	}
+
+	// "If follows line break is true, and the first member of node list does
+	// not follow a line break, call createElement("br") on the context object
+	// and insert the result immediately before the first member of node list."
+	if (followsLineBreak_
+	&& !followsLineBreak(nodeList[0])) {
+		nodeList[0].parentNode.insertBefore(document.createElement("br"), nodeList[0]);
+	}
+
+	// "If the last member of node list is an inline node other than a br, and
+	// the first child of original parent is a br, and original parent is not
+	// an inline node, remove the first child of original parent from original
+	// parent."
+	if (isInlineNode(nodeList[nodeList.length - 1])
+	&& !isHtmlElement(nodeList[nodeList.length - 1], "br")
+	&& isHtmlElement(originalParent.firstChild, "br")
+	&& !isInlineNode(originalParent)) {
+		originalParent.removeChild(originalParent.firstChild);
+	}
+
+	// "If original parent has no children:"
+	if (!originalParent.hasChildNodes()) {
+		// "Remove original parent from its parent."
+		originalParent.parentNode.removeChild(originalParent);
+
+		// "If precedes line break is true, and the last member of node list
+		// does not precede a line break, call createElement("br") on the
+		// context object and insert the result immediately after the last
+		// member of node list."
+		if (precedesLineBreak_
+		&& !precedesLineBreak(nodeList[nodeList.length - 1])) {
+			nodeList[nodeList.length - 1].parentNode.insertBefore(document.createElement("br"), nodeList[nodeList.length - 1].nextSibling);
+		}
+
+	// "Otherwise, remove extraneous line breaks before original parent."
+	} else {
+		removeExtraneousLineBreaksBefore(originalParent);
+	}
+
+	// "If node list's last member's nextSibling is null, but its parent is not
+	// null, remove extraneous line breaks at the end of node list's last
+	// member's parent."
+	if (!nodeList[nodeList.length - 1].nextSibling
+	&& nodeList[nodeList.length - 1].parentNode) {
+		removeExtraneousLineBreaksAtTheEndOf(nodeList[nodeList.length - 1].parentNode);
+	}
+}
+
+// "To remove a node node while preserving its descendants, split the parent of
+// node's children."
+function removePreservingDescendants(node) {
+	splitParent([].slice.call(node.childNodes));
+}
+
 function indentNodes(nodeList) {
 	// "If node list is empty, do nothing and abort these steps."
 	if (!nodeList.length) {
--- a/source.html	Tue Jul 05 15:42:44 2011 -0600
+++ b/source.html	Tue Jul 05 15:56:37 2011 -0600
@@ -839,145 +839,6 @@
   <li>Return false if <var>new range</var>'s [[rangeend]] is [[bpafter]]
   (<var>node</var>, <var>offset</var>), true otherwise.
 </ol>
-
-<p>To <dfn>split the parent</dfn> of a list <var>node list</var> of consecutive
-[[sibling]] [[nodes]]:
-
-<p class=XXX>Pretty much any time we call this algorithm, it can cause trouble
-if the parent had styles, classes, etc.  There's not going to be any general
-way to handle this, but we should at least try to handle the special case of
-inline styles, because Firefox does actually add them to arbitrary elements.
-Also, when splitting out of an inline parent, it might be good to wrap all the
-inline descendants in a clone of the former parent.
-
-<ol>
-  <li>Let <var>original parent</var> be the [[parent]] of the first member of
-  <var>node list</var>.
-
-  <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 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 first [[child]] of <var>original parent</var> is in <var>node
-  list</var>, and <var>original parent</var> <span>follows a line break</span>,
-  set <var>follows line break</var> to true.  Otherwise, set <var>follows line
-  break</var> to false.
-
-  <li>If the last [[child]] of <var>original parent</var> is in <var>node
-  list</var>, and <var>original parent</var> <span>precedes a line
-  break</span>, set <var>precedes line break</var> to true.  Otherwise, set
-  <var>precedes line break</var> to false.
-
-  <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
-  them to become part of any ranges that immediately follow.  For instance, if
-  we're hitting "bar" in
-
-  <xmp><div><p>foo<p>bar</div>{<p>baz}</xmp>
-
-  <p>it becomes
-
-  <xmp><div><p>foo</div>{<p>bar<p>baz}</xmp>
-
-  <p>instead of
-
-  <xmp><div><p>foo</div><p>bar{<p>baz}</xmp>
-
-  <p>because of how range mutation rules work.  This doesn't happen if we
-  insert before.  Probably this isn't important enough to try working around,
-  though.
-  </div>
-
-  <ol>
-    <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
-    ranges</span>.
-
-    <li>If <var>precedes line break</var> is true, and the last member of
-    <var>node list</var> does not <span title="precedes a line break">precede a
-    line break</span>, call [[createelement|"br"]] on the [[contextobject]] and
-    insert the result immediately after the last member of <var>node
-    list</var>.
-
-    <li><span>Remove extraneous line breaks at the end of</span> <var>original
-    parent</var>.
-
-    <li>Abort these steps.
-  </ol>
-
-  <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
-    data-anolis-spec=domcore title=dom-Node-cloneNode>cloneNode(false)</code>
-    on <var>original parent</var>.
-
-    <li>If <var>original parent</var> has an [[id]] attribute, unset it.
-
-    <li>Insert <var>cloned parent</var> into the [[parent]] of <var>original
-    parent</var> immediately before <var>original parent</var>.
-
-    <li>While the [[previoussibling]] of the first member of <var>node
-    list</var> is not null, append the first [[child]] of <var>original
-    parent</var> as the last [[child]] of <var>cloned parent</var>,
-    <span>preserving ranges</span>.
-  </ol>
-
-  <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>.
-  <!-- Notice that a boundary point that was immediately before the element
-  will now be immediately before its children, just because of the regular
-  range mutation rules, without needing to worry about preserving ranges.
-  Likewise for boundary points immediately after the element, if we wind up
-  removing the element in the final step.  Preserving ranges is only necessary
-  for the sake of boundary points in the element or its descendants. -->
-
-  <li>If <var>follows line break</var> is true, and the first member of
-  <var>node list</var> does not <span title="follows a line break">follow a
-  line break</span>, call [[createelement|"br"]] on the [[contextobject]] and
-  insert the result immediately before the first member of <var>node
-  list</var>.
-
-  <li>If the last member of <var>node list</var> is an <span>inline node</span>
-  other than a [[br]], and the first [[child]] of <var>original parent</var> is
-  a [[br]], and <var>original parent</var> is not an <span>inline node</span>,
-  remove the first [[child]] of <var>original parent</var> from <var>original
-  parent</var>.
-
-  <li>If <var>original parent</var> has no [[children]]:
-
-  <ol>
-    <li>Remove <var>original parent</var> from its [[parent]].
-
-    <li>If <var>precedes line break</var> is true, and the last member of
-    <var>node list</var> does not <span title="precedes a line break">precede a
-    line break</span>, call [[createelement|"br"]] on the [[contextobject]] and
-    insert the result immediately after the last member of <var>node
-    list</var>.
-  </ol>
-
-  <li>Otherwise, <span>remove extraneous line breaks before</span>
-  <var>original parent</var>.
-
-  <li>If <var>node list</var>'s last member's [[nextsibling]] is null,
-  but its [[parent]] is not null, <span>remove extraneous line breaks at the
-  end of</span> <var>node list</var>'s last member's [[parent]].
-  <!-- The parent might be null if it's a br that we removed in the last step,
-  in which case this step isn't necessary. -->
-</ol>
-
-<p>To remove a [[node]] <var>node</var> while <dfn>preserving its
-descendants</dfn>, <span>split the parent</span> of <var>node</var>'s
-[[children]].
 <!-- @} -->
 
 <h3>Wrapping a list of nodes</h3>
@@ -1512,7 +1373,11 @@
   <ol>
     <li>Let <var>children</var> be the [[children]] of <var>element</var>.
 
-    <li>Remove <var>element</var>, <span>preserving its descendants</span>.
+    <li>For each <var>child</var> in <var>children</var>, insert
+    <var>child</var> into <var>element</var>'s [[parent]] immediately before
+    <var>element</var>, <span>preserving ranges</span>.
+
+    <li>Remove <var>element</var> from its [[parent]].
 
     <li>Return <var>children</var>.
   </ol>
@@ -3121,6 +2986,145 @@
   of <var>node</var>.
 </ol>
 
+<p>To <dfn>split the parent</dfn> of a list <var>node list</var> of consecutive
+[[sibling]] [[nodes]]:
+
+<p class=XXX>Pretty much any time we call this algorithm, it can cause trouble
+if the parent had styles, classes, etc.  There's not going to be any general
+way to handle this, but we should at least try to handle the special case of
+inline styles, because Firefox does actually add them to arbitrary elements.
+Also, when splitting out of an inline parent, it might be good to wrap all the
+inline descendants in a clone of the former parent.
+
+<ol>
+  <li>Let <var>original parent</var> be the [[parent]] of the first member of
+  <var>node list</var>.
+
+  <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 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 first [[child]] of <var>original parent</var> is in <var>node
+  list</var>, and <var>original parent</var> <span>follows a line break</span>,
+  set <var>follows line break</var> to true.  Otherwise, set <var>follows line
+  break</var> to false.
+
+  <li>If the last [[child]] of <var>original parent</var> is in <var>node
+  list</var>, and <var>original parent</var> <span>precedes a line
+  break</span>, set <var>precedes line break</var> to true.  Otherwise, set
+  <var>precedes line break</var> to false.
+
+  <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
+  them to become part of any ranges that immediately follow.  For instance, if
+  we're hitting "bar" in
+
+  <xmp><div><p>foo<p>bar</div>{<p>baz}</xmp>
+
+  <p>it becomes
+
+  <xmp><div><p>foo</div>{<p>bar<p>baz}</xmp>
+
+  <p>instead of
+
+  <xmp><div><p>foo</div><p>bar{<p>baz}</xmp>
+
+  <p>because of how range mutation rules work.  This doesn't happen if we
+  insert before.  Probably this isn't important enough to try working around,
+  though.
+  </div>
+
+  <ol>
+    <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
+    ranges</span>.
+
+    <li>If <var>precedes line break</var> is true, and the last member of
+    <var>node list</var> does not <span title="precedes a line break">precede a
+    line break</span>, call [[createelement|"br"]] on the [[contextobject]] and
+    insert the result immediately after the last member of <var>node
+    list</var>.
+
+    <li><span>Remove extraneous line breaks at the end of</span> <var>original
+    parent</var>.
+
+    <li>Abort these steps.
+  </ol>
+
+  <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
+    data-anolis-spec=domcore title=dom-Node-cloneNode>cloneNode(false)</code>
+    on <var>original parent</var>.
+
+    <li>If <var>original parent</var> has an [[id]] attribute, unset it.
+
+    <li>Insert <var>cloned parent</var> into the [[parent]] of <var>original
+    parent</var> immediately before <var>original parent</var>.
+
+    <li>While the [[previoussibling]] of the first member of <var>node
+    list</var> is not null, append the first [[child]] of <var>original
+    parent</var> as the last [[child]] of <var>cloned parent</var>,
+    <span>preserving ranges</span>.
+  </ol>
+
+  <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>.
+  <!-- Notice that a boundary point that was immediately before the element
+  will now be immediately before its children, just because of the regular
+  range mutation rules, without needing to worry about preserving ranges.
+  Likewise for boundary points immediately after the element, if we wind up
+  removing the element in the final step.  Preserving ranges is only necessary
+  for the sake of boundary points in the element or its descendants. -->
+
+  <li>If <var>follows line break</var> is true, and the first member of
+  <var>node list</var> does not <span title="follows a line break">follow a
+  line break</span>, call [[createelement|"br"]] on the [[contextobject]] and
+  insert the result immediately before the first member of <var>node
+  list</var>.
+
+  <li>If the last member of <var>node list</var> is an <span>inline node</span>
+  other than a [[br]], and the first [[child]] of <var>original parent</var> is
+  a [[br]], and <var>original parent</var> is not an <span>inline node</span>,
+  remove the first [[child]] of <var>original parent</var> from <var>original
+  parent</var>.
+
+  <li>If <var>original parent</var> has no [[children]]:
+
+  <ol>
+    <li>Remove <var>original parent</var> from its [[parent]].
+
+    <li>If <var>precedes line break</var> is true, and the last member of
+    <var>node list</var> does not <span title="precedes a line break">precede a
+    line break</span>, call [[createelement|"br"]] on the [[contextobject]] and
+    insert the result immediately after the last member of <var>node
+    list</var>.
+  </ol>
+
+  <li>Otherwise, <span>remove extraneous line breaks before</span>
+  <var>original parent</var>.
+
+  <li>If <var>node list</var>'s last member's [[nextsibling]] is null,
+  but its [[parent]] is not null, <span>remove extraneous line breaks at the
+  end of</span> <var>node list</var>'s last member's [[parent]].
+  <!-- The parent might be null if it's a br that we removed in the last step,
+  in which case this step isn't necessary. -->
+</ol>
+
+<p>To remove a [[node]] <var>node</var> while <dfn>preserving its
+descendants</dfn>, <span>split the parent</span> of <var>node</var>'s
+[[children]].
+
 <p>To <dfn>indent</dfn> a list <var>node list</var> of consecutive [[sibling]]
 [[nodes]]:
 <!--