--- a/editcommands.html	Mon Jul 11 13:58:51 2011 -0600
+++ b/editcommands.html	Tue Jul 12 11:28:30 2011 -0600
@@ -38,7 +38,7 @@
 <body class=draft>
 <div class=head id=head>
 <h1>HTML Editing Commands</h1>
-<h2 class="no-num no-toc" id=work-in-progress-—-last-update-11-july-2011>Work in Progress — Last Update 11 July 2011</h2>
+<h2 class="no-num no-toc" id=work-in-progress-—-last-update-12-july-2011>Work in Progress — Last Update 12 July 2011</h2>
 <dl>
  <dt>Editor
  <dd>Aryeh Gregor <ayg+spec@aryeh.name>
@@ -328,6 +328,15 @@
   especially since in many cases, the command's effect isn't currently
   interoperable anyway.  I'll switch them back to doing nothing if implementers
   think this is a problem.
+
+  <li>The CSS styling flag is an issue.  Currently authors are forced to turn
+  it entirely on or entirely off.  If it's on, it produces stuff like <code title=""><span style=font-weight:bold></code> instead of <code title=""><b></code>, while if it's off, it produces stuff like <code title=""><font color=red></code> instead of <code title=""><span
+  style=color:red></code>.  The issue is that authors might want a mix, like
+  making the markup as concise as possible while still conforming, and they
+  can't do that.  Changing the flag on a per-command basis doesn't help because
+  of things like the "restore the values" algorithm, which might create several
+  different types of style at once and has to use the same styling flag for all
+  of them.
 </ul>
 
 <p class=XXX>A variety of other issues are also noted in the text, formatted
@@ -1521,6 +1530,65 @@
   <a href=#preserving-ranges>preserving ranges</a>.
 </ol>
 
+<p>To <dfn id=record-the-values>record the values</dfn> of a list of <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> <var title="">node list</var>:
+
+<ol>
+  <li>Let <var title="">values</var> be a list of (<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>, <a href=#command>command</a>,
+  <a href=#specified-value>specified value</a>) triples, initially empty.
+
+  <li>For each <var title="">node</var> in <var title="">node list</var>, for each
+  <var title="">command</var> in the list "subscript", "bold", "fontName", "fontSize",
+  "foreColor", "hiliteColor", "italic", "strikethrough", and "underline" in
+  that order:
+  <!-- As with removeFormat, we put subscript first so it doesn't interfere
+  with fontSize, and omit superscript because it's redundant with subscript.
+  -->
+
+  <ol>
+    <li>Let <var title="">ancestor</var> equal <var title="">node</var>.
+
+    <li>If <var title="">ancestor</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>, set it to 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>While <var title="">ancestor</var> is 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> and its <a href=#specified-value>specified
+    value</a> for <var title="">command</var> is null, set it to 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="">ancestor</var> is 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>, add (<var title="">node</var>,
+    <var title="">command</var>, <var title="">ancestor</var>'s <a href=#specified-value>specified value</a> for
+    <var title="">command</var>) to <var title="">values</var>.  Otherwise add (<var title="">node</var>,
+    <var title="">command</var>, null) to <var title="">values</var>.
+  </ol>
+
+  <li>Return <var title="">values</var>.
+</ol>
+
+<p>To <dfn id=restore-the-values>restore the values</dfn> specified by a list <var title="">values</var>
+returned by the <a href=#record-the-values>record the values</a> algorithm:
+
+<ol>
+  <li>For each (<var title="">node</var>, <var title="">command</var>, <var title="">value</var>) triple
+  in <var title="">values</var>:
+
+  <ol>
+    <li>Let <var title="">ancestor</var> equal <var title="">node</var>.
+
+    <li>If <var title="">ancestor</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>, set it to 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>While <var title="">ancestor</var> is 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> and its <a href=#specified-value>specified
+    value</a> for <var title="">command</var> is null, set it to 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="">value</var> is null and <var title="">ancestor</var> is 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>,
+    <a href=#push-down-values>push down values</a> on <var title="">node</var> for <var title="">command</var>,
+    with <var title="">new value</var> null.
+
+    <li>Otherwise, if <var title="">ancestor</var> is 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> and its
+    <a href=#specified-value>specified value</a> for <var title="">command</var> is different from
+    <var title="">value</var>, or if <var title="">ancestor</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> and
+    <var title="">value</var> is not null, <a href=#force-the-value>force the value</a> of
+    <var title="">command</var> to <var title="">value</var> on <var title="">node</var>.
+  </ol>
+</ol>
+
+
 
 <h3 id="clearing-an-element's-value"><span class=secno>7.3 </span>Clearing an element's value</h3>
 
@@ -3063,18 +3131,26 @@
 "dt", or "dd".
 
 <p>The <dfn id=default-single-line-container-name>default single-line container name</dfn> is "p".
-<!-- Possibly to be made configurable later. -->
+<!-- TODO V2: Make this configurable. -->
 
 
 <h3 id=assorted-block-formatting-command-algorithms><span class=secno>8.2 </span>Assorted block formatting command algorithms</h3>
 
 <p>To <dfn id=fix-disallowed-ancestors>fix disallowed ancestors</dfn> of <var title="">node</var>:
+<!-- TODO V2: When breaking a non-inline element out of an inline element, like
+p in b or whatever, it would make sense to re-wrap the contents in the inline
+tag. -->
 
 <ol>
   <li>If <var title="">node</var> is not <a href=#editable>editable</a>, abort these steps.
 
   <li>If <var title="">node</var> is not an <a href=#allowed-child>allowed child</a> of any of its
-  <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestors</a> <a href=#in-the-same-editing-host>in the same editing host</a>:
+  <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestors</a> <a href=#in-the-same-editing-host>in the same editing host</a>, and is not an <a href=#html-element>HTML
+  element</a> with <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-local-name title=concept-element-local-name>local name</a> equal to the <a href=#default-single-line-container-name>default single-line
+  container name</a>:
+  <!-- The requirement about default containers is to prevent an infinite loop.
+  This case is really intended to handle stuff like list items or table cells
+  that wander outside their proper place. -->
 
   <ol>
     <li>If <var title="">node</var> is a <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/html/#the-dd-element>dd</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/html/#the-dt-element>dt</a></code>, <a href=#wrap>wrap</a> the
@@ -3101,9 +3177,14 @@
     <li>Abort these steps.
   </ol>
 
+  <li><a href=#record-the-values>Record the values</a> of the one-<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> list consisting of
+  <var title="">node</var>, and let <var title="">values</var> be the result.
+
   <li>While <var title="">node</var> is not an <a href=#allowed-child>allowed child</a> of 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>, <a href=#split-the-parent>split the parent</a> of the one-<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> list consisting
   of <var title="">node</var>.
+
+  <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
 </ol>
 
 <p>To <dfn id=normalize-sublists>normalize sublists</dfn> in 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="">item</var>:
@@ -3730,7 +3811,7 @@
     <li>If <var title="">end block</var>'s <code class=external data-anolis-spec=domcore title=dom-Node-firstChild><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-firstchild>firstChild</a></code> is not an <a href=#inline-node>inline
     node</a>, abort these steps.
 
-    <li>Let <var title="">children</var> be an array of <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>, initially empty.
+    <li>Let <var title="">children</var> be a list of <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>, initially empty.
 
     <li>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="">end block</var> to
     <var title="">children</var>.
@@ -3740,6 +3821,9 @@
     node</a>, append <var title="">children</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> to
     <var title="">children</var>.
 
+    <li><a href=#record-the-values>Record the values</a> of <var title="">children</var>, and let
+    <var title="">values</var> be the result.
+
     <li>While <var title="">children</var>'s first 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> is not <var title="">start
     block</var>, <a href=#split-the-parent>split the parent</a> of <var title="">children</var>.
 
@@ -3765,9 +3849,21 @@
     node</a> and <var title="">start block</var>'s <code class=external data-anolis-spec=domcore title=dom-Node-lastChild><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-lastchild>lastChild</a></code> 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>, remove
     <var title="">start block</var>'s <code class=external data-anolis-spec=domcore title=dom-Node-lastChild><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-lastchild>lastChild</a></code> from it.
 
-    <li>While 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="">reference node</var> is neither null
-    nor 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> nor a <a href=#block-node>block node</a>, append 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="">reference 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="">start block</var>,
+    <li>Let <var title="">nodes to move</var> be a list of <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>, initially empty.
+
+    <li>If <var title="">reference node</var>'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 neither null nor 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> nor a <a href=#block-node>block node</a>, append it to <var title="">nodes to
+    move</var>.
+
+    <li>While <var title="">nodes to move</var> is nonempty and its 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 neither null nor 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> nor a <a href=#block-node>block node</a>,
+    append it to <var title="">nodes to move</var>.
+
+    <li><a href=#record-the-values>Record the values</a> of <var title="">nodes to move</var>, and let
+    <var title="">values</var> be the result.
+
+    <li>For each <var title="">node</var> in <var title="">nodes to move</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="">start block</var>,
     <a href=#preserving-ranges>preserving ranges</a>.
 
     <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 <var title="">reference node</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>, remove
@@ -3786,6 +3882,9 @@
     and <var title="">start block</var>'s <code class=external data-anolis-spec=domcore title=dom-Node-lastChild><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-lastchild>lastChild</a></code> 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>, remove <var title="">start
     block</var>'s <code class=external data-anolis-spec=domcore title=dom-Node-lastChild><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-lastchild>lastChild</a></code> from it.
 
+    <li><a href=#record-the-values>Record the values</a> of <var title="">end block</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>,
+    and let <var title="">values</var> be the result.
+
     <li>While <var title="">end block</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>, 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="">end block</var> to <var title="">start block</var>, <a href=#preserving-ranges>preserving
     ranges</a>.
@@ -3795,6 +3894,8 @@
     <var title="">parent</var>, then set <var title="">end block</var> to <var title="">parent</var>.
   </ol>
 
+  <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
+
   <li>If <var title="">start block</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>, 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 append the result 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="">start block</var>.
@@ -3806,13 +3907,6 @@
 <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>.
@@ -4342,26 +4436,6 @@
   indentation element, as does the spec.
   -->
 
-  <div class=XXX>
-  <p>We don't handle a case like
-
-  </p><xmp><ol><ol style="color: red"><li>foo<li>bar</ol><li>baz</ol></xmp>
-
-  <p>If the inner <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code> is selected to be outdented, "foo" and "bar" will stop
-  being red.  It seems nontrivial to handle this case in general, since we
-  can't group <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code>s.  If the list we're outdenting is a child of a non-list,
-  then we can just change it to a div.  Hopefully
-  <a href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=13128">HTML bug
-  13128</a> will get fixed, in which case I can just use a div here too.
-  </div>
-  <!--
-  Chrome 12 dev seems to special-case style attributes by converting them to
-  the corresponding inline markup elements (at least in easy cases like color).
-  For other attributes and non-WebKit browsers (IE9/FF4/O11.10), it looks like
-  all the attributes are just removed.  Maybe we should try to copy WebKit
-  here.
-  -->
-
   <ol>
     <li>Unset the <code class=external data-anolis-spec=html title=attr-ol-reversed><a href=http://www.whatwg.org/html/#attr-ol-reversed>reversed</a></code>, <code class=external data-anolis-spec=html title=attr-ol-start><a href=http://www.whatwg.org/html/#attr-ol-start>start</a></code>, and <code class=external data-anolis-spec=html title=attr-ol-type><a href=http://www.whatwg.org/html/#attr-ol-type>type</a></code> attributes of <var title="">node</var>, if any are
     set.
@@ -4370,8 +4444,23 @@
 
     <li>If <var title="">node</var> has attributes, and 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 an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code>
     or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>, <a href=#set-the-tag-name>set the tag name</a> of <var title="">node</var> to "div".
-
-    <li>Otherwise remove <var title="">node</var>, <a href=#preserving-its-descendants>preserving its descendants</a>.
+    <!--
+    We can't turn it into a div if it's the child of an ol or ul, because
+    that's not currently allowed.  TODO V2: change this if
+    http://www.w3.org/Bugs/Public/show_bug.cgi?id=13128 is fixed and we can
+    make it a div.
+    -->
+
+    <li>Otherwise:
+
+    <ol>
+      <li><a href=#record-the-values>Record the values</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>, and
+      let <var title="">values</var> be the result.
+
+      <li>Remove <var title="">node</var>, <a href=#preserving-its-descendants>preserving its descendants</a>.
+
+      <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
+    </ol>
 
     <li><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of each member of
     <var title="">children</var>.
@@ -4798,10 +4887,15 @@
     <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">tag name</var>, remove the first member from <var title="">node
     list</var> and append it to <var title="">sublist</var>.
 
+    <li><a href=#record-the-values>Record the values</a> of <var title="">sublist</var>, and let
+    <var title="">values</var> be the result.
+
     <li><a href=#split-the-parent>Split the parent</a> of <var title="">sublist</var>.
 
     <li><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of each member of
     <var title="">sublist</var>.
+
+    <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
   </ol>
 
   <li>Otherwise, while <var title="">node list</var> is not empty:
@@ -4822,8 +4916,9 @@
 
     <li>If <var title="">sublist</var> contains more than one member, <a href=#wrap>wrap</a>
     <var title="">sublist</var>, with <a href=#sibling-criteria>sibling criteria</a> matching nothing and
-    <a href=#new-parent-instructions>new parent instructions</a> returning the result of calling <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("li")</a></code> on the
-    <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>.  Let <var title="">node</var> be the result.
+    <a href=#new-parent-instructions>new parent instructions</a> returning the result of calling
+    <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("li")</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>.  Let <var title="">node</var> be
+    the result.
 
     <li>Otherwise, let <var title="">node</var> be the sole member of
     <var title="">sublist</var>.
@@ -4834,14 +4929,18 @@
     <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="">node</var>.
 
+      <li><a href=#record-the-values>Record the values</a> of <var title="">children</var>, and let
+      <var title="">values</var> be the result.
+
       <li>Remove <var title="">node</var>, <a href=#preserving-its-descendants>preserving its descendants</a>.
 
       <li><a href=#wrap>Wrap</a> <var title="">children</var>, with <a href=#sibling-criteria>sibling
       criteria</a> matching any <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-local-name title=concept-element-local-name>local name</a>
-      <var title="">tag name</var> and <a href=#new-parent-instructions>new parent
-      instructions</a> returning the result of calling <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(<var title="">tag
-      name</var>)</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>.  Let <var title="">node</var> be the
-      result.
+      <var title="">tag name</var> and <a href=#new-parent-instructions>new parent instructions</a> returning
+      the result of calling <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(<var title="">tag name</var>)</a></code> on the
+      <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>.  Let <var title="">node</var> be the result.
+
+      <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
 
       <li>Prepend the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendants</a> of <var title="">node</var> that are <a href=#html-element title="HTML element">HTML elements</a> with <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">other
       tag name</var> (if any) to <var title="">node list</var>.
@@ -4883,6 +4982,9 @@
     with <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">other tag name</var>:
 
     <ol>
+      <li><a href=#record-the-values>Record the values</a> of the one-<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> list consisting of
+      <var title="">node</var>, and let <var title="">values</var> be the result.
+
       <li><a href=#split-the-parent>Split the parent</a> of the one-<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> list consisting of
       <var title="">node</var>.
 
@@ -4890,8 +4992,9 @@
       <var title="">node</var>, with <a href=#sibling-criteria>sibling criteria</a> matching any
       <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">tag name</var>,
       and with <a href=#new-parent-instructions>new parent instructions</a> returning the result of
-      calling <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(<var title="">tag
-      name</var>)</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>.
+      calling <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(<var title="">tag name</var>)</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>.
+
+      <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
 
       <li>Prepend the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendants</a> of <var title="">node</var> that are <a href=#html-element title="HTML element">HTML elements</a> with <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">other
       tag name</var> (if any) to <var title="">node list</var>.
@@ -5160,9 +5263,14 @@
     <li><a href=#normalize-sublists>Normalize sublists</a> of each <var title="">item</var> in
     <var title="">items</var>.
 
+    <li><a href=#record-the-values>Record the values</a> of the one-<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> list consisting of
+    <var title="">node</var>, and let <var title="">values</var> be the result.
+
     <li><a href=#split-the-parent>Split the parent</a> of the one-<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> list consisting of
     <var title="">node</var>.
 
+    <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
+
     <li>If <var title="">node</var> is a <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/html/#the-dd-element>dd</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/html/#the-dt-element>dt</a></code>, and it is not an
     <a href=#allowed-child>allowed child</a> of any of its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestors</a> <a href=#in-the-same-editing-host>in the same
     editing host</a>, <a href=#set-the-tag-name>set the tag name</a> of <var title="">node</var> to
@@ -5438,6 +5546,9 @@
   of "p" or a <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/html/#the-dd-element>dd</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/html/#the-dt-element>dt</a></code>, and <var title="">node</var> is not the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of
   a <a href=#prohibited-paragraph-child>prohibited paragraph child</a>.
 
+  <li><a href=#record-the-values>Record the values</a> of <var title="">node list</var>, and let
+  <var title="">values</var> be the result.
+
   <li>For each <var title="">node</var> in <var title="">node list</var>, while <var title="">node</var>
   is the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendant</a> of an <a href=#editable>editable</a> <a href=#html-element>HTML element</a>
   <a href=#in-the-same-editing-host>in the same editing host</a>, which has <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-element-local-name title=concept-element-local-name>local name</a> "address",
@@ -5458,6 +5569,8 @@
   out of lists or tables or such if they happen to be nested in a <div>.
   -->
 
+  <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
+
   <!--
   We have two different behaviors, one for div and p and one for everything
   else.  The basic difference is that for div and p, we assume that it should
@@ -5518,9 +5631,14 @@
       <li>Let <var title="">sublist</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 the first member of
       <var title="">node list</var>.
 
+      <li><a href=#record-the-values>Record the values</a> of <var title="">sublist</var>, and let
+      <var title="">values</var> be the result.
+
       <li>Remove the first member of <var title="">node list</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>,
       <a href=#preserving-its-descendants>preserving its descendants</a>.
 
+      <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
+
       <li>Remove the first member from <var title="">node list</var>.
     </ol>
 
@@ -6777,37 +6895,33 @@
 
   <li>Let <var title="">node list</var> be a list of <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>, initially empty.
 
-  <li>For each <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> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#contained>contained</a> in <var title="">new range</var>:
-
-  <ol>
-    <li>If the last member of <var title="">node list</var> (if any) is an <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a>
-    of <var title="">node</var>, or if <var title="">node</var> is not <a href=#editable>editable</a>,
-    continue with the next <var title="">node</var>.
-
-    <!--
-    This step is kind of weird.  For regular outdenting, we start at the inside
-    and outdent going out, so that we remove the innermost indentation, on the
-    theory that that will produce the cleanest markup (remove the most nodes).
-    For lists, we remove the outermost indentation, because it makes a
-    difference whether we remove inner or outer indentation, and logically we
-    want to remove outer.  E.g.,
-
-      <ol><li>foo</li><ul><li>bar</li></ul></ol>
-
-    should become
-
-      foo<ul><li>bar</li></ul>
-
-    not
-
-      foo<ol><li>bar</li></ol>.
-
-    But this is a bit weird and I'm wondering if it's really correct.
-    -->
-    <li>If <var title="">node</var> has no <a href=#editable>editable</a> <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendants</a>, or is
-    an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>, or is an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code> whose <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 an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code> or
-    <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>, append it to <var title="">node list</var>.
-  </ol>
+  <li>For each <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> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#contained>contained</a> in <var title="">new range</var>,
+  append <var title="">node</var> to <var title="">node list</var> if the last member of
+  <var title="">node list</var> (if any) is not an <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">node</var>;
+  <var title="">node</var> is <a href=#editable>editable</a>; and either <var title="">node</var> has no
+  <a href=#editable>editable</a> <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-descendant title=concept-tree-descendant>descendants</a>, or is an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>, or is an
+  <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code> whose <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 an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>.
+  <!--
+  This step is kind of weird.  For regular outdenting, we start at the inside
+  and outdent going out, so that we remove the innermost indentation, on the
+  theory that that will produce the cleanest markup (remove the most nodes).
+  For lists, we remove the outermost indentation, because it makes a difference
+  whether we remove inner or outer indentation, and logically we want to remove
+  outer.  E.g.,
+
+    <ol><li>foo</li><ul><li>bar</li></ul></ol>
+
+  should become
+
+    foo<ul><li>bar</li></ul>
+
+  not
+
+    foo<ol><li>bar</li></ol>.
+
+  But this is a bit weird and I'm wondering if it's really correct.  TODO V2:
+  Reexamine this.
+  -->
 
   <li>While <var title="">node list</var> is not empty:
 
@@ -6828,10 +6942,15 @@
     list</var> is not an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>, remove the first member of <var title="">node
     list</var> and append it to <var title="">sublist</var>.
 
+    <li><a href=#record-the-values>Record the values</a> of <var title="">sublist</var>, and let
+    <var title="">values</var> be the result.
+
     <li><a href=#split-the-parent>Split the parent</a> of <var title="">sublist</var>.
 
     <li><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of each member of
     <var title="">sublist</var>.
+
+    <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
   </ol>
 </ol>
 
--- a/implementation.js	Mon Jul 11 13:58:51 2011 -0600
+++ b/implementation.js	Tue Jul 12 11:28:30 2011 -0600
@@ -2054,6 +2054,91 @@
 	movePreservingRanges(node, candidate, -1);
 }
 
+function recordValues(nodeList) {
+	// "Let values be a list of (node, command, specified value) triples,
+	// initially empty."
+	var values = [];
+
+	// "For each node in node list, for each command in the list "subscript",
+	// "bold", "fontName", "fontSize", "foreColor", "hiliteColor", "italic",
+	// "strikethrough", and "underline" in that order:"
+	nodeList.forEach(function(node) {
+		["subscript", "bold", "fontname", "fontsize", "forecolor",
+		"hilitecolor", "italic", "strikethrough", "underline"].forEach(function(command) {
+			// "Let ancestor equal node."
+			var ancestor = node;
+
+			// "If ancestor is not an Element, set it to its parent."
+			if (ancestor.nodeType != Node.ELEMENT_NODE) {
+				ancestor = ancestor.parentNode;
+			}
+
+			// "While ancestor is an Element and its specified value for
+			// command is null, set it to its parent."
+			while (ancestor
+			&& ancestor.nodeType == Node.ELEMENT_NODE
+			&& getSpecifiedValue(ancestor, command) === null) {
+				ancestor = ancestor.parentNode;
+			}
+
+			// "If ancestor is an Element, add (node, command, ancestor's
+			// specified value for command) to values. Otherwise add (node,
+			// command, null) to values."
+			if (ancestor && ancestor.nodeType == Node.ELEMENT_NODE) {
+				values.push([node, command, getSpecifiedValue(ancestor, command)]);
+			} else {
+				values.push([node, command, null]);
+			}
+		});
+	});
+
+	// "Return values."
+	return values;
+}
+
+function restoreValues(values) {
+	// "For each (node, command, value) triple in values:"
+	values.forEach(function(triple) {
+		var node = triple[0];
+		var command = triple[1];
+		var value = triple[2];
+
+		// "Let ancestor equal node."
+		var ancestor = node;
+
+		// "If ancestor is not an Element, set it to its parent."
+		if (!ancestor || ancestor.nodeType != Node.ELEMENT_NODE) {
+			ancestor = ancestor.parentNode;
+		}
+
+		// "While ancestor is an Element and its specified value for command is
+		// null, set it to its parent."
+		while (ancestor
+		&& ancestor.nodeType == Node.ELEMENT_NODE
+		&& getSpecifiedValue(ancestor, command) === null) {
+			ancestor = ancestor.parentNode;
+		}
+
+		// "If value is null and ancestor is an Element, push down values on
+		// node for command, with new value null."
+		if (value === null
+		&& ancestor
+		&& ancestor.nodeType == Node.ELEMENT_NODE) {
+			pushDownValues(node, command, null);
+
+		// "Otherwise, if ancestor is an Element and its specified value for
+		// command is different from value, or if ancestor is not an Element
+		// and value is not null, force the value of command to value on node."
+		} else if ((ancestor
+		&& ancestor.nodeType == Node.ELEMENT_NODE
+		&& !valuesEqual(command, getSpecifiedValue(ancestor, command), value))
+		|| ((!ancestor || ancestor.nodeType != Node.ELEMENT_NODE)
+		&& value !== null)) {
+			forceValue(node, command, value);
+		}
+	});
+}
+
 //@}
 
 ///// Clearing an element's value /////
@@ -3443,11 +3528,13 @@
 	}
 
 	// "If node is not an allowed child of any of its ancestors in the same
-	// editing host:"
+	// editing host, and is not an HTML element with local name equal to the
+	// default single-line container name:"
 	if (getAncestors(node).every(function(ancestor) {
 		return !inSameEditingHost(node, ancestor)
 			|| !isAllowedChild(node, ancestor)
-	})) {
+	})
+	&& !isHtmlElement(node, defaultSingleLineContainerName)) {
 		// "If node is a dd or dt, wrap the one-node list consisting of node,
 		// with sibling criteria matching any dl with no attributes, and new
 		// parent instructions returning the result of calling
@@ -3483,11 +3570,18 @@
 		return;
 	}
 
+	// "Record the values of the one-node list consisting of node, and let
+	// values be the result."
+	var values = recordValues([node]);
+
 	// "While node is not an allowed child of its parent, split the parent of
 	// the one-node list consisting of node."
 	while (!isAllowedChild(node, node.parentNode)) {
 		splitParent([node]);
 	}
+
+	// "Restore the values from values."
+	restoreValues(values);
 }
 
 function normalizeSublists(item) {
@@ -4189,7 +4283,7 @@
 			return;
 		}
 
-		// "Let children be an array of nodes, initially empty."
+		// "Let children be a list of nodes, initially empty."
 		var children = [];
 
 		// "Append the first child of end block to children."
@@ -4203,6 +4297,9 @@
 			children.push(children[children.length - 1].nextSibling);
 		}
 
+		// "Record the values of children, and let values be the result."
+		var values = recordValues(children);
+
 		// "While children's first member's parent is not start block, split
 		// the parent of children."
 		while (children[0].parentNode != startBlock) {
@@ -4239,14 +4336,35 @@
 			startBlock.removeChild(startBlock.lastChild);
 		}
 
-		// "While the nextSibling of reference node is neither null nor a br
-		// nor a block node, append the nextSibling of reference node as the
-		// last child of start block, preserving ranges."
-		while (referenceNode.nextSibling
+		// "Let nodes to move be a list of nodes, initially empty."
+		var nodesToMove = [];
+
+		// "If reference node's nextSibling is neither null nor a br nor a
+		// block node, append it to nodes to move."
+		if (referenceNode.nextSibling
 		&& !isHtmlElement(referenceNode.nextSibling, "br")
 		&& !isBlockNode(referenceNode.nextSibling)) {
-			movePreservingRanges(referenceNode.nextSibling, startBlock, -1);
-		}
+			nodesToMove.push(referenceNode.nextSibling);
+		}
+
+		// "While nodes to move is nonempty and its last member's nextSibling
+		// is neither null nor a br nor a block node, append it to nodes to
+		// move."
+		if (nodesToMove.length
+		&& nodesToMove[nodesToMove.length - 1].nextSibling
+		&& !isHtmlElement(nodesToMove[nodesToMove.length - 1].nextSibling, "br")
+		&& !isBlockNode(nodesToMove[nodesToMove.length - 1].nextSibling)) {
+			nodesToMove.push(nodesToMove[nodesToMove.length - 1].nextSibling);
+		}
+
+		// "Record the values of nodes to move, and let values be the result."
+		var values = recordValues(nodesToMove);
+
+		// "For each node in nodes to move, append node as the last child of
+		// start block, preserving ranges."
+		nodesToMove.forEach(function(node) {
+			movePreservingRanges(node, startBlock, -1);
+		});
 
 		// "If the nextSibling of reference node is a br, remove it from its
 		// parent."
@@ -4268,6 +4386,10 @@
 			startBlock.removeChild(startBlock.lastChild);
 		}
 
+		// "Record the values of end block's children, and let values be the
+		// result."
+		var values = recordValues([].slice.call(endBlock.childNodes));
+
 		// "While end block has children, append the first child of end block
 		// to start block, preserving ranges."
 		while (endBlock.hasChildNodes()) {
@@ -4284,6 +4406,9 @@
 		}
 	}
 
+	// "Restore the values from values."
+	restoreValues(values);
+
 	// "If start block has no children, call createElement("br") on the context
 	// object and append the result as the last child of start block."
 	if (!startBlock.hasChildNodes()) {
@@ -4794,9 +4919,17 @@
 		&& !isHtmlElement(node.parentNode, ["OL", "UL"])) {
 			setTagName(node, "div");
 
-		// "Otherwise remove node, preserving its descendants."
+		// "Otherwise:"
 		} else {
+			// "Record the values of node's children, and let values be the
+			// result."
+			var values = recordValues([].slice.call(node.childNodes));
+
+			// "Remove node, preserving its descendants."
 			removePreservingDescendants(node);
+
+			// "Restore the values from values."
+			restoreValues(values);
 		}
 
 		// "Fix disallowed ancestors of each member of children."
@@ -4877,24 +5010,13 @@
 
 	// "Let items be a list of all lis that are ancestor containers of the
 	// range's start and/or end node."
-	//
-	// Has to be in tree order, remember!
-	var items = [];
-	for (var node = range.endContainer; node != range.commonAncestorContainer; node = node.parentNode) {
-		if (isHtmlElement(node, "LI")) {
-			items.unshift(node);
-		}
-	}
-	for (var node = range.startContainer; node != range.commonAncestorContainer; node = node.parentNode) {
-		if (isHtmlElement(node, "LI")) {
-			items.unshift(node);
-		}
-	}
-	for (var node = range.commonAncestorContainer; node; node = node.parentNode) {
-		if (isHtmlElement(node, "LI")) {
-			items.unshift(node);
-		}
-	}
+	var items = getDescendants(document).filter(function(node) {
+		return isHtmlElement(node, "li")
+			&& (isAncestor(node, range.startContainer)
+			|| node == range.startContainer
+			|| isAncestor(node, range.endContainer)
+			|| node == range.endContainer);
+	});
 
 	// "For each item in items, normalize sublists of item."
 	for (var i = 0; i < items.length; i++) {
@@ -4905,28 +5027,19 @@
 	var newRange = blockExtend(range);
 
 	// "Let node list be a list of nodes, initially empty."
-	var nodeList = [];
-
+	//
 	// "For each node node contained in new range, if node is editable; the
 	// last member of node list (if any) is not an ancestor of node; node
 	// is not an indentation element; and either node is an ol or ul, or its
 	// parent is an ol or ul, or it is an allowed child of "li"; then append
 	// node to node list."
-	for (
-		var node = newRange.startContainer;
-		node != nextNodeDescendants(newRange.endContainer);
-		node = nextNode(node)
-	) {
-		if (isEditable(node)
-		&& isContained(node, newRange)
-		&& (!nodeList.length || !isAncestor(nodeList[nodeList.length - 1], node))
+	var nodeList = getContainedNodes(newRange, function(node) {
+		return isEditable(node)
 		&& !isIndentationElement(node)
 		&& (isHtmlElement(node, ["OL", "UL"])
 		|| isHtmlElement(node.parentNode, ["OL", "UL"])
-		|| isAllowedChild(node, "li"))) {
-			nodeList.push(node);
-		}
-	}
+		|| isAllowedChild(node, "li"));
+	});
 
 	// "If mode is "disable", then while node list is not empty:"
 	if (mode == "disable") {
@@ -4956,6 +5069,9 @@
 				sublist.push(nodeList.shift());
 			}
 
+			// "Record the values of sublist, and let values be the result."
+			var values = recordValues(sublist);
+
 			// "Split the parent of sublist."
 			splitParent(sublist);
 
@@ -4963,6 +5079,9 @@
 			for (var i = 0; i < sublist.length; i++) {
 				fixDisallowedAncestors(sublist[i]);
 			}
+
+			// "Restore the values from values."
+			restoreValues(values);
 		}
 
 	// "Otherwise, while node list is not empty:"
@@ -5009,6 +5128,10 @@
 				// "Let children be the children of node."
 				var children = [].slice.call(node.childNodes);
 
+				// "Record the values of children, and let values be the
+				// result."
+				var values = recordValues(children);
+
 				// "Remove node, preserving its descendants."
 				removePreservingDescendants(node);
 
@@ -5020,6 +5143,9 @@
 					function(node) { return isHtmlElement(node, tagName) },
 					function() { return document.createElement(tagName) });
 
+				// "Restore the values from values."
+				restoreValues(values);
+
 				// "Prepend the descendants of node that are HTML elements with
 				// local name other tag name (if any) to node list."
 				nodeList = [].slice.call(node.querySelectorAll(otherTagName)).concat(nodeList);
@@ -5037,6 +5163,10 @@
 			// "If node is the child of an HTML element with local name other
 			// tag name:"
 			if (isHtmlElement(node.parentNode, otherTagName)) {
+				// "Record the values of the one-node list consisting of node,
+				// and let values be the result."
+				var values = recordValues([node]);
+
 				// "Split the parent of the one-node list consisting of
 				// node."
 				splitParent([node]);
@@ -5049,6 +5179,9 @@
 					function(node) { return isHtmlElement(node, tagName) },
 					function() { return document.createElement(tagName) });
 
+				// "Restore the values from values."
+				restoreValues(values);
+
 				// "Prepend the descendants of node that are HTML elements with
 				// local name other tag name (if any) to node list."
 				nodeList = [].slice.call(node.querySelectorAll(otherTagName)).concat(nodeList);
@@ -5350,9 +5483,16 @@
 				normalizeSublists(items[i]);
 			}
 
+			// "Record the values of the one-node list consisting of node, and
+			// let values be the result."
+			var values = recordValues([node]);
+
 			// "Split the parent of the one-node list consisting of node."
 			splitParent([node]);
 
+			// "Restore the values from values."
+			restoreValues(values);
+
 			// "If node is a dd or dt, and it is not an allowed child of any of
 			// its ancestors in the same editing host, set the tag name of node
 			// to the default single-line container name and let node be the
@@ -5595,6 +5735,9 @@
 				&& !getDescendants(node).some(isProhibitedParagraphChild);
 		});
 
+		// "Record the values of node list, and let values be the result."
+		var values = recordValues(nodeList);
+
 		// "For each node in node list, while node is the descendant of an
 		// editable HTML element in the same editing host, which has local name
 		// "address", "dd", "div", "dt", "h1", "h2", "h3", "h4", "h5", "h6",
@@ -5613,6 +5756,9 @@
 			}
 		}
 
+		// "Restore the values from values."
+		restoreValues(values);
+
 		// "While node list is not empty:"
 		while (nodeList.length) {
 			var sublist;
@@ -5624,10 +5770,17 @@
 				// list."
 				sublist = [].slice.call(nodeList[0].childNodes);
 
+				// "Record the values of sublist, and let values be the
+				// result."
+				var values = recordValues(sublist);
+
 				// "Remove the first member of node list from its parent,
 				// preserving its descendants."
 				removePreservingDescendants(nodeList[0]);
 
+				// "Restore the values from values."
+				restoreValues(values);
+
 				// "Remove the first member from node list."
 				nodeList.shift();
 
@@ -6891,24 +7044,13 @@
 	action: function() {
 		// "Let items be a list of all lis that are ancestor containers of the
 		// active range's start and/or end node."
-		//
-		// Has to be in tree order, remember!
-		var items = [];
-		for (var node = getActiveRange().endContainer; node != getActiveRange().commonAncestorContainer; node = node.parentNode) {
-			if (isHtmlElement(node, "LI")) {
-				items.unshift(node);
-			}
-		}
-		for (var node = getActiveRange().startContainer; node != getActiveRange().commonAncestorContainer; node = node.parentNode) {
-			if (isHtmlElement(node, "LI")) {
-				items.unshift(node);
-			}
-		}
-		for (var node = getActiveRange().commonAncestorContainer; node; node = node.parentNode) {
-			if (isHtmlElement(node, "LI")) {
-				items.unshift(node);
-			}
-		}
+		var items = getDescendants(document).filter(function(node) {
+			return isHtmlElement(node, "li")
+				&& (isAncestor(node, getActiveRange().startContainer)
+				|| node == getActiveRange().startContainer
+				|| isAncestor(node, getActiveRange().endContainer)
+				|| node == getActiveRange().endContainer);
+		});
 
 		// "For each item in items, normalize sublists of item."
 		for (var i = 0; i < items.length; i++) {
@@ -6919,34 +7061,17 @@
 		var newRange = blockExtend(getActiveRange());
 
 		// "Let node list be a list of nodes, initially empty."
-		var nodeList = [];
-
-		// "For each node node contained in new range:"
-		for (
-			var node = newRange.startContainer;
-			node != nextNodeDescendants(newRange.endContainer);
-			node = nextNode(node)
-		) {
-			if (!isContained(node, newRange)) {
-				continue;
-			}
-
-			// "If the last member of node list (if any) is an ancestor of
-			// node, or if node is not editable, continue with the next node."
-			if ((nodeList.length && isAncestor(nodeList[nodeList.length - 1], node))
-			|| !isEditable(node)) {
-				continue;
-			}
-
-			// "If node has no editable descendants, or is an ol or ul, or is
-			// an li whose parent is an ol or ul, append it to node list."
-			if (!hasEditableDescendants(node)
-			|| isHtmlElement(node, ["OL", "UL"])
-			|| (isHtmlElement(node, "LI")
-			&& isHtmlElement(node.parentNode, ["OL", "UL"]))) {
-				nodeList.push(node);
-			}
-		}
+		//
+		// "For each node node contained in new range, append node to node list
+		// if the last member of node list (if any) is not an ancestor of node;
+		// node is editable; and either node has no editable descendants, or is
+		// an ol or ul, or is an li whose parent is an ol or ul."
+		var nodeList = getContainedNodes(newRange, function(node) {
+			return isEditable(node)
+				&& (!getDescendants(node).some(isEditable)
+				|| isHtmlElement(node, ["ol", "ul"])
+				|| (isHtmlElement(node, "li") && isHtmlElement(node.parentNode, ["ol", "ul"])));
+		});
 
 		// "While node list is not empty:"
 		while (nodeList.length) {
@@ -6980,13 +7105,17 @@
 				sublist.push(nodeList.shift());
 			}
 
+			// "Record the values of sublist, and let values be the result."
+			var values = recordValues(sublist);
+
 			// "Split the parent of sublist, with new parent null."
 			splitParent(sublist);
 
 			// "Fix disallowed ancestors of each member of sublist."
-			for (var i = 0; i < sublist.length; i++) {
-				fixDisallowedAncestors(sublist[i]);
-			}
+			sublist.forEach(fixDisallowedAncestors);
+
+			// "Restore the values from values."
+			restoreValues(values);
 		}
 	}
 };
--- a/source.html	Mon Jul 11 13:58:51 2011 -0600
+++ b/source.html	Tue Jul 12 11:28:30 2011 -0600
@@ -256,6 +256,18 @@
   especially since in many cases, the command's effect isn't currently
   interoperable anyway.  I'll switch them back to doing nothing if implementers
   think this is a problem.
+
+  <li>The CSS styling flag is an issue.  Currently authors are forced to turn
+  it entirely on or entirely off.  If it's on, it produces stuff like <code
+  title><span style=font-weight:bold></code> instead of <code
+  title><b></code>, while if it's off, it produces stuff like <code
+  title><font color=red></code> instead of <code title><span
+  style=color:red></code>.  The issue is that authors might want a mix, like
+  making the markup as concise as possible while still conforming, and they
+  can't do that.  Changing the flag on a per-command basis doesn't help because
+  of things like the "restore the values" algorithm, which might create several
+  different types of style at once and has to use the same styling flag for all
+  of them.
 </ul>
 
 <p class=XXX>A variety of other issues are also noted in the text, formatted
@@ -1474,6 +1486,65 @@
   <li>Append the <var>node</var> as the last [[child]] of <var>candidate</var>,
   <span>preserving ranges</span>.
 </ol>
+
+<p>To <dfn>record the values</dfn> of a list of [[nodes]] <var>node list</var>:
+
+<ol>
+  <li>Let <var>values</var> be a list of ([[node]], <span>command</span>,
+  <span>specified value</span>) triples, initially empty.
+
+  <li>For each <var>node</var> in <var>node list</var>, for each
+  <var>command</var> in the list "subscript", "bold", "fontName", "fontSize",
+  "foreColor", "hiliteColor", "italic", "strikethrough", and "underline" in
+  that order:
+  <!-- As with removeFormat, we put subscript first so it doesn't interfere
+  with fontSize, and omit superscript because it's redundant with subscript.
+  -->
+
+  <ol>
+    <li>Let <var>ancestor</var> equal <var>node</var>.
+
+    <li>If <var>ancestor</var> is not an [[element]], set it to its [[parent]].
+
+    <li>While <var>ancestor</var> is an [[element]] and its <span>specified
+    value</span> for <var>command</var> is null, set it to its [[parent]].
+
+    <li>If <var>ancestor</var> is an [[element]], add (<var>node</var>,
+    <var>command</var>, <var>ancestor</var>'s <span>specified value</span> for
+    <var>command</var>) to <var>values</var>.  Otherwise add (<var>node</var>,
+    <var>command</var>, null) to <var>values</var>.
+  </ol>
+
+  <li>Return <var>values</var>.
+</ol>
+
+<p>To <dfn>restore the values</dfn> specified by a list <var>values</var>
+returned by the <span>record the values</span> algorithm:
+
+<ol>
+  <li>For each (<var>node</var>, <var>command</var>, <var>value</var>) triple
+  in <var>values</var>:
+
+  <ol>
+    <li>Let <var>ancestor</var> equal <var>node</var>.
+
+    <li>If <var>ancestor</var> is not an [[element]], set it to its [[parent]].
+
+    <li>While <var>ancestor</var> is an [[element]] and its <span>specified
+    value</span> for <var>command</var> is null, set it to its [[parent]].
+
+    <li>If <var>value</var> is null and <var>ancestor</var> is an [[element]],
+    <span>push down values</span> on <var>node</var> for <var>command</var>,
+    with <var>new value</var> null.
+
+    <li>Otherwise, if <var>ancestor</var> is an [[element]] and its
+    <span>specified value</span> for <var>command</var> is different from
+    <var>value</var>, or if <var>ancestor</var> is not an [[element]] and
+    <var>value</var> is not null, <span>force the value</span> of
+    <var>command</var> to <var>value</var> on <var>node</var>.
+  </ol>
+</ol>
+
 <!-- @} -->
 
 <h3>Clearing an element's value</h3>
@@ -3039,18 +3110,26 @@
 "dt", or "dd".
 
 <p>The <dfn>default single-line container name</dfn> is "p".
-<!-- Possibly to be made configurable later. -->
+<!-- TODO V2: Make this configurable. -->
 <!-- @} -->
 
 <h3>Assorted block formatting command algorithms</h3>
 <!-- @{ -->
 <p>To <dfn>fix disallowed ancestors</dfn> of <var>node</var>:
+<!-- TODO V2: When breaking a non-inline element out of an inline element, like
+p in b or whatever, it would make sense to re-wrap the contents in the inline
+tag. -->
 
 <ol>
   <li>If <var>node</var> is not <span>editable</span>, abort these steps.
 
   <li>If <var>node</var> is not an <span>allowed child</span> of any of its
-  [[ancestors]] <span>in the same editing host</span>:
+  [[ancestors]] <span>in the same editing host</span>, and is not an <span>HTML
+  element</span> with [[localname]] equal to the <span>default single-line
+  container name</span>:
+  <!-- The requirement about default containers is to prevent an infinite loop.
+  This case is really intended to handle stuff like list items or table cells
+  that wander outside their proper place. -->
 
   <ol>
     <li>If <var>node</var> is a [[dd]] or [[dt]], <span>wrap</span> the
@@ -3077,9 +3156,14 @@
     <li>Abort these steps.
   </ol>
 
+  <li><span>Record the values</span> of the one-[[node]] list consisting of
+  <var>node</var>, and let <var>values</var> be the result.
+
   <li>While <var>node</var> is not an <span>allowed child</span> of its
   [[parent]], <span>split the parent</span> of the one-[[node]] list consisting
   of <var>node</var>.
+
+  <li><span>Restore the values</span> from <var>values</var>.
 </ol>
 
 <p>To <dfn>normalize sublists</dfn> in a [[node]] <var>item</var>:
@@ -3709,7 +3793,7 @@
     <li>If <var>end block</var>'s [[firstchild]] is not an <span>inline
     node</span>, abort these steps.
 
-    <li>Let <var>children</var> be an array of [[nodes]], initially empty.
+    <li>Let <var>children</var> be a list of [[nodes]], initially empty.
 
     <li>Append the first [[child]] of <var>end block</var> to
     <var>children</var>.
@@ -3719,6 +3803,9 @@
     node</span>, append <var>children</var>'s last member's [[nextsibling]] to
     <var>children</var>.
 
+    <li><span>Record the values</span> of <var>children</var>, and let
+    <var>values</var> be the result.
+
     <li>While <var>children</var>'s first member's [[parent]] is not <var>start
     block</var>, <span>split the parent</span> of <var>children</var>.
 
@@ -3744,9 +3831,21 @@
     node</span> and <var>start block</var>'s [[lastchild]] is a [[br]], remove
     <var>start block</var>'s [[lastchild]] from it.
 
-    <li>While the [[nextsibling]] of <var>reference node</var> is neither null
-    nor a [[br]] nor a <span>block node</span>, append the [[nextsibling]] of
-    <var>reference node</var> as the last [[child]] of <var>start block</var>,
+    <li>Let <var>nodes to move</var> be a list of [[nodes]], initially empty.
+
+    <li>If <var>reference node</var>'s [[nextsibling]] is neither null nor a
+    [[br]] nor a <span>block node</span>, append it to <var>nodes to
+    move</var>.
+
+    <li>While <var>nodes to move</var> is nonempty and its last member's
+    [[nextsibling]] is neither null nor a [[br]] nor a <span>block node</span>,
+    append it to <var>nodes to move</var>.
+
+    <li><span>Record the values</span> of <var>nodes to move</var>, and let
+    <var>values</var> be the result.
+
+    <li>For each <var>node</var> in <var>nodes to move</var>, append
+    <var>node</var> as the last [[child]] of <var>start block</var>,
     <span>preserving ranges</span>.
 
     <li>If the [[nextsibling]] of <var>reference node</var> is a [[br]], remove
@@ -3765,6 +3864,9 @@
     and <var>start block</var>'s [[lastchild]] is a [[br]], remove <var>start
     block</var>'s [[lastchild]] from it.
 
+    <li><span>Record the values</span> of <var>end block</var>'s [[children]],
+    and let <var>values</var> be the result.
+
     <li>While <var>end block</var> has [[children]], append the first [[child]]
     of <var>end block</var> to <var>start block</var>, <span>preserving
     ranges</span>.
@@ -3774,6 +3876,8 @@
     <var>parent</var>, then set <var>end block</var> to <var>parent</var>.
   </ol>
 
+  <li><span>Restore the values</span> from <var>values</var>.
+
   <li>If <var>start block</var> has no [[children]], call
   [[createelement|"br"]] on the [[contextobject]] and append the result as the
   last [[child]] of <var>start block</var>.
@@ -3785,13 +3889,6 @@
 <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>.
@@ -4326,26 +4423,6 @@
   indentation element, as does the spec.
   -->
 
-  <div class=XXX>
-  <p>We don't handle a case like
-
-  <xmp><ol><ol style="color: red"><li>foo<li>bar</ol><li>baz</ol></xmp>
-
-  <p>If the inner [[ol]] is selected to be outdented, "foo" and "bar" will stop
-  being red.  It seems nontrivial to handle this case in general, since we
-  can't group [[li]]s.  If the list we're outdenting is a child of a non-list,
-  then we can just change it to a div.  Hopefully
-  <a href=http://www.w3.org/Bugs/Public/show_bug.cgi?id=13128>HTML bug
-  13128</a> will get fixed, in which case I can just use a div here too.
-  </div>
-  <!--
-  Chrome 12 dev seems to special-case style attributes by converting them to
-  the corresponding inline markup elements (at least in easy cases like color).
-  For other attributes and non-WebKit browsers (IE9/FF4/O11.10), it looks like
-  all the attributes are just removed.  Maybe we should try to copy WebKit
-  here.
-  -->
-
   <ol>
     <li>Unset the <code data-anolis-spec=html
     title=attr-ol-reversed>reversed</code>, <code data-anolis-spec=html
@@ -4357,8 +4434,23 @@
 
     <li>If <var>node</var> has attributes, and its [[parent]] is not an [[ol]]
     or [[ul]], <span>set the tag name</span> of <var>node</var> to "div".
-
-    <li>Otherwise remove <var>node</var>, <span>preserving its descendants</span>.
+    <!--
+    We can't turn it into a div if it's the child of an ol or ul, because
+    that's not currently allowed.  TODO V2: change this if
+    http://www.w3.org/Bugs/Public/show_bug.cgi?id=13128 is fixed and we can
+    make it a div.
+    -->
+
+    <li>Otherwise:
+
+    <ol>
+      <li><span>Record the values</span> of <var>node</var>'s [[children]], and
+      let <var>values</var> be the result.
+
+      <li>Remove <var>node</var>, <span>preserving its descendants</span>.
+
+      <li><span>Restore the values</span> from <var>values</var>.
+    </ol>
 
     <li><span>Fix disallowed ancestors</span> of each member of
     <var>children</var>.
@@ -4785,10 +4877,15 @@
     [[localname]] <var>tag name</var>, remove the first member from <var>node
     list</var> and append it to <var>sublist</var>.
 
+    <li><span>Record the values</span> of <var>sublist</var>, and let
+    <var>values</var> be the result.
+
     <li><span>Split the parent</span> of <var>sublist</var>.
 
     <li><span>Fix disallowed ancestors</span> of each member of
     <var>sublist</var>.
+
+    <li><span>Restore the values</span> from <var>values</var>.
   </ol>
 
   <li>Otherwise, while <var>node list</var> is not empty:
@@ -4809,10 +4906,9 @@
 
     <li>If <var>sublist</var> contains more than one member, <span>wrap</span>
     <var>sublist</var>, with <span>sibling criteria</span> matching nothing and
-    <span>new parent instructions</span> returning the result of calling <code
-    data-anolis-spec=domcore
-    title=dom-Document-createElement>createElement("li")</code> on the
-    [[contextobject]].  Let <var>node</var> be the result.
+    <span>new parent instructions</span> returning the result of calling
+    [[createelement|"li"]] on the [[contextobject]].  Let <var>node</var> be
+    the result.
 
     <li>Otherwise, let <var>node</var> be the sole member of
     <var>sublist</var>.
@@ -4823,16 +4919,18 @@
     <ol>
       <li>Let <var>children</var> be the [[children]] of <var>node</var>.
 
+      <li><span>Record the values</span> of <var>children</var>, and let
+      <var>values</var> be the result.
+
       <li>Remove <var>node</var>, <span>preserving its descendants</span>.
 
       <li><span>Wrap</span> <var>children</var>, with <span>sibling
       criteria</span> matching any <span>HTML element</span> with [[localname]]
-      <var>tag name</var> and <span>new parent
-      instructions</span> returning the result of calling <code
-      data-anolis-spec=domcore
-      title=dom-Document-createElement>createElement(<var>tag
-      name</var>)</code> on the [[contextobject]].  Let <var>node</var> be the
-      result.
+      <var>tag name</var> and <span>new parent instructions</span> returning
+      the result of calling [[createelement|<var>tag name</var>]] on the
+      [[contextobject]].  Let <var>node</var> be the result.
+
+      <li><span>Restore the values</span> from <var>values</var>.
 
       <li>Prepend the [[descendants]] of <var>node</var> that are <span
       title="HTML element">HTML elements</span> with [[localname]] <var>other
@@ -4875,6 +4973,9 @@
     with [[localname]] <var>other tag name</var>:
 
     <ol>
+      <li><span>Record the values</span> of the one-[[node]] list consisting of
+      <var>node</var>, and let <var>values</var> be the result.
+
       <li><span>Split the parent</span> of the one-[[node]] list consisting of
       <var>node</var>.
 
@@ -4882,9 +4983,9 @@
       <var>node</var>, with <span>sibling criteria</span> matching any
       <span>HTML element</span> with [[localname]] <var>tag name</var>,
       and with <span>new parent instructions</span> returning the result of
-      calling <code data-anolis-spec=domcore
-      title=dom-Document-createElement>createElement(<var>tag
-      name</var>)</code> on the [[contextobject]].
+      calling [[createelement|<var>tag name</var>]] on the [[contextobject]].
+
+      <li><span>Restore the values</span> from <var>values</var>.
 
       <li>Prepend the [[descendants]] of <var>node</var> that are <span
       title="HTML element">HTML elements</span> with [[localname]] <var>other
@@ -5159,9 +5260,14 @@
     <li><span>Normalize sublists</span> of each <var>item</var> in
     <var>items</var>.
 
+    <li><span>Record the values</span> of the one-[[node]] list consisting of
+    <var>node</var>, and let <var>values</var> be the result.
+
     <li><span>Split the parent</span> of the one-[[node]] list consisting of
     <var>node</var>.
 
+    <li><span>Restore the values</span> from <var>values</var>.
+
     <li>If <var>node</var> is a [[dd]] or [[dt]], and it is not an
     <span>allowed child</span> of any of its [[ancestors]] <span>in the same
     editing host</span>, <span>set the tag name</span> of <var>node</var> to
@@ -5437,6 +5543,9 @@
   of "p" or a [[dd]] or [[dt]], and <var>node</var> is not the [[ancestor]] of
   a <span>prohibited paragraph child</span>.
 
+  <li><span>Record the values</span> of <var>node list</var>, and let
+  <var>values</var> be the result.
+
   <li>For each <var>node</var> in <var>node list</var>, while <var>node</var>
   is the [[descendant]] of an <span>editable</span> <span>HTML element</span>
   <span>in the same editing host</span>, which has [[localname]] "address",
@@ -5457,6 +5566,8 @@
   out of lists or tables or such if they happen to be nested in a <div>.
   -->
 
+  <li><span>Restore the values</span> from <var>values</var>.
+
   <!--
   We have two different behaviors, one for div and p and one for everything
   else.  The basic difference is that for div and p, we assume that it should
@@ -5517,9 +5628,14 @@
       <li>Let <var>sublist</var> be the [[children]] of the first member of
       <var>node list</var>.
 
+      <li><span>Record the values</span> of <var>sublist</var>, and let
+      <var>values</var> be the result.
+
       <li>Remove the first member of <var>node list</var> from its [[parent]],
       <span>preserving its descendants</span>.
 
+      <li><span>Restore the values</span> from <var>values</var>.
+
       <li>Remove the first member from <var>node list</var>.
     </ol>
 
@@ -6791,37 +6907,33 @@
 
   <li>Let <var>node list</var> be a list of [[nodes]], initially empty.
 
-  <li>For each [[node]] <var>node</var> [[contained]] in <var>new range</var>:
-
-  <ol>
-    <li>If the last member of <var>node list</var> (if any) is an [[ancestor]]
-    of <var>node</var>, or if <var>node</var> is not <span>editable</span>,
-    continue with the next <var>node</var>.
-
-    <!--
-    This step is kind of weird.  For regular outdenting, we start at the inside
-    and outdent going out, so that we remove the innermost indentation, on the
-    theory that that will produce the cleanest markup (remove the most nodes).
-    For lists, we remove the outermost indentation, because it makes a
-    difference whether we remove inner or outer indentation, and logically we
-    want to remove outer.  E.g.,
-
-      <ol><li>foo</li><ul><li>bar</li></ul></ol>
-
-    should become
-
-      foo<ul><li>bar</li></ul>
-
-    not
-
-      foo<ol><li>bar</li></ol>.
-
-    But this is a bit weird and I'm wondering if it's really correct.
-    -->
-    <li>If <var>node</var> has no <span>editable</span> [[descendants]], or is
-    an [[ol]] or [[ul]], or is an [[li]] whose [[parent]] is an [[ol]] or
-    [[ul]], append it to <var>node list</var>.
-  </ol>
+  <li>For each [[node]] <var>node</var> [[contained]] in <var>new range</var>,
+  append <var>node</var> to <var>node list</var> if the last member of
+  <var>node list</var> (if any) is not an [[ancestor]] of <var>node</var>;
+  <var>node</var> is <span>editable</span>; and either <var>node</var> has no
+  <span>editable</span> [[descendants]], or is an [[ol]] or [[ul]], or is an
+  [[li]] whose [[parent]] is an [[ol]] or [[ul]].
+  <!--
+  This step is kind of weird.  For regular outdenting, we start at the inside
+  and outdent going out, so that we remove the innermost indentation, on the
+  theory that that will produce the cleanest markup (remove the most nodes).
+  For lists, we remove the outermost indentation, because it makes a difference
+  whether we remove inner or outer indentation, and logically we want to remove
+  outer.  E.g.,
+
+    <ol><li>foo</li><ul><li>bar</li></ul></ol>
+
+  should become
+
+    foo<ul><li>bar</li></ul>
+
+  not
+
+    foo<ol><li>bar</li></ol>.
+
+  But this is a bit weird and I'm wondering if it's really correct.  TODO V2:
+  Reexamine this.
+  -->
 
   <li>While <var>node list</var> is not empty:
 
@@ -6842,10 +6954,15 @@
     list</var> is not an [[ol]] or [[ul]], remove the first member of <var>node
     list</var> and append it to <var>sublist</var>.
 
+    <li><span>Record the values</span> of <var>sublist</var>, and let
+    <var>values</var> be the result.
+
     <li><span>Split the parent</span> of <var>sublist</var>.
 
     <li><span>Fix disallowed ancestors</span> of each member of
     <var>sublist</var>.
+
+    <li><span>Restore the values</span> from <var>values</var>.
   </ol>
 </ol>
 <!-- @} -->
--- a/tests.js	Mon Jul 11 13:58:51 2011 -0600
+++ b/tests.js	Tue Jul 12 11:28:30 2011 -0600
@@ -433,6 +433,37 @@
 		'<div><div><p>foo</p></div></div><div><div><!--abc--><div>[]bar</div></div></div>',
 		'<div><div><p>foo</p></div></div><div><div><div><!--abc-->[]bar</div></div></div>',
 
+		// Styled stuff with collapsed selection
+		'<p style=color:red>foo<p>[]bar',
+		'<p style=color:red>foo<p style=color:blue>[]bar',
+		'<p>foo<p style=color:blue>[]bar',
+		'<p><font color=red>foo</font><p>[]bar',
+		'<p><font color=red>foo</font><p><font color=blue>[]bar</font>',
+		'<p>foo<p><font color=blue>[]bar</font>',
+		'<p><span style=color:red>foo</font><p>[]bar',
+		'<p><span style=color:red>foo</font><p><span style=color:blue>[]bar</font>',
+		'<p>foo<p><span style=color:blue>[]bar</font>',
+
+		'<p style=background-color:salmon>foo<p>[]bar',
+		'<p style=background-color:salmon>foo<p style=background-color:aqua>[]bar',
+		'<p>foo<p style=background-color:aqua>[]bar',
+		'<p><span style=background-color:salmon>foo</font><p>[]bar',
+		'<p><span style=background-color:salmon>foo</font><p><span style=background-color:aqua>[]bar</font>',
+		'<p>foo<p><span style=background-color:aqua>[]bar</font>',
+
+		'<p style=text-decoration:underline>foo<p>[]bar',
+		'<p style=text-decoration:underline>foo<p style=text-decoration:line-through>[]bar',
+		'<p>foo<p style=text-decoration:line-through>[]bar',
+		'<p><u>foo</u><p>[]bar',
+		'<p><u>foo</u><p><s>[]bar</s>',
+		'<p>foo<p><s>[]bar</s>',
+
+		'<p style=color:red>foo</p>[]bar',
+		'foo<p style=color:blue>[]bar',
+		'<div style=color:red><p style=color:green>foo</div>[]bar',
+		'<div style=color:red><p style=color:green>foo</div><p style=color:blue>[]bar',
+		'<p style=color:red>foo<div style=color:blue><p style=color:green>[]bar',
+
 		// Uncollapsed selection
 		'foo[bar]baz',
 
@@ -1043,6 +1074,8 @@
 		'<p>[foo<h1>bar]</h1>',
 		'<h1>[foo</h1><h2>bar]</h2>',
 		'<div>[foo</div>bar]',
+
+		['<p>', '<div style=color:red>[foo]</div>'],
 	],
 	//@}
 	forwarddelete: [
@@ -1198,6 +1231,37 @@
 		'<div><div><p>foo[]</p></div></div><div><div><!--abc--><div>bar</div></div></div>',
 		'<div><div><p>foo[]</p></div></div><div><div><div><!--abc-->bar</div></div></div>',
 
+		// Styled stuff with collapsed selection
+		'<p style=color:red>foo[]<p>bar',
+		'<p style=color:red>foo[]<p style=color:blue>bar',
+		'<p>foo[]<p style=color:blue>bar',
+		'<p><font color=red>foo[]</font><p>bar',
+		'<p><font color=red>foo[]</font><p><font color=blue>bar</font>',
+		'<p>foo[]<p><font color=blue>bar</font>',
+		'<p><span style=color:red>foo[]</font><p>bar',
+		'<p><span style=color:red>foo[]</font><p><span style=color:blue>bar</font>',
+		'<p>foo[]<p><span style=color:blue>bar</font>',
+
+		'<p style=background-color:salmon>foo[]<p>bar',
+		'<p style=background-color:salmon>foo[]<p style=background-color:aqua>bar',
+		'<p>foo[]<p style=background-color:aqua>bar',
+		'<p><span style=background-color:salmon>foo[]</font><p>bar',
+		'<p><span style=background-color:salmon>foo[]</font><p><span style=background-color:aqua>bar</font>',
+		'<p>foo[]<p><span style=background-color:aqua>bar</font>',
+
+		'<p style=text-decoration:underline>foo[]<p>bar',
+		'<p style=text-decoration:underline>foo[]<p style=text-decoration:line-through>bar',
+		'<p>foo[]<p style=text-decoration:line-through>bar',
+		'<p><u>foo[]</u><p>bar',
+		'<p><u>foo[]</u><p><s>bar</s>',
+		'<p>foo[]<p><s>bar</s>',
+
+		'<p style=color:red>foo[]</p>bar',
+		'foo[]<p style=color:blue>bar',
+		'<div style=color:red><p style=color:green>foo[]</div>bar',
+		'<div style=color:red><p style=color:green>foo[]</div><p style=color:blue>bar',
+		'<p style=color:red>foo[]<div style=color:blue><p style=color:green>bar',
+
 		// Uncollapsed selection (should be same as delete command)
 		'foo[bar]baz',
 
@@ -1639,6 +1703,10 @@
 
 		['<nobr>abc</nobr>', '<nobr>f[o]o</nobr>'],
 		['<nobr>abc</nobr>', 'f[o]o'],
+
+		['<p>abc', '<font color=red>foo[]bar</font>'],
+		['<p>abc', '<span style=color:red>foo[]bar</span>'],
+		['<p>abc', '<span style=font-variant:small-caps>foo[]bar</span>'],
 	],
 	//@}
 	insertimage: [