Mostly-working insertOrderedList
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Mon, 09 May 2011 15:59:56 -0600
changeset 99 6f63f6aa573a
parent 98 5ff17073b64e
child 100 92484a18d548
Mostly-working insertOrderedList
autoimplementation.html
editcommands.html
implementation.js
source.html
--- a/autoimplementation.html	Sun May 08 15:17:33 2011 -0600
+++ b/autoimplementation.html	Mon May 09 15:59:56 2011 -0600
@@ -652,6 +652,84 @@
 
 		'<ol><li>foo</ol>[bar]',
 		'<ul><li>foo</ul>[bar]',
+
+		// Various <ol> stuff
+		'<ol><li>foo<li>[bar]<li>baz</ol>',
+		'<ol data-start=1 data-end=2><li>foo<li>bar<li>baz</ol>',
+		'<ol><li>foo</ol>[bar]',
+		'<ol><li>[foo]<br>bar<li>baz</ol>',
+		'<ol><li>foo<br>[bar]<li>baz</ol>',
+		'<ol><li><div>[foo]</div>bar<li>baz</ol>',
+		'<ol><li>foo<ol><li>[bar]<li>baz</ol><li>quz</ol>',
+		'<ol><li>foo<ol><li>bar<li>[baz]</ol><li>quz</ol>',
+		'<ol><li>foo</li><ol><li>[bar]<li>baz</ol><li>quz</ol>',
+		'<ol><li>foo</li><ol data-start=0 data-end=1><li>bar<li>baz</ol><li>quz</ol>',
+		'<ol><li>foo</li><ol><li>bar<li>[baz]</ol><li>quz</ol>',
+		'<ol><li>foo</li><ol data-start=1 data-end=2><li>bar<li>baz</ol><li>quz</ol>',
+		'<ol><li>foo<ol><li>b[a]r</ol><li>baz</ol>',
+		'<ol><li>foo</li><ol><li>b[a]r</ol><li>baz</ol>',
+		'<ol><li>foo{<ol><li>bar</ol>}<li>baz</ol>',
+		'<ol><li>foo</li>{<ol><li>bar</ol>}<li>baz</ol>',
+		'<ol><li>[foo]<ol><li>bar</ol><li>baz</ol>',
+		'<ol><li>[foo]</li><ol><li>bar</ol><li>baz</ol>',
+		'<ol><li>foo<li>[bar]<ol><li>baz</ol><li>quz</ol>',
+		'<ol><li>foo<li>[bar]</li><ol><li>baz</ol><li>quz</ol>',
+		'<ol><li>foo<ol><li>bar<li>baz</ol><li>[quz]</ol>',
+		'<ol><li>foo</li><ol><li>bar<li>baz</ol><li>[quz]</ol>',
+
+		// Multiple items at once.
+		'<ol><li>foo<li>b[ar<li>baz]</ol>',
+		'<ol><li>[foo<ol><li>bar]</ol><li>baz</ol>',
+		'<ol><li>[foo</li><ol><li>bar]</ol><li>baz</ol>',
+		'<ol><li>foo<ol><li>b[ar</ol><li>b]az</ol>',
+		'<ol><li>foo</li><ol><li>b[ar</ol><li>b]az</ol>',
+		'<ol><li>[foo<ol><li>bar</ol><li>baz]</ol><p>extra',
+		'<ol><li>[foo</li><ol><li>bar</ol><li>baz]</ol><p>extra',
+
+		// We probably can't actually get this DOM . . .
+		'<ol><li>[foo]<ol><li>bar</ol>baz</ol>',
+		'<ol><li>foo<ol><li>[bar]</ol>baz</ol>',
+		'<ol><li>foo<ol><li>bar</ol>[baz]</ol>',
+		'<ol><li>[foo<ol><li>bar]</ol>baz</ol>',
+
+		// Same stuff but with <ul>
+		'<ul><li>foo<li>[bar]<li>baz</ul>',
+		'<ol data-start=1 data-end=2><li>foo<li>bar<li>baz</ul>',
+		'<ul><li>foo</ul>[bar]',
+		'<ul><li>[foo]<br>bar<li>baz</ul>',
+		'<ul><li>foo<br>[bar]<li>baz</ul>',
+		'<ul><li><div>[foo]</div>bar<li>baz</ul>',
+		'<ul><li>foo<ul><li>[bar]<li>baz</ul><li>quz</ul>',
+		'<ul><li>foo<ul><li>bar<li>[baz]</ul><li>quz</ul>',
+		'<ul><li>foo</li><ul><li>[bar]<li>baz</ul><li>quz</ul>',
+		'<ul><li>foo</li><ol data-start=0 data-end=1><li>bar<li>baz</ul><li>quz</ul>',
+		'<ul><li>foo</li><ul><li>bar<li>[baz]</ul><li>quz</ul>',
+		'<ul><li>foo</li><ol data-start=1 data-end=2><li>bar<li>baz</ul><li>quz</ul>',
+		'<ul><li>foo<ul><li>b[a]r</ul><li>baz</ul>',
+		'<ul><li>foo</li><ul><li>b[a]r</ul><li>baz</ul>',
+		'<ul><li>foo{<ul><li>bar</ul>}<li>baz</ul>',
+		'<ul><li>foo</li>{<ul><li>bar</ul>}<li>baz</ul>',
+		'<ul><li>[foo]<ul><li>bar</ul><li>baz</ul>',
+		'<ul><li>[foo]</li><ul><li>bar</ul><li>baz</ul>',
+		'<ul><li>foo<li>[bar]<ul><li>baz</ul><li>quz</ul>',
+		'<ul><li>foo<li>[bar]</li><ul><li>baz</ul><li>quz</ul>',
+		'<ul><li>foo<ul><li>bar<li>baz</ul><li>[quz]</ul>',
+		'<ul><li>foo</li><ul><li>bar<li>baz</ul><li>[quz]</ul>',
+
+		// Multiple items at once.
+		'<ul><li>foo<li>b[ar<li>baz]</ul>',
+		'<ul><li>[foo<ul><li>bar]</ul><li>baz</ul>',
+		'<ul><li>[foo</li><ul><li>bar]</ul><li>baz</ul>',
+		'<ul><li>foo<ul><li>b[ar</ul><li>b]az</ul>',
+		'<ul><li>foo</li><ul><li>b[ar</ul><li>b]az</ul>',
+		'<ul><li>[foo<ul><li>bar</ul><li>baz]</ul><p>extra',
+		'<ul><li>[foo</li><ul><li>bar</ul><li>baz]</ul><p>extra',
+
+		// We probably can't actually get this DOM . . .
+		'<ul><li>[foo]<ul><li>bar</ul>baz</ul>',
+		'<ul><li>foo<ul><li>[bar]</ul>baz</ul>',
+		'<ul><li>foo<ul><li>bar</ul>[baz]</ul>',
+		'<ul><li>[foo<ul><li>bar]</ul>baz</ul>',
 	],
 	insertunorderedlist: [
 	],
@@ -809,7 +887,7 @@
 		'<ol><li>foo<ol><li>bar<li>baz</ol><li>[quz]</ol>',
 		'<ol><li>foo</li><ol><li>bar<li>baz</ol><li>[quz]</ol>',
 
-		// Try indenting multiple items at once.
+		// Try outdenting multiple items at once.
 		'<ol><li>foo<li>b[ar<li>baz]</ol>',
 		'<ol><li>[foo<ol><li>bar]</ol><li>baz</ol>',
 		'<ol><li>[foo</li><ol><li>bar]</ol><li>baz</ol>',
--- a/editcommands.html	Sun May 08 15:17:33 2011 -0600
+++ b/editcommands.html	Mon May 09 15:59:56 2011 -0600
@@ -27,7 +27,7 @@
 <body class=draft>
 <div class=head id=head>
 <h1>HTML Editing Commands</h1>
-<h2 class="no-num no-toc" id=work-in-progress-&mdash;-last-update-8-may-2011>Work in Progress &mdash; Last Update 8 May 2011</h2>
+<h2 class="no-num no-toc" id=work-in-progress-&mdash;-last-update-9-may-2011>Work in Progress &mdash; Last Update 9 May 2011</h2>
 <dl>
  <dt>Editor
  <dd>Aryeh Gregor &lt;ayg+spec@aryeh.name&gt;
@@ -230,7 +230,7 @@
   <li>Return <var title="">replacement element</var>.
 </ol>
 
-<p>To remove a node <var title="">node</var> while <dfn id=preserving-its-descendants>preserving its
+<p>To remove a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> <var title="">node</var> while <dfn id=preserving-its-descendants>preserving its
 descendants</dfn>:
 
 <ol>
@@ -248,6 +248,32 @@
   <li>Return <var title="">children</var>.
 </ol>
 
+<p>To <dfn id=split-the-parent>split the parent</dfn> of a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> <var title="">node</var>:
+
+<ol>
+  <li>If <var title="">node</var>'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> or <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> is null, do nothing
+  and abort these steps.
+
+  <li>Let <var title="">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 <var title="">node</var>.
+
+  <li>Let <var title="">new parent</var> be the result of calling <code class=external data-anolis-spec=domcore title=dom-Node-cloneNode><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-clonenode>cloneNode(false)</a></code>
+  on <var title="">parent</var>.
+
+  <p class=XXX>This will duplicate id's, as well as other bad things.  Do we
+  care?  We don't want to not copy attributes at all, because that wouldn't
+  copy style attributes, and Firefox in CSS mode will actually add style
+  attributes to any elements it feels like.  If we do exclude id's, even though
+  they'd only occur if someone manually added them, do we want to exclude other
+  things like itemid or accesskey or . . .
+
+  <li>Insert <var title="">new parent</var> into the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">parent</var>
+  immediately after <var title="">parent</var>.
+
+  <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="">node</var> is not null, insert 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="">parent</var> as the first <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">new
+  parent</var>, <a href=#preserving-ranges>preserving ranges</a>.
+</ol>
+
 <p>An <dfn id=editing-host>editing host</dfn> is a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a> that is either an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code> with
 a <code class=external data-anolis-spec=html title=attr-contenteditable><a href=http://www.whatwg.org/html/#attr-contenteditable>contenteditable</a></code>
 attribute set to the true state, or a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#document>Document</a></code> whose <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/html/#designmode>designMode</a></code> is enabled.
@@ -2532,6 +2558,190 @@
 
 Sheesh, lists are complicated.
 -->
+<dt><code title=""><dfn id=command-insertorderedlist title=command-insertorderedlist>insertOrderedList</dfn></code>
+
+<dd><strong>Action</strong>:
+
+<ol>
+  <li>Let <var title="">items</var> be a list of all <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 that are
+  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#ancestor-container title="ancestor container">ancestor containers</a> of the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> and/or <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a>
+  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>.
+
+  <li>For each <var title="">item</var> in <var title="">items</var>, <a href=#normalize-sublists>normalize
+  sublists</a> of <var title="">item</var>.
+  <!-- This overnormalizes, but it seems like the simplest solution for now.
+  -->
+
+  <li><a href=#block-extend>Block-extend</a> the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a>, and let <var title="">new range</var> be
+  the result.
+
+  <li>If the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">new range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> with
+  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> equal to its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>:
+
+  <ol>
+    <li>Remove that <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code> from its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+
+    <li>While the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> of <var title="">new range</var> is equal to
+    the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, set the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> of
+    <var title="">new range</var> to (<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 <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, 1 +
+    <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>).
+  </ol>
+
+  <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>,
+  if <var title="">node</var> 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
+  either <var title="">node</var> 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 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 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 it can be the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of 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>; then append
+  <var title="">node</var> to <var title="">node list</var>.
+
+  <li>While <var title="">node list</var> is not empty:
+
+  <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>If the first member of <var title="">node list</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>, append it to
+    <var title="">sublist</var> (without removing it from <var title="">node list</var>).
+    <!-- It will be removed later, since in every pass we get rid of the first
+    member of node list if it's a br. -->
+
+    <li>Otherwise, remove the first member of <var title="">node list</var> and append
+    it to <var title="">sublist</var>.
+
+    <li>If the first member of <var title="">sublist</var> 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>,
+    <a href=#outdent>outdent</a> it.
+
+    <li>Otherwise, if the first member of <var title="">sublist</var> is a <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 the first member of <var title="">sublist</var> to
+    "ol".
+
+    <li>Otherwise, if 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="">sublist</var>
+    is an <a href=#editable>editable</a> <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code>:
+    <!-- Outdent -->
+
+    <ol>
+      <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
+      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 from <var title="">node list</var>
+      and append it to <var title="">sublist</var>.
+
+      <li><a href=#list-outdent>List-outdent</a> <var title="">sublist</var>.
+    </ol>
+
+    <li>Otherwise, if 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="">sublist</var>
+    is an <a href=#editable>editable</a> <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>:
+    <!-- Split up the parent -->
+
+    <ol>
+      <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
+      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 from <var title="">node list</var>
+      and append it to <var title="">sublist</var>.
+
+      <li>If the <code class=external data-anolis-spec=domcore title=dom-Node-previousSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-previoussibling>previousSibling</a></code> of the first member of <var title="">sublist</var>
+      is null:
+
+      <ol>
+        <li>Let <var title="">ol</var> be the <code class=external data-anolis-spec=domcore title=dom-Node-previousSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-previoussibling>previousSibling</a></code> of the <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="">sublist</var>.
+
+        <li>If <var title="">ol</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>, let <var title="">ol</var> be 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("ol")</a></code> on the
+        <code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument>ownerDocument</a></code> of the first member of <var title="">sublist</var>.  Then
+        insert <var title="">ol</var> into the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of the <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="">sublist</var>, immediately before 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="">sublist</var>.
+
+        <li>For each <var title="">node</var> in <var title="">sublist</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="">ol</var>,
+        <a href=#preserving-ranges>preserving ranges</a>.
+      </ol>
+
+      <li>Otherwise:
+
+      <ol>
+        <li><a href=#split-the-parent>Split the parent</a> of the last member of
+        <var title="">sublist</var>.
+
+        <li>Let <var title="">ol</var> be the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of the <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="">sublist</var>.
+
+        <li>If <var title="">ol</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>, let <var title="">ol</var> be 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("ol")</a></code> on the
+        <code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument>ownerDocument</a></code> of the first member of <var title="">sublist</var>.  Then
+        insert <var title="">ol</var> into the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of the <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="">sublist</var>, immediately after 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="">sublist</var>.
+
+        <li>For each <var title="">node</var> in <var title="">sublist</var> <em>in reverse
+        order</em>, insert <var title="">node</var> as the first <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of
+        <var title="">ol</var>, <a href=#preserving-ranges>preserving ranges</a>.
+      </ol>
+    </ol>
+
+    <li>Otherwise:
+    <!-- General case.  Add an ol wrapper for each line.  <br> breaks apart
+    <li>'s, and multiple consecutive <br>s or trailing <br>s become empty
+    <li>s. -->
+
+    <ol>
+      <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 last member of <var title="">sublist</var> and first
+      member of <var title="">node list</var> are both <a href=#inline-node title="inline node">inline
+      nodes</a> that are not <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>s, remove the first member from <var title="">node
+      list</var> and append it to <var title="">sublist</var>.
+
+      <li>Let <var title="">li</var> be 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
+      <code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument>ownerDocument</a></code> of the first member of <var title="">sublist</var>.
+
+      <li>If the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of the last member of <var title="">sublist</var> 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>:
+
+      <ol>
+        <li>Insert <var title="">li</var> as the first <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of 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>.
+
+        <li>If the first member of <var title="">sublist</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 it
+        from <var title="">sublist</var>.
+
+        <li>For each <var title="">node</var> in <var title="">sublist</var> <em>in reverse
+        order</em>, insert <var title="">node</var> as the first <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of
+        <var title="">li</var>, <a href=#preserving-ranges>preserving ranges</a>.
+      </ol>
+
+      <li>Otherwise:
+
+      <ol>
+        <li>Let <var title="">ol</var> be the <code class=external data-anolis-spec=domcore title=dom-Node-previousSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-previoussibling>previousSibling</a></code> of the first member of
+        <var title="">sublist</var>.
+
+        <li>If <var title="">ol</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>, let <var title="">ol</var> be 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("ol")</a></code> on the
+        <code class=external data-anolis-spec=domcore title=dom-Node-ownerDocument><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-ownerdocument>ownerDocument</a></code> of the first member of <var title="">sublist</var>.  Insert
+        <var title="">ol</var> into the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of the first member of
+        <var title="">sublist</var> immediately before the first member of
+        <var title="">sublist</var>.
+
+        <li>Append <var title="">li</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="">ol</var>.
+
+        <li>If the first member of <var title="">sublist</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 it
+        from <var title="">sublist</var>.
+
+        <li>For each <var title="">node</var> in <var title="">sublist</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="">li</var>,
+        <a href=#preserving-ranges>preserving ranges</a>.
+      </ol>
+    </ol>
+
+    <li>If the first member of <var title="">node list</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 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>, then remove it
+    from <var title="">node list</var>.
+  </ol>
+</ol>
 
 
 <dt><code title=""><dfn id=command-italic title=command-italic>italic</dfn></code>
@@ -2867,27 +3077,7 @@
     <li>Abort these steps.
   </ol>
 
-  <li>If the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of the last member of <var title="">node list</var> is not
-  null:
-
-  <ol>
-    <li>Let <var title="">new parent</var> be the result of calling <code class=external data-anolis-spec=domcore title=dom-Node-cloneNode><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-clonenode>cloneNode(false)</a></code>
-    on <var title="">parent</var>.
-
-    <p class=XXX>This will duplicate id's, as well as other bad things.  Do we
-    care?  We don't want to not copy attributes at all, because that wouldn't
-    copy style attributes, and Firefox in CSS mode will actually add style
-    attributes to any elements it feels like.  If we do exclude id's, even
-    though they'd only occur if someone manually added them, do we want to
-    exclude other things like itemid or accesskey or . . .
-
-    <li>Insert <var title="">new parent</var> into the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">parent</var>
-    immediately after <var title="">parent</var>.
-
-    <li>While <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of the last member of <var title="">node list</var> is not
-    null, insert 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="">parent</var> as the first <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a>
-    of <var title="">new parent</var>, <a href=#preserving-ranges>preserving ranges</a>.
-  </ol>
+  <li><a href=#split-the-parent>Split the parent</a> of the last member of <var title="">node list</var>.
 
   <li>For each <var title="">node</var> in <var title="">node list</var>, <em>in reverse
   order</em>:
--- a/implementation.js	Sun May 08 15:17:33 2011 -0600
+++ b/implementation.js	Mon May 09 15:59:56 2011 -0600
@@ -404,6 +404,29 @@
 	return children;
 }
 
+function splitParent(node) {
+	// "If node's parent or nextSibling is null, do nothing and abort these
+	// steps."
+	if (!node.parentNode || !node.nextSibling) {
+		return;
+	}
+
+	// "Let parent be the parent of node."
+	var parent_ = node.parentNode;
+
+	// "Let new parent be the result of calling cloneNode(false) on parent."
+	var newParent = parent_.cloneNode(false);
+
+	// "Insert new parent into the parent of parent immediately after parent."
+	parent_.parentNode.insertBefore(newParent, parent_.nextSibling);
+
+	// "While the nextSibling of node is not null, insert the last child of
+	// parent as the first child of new parent, preserving ranges."
+	while (node.nextSibling) {
+		movePreservingRanges(parent_.lastChild, newParent, 0);
+	}
+}
+
 // "An editing host is a node that is either an Element with a contenteditable
 // attribute set to the true state, or a Document whose designMode is enabled."
 function isEditingHost(node) {
@@ -2426,6 +2449,261 @@
 		img.removeAttribute("height");
 		break;
 
+		case "insertorderedlist":
+		// "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);
+			}
+		}
+
+		// "For each item in items, normalize sublists of item."
+		for (var i = 0; i < items.length; i++) {
+			normalizeSublists(items[i]);
+		}
+
+		// "Block-extend the range, and let new range be the result."
+		var newRange = blockExtendRange(range);
+
+		// "If the child of new range's end node with index equal to its end
+		// offset is a br:"
+		var end = newRange.endContainer.childNodes[newRange.endOffset];
+		if (isHtmlElement(end) && end.tagName == "BR") {
+			// "Remove that br from its parent."
+			end.parentNode.removeChild(end);
+
+			// "While the end offset of new range is equal to the length of its
+			// end node, set the end of new range to (parent of end node, 1 +
+			// index of end node)."
+			while (newRange.endOffset == getNodeLength(newRange.endContainer)) {
+				newRange.setEnd(newRange.endContainer.parentNode, 1 + getNodeIndex(newRange.endContainer));
+			}
+		}
+
+		// "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; and
+		// either node is an ol or ul, or its parent is an ol or ul, or it can
+		// be the child of an 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))
+			&& (isHtmlElement(node, "OL")
+			|| isHtmlElement(node, "UL")
+			|| isHtmlElement(node.parentNode, "OL")
+			|| isHtmlElement(node.parentNode, "UL")
+			// As usual with content restrictions, we fake it for testing
+			// purposes.
+			|| !isHtmlElement(node)
+			|| ["THEAD", "TBODY", "TR", "TH", "TD", "DT", "DD"].indexOf(node.tagName) == -1)) {
+				nodeList.push(node);
+			}
+		}
+
+		// "While node list is not empty:"
+		while (nodeList.length) {
+			// "Let sublist be an empty list of nodes."
+			var sublist = [];
+
+			// "If the first member of node list is a br, append it to sublist
+			// (without removing it from node list)."
+			if (isHtmlElement(nodeList[0], "BR")) {
+				sublist.push(nodeList[0]);
+
+			// "Otherwise, remove the first member of node list and append it to sublist."
+			} else {
+				sublist.push(nodeList.shift());
+			}
+
+			// "If the first member of sublist is an ol, outdent it."
+			if (isHtmlElement(sublist[0], "OL")) {
+				outdentNode(sublist[0]);
+			// "Otherwise, if the first member of sublist is a ul, set the tag
+			// name of the first member of sublist to "ol"."
+			} else if (isHtmlElement(sublist[0], "UL")) {
+				setTagName(sublist[0], "ol");
+			// "Otherwise, if the parent of the first member of sublist is an
+			// editable ol:"
+			} else if (isHtmlElement(sublist[0].parentNode, "OL")
+			&& isEditable(sublist[0].parentNode)) {
+				// "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 an ol or ul, remove the
+				// first member from node list and append it to sublist."
+				while (nodeList.length
+				&& nodeList[0] == sublist[sublist.length - 1].nextSibling
+				&& !isHtmlElement(nodeList[0], "OL")
+				&& !isHtmlElement(nodeList[0], "UL")) {
+					sublist.push(nodeList.shift());
+				}
+
+				// "List-outdent sublist."
+				listOutdent(sublist);
+
+			// "Otherwise, if the parent of the first member of sublist is an
+			// editable ul:"
+			} else if (isHtmlElement(sublist[0].parentNode, "UL")
+			&& isEditable(sublist[0].parentNode)) {
+				// "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 an ol or ul, remove the
+				// first member from node list and append it to sublist."
+				while (nodeList.length
+				&& nodeList[0] == sublist[sublist.length -1].nextSibling
+				&& !isHtmlElement(nodeList[0], "OL")
+				&& !isHtmlElement(nodeList[0], "UL")) {
+					sublist.push(nodeList.shift());
+				}
+
+				// "If the previousSibling of the first member of sublist is
+				// null:"
+				if (!sublist[0].previousSibling) {
+					// "Let ol be the previousSibling of the parent of the
+					// first member of sublist."
+					var ol = sublist[0].parentNode.previousSibling;
+
+					// "If ol is not an ol, let ol be the result of calling
+					// createElement("ol") on the ownerDocument of the first
+					// member of sublist. Then insert ol into the parent of the
+					// parent of the first member of sublist, immediately
+					// before the parent of the first member of sublist."
+					if (!isHtmlElement(ol, "OL")) {
+						ol = sublist[0].ownerDocument.createElement("ol");
+						sublist[0].parentNode.parentNode.insertBefore(ol, sublist[0].parentNode);
+					}
+
+					// "For each node in sublist, append node as the last child
+					// of ol, preserving ranges."
+					for (var i = 0; i < sublist.length; i++) {
+						movePreservingRanges(sublist[i], ol, ol.childNodes.length);
+					}
+
+				// "Otherwise:"
+				} else {
+					// "Split the parent of the last member of sublist."
+					splitParent(sublist[sublist.length - 1]);
+
+					// "Let ol be the nextSibling of the parent of the first
+					// member of sublist."
+					var ol = sublist[0].parentNode.nextSibling;
+
+					// "If ol is not an ol, let ol be the result of calling
+					// createElement("ol") on the ownerDocument of the first
+					// member of sublist. Then insert ol into the parent of the
+					// parent of the first member of sublist, immediately after
+					// the parent of the first member of sublist."
+					if (!isHtmlElement(ol, "OL")) {
+						ol = sublist[0].ownerDocument.createElement("ol");
+						sublist[0].parentNode.parentNode.insertBefore(ol, sublist[0].parentNode.nextSibling);
+					}
+
+					// "For each node in sublist in reverse order, insert node
+					// as the first child of ol, preserving ranges."
+					for (var i = sublist.length - 1; i >= 0; i--) {
+						movePreservingRanges(sublist[i], ol, 0);
+					}
+				}
+			// "Otherwise:"
+			} else {
+				// "While node list is not empty, and the first member of node
+				// list is the nextSibling of the last member of sublist, and
+				// the last member of sublist and first member of node list are
+				// both inline nodes that are not brs, remove the first member
+				// from node list and append it to sublist."
+				while (nodeList.length
+				&& nodeList[0] == sublist[sublist.length -1].nextSibling
+				&& isInlineNode(nodeList[0])
+				&& isInlineNode(sublist[sublist.length -1])
+				&& !isHtmlElement(nodeList[0], "BR")
+				&& !isHtmlElement(sublist[sublist.length -1], "BR")) {
+					sublist.push(nodeList.shift());
+				}
+
+				// "Let li be the result of calling createElement("li") on the
+				// ownerDocument of the first member of sublist."
+				var li = sublist[0].ownerDocument.createElement("li");
+
+				// "If the nextSibling of the last member of sublist is an ol:"
+				if (isHtmlElement(sublist[sublist.length - 1].nextSibling, "OL")) {
+					// "Insert li as the first child of the nextSibling of the
+					// last member of sublist."
+					sublist[sublist.length - 1].nextSibling.insertBefore(li, sublist[sublist.length - 1].nextSibling.firstChild);
+
+					// "If the first member of sublist is a br, remove it from
+					// sublist."
+					if (isHtmlElement(sublist[0], "BR")) {
+						sublist.shift();
+					}
+
+					// "For each node in sublist in reverse order, insert node
+					// as the first child of li, preserving ranges."
+					for (var i = sublist.length - 1; i >= 0; i--) {
+						movePreservingRanges(sublist[i], li, 0);
+					}
+				// "Otherwise:"
+				} else {
+					// "Let ol be the previousSibling of the first member of
+					// sublist."
+					var ol = sublist[0].previousSibling;
+
+					// "If ol is not an ol, let ol be the result of calling
+					// createElement("ol") on the ownerDocument of the first
+					// member of sublist. Insert ol into the parent of the
+					// first member of sublist immediately before the first
+					// member of sublist."
+					if (!isHtmlElement(ol, "OL")) {
+						ol = sublist[0].ownerDocument.createElement("ol");
+						sublist[0].parentNode.insertBefore(ol, sublist[0]);
+					}
+
+					// "Append li as the last child of ol."
+					ol.appendChild(li);
+
+					// "If the first member of sublist is a br, remove it from
+					// sublist."
+					if (isHtmlElement(sublist[0], "BR")) {
+						sublist.shift();
+					}
+
+					// "For each node in sublist, append node as the last child
+					// of li, preserving ranges."
+					for (var i = 0; i < sublist.length; i++) {
+						movePreservingRanges(sublist[i], li, li.childNodes.length);
+					}
+				}
+			}
+
+			// "If the first member of node list is a br, remove the first
+			// member of node list from its parent, then remove it from node
+			// list."
+			if (isHtmlElement(nodeList[0], "BR")) {
+				nodeList[0].parentNode.removeChild(nodeList[0]);
+				nodeList.shift();
+			}
+		}
+		break;
+
 		case "italic":
 		// "Decompose the range. If the state of the range for this command is
 		// then true, set the value of each returned node with new value
@@ -3073,23 +3351,8 @@
 		return;
 	}
 
-	// "If the nextSibling of the last member of node list is not null:"
-	if (nodeList[nodeList.length - 1].nextSibling) {
-		// "Let new parent be the result of calling cloneNode(false) on
-		// parent."
-		var newParent = parent_.cloneNode(false);
-
-		// "Insert new parent into the parent of parent immediately after
-		// parent."
-		parent_.parentNode.insertBefore(newParent, parent_.nextSibling);
-
-		// "While nextSibling of the last member of node list is not null,
-		// insert the last child of parent as the first child of new
-		// parent, preserving ranges."
-		while (nodeList[nodeList.length - 1].nextSibling) {
-			movePreservingRanges(parent_.lastChild, newParent, 0);
-		}
-	}
+	// "Split the parent of the last member of node list."
+	splitParent(nodeList[nodeList.length - 1]);
 
 	// "For each node in node list, in reverse order:"
 	for (var i = nodeList.length - 1; i >= 0; i--) {
--- a/source.html	Sun May 08 15:17:33 2011 -0600
+++ b/source.html	Mon May 09 15:59:56 2011 -0600
@@ -218,7 +218,7 @@
   <li>Return <var>replacement element</var>.
 </ol>
 
-<p>To remove a node <var>node</var> while <dfn>preserving its
+<p>To remove a [[node]] <var>node</var> while <dfn>preserving its
 descendants</dfn>:
 
 <ol>
@@ -236,6 +236,33 @@
   <li>Return <var>children</var>.
 </ol>
 
+<p>To <dfn>split the parent</dfn> of a [[node]] <var>node</var>:
+
+<ol>
+  <li>If <var>node</var>'s [[parent]] or [[nextsibling]] is null, do nothing
+  and abort these steps.
+
+  <li>Let <var>parent</var> be the [[parent]] of <var>node</var>.
+
+  <li>Let <var>new parent</var> be the result of calling <code
+  data-anolis-spec=domcore title=dom-Node-cloneNode>cloneNode(false)</code>
+  on <var>parent</var>.
+
+  <p class=XXX>This will duplicate id's, as well as other bad things.  Do we
+  care?  We don't want to not copy attributes at all, because that wouldn't
+  copy style attributes, and Firefox in CSS mode will actually add style
+  attributes to any elements it feels like.  If we do exclude id's, even though
+  they'd only occur if someone manually added them, do we want to exclude other
+  things like itemid or accesskey or . . .
+
+  <li>Insert <var>new parent</var> into the [[parent]] of <var>parent</var>
+  immediately after <var>parent</var>.
+
+  <li>While the [[nextsibling]] of <var>node</var> is not null, insert the last
+  [[child]] of <var>parent</var> as the first [[child]] of <var>new
+  parent</var>, <span>preserving ranges</span>.
+</ol>
+
 <p>An <dfn>editing host</dfn> is a [[node]] that is either an [[element]] with
 a <code data-anolis-spec=html title=attr-contenteditable>contenteditable</code>
 attribute set to the true state, or a [[document]] whose <code
@@ -2574,6 +2601,195 @@
 
 Sheesh, lists are complicated.
 -->
+<dt><code title><dfn title=command-insertorderedlist>insertOrderedList</dfn></code>
+
+<dd><strong>Action</strong>:
+
+<ol>
+  <li>Let <var>items</var> be a list of all [[li]]s that are
+  [[ancestorcontainers]] of the [[range]]'s [[rangestart]] and/or [[rangeend]]
+  [[bpnode]].
+
+  <li>For each <var>item</var> in <var>items</var>, <span>normalize
+  sublists</span> of <var>item</var>.
+  <!-- This overnormalizes, but it seems like the simplest solution for now.
+  -->
+
+  <li><span>Block-extend</span> the [[range]], and let <var>new range</var> be
+  the result.
+
+  <li>If the [[child]] of <var>new range</var>'s [[rangeend]] [[bpnode]] with
+  [[index]] equal to its [[rangeend]] [[bpoffset]] is a [[br]]:
+
+  <ol>
+    <li>Remove that [[br]] from its [[parent]].
+
+    <li>While the [[rangeend]] [[bpoffset]] of <var>new range</var> is equal to
+    the [[nodelength]] of its [[rangeend]] [[bpnode]], set the [[rangeend]] of
+    <var>new range</var> to ([[parent]] of [[rangeend]] [[bpnode]], 1 +
+    [[index]] of [[rangeend]] [[bpnode]]).
+  </ol>
+
+  <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>,
+  if <var>node</var> is <span>editable</span>; the last member of <var>node
+  list</var> (if any) is not an [[ancestor]] of <var>node</var>; and
+  either <var>node</var> is an [[ol]] or [[ul]], or its [[parent]] is an [[ol]]
+  or [[ul]], or it can be the [[child]] of an [[li]]; then append
+  <var>node</var> to <var>node list</var>.
+
+  <li>While <var>node list</var> is not empty:
+
+  <ol>
+    <li>Let <var>sublist</var> be an empty list of [[nodes]].
+
+    <li>If the first member of <var>node list</var> is a [[br]], append it to
+    <var>sublist</var> (without removing it from <var>node list</var>).
+    <!-- It will be removed later, since in every pass we get rid of the first
+    member of node list if it's a br. -->
+
+    <li>Otherwise, remove the first member of <var>node list</var> and append
+    it to <var>sublist</var>.
+
+    <li>If the first member of <var>sublist</var> is an [[ol]],
+    <span>outdent</span> it.
+
+    <li>Otherwise, if the first member of <var>sublist</var> is a [[ul]],
+    <span>set the tag name</span> of the first member of <var>sublist</var> to
+    "ol".
+
+    <li>Otherwise, if the [[parent]] of the first member of <var>sublist</var>
+    is an <span>editable</span> [[ol]]:
+    <!-- Outdent -->
+
+    <ol>
+      <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
+      an [[ol]] or [[ul]], remove the first member from <var>node list</var>
+      and append it to <var>sublist</var>.
+
+      <li><span>List-outdent</span> <var>sublist</var>.
+    </ol>
+
+    <li>Otherwise, if the [[parent]] of the first member of <var>sublist</var>
+    is an <span>editable</span> [[ul]]:
+    <!-- Split up the parent -->
+
+    <ol>
+      <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
+      an [[ol]] or [[ul]], remove the first member from <var>node list</var>
+      and append it to <var>sublist</var>.
+
+      <li>If the [[previoussibling]] of the first member of <var>sublist</var>
+      is null:
+
+      <ol>
+        <li>Let <var>ol</var> be the [[previoussibling]] of the [[parent]] of
+        the first member of <var>sublist</var>.
+
+        <li>If <var>ol</var> is not an [[ol]], let <var>ol</var> be the result
+        of calling <code data-anolis-spec=domcore
+        title=dom-Document-createElement>createElement("ol")</code> on the
+        [[ownerdocument]] of the first member of <var>sublist</var>.  Then
+        insert <var>ol</var> into the [[parent]] of the [[parent]] of the first
+        member of <var>sublist</var>, immediately before the [[parent]] of the
+        first member of <var>sublist</var>.
+
+        <li>For each <var>node</var> in <var>sublist</var>, append
+        <var>node</var> as the last [[child]] of <var>ol</var>,
+        <span>preserving ranges</span>.
+      </ol>
+
+      <li>Otherwise:
+
+      <ol>
+        <li><span>Split the parent</span> of the last member of
+        <var>sublist</var>.
+
+        <li>Let <var>ol</var> be the [[nextsibling]] of the [[parent]] of the
+        first member of <var>sublist</var>.
+
+        <li>If <var>ol</var> is not an [[ol]], let <var>ol</var> be the result
+        of calling <code data-anolis-spec=domcore
+        title=dom-Document-createElement>createElement("ol")</code> on the
+        [[ownerdocument]] of the first member of <var>sublist</var>.  Then
+        insert <var>ol</var> into the [[parent]] of the [[parent]] of the first
+        member of <var>sublist</var>, immediately after the [[parent]] of the
+        first member of <var>sublist</var>.
+
+        <li>For each <var>node</var> in <var>sublist</var> <em>in reverse
+        order</em>, insert <var>node</var> as the first [[child]] of
+        <var>ol</var>, <span>preserving ranges</span>.
+      </ol>
+    </ol>
+
+    <li>Otherwise:
+    <!-- General case.  Add an ol wrapper for each line.  <br> breaks apart
+    <li>'s, and multiple consecutive <br>s or trailing <br>s become empty
+    <li>s. -->
+
+    <ol>
+      <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 last member of <var>sublist</var> and first
+      member of <var>node list</var> are both <span title="inline node">inline
+      nodes</span> that are not [[br]]s, remove the first member from <var>node
+      list</var> and append it to <var>sublist</var>.
+
+      <li>Let <var>li</var> be the result of calling <code
+      data-anolis-spec=domcore
+      title=dom-Document-createElement>createElement("li")</code> on the
+      [[ownerdocument]] of the first member of <var>sublist</var>.
+
+      <li>If the [[nextsibling]] of the last member of <var>sublist</var> is an
+      [[ol]]:
+
+      <ol>
+        <li>Insert <var>li</var> as the first [[child]] of the [[nextsibling]]
+        of the last member of <var>sublist</var>.
+
+        <li>If the first member of <var>sublist</var> is a [[br]], remove it
+        from <var>sublist</var>.
+
+        <li>For each <var>node</var> in <var>sublist</var> <em>in reverse
+        order</em>, insert <var>node</var> as the first [[child]] of
+        <var>li</var>, <span>preserving ranges</span>.
+      </ol>
+
+      <li>Otherwise:
+
+      <ol>
+        <li>Let <var>ol</var> be the [[previoussibling]] of the first member of
+        <var>sublist</var>.
+
+        <li>If <var>ol</var> is not an [[ol]], let <var>ol</var> be the result
+        of calling <code data-anolis-spec=domcore
+        title=dom-Document-createElement>createElement("ol")</code> on the
+        [[ownerdocument]] of the first member of <var>sublist</var>.  Insert
+        <var>ol</var> into the [[parent]] of the first member of
+        <var>sublist</var> immediately before the first member of
+        <var>sublist</var>.
+
+        <li>Append <var>li</var> as the last [[child]] of <var>ol</var>.
+
+        <li>If the first member of <var>sublist</var> is a [[br]], remove it
+        from <var>sublist</var>.
+
+        <li>For each <var>node</var> in <var>sublist</var>, append
+        <var>node</var> as the last [[child]] of <var>li</var>,
+        <span>preserving ranges</span>.
+      </ol>
+    </ol>
+
+    <li>If the first member of <var>node list</var> is a [[br]], remove the
+    first member of <var>node list</var> from its [[parent]], then remove it
+    from <var>node list</var>.
+  </ol>
+</ol>
 
 
 <dt><code title><dfn title=command-italic>italic</dfn></code>
@@ -2916,28 +3132,7 @@
     <li>Abort these steps.
   </ol>
 
-  <li>If the [[nextsibling]] of the last member of <var>node list</var> is not
-  null:
-
-  <ol>
-    <li>Let <var>new parent</var> be the result of calling <code
-    data-anolis-spec=domcore title=dom-Node-cloneNode>cloneNode(false)</code>
-    on <var>parent</var>.
-
-    <p class=XXX>This will duplicate id's, as well as other bad things.  Do we
-    care?  We don't want to not copy attributes at all, because that wouldn't
-    copy style attributes, and Firefox in CSS mode will actually add style
-    attributes to any elements it feels like.  If we do exclude id's, even
-    though they'd only occur if someone manually added them, do we want to
-    exclude other things like itemid or accesskey or . . .
-
-    <li>Insert <var>new parent</var> into the [[parent]] of <var>parent</var>
-    immediately after <var>parent</var>.
-
-    <li>While [[nextsibling]] of the last member of <var>node list</var> is not
-    null, insert the last [[child]] of <var>parent</var> as the first [[child]]
-    of <var>new parent</var>, <span>preserving ranges</span>.
-  </ol>
+  <li><span>Split the parent</span> of the last member of <var>node list</var>.
 
   <li>For each <var>node</var> in <var>node list</var>, <em>in reverse
   order</em>: