Un-split out "block-format" algorithm
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Sun, 19 Jun 2011 09:59:35 -0600
changeset 286 0bc95f262c1c
parent 285 5813f549e4d2
child 287 cd35d1aab6a5
Un-split out "block-format" algorithm

Now only one caller, so it doesn't need to be split out.
editcommands.html
implementation.js
source.html
--- a/editcommands.html	Sun Jun 19 09:52:21 2011 -0600
+++ b/editcommands.html	Sun Jun 19 09:59:35 2011 -0600
@@ -104,26 +104,25 @@
    <li><a href=#assorted-block-formatting-command-algorithms><span class=secno>7.2 </span>Assorted block formatting command algorithms</a></li>
    <li><a href=#allowed-children><span class=secno>7.3 </span>Allowed children</a></li>
    <li><a href=#block-extending-a-range><span class=secno>7.4 </span>Block-extending a range</a></li>
-   <li><a href=#block-formatting-a-node-list><span class=secno>7.5 </span>Block-formatting a node list</a></li>
-   <li><a href=#deleting-the-contents-of-a-range><span class=secno>7.6 </span>Deleting the contents of a range</a></li>
-   <li><a href=#outdenting-a-node><span class=secno>7.7 </span>Outdenting a node</a></li>
-   <li><a href=#toggling-lists><span class=secno>7.8 </span>Toggling lists</a></li>
-   <li><a href=#justifying-the-selection><span class=secno>7.9 </span>Justifying the selection</a></li>
-   <li><a href=#the-delete-command><span class=secno>7.10 </span>The <code title="">delete</code> command</a></li>
-   <li><a href=#the-formatblock-command><span class=secno>7.11 </span>The <code title="">formatBlock</code> command</a></li>
-   <li><a href=#the-forwarddelete-command><span class=secno>7.12 </span>The <code title="">forwardDelete</code> command</a></li>
-   <li><a href=#the-indent-command><span class=secno>7.13 </span>The <code title="">indent</code> command</a></li>
-   <li><a href=#the-inserthtml-command><span class=secno>7.14 </span>The <code title="">insertHTML</code> command</a></li>
-   <li><a href=#the-insertimage-command><span class=secno>7.15 </span>The <code title="">insertImage</code> command</a></li>
-   <li><a href=#the-inserthorizontalrule-command><span class=secno>7.16 </span>The <code title="">insertHorizontalRule</code> command</a></li>
-   <li><a href=#the-insertorderedlist-command><span class=secno>7.17 </span>The <code title="">insertOrderedList</code> command</a></li>
-   <li><a href=#the-insertparagraph-command><span class=secno>7.18 </span>The <code title="">insertParagraph</code> command</a></li>
-   <li><a href=#the-insertunorderedlist-command><span class=secno>7.19 </span>The <code title="">insertUnorderedList</code> command</a></li>
-   <li><a href=#the-justifycenter-command><span class=secno>7.20 </span>The <code title="">justifyCenter</code> command</a></li>
-   <li><a href=#the-justifyfull-command><span class=secno>7.21 </span>The <code title="">justifyFull</code> command</a></li>
-   <li><a href=#the-justifyleft-command><span class=secno>7.22 </span>The <code title="">justifyLeft</code> command</a></li>
-   <li><a href=#the-justifyright-command><span class=secno>7.23 </span>The <code title="">justifyRight</code> command</a></li>
-   <li><a href=#the-outdent-command><span class=secno>7.24 </span>The <code title="">outdent</code> command</a></ol></li>
+   <li><a href=#deleting-the-contents-of-a-range><span class=secno>7.5 </span>Deleting the contents of a range</a></li>
+   <li><a href=#outdenting-a-node><span class=secno>7.6 </span>Outdenting a node</a></li>
+   <li><a href=#toggling-lists><span class=secno>7.7 </span>Toggling lists</a></li>
+   <li><a href=#justifying-the-selection><span class=secno>7.8 </span>Justifying the selection</a></li>
+   <li><a href=#the-delete-command><span class=secno>7.9 </span>The <code title="">delete</code> command</a></li>
+   <li><a href=#the-formatblock-command><span class=secno>7.10 </span>The <code title="">formatBlock</code> command</a></li>
+   <li><a href=#the-forwarddelete-command><span class=secno>7.11 </span>The <code title="">forwardDelete</code> command</a></li>
+   <li><a href=#the-indent-command><span class=secno>7.12 </span>The <code title="">indent</code> command</a></li>
+   <li><a href=#the-inserthtml-command><span class=secno>7.13 </span>The <code title="">insertHTML</code> command</a></li>
+   <li><a href=#the-insertimage-command><span class=secno>7.14 </span>The <code title="">insertImage</code> command</a></li>
+   <li><a href=#the-inserthorizontalrule-command><span class=secno>7.15 </span>The <code title="">insertHorizontalRule</code> command</a></li>
+   <li><a href=#the-insertorderedlist-command><span class=secno>7.16 </span>The <code title="">insertOrderedList</code> command</a></li>
+   <li><a href=#the-insertparagraph-command><span class=secno>7.17 </span>The <code title="">insertParagraph</code> command</a></li>
+   <li><a href=#the-insertunorderedlist-command><span class=secno>7.18 </span>The <code title="">insertUnorderedList</code> command</a></li>
+   <li><a href=#the-justifycenter-command><span class=secno>7.19 </span>The <code title="">justifyCenter</code> command</a></li>
+   <li><a href=#the-justifyfull-command><span class=secno>7.20 </span>The <code title="">justifyFull</code> command</a></li>
+   <li><a href=#the-justifyleft-command><span class=secno>7.21 </span>The <code title="">justifyLeft</code> command</a></li>
+   <li><a href=#the-justifyright-command><span class=secno>7.22 </span>The <code title="">justifyRight</code> command</a></li>
+   <li><a href=#the-outdent-command><span class=secno>7.23 </span>The <code title="">outdent</code> command</a></ol></li>
  <li><a href=#miscellaneous-commands><span class=secno>8 </span>Miscellaneous commands</a>
   <ol>
    <li><a href=#the-selectall-command><span class=secno>8.1 </span>The <code title="">selectAll</code> command</a></li>
@@ -3055,147 +3054,7 @@
 </ol>
 
 
-<h3 id=block-formatting-a-node-list><span class=secno>7.5 </span>Block-formatting a node list</h3>
-
-<p class=XXX>Why is this a separate section?  There's only one caller.
-Probably want to merge it back.
-
-<p>To <dfn id=block-format>block-format</dfn> 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="">input nodes</var> to a
-string <var title="">value</var>:
-
-<ol>
-  <li>For each <var title="">node</var> in <var title="">input nodes</var>, while either
-  <var title="">node</var> is 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>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> 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>
-  "address", "h1", "h2", "h3", "h4", "h5", "h6", "p", or "pre"; or
-  <var title="">node</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is not null, and "p" is not an <a href=#allowed-child>allowed
-  child</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-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>.
-
-  <div class=XXX>
-  <p>This is needed so we don't get things like p nested inside address, and
-  instead convert part of the multi-line address into a p.  But div can contain
-  any of these things, so we don't break that apart ever, which is bad.  It
-  means if you have
-
-  </p><xmp><div>foo<br>bar</div></xmp>
-
-  <p>then formatBlocking "foo" then "bar" as p has different results from doing
-  both at once.  Maybe we should split divs as well, but only if they're the
-  parent of the node we're dealing with?  Or just split divs always, and hope
-  the "in the same editing host" thing handles it?
-  </div>
-
-  <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 <var title="">node</var> in <var title="">input nodes</var>, <a href=#fix-prohibited-paragraph-descendants>fix prohibited
-  paragraph descendants</a> of <var title="">node</var>, and append the resulting
-  <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> to <var title="">node list</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
-  be one line per element, while for other elements, we put in multiple lines
-  separated by <br>.  So if you do formatBlock to p on
-
-    <div>foo</div><div>bar</div> or
-    foo<br>bar
-
-  you get
-
-    <p>foo</p><p>bar</p>
-
-  but formatBlock to h1 will get you
-
-    <h1>foo<br>bar</h1>.
-
-  IE9 will just change the elements as they are, so it gives
-  <p>foo</p><p>bar</p> and <h1>foo</h1><h1>bar</h1> for
-  <div>foo</div><div>bar</div>, but <p>foo<br>bar</p> and <h1>foo<br>bar</h1>
-  for foo<br>bar.  This is unreasonable, but the two possible inputs here look
-  identical to the user and might have been produced by identical user input.
-
-  Firefox 5.0a2 will give results like <p>foo</p><p>bar</p> or
-  <h1>foo</h1><h1>bar</h1> no matter what (modulo oddities in its handling of
-  divs).  Opera 11.10 is similar, except it leaves a trailing <br> in the first
-  element.
-
-  Chrome 13 dev will give results like <p>foo<br>bar</p> or <h1>foo<br>bar</h1>
-  no matter what.
-
-  The specced behavior is a compromise between the existing behaviors,
-  predicated on the fact that <h1>foo</h1><h1>bar</h1> almost never makes
-  sense, and <p>foo<br>bar</p> isn't usually what's wanted either.
-  -->
-  <li>If <var title="">value</var> is "div" or "p", then while <var title="">node list</var> is
-  not empty:
-
-  <ol>
-    <li>If the first member of <var title="">node list</var> is a <a href=#non-list-single-line-container>non-list
-    single-line container</a>, <a href=#set-the-tag-name>set the tag name</a> of the first
-    member of <var title="">node list</var> to <var title="">value</var>, then remove the first
-    member from <var title="">node list</var> and continue this loop from the beginning.
-
-    <li>Let <var title="">sublist</var> be an empty 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>.
-
-    <li>Remove the first member of <var title="">node list</var> and append it to
-    <var title="">sublist</var>.
-
-    <li>While <var title="">node list</var> is not empty, and the first member of
-    <var title="">node list</var> is the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of the last member of
-    <var title="">sublist</var>, and the first member of <var title="">node list</var> is not a
-    <a href=#non-list-single-line-container>non-list single-line container</a>, and the last member of
-    <var title="">sublist</var> is not a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, remove the first member of <var title="">node
-    list</var> and append it to <var title="">sublist</var>.
-
-    <li><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 running <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="">value</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>.
-  </ol>
-
-  <li>Otherwise, while <var title="">node list</var> is not empty:
-
-  <ol>
-    <li>If the first member of <var title="">node list</var> is a <a href=#non-list-single-line-container>non-list
-    single-line container</a>:
-
-    <ol>
-      <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>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>Remove the first member from <var title="">node list</var>.
-    </ol>
-
-    <li>Otherwise:
-
-    <ol>
-      <li>Let <var title="">sublist</var> be an empty 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>.
-
-      <li>Remove the first member of <var title="">node list</var> and append it to
-      <var title="">sublist</var>.
-
-      <li>While <var title="">node list</var> is not empty, and the first member of
-      <var title="">node list</var> is the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of the last member of
-      <var title="">sublist</var>, and the first member of <var title="">node list</var> is not a
-      <a href=#non-list-single-line-container>non-list single-line container</a>, and the last member of
-      <var title="">sublist</var> is not a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, remove the first member of <var title="">node
-      list</var> and append it to <var title="">sublist</var>.
-    </ol>
-
-    <li><a href=#wrap>Wrap</a> <var title="">sublist</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="">value</var> and no attributes, and <a href=#new-parent-instructions>new parent
-    instructions</a> returning the result of running
-    <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="">value</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>.
-  </ol>
-</ol>
-
-
-<h3 id=deleting-the-contents-of-a-range><span class=secno>7.6 </span>Deleting the contents of a range</h3>
+<h3 id=deleting-the-contents-of-a-range><span class=secno>7.5 </span>Deleting the contents of a range</h3>
 
 <p>To <dfn id=delete-the-contents>delete the contents</dfn> of a <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> <var title="">range</var>:
 
@@ -3571,7 +3430,7 @@
 </ol>
 
 
-<h3 id=outdenting-a-node><span class=secno>7.7 </span>Outdenting a node</h3>
+<h3 id=outdenting-a-node><span class=secno>7.6 </span>Outdenting a node</h3>
 
 <p>To <dfn id=outdent>outdent</dfn> a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> <var title="">node</var>:
 
@@ -3767,7 +3626,7 @@
 </ol>
 
 
-<h3 id=toggling-lists><span class=secno>7.8 </span>Toggling lists</h3>
+<h3 id=toggling-lists><span class=secno>7.7 </span>Toggling lists</h3>
 
 <!--
 Research for insertOrderedList/insertUnorderedList: tested the following
@@ -4292,7 +4151,7 @@
 </ol>
 
 
-<h3 id=justifying-the-selection><span class=secno>7.9 </span>Justifying the selection</h3>
+<h3 id=justifying-the-selection><span class=secno>7.8 </span>Justifying the selection</h3>
 
 <!--
 There are two basic ways it works: using the align attribute, and using CSS
@@ -4409,7 +4268,7 @@
 </ol>
 
 
-<h3 id=the-delete-command><span class=secno>7.10 </span><dfn>The <code title="">delete</code> command</dfn></h3>
+<h3 id=the-delete-command><span class=secno>7.9 </span><dfn>The <code title="">delete</code> command</dfn></h3>
 
 <p><a href=#action>Action</a>:
 
@@ -4682,7 +4541,7 @@
 </ol>
 
 
-<h3 id=the-formatblock-command><span class=secno>7.11 </span><dfn>The <code title="">formatBlock</code> command</dfn></h3>
+<h3 id=the-formatblock-command><span class=secno>7.10 </span><dfn>The <code title="">formatBlock</code> command</dfn></h3>
 
 <!--
 Tested browser versions: IE9, Firefox 4.0, Chrome 13 dev, Opera 11.10.
@@ -4754,20 +4613,147 @@
   <li><a href=#block-extend>Block-extend</a> the <a href=#active-range>active range</a>, and let <var title="">new
   range</var> be the result.
 
-  <li>Let <var title="">node list</var> be an empty 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>.
+  <li>Let <var title="">original node list</var> be an empty 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>.
 
   <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 it is
-  <a href=#editable>editable</a>, 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>, and <var title="">node</var> is either a
-  <a href=#non-list-single-line-container>non-list single-line container</a> or an <a href=#allowed-child>allowed child</a>
-  of "p".
-
-  <li><a href=#block-format>Block-format</a> <var title="">node list</var>.
+  append <var title="">node</var> to <var title="">original node list</var> if it is
+  <a href=#editable>editable</a>, the last member of <var title="">original 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>, and <var title="">node</var> is either
+  a <a href=#non-list-single-line-container>non-list single-line container</a> or an <a href=#allowed-child>allowed
+  child</a> of "p".
+
+  <li>For each <var title="">node</var> in <var title="">original node list</var>, while either
+  <var title="">node</var> is 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>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> 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>
+  "address", "h1", "h2", "h3", "h4", "h5", "h6", "p", or "pre"; or
+  <var title="">node</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is not null, and "p" is not an <a href=#allowed-child>allowed
+  child</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-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>.
+
+  <div class=XXX>
+  <p>This is needed so we don't get things like p nested inside address, and
+  instead convert part of the multi-line address into a p.  But div can contain
+  any of these things, so we don't break that apart ever, which is bad.  It
+  means if you have
+
+  </p><xmp><div>foo<br>bar</div></xmp>
+
+  <p>then formatBlocking "foo" then "bar" as p has different results from doing
+  both at once.  Maybe we should split divs as well, but only if they're the
+  parent of the node we're dealing with?  Or just split divs always, and hope
+  the "in the same editing host" thing handles it?
+  </div>
+
+  <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 <var title="">node</var> in <var title="">original node list</var>, <a href=#fix-prohibited-paragraph-descendants>fix
+  prohibited paragraph descendants</a> of <var title="">node</var>, and append the
+  resulting <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> to <var title="">node list</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
+  be one line per element, while for other elements, we put in multiple lines
+  separated by <br>.  So if you do formatBlock to p on
+
+    <div>foo</div><div>bar</div> or
+    foo<br>bar
+
+  you get
+
+    <p>foo</p><p>bar</p>
+
+  but formatBlock to h1 will get you
+
+    <h1>foo<br>bar</h1>.
+
+  IE9 will just change the elements as they are, so it gives
+  <p>foo</p><p>bar</p> and <h1>foo</h1><h1>bar</h1> for
+  <div>foo</div><div>bar</div>, but <p>foo<br>bar</p> and <h1>foo<br>bar</h1>
+  for foo<br>bar.  This is unreasonable, but the two possible inputs here look
+  identical to the user and might have been produced by identical user input.
+
+  Firefox 5.0a2 will give results like <p>foo</p><p>bar</p> or
+  <h1>foo</h1><h1>bar</h1> no matter what (modulo oddities in its handling of
+  divs).  Opera 11.10 is similar, except it leaves a trailing <br> in the first
+  element.
+
+  Chrome 13 dev will give results like <p>foo<br>bar</p> or <h1>foo<br>bar</h1>
+  no matter what.
+
+  The specced behavior is a compromise between the existing behaviors,
+  predicated on the fact that <h1>foo</h1><h1>bar</h1> almost never makes
+  sense, and <p>foo<br>bar</p> isn't usually what's wanted either.
+  -->
+  <li>If <var title="">value</var> is "div" or "p", then while <var title="">node list</var> is
+  not empty:
+
+  <ol>
+    <li>If the first member of <var title="">node list</var> is a <a href=#non-list-single-line-container>non-list
+    single-line container</a>, <a href=#set-the-tag-name>set the tag name</a> of the first
+    member of <var title="">node list</var> to <var title="">value</var>, then remove the first
+    member from <var title="">node list</var> and continue this loop from the beginning.
+
+    <li>Let <var title="">sublist</var> be an empty 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>.
+
+    <li>Remove the first member of <var title="">node list</var> and append it to
+    <var title="">sublist</var>.
+
+    <li>While <var title="">node list</var> is not empty, and the first member of
+    <var title="">node list</var> is the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of the last member of
+    <var title="">sublist</var>, and the first member of <var title="">node list</var> is not a
+    <a href=#non-list-single-line-container>non-list single-line container</a>, and the last member of
+    <var title="">sublist</var> is not a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, remove the first member of <var title="">node
+    list</var> and append it to <var title="">sublist</var>.
+
+    <li><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 running <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="">value</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>.
+  </ol>
+
+  <li>Otherwise, while <var title="">node list</var> is not empty:
+
+  <ol>
+    <li>If the first member of <var title="">node list</var> is a <a href=#non-list-single-line-container>non-list
+    single-line container</a>:
+
+    <ol>
+      <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>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>Remove the first member from <var title="">node list</var>.
+    </ol>
+
+    <li>Otherwise:
+
+    <ol>
+      <li>Let <var title="">sublist</var> be an empty 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>.
+
+      <li>Remove the first member of <var title="">node list</var> and append it to
+      <var title="">sublist</var>.
+
+      <li>While <var title="">node list</var> is not empty, and the first member of
+      <var title="">node list</var> is the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of the last member of
+      <var title="">sublist</var>, and the first member of <var title="">node list</var> is not a
+      <a href=#non-list-single-line-container>non-list single-line container</a>, and the last member of
+      <var title="">sublist</var> is not a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, remove the first member of <var title="">node
+      list</var> and append it to <var title="">sublist</var>.
+    </ol>
+
+    <li><a href=#wrap>Wrap</a> <var title="">sublist</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="">value</var> and no attributes, and <a href=#new-parent-instructions>new parent
+    instructions</a> returning the result of running
+    <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="">value</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>.
+  </ol>
 </ol>
 
 
-<h3 id=the-forwarddelete-command><span class=secno>7.12 </span><dfn>The <code title="">forwardDelete</code> command</dfn></h3>
+<h3 id=the-forwarddelete-command><span class=secno>7.11 </span><dfn>The <code title="">forwardDelete</code> command</dfn></h3>
 
 <p><a href=#action>Action</a>:
 <!-- Copy-pasted from delete, see there for comments. -->
@@ -4909,7 +4895,7 @@
 </ol>
 
 
-<h3 id=the-indent-command><span class=secno>7.13 </span><dfn>The <code title="">indent</code> command</dfn></h3>
+<h3 id=the-indent-command><span class=secno>7.12 </span><dfn>The <code title="">indent</code> command</dfn></h3>
 
 <!--
 IE9: Outputs <blockquote style="margin-right: 0px" dir="ltr">, or when
@@ -5013,7 +4999,7 @@
 </ol>
 
 
-<h3 id=the-inserthtml-command><span class=secno>7.14 </span><dfn>The <code title="">insertHTML</code> command</dfn></h3>
+<h3 id=the-inserthtml-command><span class=secno>7.13 </span><dfn>The <code title="">insertHTML</code> command</dfn></h3>
 
 <!--
 Not supported by IE9.  Handling of disallowed children is interesting:
@@ -5083,7 +5069,7 @@
 </ol>
 
 
-<h3 id=the-insertimage-command><span class=secno>7.15 </span><dfn>The <code title="">insertImage</code> command</dfn></h3>
+<h3 id=the-insertimage-command><span class=secno>7.14 </span><dfn>The <code title="">insertImage</code> command</dfn></h3>
 
 <p><a href=#action>Action</a>:
 
@@ -5128,7 +5114,7 @@
 </ol>
 
 
-<h3 id=the-inserthorizontalrule-command><span class=secno>7.16 </span><dfn>The <code title="">insertHorizontalRule</code> command</dfn></h3>
+<h3 id=the-inserthorizontalrule-command><span class=secno>7.15 </span><dfn>The <code title="">insertHorizontalRule</code> command</dfn></h3>
 
 <p><a href=#action>Action</a>:
 
@@ -5181,13 +5167,13 @@
 </ol>
 
 
-<h3 id=the-insertorderedlist-command><span class=secno>7.17 </span><dfn>The <code title="">insertOrderedList</code> command</dfn></h3>
+<h3 id=the-insertorderedlist-command><span class=secno>7.16 </span><dfn>The <code title="">insertOrderedList</code> command</dfn></h3>
 
 <p><a href=#action>Action</a>: <a href=#toggle-lists>Toggle lists</a> with <var title="">tag name</var>
 "ol".
 
 
-<h3 id=the-insertparagraph-command><span class=secno>7.18 </span><dfn>The <code title="">insertParagraph</code> command</dfn></h3>
+<h3 id=the-insertparagraph-command><span class=secno>7.17 </span><dfn>The <code title="">insertParagraph</code> command</dfn></h3>
 
 <!--
 There are three major behaviors here.  Firefox 5.0a2 behaves identically to
@@ -5438,36 +5424,36 @@
 </ol>
 
 
-<h3 id=the-insertunorderedlist-command><span class=secno>7.19 </span><dfn>The <code title="">insertUnorderedList</code> command</dfn></h3>
+<h3 id=the-insertunorderedlist-command><span class=secno>7.18 </span><dfn>The <code title="">insertUnorderedList</code> command</dfn></h3>
 <p><a href=#action>Action</a>: <a href=#toggle-lists>Toggle lists</a> with <var title="">tag name</var>
 "ul".
 
 
-<h3 id=the-justifycenter-command><span class=secno>7.20 </span><dfn>The <code title="">justifyCenter</code> command</dfn></h3>
+<h3 id=the-justifycenter-command><span class=secno>7.19 </span><dfn>The <code title="">justifyCenter</code> command</dfn></h3>
 
 <p><a href=#action>Action</a>: <a href=#justify-the-selection>Justify the selection</a> with
 <var title="">alignment</var> "center".
 
 
-<h3 id=the-justifyfull-command><span class=secno>7.21 </span><dfn>The <code title="">justifyFull</code> command</dfn></h3>
+<h3 id=the-justifyfull-command><span class=secno>7.20 </span><dfn>The <code title="">justifyFull</code> command</dfn></h3>
 
 <p><a href=#action>Action</a>: <a href=#justify-the-selection>Justify the selection</a> with
 <var title="">alignment</var> "justify".
 
 
-<h3 id=the-justifyleft-command><span class=secno>7.22 </span><dfn>The <code title="">justifyLeft</code> command</dfn></h3>
+<h3 id=the-justifyleft-command><span class=secno>7.21 </span><dfn>The <code title="">justifyLeft</code> command</dfn></h3>
 
 <p><a href=#action>Action</a>: <a href=#justify-the-selection>Justify the selection</a> with
 <var title="">alignment</var> "left".
 
 
-<h3 id=the-justifyright-command><span class=secno>7.23 </span><dfn>The <code title="">justifyRight</code> command</dfn></h3>
+<h3 id=the-justifyright-command><span class=secno>7.22 </span><dfn>The <code title="">justifyRight</code> command</dfn></h3>
 
 <p><a href=#action>Action</a>: <a href=#justify-the-selection>Justify the selection</a> with
 <var title="">alignment</var> "right".
 
 
-<h3 id=the-outdent-command><span class=secno>7.24 </span><dfn>The <code title="">outdent</code> command</dfn></h3>
+<h3 id=the-outdent-command><span class=secno>7.23 </span><dfn>The <code title="">outdent</code> command</dfn></h3>
 
 <p><a href=#action>Action</a>:
 
--- a/implementation.js	Sun Jun 19 09:52:21 2011 -0600
+++ b/implementation.js	Sun Jun 19 09:59:35 2011 -0600
@@ -4006,145 +4006,6 @@
 
 //@}
 
-///// Block-formatting a node list /////
-//@{
-
-function blockFormat(inputNodes, value) {
-	// "For each node in input nodes, while either node is a descendant of an
-	// editable HTML element in the same editing host with local name
-	// "address", "h1", "h2", "h3", "h4", "h5", "h6", "p", or "pre"; or node's
-	// parent is not null, and "p" is not an allowed child of node's parent:
-	// split the parent of the one-node list consisting of node."
-	for (var i = 0; i < inputNodes.length; i++) {
-		var node = inputNodes[i];
-
-		while (true) {
-			if (node.parentNode
-			&& !isAllowedChild("p", node.parentNode)) {
-				splitParent([node]);
-				continue;
-			}
-
-			var ancestor = node.parentNode;
-			while (ancestor
-			&& !isHtmlElement(ancestor, ["ADDRESS", "H1", "H2", "H3", "H4", "H5", "H6", "P", "PRE"])) {
-				ancestor = ancestor.parentNode;
-			}
-			if (ancestor
-			&& isEditable(ancestor)
-			&& inSameEditingHost(node, ancestor)) {
-				splitParent([node]);
-			} else {
-				break;
-			}
-		}
-	}
-
-	// "Let node list be a list of nodes, initially empty."
-	var nodeList = [];
-
-	// "For each node in input nodes, fix prohibited paragraph descendants of
-	// node, and append the resulting nodes to node list."
-	for (var i = 0; i < inputNodes.length; i++) {
-		nodeList = nodeList.concat(fixProhibitedParagraphDescendants(inputNodes[i]));
-	}
-
-	// "If value is "div" or "p", then while node list is not empty:"
-	if (value == "div" || value == "p") {
-		while (nodeList.length) {
-			// "If the first member of node list is a non-list single-line
-			// container, set the tag name of the first member of node list
-			// to value, then remove the first member from node list and
-			// continue this loop from the beginning."
-			if (isNonListSingleLineContainer(nodeList[0])) {
-				setTagName(nodeList[0], value);
-				nodeList.shift();
-				continue;
-			}
-
-			// "Let sublist be an empty list of nodes."
-			var sublist = [];
-
-			// "Remove the first member of node list and append it to
-			// sublist."
-			sublist.push(nodeList.shift());
-
-			// "While node list is not empty, and the first member of node
-			// list is the nextSibling of the last member of sublist, and
-			// the first member of node list is not a non-list single-line
-			// container, and the last member of sublist is not a br,
-			// remove the first member of node list and append it to
-			// sublist."
-			while (nodeList.length
-			&& nodeList[0] == sublist[sublist.length - 1].nextSibling
-			&& !isNonListSingleLineContainer(nodeList[0])
-			&& !isHtmlElement(sublist[sublist.length - 1], "BR")) {
-				sublist.push(nodeList.shift());
-			}
-
-			// "Wrap sublist, with sibling criteria matching nothing and
-			// new parent instructions returning the result of running
-			// createElement(value) on the context object."
-			wrap(sublist,
-				function() { return false },
-				function() { return document.createElement(value) });
-		}
-
-	// "Otherwise, while node list is not empty:"
-	} else {
-		while (nodeList.length) {
-			var sublist;
-
-			// "If the first member of node list is a non-list single-line
-			// container:"
-			if (isNonListSingleLineContainer(nodeList[0])) {
-				// "Let sublist be the children of the first member of node
-				// list."
-				sublist = [].slice.call(nodeList[0].childNodes);
-
-				// "Remove the first member of node list from its parent,
-				// preserving its descendants."
-				removePreservingDescendants(nodeList[0]);
-
-				// "Remove the first member from node list."
-				nodeList.shift();
-
-			// "Otherwise:"
-			} else {
-				// "Let sublist be an empty list of nodes."
-				sublist = [];
-
-				// "Remove the first member of node list and append it to
-				// sublist."
-				sublist.push(nodeList.shift());
-
-				// "While node list is not empty, and the first member of
-				// node list is the nextSibling of the last member of
-				// sublist, and the first member of node list is not a
-				// non-list single-line container, and the last member of
-				// sublist is not a br, remove the first member of node
-				// list and append it to sublist."
-				while (nodeList.length
-				&& nodeList[0] == sublist[sublist.length - 1].nextSibling
-				&& !isNonListSingleLineContainer(nodeList[0])
-				&& !isHtmlElement(sublist[sublist.length - 1], "BR")) {
-					sublist.push(nodeList.shift());
-				}
-			}
-
-			// "Wrap sublist, with sibling criteria matching any HTML
-			// element with local name value and no attributes, and new
-			// parent instructions returning the result of running
-			// createElement(value) on the context object."
-			wrap(sublist,
-				function(node) { return isHtmlElement(node, value.toUpperCase()) && !node.attributes.length },
-				function() { return document.createElement(value) });
-		}
-	}
-}
-
-//@}
-
 ///// Outdenting a node /////
 //@{
 
@@ -5003,21 +4864,151 @@
 		// "Block-extend the active range, and let new range be the result."
 		var newRange = blockExtendRange(getActiveRange());
 
-		// "Let node list be an empty list of nodes."
-		var nodeList = [];
-
-		// "For each node node contained in new range, append node to node list
-		// if it is editable, the last member of node list (if any) is not an
-		// ancestor of node, and node is either a non-list single-line
-		// container or an allowed child of "p"."
-		nodeList = collectContainedNodes(newRange, function(node) {
+		// "Let original node list be an empty list of nodes."
+		var originalNodeList = [];
+
+		// "For each node node contained in new range, append node to original
+		// node list if it is editable, the last member of original node list
+		// (if any) is not an ancestor of node, and node is either a non-list
+		// single-line container or an allowed child of "p"."
+		originalNodeList = collectContainedNodes(newRange, function(node) {
 			return isEditable(node)
 				&& (isNonListSingleLineContainer(node)
 				|| isAllowedChild(node, "p"));
 		});
 
-		// "Block-format node list."
-		blockFormat(nodeList, value);
+		// "For each node in original node list, while either node is a
+		// descendant of an editable HTML element in the same editing host with
+		// local name "address", "h1", "h2", "h3", "h4", "h5", "h6", "p", or
+		// "pre"; or node's parent is not null, and "p" is not an allowed child
+		// of node's parent: split the parent of the one-node list consisting
+		// of node."
+		for (var i = 0; i < originalNodeList.length; i++) {
+			var node = originalNodeList[i];
+
+			while (true) {
+				if (node.parentNode
+				&& !isAllowedChild("p", node.parentNode)) {
+					splitParent([node]);
+					continue;
+				}
+
+				var ancestor = node.parentNode;
+				while (ancestor
+				&& !isHtmlElement(ancestor, ["ADDRESS", "H1", "H2", "H3", "H4", "H5", "H6", "P", "PRE"])) {
+					ancestor = ancestor.parentNode;
+				}
+				if (ancestor
+				&& isEditable(ancestor)
+				&& inSameEditingHost(node, ancestor)) {
+					splitParent([node]);
+				} else {
+					break;
+				}
+			}
+		}
+
+		// "Let node list be a list of nodes, initially empty."
+		var nodeList = [];
+
+		// "For each node in original node list, fix prohibited paragraph
+		// descendants of node, and append the resulting nodes to node list."
+		for (var i = 0; i < originalNodeList.length; i++) {
+			nodeList = nodeList.concat(fixProhibitedParagraphDescendants(originalNodeList[i]));
+		}
+
+		// "If value is "div" or "p", then while node list is not empty:"
+		if (value == "div" || value == "p") {
+			while (nodeList.length) {
+				// "If the first member of node list is a non-list single-line
+				// container, set the tag name of the first member of node list
+				// to value, then remove the first member from node list and
+				// continue this loop from the beginning."
+				if (isNonListSingleLineContainer(nodeList[0])) {
+					setTagName(nodeList[0], value);
+					nodeList.shift();
+					continue;
+				}
+
+				// "Let sublist be an empty list of nodes."
+				var sublist = [];
+
+				// "Remove the first member of node list and append it to
+				// sublist."
+				sublist.push(nodeList.shift());
+
+				// "While node list is not empty, and the first member of node
+				// list is the nextSibling of the last member of sublist, and
+				// the first member of node list is not a non-list single-line
+				// container, and the last member of sublist is not a br,
+				// remove the first member of node list and append it to
+				// sublist."
+				while (nodeList.length
+				&& nodeList[0] == sublist[sublist.length - 1].nextSibling
+				&& !isNonListSingleLineContainer(nodeList[0])
+				&& !isHtmlElement(sublist[sublist.length - 1], "BR")) {
+					sublist.push(nodeList.shift());
+				}
+
+				// "Wrap sublist, with sibling criteria matching nothing and
+				// new parent instructions returning the result of running
+				// createElement(value) on the context object."
+				wrap(sublist,
+					function() { return false },
+					function() { return document.createElement(value) });
+			}
+
+		// "Otherwise, while node list is not empty:"
+		} else {
+			while (nodeList.length) {
+				var sublist;
+
+				// "If the first member of node list is a non-list single-line
+				// container:"
+				if (isNonListSingleLineContainer(nodeList[0])) {
+					// "Let sublist be the children of the first member of node
+					// list."
+					sublist = [].slice.call(nodeList[0].childNodes);
+
+					// "Remove the first member of node list from its parent,
+					// preserving its descendants."
+					removePreservingDescendants(nodeList[0]);
+
+					// "Remove the first member from node list."
+					nodeList.shift();
+
+				// "Otherwise:"
+				} else {
+					// "Let sublist be an empty list of nodes."
+					sublist = [];
+
+					// "Remove the first member of node list and append it to
+					// sublist."
+					sublist.push(nodeList.shift());
+
+					// "While node list is not empty, and the first member of
+					// node list is the nextSibling of the last member of
+					// sublist, and the first member of node list is not a
+					// non-list single-line container, and the last member of
+					// sublist is not a br, remove the first member of node
+					// list and append it to sublist."
+					while (nodeList.length
+					&& nodeList[0] == sublist[sublist.length - 1].nextSibling
+					&& !isNonListSingleLineContainer(nodeList[0])
+					&& !isHtmlElement(sublist[sublist.length - 1], "BR")) {
+						sublist.push(nodeList.shift());
+					}
+				}
+
+				// "Wrap sublist, with sibling criteria matching any HTML
+				// element with local name value and no attributes, and new
+				// parent instructions returning the result of running
+				// createElement(value) on the context object."
+				wrap(sublist,
+					function(node) { return isHtmlElement(node, value.toUpperCase()) && !node.attributes.length },
+					function() { return document.createElement(value) });
+			}
+		}
 	}
 };
 //@}
--- a/source.html	Sun Jun 19 09:52:21 2011 -0600
+++ b/source.html	Sun Jun 19 09:59:35 2011 -0600
@@ -3041,146 +3041,6 @@
 </ol>
 <!-- @} -->
 
-<h3>Block-formatting a node list</h3>
-<!-- @{ -->
-<p class=XXX>Why is this a separate section?  There's only one caller.
-Probably want to merge it back.
-
-<p>To <dfn>block-format</dfn> a list of [[nodes]] <var>input nodes</var> to a
-string <var>value</var>:
-
-<ol>
-  <li>For each <var>node</var> in <var>input nodes</var>, while either
-  <var>node</var> is a [[descendant]] of an <span>editable</span> <span>HTML
-  element</span> <span>in the same editing host</span> with [[localname]]
-  "address", "h1", "h2", "h3", "h4", "h5", "h6", "p", or "pre"; or
-  <var>node</var>'s [[parent]] is not null, and "p" is not an <span>allowed
-  child</span> of <var>node</var>'s [[parent]]: <span>split the parent</span>
-  of the one-[[node]] list consisting of <var>node</var>.
-
-  <div class=XXX>
-  <p>This is needed so we don't get things like p nested inside address, and
-  instead convert part of the multi-line address into a p.  But div can contain
-  any of these things, so we don't break that apart ever, which is bad.  It
-  means if you have
-
-  <xmp><div>foo<br>bar</div></xmp>
-
-  <p>then formatBlocking "foo" then "bar" as p has different results from doing
-  both at once.  Maybe we should split divs as well, but only if they're the
-  parent of the node we're dealing with?  Or just split divs always, and hope
-  the "in the same editing host" thing handles it?
-  </div>
-
-  <li>Let <var>node list</var> be a list of [[nodes]], initially empty.
-
-  <li>For each <var>node</var> in <var>input nodes</var>, <span>fix prohibited
-  paragraph descendants</span> of <var>node</var>, and append the resulting
-  [[nodes]] to <var>node list</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
-  be one line per element, while for other elements, we put in multiple lines
-  separated by <br>.  So if you do formatBlock to p on
-
-    <div>foo</div><div>bar</div> or
-    foo<br>bar
-
-  you get
-
-    <p>foo</p><p>bar</p>
-
-  but formatBlock to h1 will get you
-
-    <h1>foo<br>bar</h1>.
-
-  IE9 will just change the elements as they are, so it gives
-  <p>foo</p><p>bar</p> and <h1>foo</h1><h1>bar</h1> for
-  <div>foo</div><div>bar</div>, but <p>foo<br>bar</p> and <h1>foo<br>bar</h1>
-  for foo<br>bar.  This is unreasonable, but the two possible inputs here look
-  identical to the user and might have been produced by identical user input.
-
-  Firefox 5.0a2 will give results like <p>foo</p><p>bar</p> or
-  <h1>foo</h1><h1>bar</h1> no matter what (modulo oddities in its handling of
-  divs).  Opera 11.10 is similar, except it leaves a trailing <br> in the first
-  element.
-
-  Chrome 13 dev will give results like <p>foo<br>bar</p> or <h1>foo<br>bar</h1>
-  no matter what.
-
-  The specced behavior is a compromise between the existing behaviors,
-  predicated on the fact that <h1>foo</h1><h1>bar</h1> almost never makes
-  sense, and <p>foo<br>bar</p> isn't usually what's wanted either.
-  -->
-  <li>If <var>value</var> is "div" or "p", then while <var>node list</var> is
-  not empty:
-
-  <ol>
-    <li>If the first member of <var>node list</var> is a <span>non-list
-    single-line container</span>, <span>set the tag name</span> of the first
-    member of <var>node list</var> to <var>value</var>, then remove the first
-    member from <var>node list</var> and continue this loop from the beginning.
-
-    <li>Let <var>sublist</var> be an empty list of [[nodes]].
-
-    <li>Remove the first member of <var>node list</var> and append it to
-    <var>sublist</var>.
-
-    <li>While <var>node list</var> is not empty, and the first member of
-    <var>node list</var> is the [[nextsibling]] of the last member of
-    <var>sublist</var>, and the first member of <var>node list</var> is not a
-    <span>non-list single-line container</span>, and the last member of
-    <var>sublist</var> is not a [[br]], remove the first member of <var>node
-    list</var> and append it to <var>sublist</var>.
-
-    <li><span>Wrap</span> <var>sublist</var>, with <span>sibling
-    criteria</span> matching nothing and <span>new parent instructions</span>
-    returning the result of running [[createelement|<var>value</var>]] on the
-    [[contextobject]].
-  </ol>
-
-  <li>Otherwise, while <var>node list</var> is not empty:
-
-  <ol>
-    <li>If the first member of <var>node list</var> is a <span>non-list
-    single-line container</span>:
-
-    <ol>
-      <li>Let <var>sublist</var> be the [[children]] of the first member of
-      <var>node list</var>.
-
-      <li>Remove the first member of <var>node list</var> from its [[parent]],
-      <span>preserving its descendants</span>.
-
-      <li>Remove the first member from <var>node list</var>.
-    </ol>
-
-    <li>Otherwise:
-
-    <ol>
-      <li>Let <var>sublist</var> be an empty list of [[nodes]].
-
-      <li>Remove the first member of <var>node list</var> and append it to
-      <var>sublist</var>.
-
-      <li>While <var>node list</var> is not empty, and the first member of
-      <var>node list</var> is the [[nextsibling]] of the last member of
-      <var>sublist</var>, and the first member of <var>node list</var> is not a
-      <span>non-list single-line container</span>, and the last member of
-      <var>sublist</var> is not a [[br]], remove the first member of <var>node
-      list</var> and append it to <var>sublist</var>.
-    </ol>
-
-    <li><span>Wrap</span> <var>sublist</var>, with <span>sibling
-    criteria</span> matching any <span>HTML element</span> with [[localname]]
-    <var>value</var> and no attributes, and <span>new parent
-    instructions</span> returning the result of running
-    [[createelement|<var>value</var>]] on the [[contextobject]].
-  </ol>
-</ol>
-<!-- @} -->
-
 <h3>Deleting the contents of a range</h3>
 <!-- @{ -->
 <p>To <dfn>delete the contents</dfn> of a [[range]] <var>range</var>:
@@ -4758,16 +4618,143 @@
   <li><span>Block-extend</span> the <span>active range</span>, and let <var>new
   range</var> be the result.
 
-  <li>Let <var>node list</var> be an empty list of [[nodes]].
+  <li>Let <var>original node list</var> be an empty list of [[nodes]].
 
   <li>For each [[node]] <var>node</var> [[contained]] in <var>new range</var>,
-  append <var>node</var> to <var>node list</var> if it is
-  <span>editable</span>, the last member of <var>node list</var> (if any) is
-  not an [[ancestor]] of <var>node</var>, and <var>node</var> is either a
-  <span>non-list single-line container</span> or an <span>allowed child</span>
-  of "p".
-
-  <li><span>Block-format</span> <var>node list</var>.
+  append <var>node</var> to <var>original node list</var> if it is
+  <span>editable</span>, the last member of <var>original node list</var> (if
+  any) is not an [[ancestor]] of <var>node</var>, and <var>node</var> is either
+  a <span>non-list single-line container</span> or an <span>allowed
+  child</span> of "p".
+
+  <li>For each <var>node</var> in <var>original node list</var>, while either
+  <var>node</var> is a [[descendant]] of an <span>editable</span> <span>HTML
+  element</span> <span>in the same editing host</span> with [[localname]]
+  "address", "h1", "h2", "h3", "h4", "h5", "h6", "p", or "pre"; or
+  <var>node</var>'s [[parent]] is not null, and "p" is not an <span>allowed
+  child</span> of <var>node</var>'s [[parent]]: <span>split the parent</span>
+  of the one-[[node]] list consisting of <var>node</var>.
+
+  <div class=XXX>
+  <p>This is needed so we don't get things like p nested inside address, and
+  instead convert part of the multi-line address into a p.  But div can contain
+  any of these things, so we don't break that apart ever, which is bad.  It
+  means if you have
+
+  <xmp><div>foo<br>bar</div></xmp>
+
+  <p>then formatBlocking "foo" then "bar" as p has different results from doing
+  both at once.  Maybe we should split divs as well, but only if they're the
+  parent of the node we're dealing with?  Or just split divs always, and hope
+  the "in the same editing host" thing handles it?
+  </div>
+
+  <li>Let <var>node list</var> be a list of [[nodes]], initially empty.
+
+  <li>For each <var>node</var> in <var>original node list</var>, <span>fix
+  prohibited paragraph descendants</span> of <var>node</var>, and append the
+  resulting [[nodes]] to <var>node list</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
+  be one line per element, while for other elements, we put in multiple lines
+  separated by <br>.  So if you do formatBlock to p on
+
+    <div>foo</div><div>bar</div> or
+    foo<br>bar
+
+  you get
+
+    <p>foo</p><p>bar</p>
+
+  but formatBlock to h1 will get you
+
+    <h1>foo<br>bar</h1>.
+
+  IE9 will just change the elements as they are, so it gives
+  <p>foo</p><p>bar</p> and <h1>foo</h1><h1>bar</h1> for
+  <div>foo</div><div>bar</div>, but <p>foo<br>bar</p> and <h1>foo<br>bar</h1>
+  for foo<br>bar.  This is unreasonable, but the two possible inputs here look
+  identical to the user and might have been produced by identical user input.
+
+  Firefox 5.0a2 will give results like <p>foo</p><p>bar</p> or
+  <h1>foo</h1><h1>bar</h1> no matter what (modulo oddities in its handling of
+  divs).  Opera 11.10 is similar, except it leaves a trailing <br> in the first
+  element.
+
+  Chrome 13 dev will give results like <p>foo<br>bar</p> or <h1>foo<br>bar</h1>
+  no matter what.
+
+  The specced behavior is a compromise between the existing behaviors,
+  predicated on the fact that <h1>foo</h1><h1>bar</h1> almost never makes
+  sense, and <p>foo<br>bar</p> isn't usually what's wanted either.
+  -->
+  <li>If <var>value</var> is "div" or "p", then while <var>node list</var> is
+  not empty:
+
+  <ol>
+    <li>If the first member of <var>node list</var> is a <span>non-list
+    single-line container</span>, <span>set the tag name</span> of the first
+    member of <var>node list</var> to <var>value</var>, then remove the first
+    member from <var>node list</var> and continue this loop from the beginning.
+
+    <li>Let <var>sublist</var> be an empty list of [[nodes]].
+
+    <li>Remove the first member of <var>node list</var> and append it to
+    <var>sublist</var>.
+
+    <li>While <var>node list</var> is not empty, and the first member of
+    <var>node list</var> is the [[nextsibling]] of the last member of
+    <var>sublist</var>, and the first member of <var>node list</var> is not a
+    <span>non-list single-line container</span>, and the last member of
+    <var>sublist</var> is not a [[br]], remove the first member of <var>node
+    list</var> and append it to <var>sublist</var>.
+
+    <li><span>Wrap</span> <var>sublist</var>, with <span>sibling
+    criteria</span> matching nothing and <span>new parent instructions</span>
+    returning the result of running [[createelement|<var>value</var>]] on the
+    [[contextobject]].
+  </ol>
+
+  <li>Otherwise, while <var>node list</var> is not empty:
+
+  <ol>
+    <li>If the first member of <var>node list</var> is a <span>non-list
+    single-line container</span>:
+
+    <ol>
+      <li>Let <var>sublist</var> be the [[children]] of the first member of
+      <var>node list</var>.
+
+      <li>Remove the first member of <var>node list</var> from its [[parent]],
+      <span>preserving its descendants</span>.
+
+      <li>Remove the first member from <var>node list</var>.
+    </ol>
+
+    <li>Otherwise:
+
+    <ol>
+      <li>Let <var>sublist</var> be an empty list of [[nodes]].
+
+      <li>Remove the first member of <var>node list</var> and append it to
+      <var>sublist</var>.
+
+      <li>While <var>node list</var> is not empty, and the first member of
+      <var>node list</var> is the [[nextsibling]] of the last member of
+      <var>sublist</var>, and the first member of <var>node list</var> is not a
+      <span>non-list single-line container</span>, and the last member of
+      <var>sublist</var> is not a [[br]], remove the first member of <var>node
+      list</var> and append it to <var>sublist</var>.
+    </ol>
+
+    <li><span>Wrap</span> <var>sublist</var>, with <span>sibling
+    criteria</span> matching any <span>HTML element</span> with [[localname]]
+    <var>value</var> and no attributes, and <span>new parent
+    instructions</span> returning the result of running
+    [[createelement|<var>value</var>]] on the [[contextobject]].
+  </ol>
 </ol>
 <!-- @} -->