Fix outdenting in corner case with nested li's
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Mon, 11 Jul 2011 13:53:21 -0600
changeset 394 373d18bf5a0e
parent 393 ebfe6360328c
child 395 5ab04f33ebba
Fix outdenting in corner case with nested li's

Specifically, where a wrapper intervenes, so that normalizing sublists
doesn't do anything. Reviewing all this stuff has made me seriously
doubt whether a lot of the special-casing of list items makes sense.
editcommands.html
implementation.js
source.html
tests.js
--- a/editcommands.html	Mon Jul 11 13:08:29 2011 -0600
+++ b/editcommands.html	Mon Jul 11 13:53:21 2011 -0600
@@ -3185,28 +3185,46 @@
   <li>If <var title="">node list</var> is empty, return "none".
 
   <li>If every member of <var title="">node list</var> is either 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 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 ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code>, and none 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> or 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 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>,
-  return "ol".
+  <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 ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code> or 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 a <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> <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 ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code>, and none 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> or 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 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>, return
+  "ol".
+  <!--
+  The child-of-child case is necessary right now because of the following:
+    <ol><li>[foo<ol><li>bar]</ol>baz</ol>
+  With the current (July 2011) block-extend algorithm, this will become:
+    {<ol><li>foo<ol><li>bar</ol>}baz</ol>
+  because of the magical li handling in block-extend.  We want this to register
+  as ol, because after normalizing sublists it will become
+    {<ol><li>foo</li><ol><li>bar</ol>}<li>baz</ol>
+
+  But the text node "foo" will wind up in node list, and is not the child of an
+  ol.  This is all very messy and has to do with questionable decisions about
+  how to handle nested lists.
+  -->
 
   <li>If every member of <var title="">node list</var> is either 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> or 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 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>, and none 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 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 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>,
-  return "ul".
+  <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 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> or 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> <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 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>,
+  and none 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 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 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>, return "ul".
   <!-- The previous two conditions are mutually exclusive, so the order is
   actually irrelevant.  Clearly they could only both hold if no member of node
-  list is an ol or ul, so if they both held, every member would have to be both
-  the child of an ol and the child of a ul.  This is impossible unless the list
-  is empty, in which case we already aborted. -->
+  list is an ol or ul, so if they both held, every member would have to be
+  either the child of an ol and of a ul, or of an ol and an li, or a ul and an
+  li, or of an li that's the child of both an ol and a ul.  This is impossible
+  unless the list is empty, in which case we already aborted. -->
 
   <li>If some member of <var title="">node list</var> is either 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 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> or <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 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>, and some member of <var title="">node
-  list</var> is either 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> or 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> or <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>,
-  return "mixed".
+  <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> or <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 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 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>
+  <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 ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code>, and some member of <var title="">node list</var> is either 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> or 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> or <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of a <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 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> <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 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>, return "mixed".
 
   <li>If some member of <var title="">node list</var> is either 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 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> or <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 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>, return "mixed ol".
+  <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> or <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 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 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>
+  <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 ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code>, return "mixed ol".
 
   <li>If some member of <var title="">node list</var> is either 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> or 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> or <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>, return "mixed ul".
+  <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> or <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of a <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 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> <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 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>, return "mixed ul".
 
   <li>Return "none".
 </ol>
@@ -3267,9 +3285,12 @@
   and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offsets</a> of <var title="">range</var>.
 
   <li>If some <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#ancestor-container title="ancestor container">ancestor container</a> of <var title="">start node</var> is an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code>, set
-  <var title="">start offset</var> to the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of the first such <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code> in
+  <var title="">start offset</var> to the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of the last such <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code> in
   <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#tree-order>tree order</a>, and set <var title="">start node</var> to that <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 <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>.
 
+  <p class=XXX>This plus the normalizing sublists stuff seems very messy.  Can
+  we do better?
+
   <li>Repeat the following steps:
 
   <ol>
@@ -3303,7 +3324,7 @@
   </ol>
 
   <li>If some <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#ancestor-container title="ancestor container">ancestor container</a> of <var title="">end node</var> is an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code>, set
-  <var title="">end offset</var> to one plus the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of the first such <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code> in
+  <var title="">end offset</var> to one plus the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of the last such <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code> in
   <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#tree-order>tree order</a>, and set <var title="">end node</var> to that <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 <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>Repeat the following steps:
@@ -4229,9 +4250,8 @@
   <var title="">node</var>, <a href=#preserving-its-descendants>preserving its descendants</a>.  Then abort these
   steps.
 
-  <!-- No browser handles the case of Firefox 4.0 in CSS mode, where it adds a
-  margin attribute to an existing element, including Firefox itself.  So let's
-  just skip it. -->
+  <p class=XXX>Look into handling indentation like Gecko in CSS mode, where a
+  margin attribute is added to a random element.
 
   <li>If <var title="">node</var> is an <a href=#indentation-element>indentation element</a>:
   <!-- This might be a simple indentation element that had style added to it by
@@ -4287,9 +4307,9 @@
   <li>Let <var title="">ancestor 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>While <var title="">current ancestor</var> is an <a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>
-  that is not a <a href=#simple-indentation-element>simple indentation element</a>, append <var title="">current
-  ancestor</var> to <var title="">ancestor list</var> and then set <var title="">current
-  ancestor</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+  that is neither a <a href=#simple-indentation-element>simple indentation element</a> nor 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> nor 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>, append <var title="">current ancestor</var> to <var title="">ancestor list</var> and
+  then set <var title="">current ancestor</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
 
   <li>If <var title="">current ancestor</var> is not an <a href=#editable>editable</a>
   <a href=#simple-indentation-element>simple indentation element</a>:
@@ -4300,14 +4320,13 @@
     <li>Let <var title="">ancestor list</var> be the empty list.
 
     <li>While <var title="">current ancestor</var> is an <a href=#editable>editable</a>
-    <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code> that is not an <a href=#indentation-element>indentation element</a>, append
-    <var title="">current ancestor</var> to <var title="">ancestor list</var> and then set
-    <var title="">current ancestor</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+    <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code> that is neither an <a href=#indentation-element>indentation element</a> nor 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> nor 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>, append <var title="">current ancestor</var> to <var title="">ancestor
+    list</var> and then set <var title="">current ancestor</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
   </ol>
 
-  <li>If <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>, and either <var title="">current
-  ancestor</var> is not an <a href=#editable>editable</a> <a href=#indentation-element>indentation
-  element</a> 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 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>:
+  <li>If <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> and <var title="">current ancestor</var>
+  is not an <a href=#editable>editable</a> <a href=#indentation-element>indentation element</a>:
   <!--
   When asked to outdent a list wrapped in a simple indentation element, Chrome
   12 dev removes the list instead of the simple indentation element.  Opera
@@ -4335,17 +4354,13 @@
   here.
   -->
 
-  <p class=XXX>What about if node isn't a child of a list, but there's a list
-  ancestor below current ancestor?  Is that even possible given how the
-  block-extend algorithm works?
-
   <ol>
     <li>Unset the <code class=external data-anolis-spec=html title=attr-ol-reversed><a href=http://www.whatwg.org/html/#attr-ol-reversed>reversed</a></code>, <code class=external data-anolis-spec=html title=attr-ol-start><a href=http://www.whatwg.org/html/#attr-ol-start>start</a></code>, and <code class=external data-anolis-spec=html title=attr-ol-type><a href=http://www.whatwg.org/html/#attr-ol-type>type</a></code> attributes of <var title="">node</var>, if any are
     set.
 
     <li>Let <var title="">children</var> be the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>children</a> of <var title="">node</var>.
 
-    <li>If <var title="">node</var> has attributes, and its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> or 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>
+    <li>If <var title="">node</var> has attributes, and its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is not an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/html/#the-ol-element>ol</a></code>
     or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/html/#the-ul-element>ul</a></code>, <a href=#set-the-tag-name>set the tag name</a> of <var title="">node</var> to "div".
 
     <li>Otherwise remove <var title="">node</var>, <a href=#preserving-its-descendants>preserving its descendants</a>.
--- a/implementation.js	Mon Jul 11 13:08:29 2011 -0600
+++ b/implementation.js	Mon Jul 11 13:53:21 2011 -0600
@@ -3558,16 +3558,26 @@
 		return "none";
 	}
 
-	// "If every member of node list is either an ol or the child of an ol, and
-	// none is a ul or an ancestor of a ul, return "ol"."
-	if (nodeList.every(function(node) { return isHtmlElement(node, "ol") || isHtmlElement(node.parentNode, "ol") })
+	// "If every member of node list is either an ol or the child of an ol or
+	// the child of a child of an li child of an ol, and none is a ul or an
+	// ancestor of a ul, return "ol"."
+	if (nodeList.every(function(node) {
+		return isHtmlElement(node, "ol")
+			|| isHtmlElement(node.parentNode, "ol")
+			|| (isHtmlElement(node.parentNode, "li") && isHtmlElement(node.parentNode.parentNode, "ol"));
+	})
 	&& !nodeList.some(function(node) { return isHtmlElement(node, "ul") || ("querySelector" in node && node.querySelector("ul")) })) {
 		return "ol";
 	}
 
-	// "If every member of node list is either a ul or the child of a ul, and
-	// none is an ol or an ancestor of an ol, return "ul"."
-	if (nodeList.every(function(node) { return isHtmlElement(node, "ul") || isHtmlElement(node.parentNode, "ul") })
+	// "If every member of node list is either a ul or the child of a ul or the
+	// child of an li child of a ul, and none is an ol or an ancestor of an ol,
+	// return "ul"."
+	if (nodeList.every(function(node) {
+		return isHtmlElement(node, "ul")
+			|| isHtmlElement(node.parentNode, "ul")
+			|| (isHtmlElement(node.parentNode, "li") && isHtmlElement(node.parentNode.parentNode, "ul"));
+	})
 	&& !nodeList.some(function(node) { return isHtmlElement(node, "ol") || ("querySelector" in node && node.querySelector("ol")) })) {
 		return "ul";
 	}
@@ -3575,28 +3585,31 @@
 	var hasOl = nodeList.some(function(node) {
 		return isHtmlElement(node, "ol")
 			|| isHtmlElement(node.parentNode, "ol")
-			|| ("querySelector" in node && node.querySelector("ol"));
+			|| ("querySelector" in node && node.querySelector("ol"))
+			|| (isHtmlElement(node.parentNode, "li") && isHtmlElement(node.parentNode.parentNode, "ol"));
 	});
 	var hasUl = nodeList.some(function(node) {
 		return isHtmlElement(node, "ul")
 			|| isHtmlElement(node.parentNode, "ul")
-			|| ("querySelector" in node && node.querySelector("ul"));
+			|| ("querySelector" in node && node.querySelector("ul"))
+			|| (isHtmlElement(node.parentNode, "li") && isHtmlElement(node.parentNode.parentNode, "ul"));
 	});
 	// "If some member of node list is either an ol or the child or ancestor of
-	// an ol, and some member of node list is either a ul or the child or
-	// ancestor of a ul, return "mixed"."
+	// an ol or the child of an li child of an ol, and some member of node list
+	// is either a ul or the child or ancestor of a ul or the child of an li
+	// child of a ul, return "mixed"."
 	if (hasOl && hasUl) {
 		return "mixed";
 	}
 
 	// "If some member of node list is either an ol or the child or ancestor of
-	// an ol, return "mixed ol"."
+	// an ol or the child of an li child of an ol, return "mixed ol"."
 	if (hasOl) {
 		return "mixed ol";
 	}
 
 	// "If some member of node list is either a ul or the child or ancestor of
-	// a ul, return "mixed ul"."
+	// a ul or the child of an li child of a ul, return "mixed ul"."
 	if (hasUl) {
 		return "mixed ul";
 	}
@@ -3660,17 +3673,14 @@
 	var endOffset = range.endOffset;
 
 	// "If some ancestor container of start node is an li, set start offset to
-	// the index of the first such li in tree order, and set start node to that
+	// the index of the last such li in tree order, and set start node to that
 	// li's parent."
-	for (
-		var ancestorContainer = startNode;
-		ancestorContainer;
-		ancestorContainer = ancestorContainer.parentNode
-	) {
-		if (isHtmlElement(ancestorContainer, "LI")) {
-			startOffset = getNodeIndex(ancestorContainer);
-			startNode = ancestorContainer.parentNode;
-		}
+	var liAncestors = getAncestors(startNode).concat(startNode)
+		.filter(function(ancestor) { return isHtmlElement(ancestor, "li") })
+		.slice(-1);
+	if (liAncestors.length) {
+		startOffset = getNodeIndex(liAncestors[0]);
+		startNode = liAncestors[0].parentNode;
 	}
 
 	// "Repeat the following steps:"
@@ -3718,17 +3728,14 @@
 	}
 
 	// "If some ancestor container of end node is an li, set end offset to one
-	// plus the index of the first such li in tree order, and set end node to
+	// plus the index of the last such li in tree order, and set end node to
 	// that li's parent."
-	for (
-		var ancestorContainer = endNode;
-		ancestorContainer;
-		ancestorContainer = ancestorContainer.parentNode
-	) {
-		if (isHtmlElement(ancestorContainer, "LI")) {
-			endOffset = 1 + getNodeIndex(ancestorContainer);
-			endNode = ancestorContainer.parentNode;
-		}
+	var liAncestors = getAncestors(endNode).concat(endNode)
+		.filter(function(ancestor) { return isHtmlElement(ancestor, "li") })
+		.slice(-1);
+	if (liAncestors.length) {
+		endOffset = 1 + getNodeIndex(liAncestors[0]);
+		endNode = liAncestors[0].parentNode;
 	}
 
 	// "Repeat the following steps:"
@@ -4735,12 +4742,13 @@
 	// "Let ancestor list be a list of nodes, initially empty."
 	var ancestorList = [];
 
-	// "While current ancestor is an editable Element that is not a simple
-	// indentation element, append current ancestor to ancestor list and then
-	// set current ancestor to its parent."
+	// "While current ancestor is an editable Element that is neither a simple
+	// indentation element nor an ol nor a ul, append current ancestor to
+	// ancestor list and then set current ancestor to its parent."
 	while (isEditable(currentAncestor)
 	&& currentAncestor.nodeType == Node.ELEMENT_NODE
-	&& !isSimpleIndentationElement(currentAncestor)) {
+	&& !isSimpleIndentationElement(currentAncestor)
+	&& !isHtmlElement(currentAncestor, ["ol", "ul"])) {
 		ancestorList.push(currentAncestor);
 		currentAncestor = currentAncestor.parentNode;
 	}
@@ -4754,23 +4762,23 @@
 		// "Let ancestor list be the empty list."
 		ancestorList = [];
 
-		// "While current ancestor is an editable Element that is not an
-		// indentation element, append current ancestor to ancestor list and
-		// then set current ancestor to its parent."
+		// "While current ancestor is an editable Element that is neither an
+		// indentation element nor an ol nor a ul, append current ancestor to
+		// ancestor list and then set current ancestor to its parent."
 		while (isEditable(currentAncestor)
 		&& currentAncestor.nodeType == Node.ELEMENT_NODE
-		&& !isIndentationElement(currentAncestor)) {
+		&& !isIndentationElement(currentAncestor)
+		&& !isHtmlElement(currentAncestor, ["ol", "ul"])) {
 			ancestorList.push(currentAncestor);
 			currentAncestor = currentAncestor.parentNode;
 		}
 	}
 
-	// "If node is an ol or ul, and either current ancestor is not an editable
-	// indentation element or node's parent is an ol or ul:"
+	// "If node is an ol or ul and current ancestor is not an editable
+	// indentation element:"
 	if (isHtmlElement(node, ["OL", "UL"])
 	&& (!isEditable(currentAncestor)
-	|| !isIndentationElement(currentAncestor)
-	|| isHtmlElement(node.parentNode, ["OL", "UL"]))) {
+	|| !isIndentationElement(currentAncestor))) {
 		// "Unset the reversed, start, and type attributes of node, if any are
 		// set."
 		node.removeAttribute("reversed");
@@ -4780,7 +4788,7 @@
 		// "Let children be the children of node."
 		var children = [].slice.call(node.childNodes);
 
-		// "If node has attributes, and its parent or not an ol or ul, set the
+		// "If node has attributes, and its parent is not an ol or ul, set the
 		// tag name of node to "div"."
 		if (node.attributes.length
 		&& !isHtmlElement(node.parentNode, ["OL", "UL"])) {
--- a/source.html	Mon Jul 11 13:08:29 2011 -0600
+++ b/source.html	Mon Jul 11 13:53:21 2011 -0600
@@ -3163,28 +3163,46 @@
   <li>If <var>node list</var> is empty, return "none".
 
   <li>If every member of <var>node list</var> is either an [[ol]] or the
-  [[child]] of an [[ol]], and none is a [[ul]] or an [[ancestor]] of a [[ul]],
-  return "ol".
+  [[child]] of an [[ol]] or the [[child]] of a [[child]] of an [[li]] [[child]]
+  of an [[ol]], and none is a [[ul]] or an [[ancestor]] of a [[ul]], return
+  "ol".
+  <!--
+  The child-of-child case is necessary right now because of the following:
+    <ol><li>[foo<ol><li>bar]</ol>baz</ol>
+  With the current (July 2011) block-extend algorithm, this will become:
+    {<ol><li>foo<ol><li>bar</ol>}baz</ol>
+  because of the magical li handling in block-extend.  We want this to register
+  as ol, because after normalizing sublists it will become
+    {<ol><li>foo</li><ol><li>bar</ol>}<li>baz</ol>
+
+  But the text node "foo" will wind up in node list, and is not the child of an
+  ol.  This is all very messy and has to do with questionable decisions about
+  how to handle nested lists.
+  -->
 
   <li>If every member of <var>node list</var> is either a [[ul]] or the
-  [[child]] of a [[ul]], and none is an [[ol]] or an [[ancestor]] of an [[ol]],
-  return "ul".
+  [[child]] of a [[ul]] or the [[child]] of an [[li]] [[child]] of a [[ul]],
+  and none is an [[ol]] or an [[ancestor]] of an [[ol]], return "ul".
   <!-- The previous two conditions are mutually exclusive, so the order is
   actually irrelevant.  Clearly they could only both hold if no member of node
-  list is an ol or ul, so if they both held, every member would have to be both
-  the child of an ol and the child of a ul.  This is impossible unless the list
-  is empty, in which case we already aborted. -->
+  list is an ol or ul, so if they both held, every member would have to be
+  either the child of an ol and of a ul, or of an ol and an li, or a ul and an
+  li, or of an li that's the child of both an ol and a ul.  This is impossible
+  unless the list is empty, in which case we already aborted. -->
 
   <li>If some member of <var>node list</var> is either an [[ol]] or the
-  [[child]] or [[ancestor]] of an [[ol]], and some member of <var>node
-  list</var> is either a [[ul]] or the [[child]] or [[ancestor]] of a [[ul]],
-  return "mixed".
+  [[child]] or [[ancestor]] of an [[ol]] or the [[child]] of an [[li]]
+  [[child]] of an [[ol]], and some member of <var>node list</var> is either a
+  [[ul]] or the [[child]] or [[ancestor]] of a [[ul]] or the [[child]] of an
+  [[li]] [[child]] of a [[ul]], return "mixed".
 
   <li>If some member of <var>node list</var> is either an [[ol]] or the
-  [[child]] or [[ancestor]] of an [[ol]], return "mixed ol".
+  [[child]] or [[ancestor]] of an [[ol]] or the [[child]] of an [[li]]
+  [[child]] of an [[ol]], return "mixed ol".
 
   <li>If some member of <var>node list</var> is either a [[ul]] or the
-  [[child]] or [[ancestor]] of a [[ul]], return "mixed ul".
+  [[child]] or [[ancestor]] of a [[ul]] or the [[child]] of an [[li]] [[child]]
+  of a [[ul]], return "mixed ul".
 
   <li>Return "none".
 </ol>
@@ -3245,9 +3263,12 @@
   and [[bpoffsets]] of <var>range</var>.
 
   <li>If some [[ancestorcontainer]] of <var>start node</var> is an [[li]], set
-  <var>start offset</var> to the [[index]] of the first such [[li]] in
+  <var>start offset</var> to the [[index]] of the last such [[li]] in
   [[treeorder]], and set <var>start node</var> to that [[li]]'s [[parent]].
 
+  <p class=XXX>This plus the normalizing sublists stuff seems very messy.  Can
+  we do better?
+
   <li>Repeat the following steps:
 
   <ol>
@@ -3281,7 +3302,7 @@
   </ol>
 
   <li>If some [[ancestorcontainer]] of <var>end node</var> is an [[li]], set
-  <var>end offset</var> to one plus the [[index]] of the first such [[li]] in
+  <var>end offset</var> to one plus the [[index]] of the last such [[li]] in
   [[treeorder]], and set <var>end node</var> to that [[li]]'s [[parent]].
 
   <li>Repeat the following steps:
@@ -4213,9 +4234,8 @@
   <var>node</var>, <span>preserving its descendants</span>.  Then abort these
   steps.
 
-  <!-- No browser handles the case of Firefox 4.0 in CSS mode, where it adds a
-  margin attribute to an existing element, including Firefox itself.  So let's
-  just skip it. -->
+  <p class=XXX>Look into handling indentation like Gecko in CSS mode, where a
+  margin attribute is added to a random element.
 
   <li>If <var>node</var> is an <span>indentation element</span>:
   <!-- This might be a simple indentation element that had style added to it by
@@ -4271,9 +4291,9 @@
   <li>Let <var>ancestor list</var> be a list of [[nodes]], initially empty.
 
   <li>While <var>current ancestor</var> is an <span>editable</span> [[element]]
-  that is not a <span>simple indentation element</span>, append <var>current
-  ancestor</var> to <var>ancestor list</var> and then set <var>current
-  ancestor</var> to its [[parent]].
+  that is neither a <span>simple indentation element</span> nor an [[ol]] nor a
+  [[ul]], append <var>current ancestor</var> to <var>ancestor list</var> and
+  then set <var>current ancestor</var> to its [[parent]].
 
   <li>If <var>current ancestor</var> is not an <span>editable</span>
   <span>simple indentation element</span>:
@@ -4284,14 +4304,13 @@
     <li>Let <var>ancestor list</var> be the empty list.
 
     <li>While <var>current ancestor</var> is an <span>editable</span>
-    [[element]] that is not an <span>indentation element</span>, append
-    <var>current ancestor</var> to <var>ancestor list</var> and then set
-    <var>current ancestor</var> to its [[parent]].
+    [[element]] that is neither an <span>indentation element</span> nor an
+    [[ol]] nor a [[ul]], append <var>current ancestor</var> to <var>ancestor
+    list</var> and then set <var>current ancestor</var> to its [[parent]].
   </ol>
 
-  <li>If <var>node</var> is an [[ol]] or [[ul]], and either <var>current
-  ancestor</var> is not an <span>editable</span> <span>indentation
-  element</span> or <var>node</var>'s [[parent]] is an [[ol]] or [[ul]]:
+  <li>If <var>node</var> is an [[ol]] or [[ul]] and <var>current ancestor</var>
+  is not an <span>editable</span> <span>indentation element</span>:
   <!--
   When asked to outdent a list wrapped in a simple indentation element, Chrome
   12 dev removes the list instead of the simple indentation element.  Opera
@@ -4319,10 +4338,6 @@
   here.
   -->
 
-  <p class=XXX>What about if node isn't a child of a list, but there's a list
-  ancestor below current ancestor?  Is that even possible given how the
-  block-extend algorithm works?
-
   <ol>
     <li>Unset the <code data-anolis-spec=html
     title=attr-ol-reversed>reversed</code>, <code data-anolis-spec=html
@@ -4332,7 +4347,7 @@
 
     <li>Let <var>children</var> be the [[children]] of <var>node</var>.
 
-    <li>If <var>node</var> has attributes, and its [[parent]] or not an [[ol]]
+    <li>If <var>node</var> has attributes, and its [[parent]] is not an [[ol]]
     or [[ul]], <span>set the tag name</span> of <var>node</var> to "div".
 
     <li>Otherwise remove <var>node</var>, <span>preserving its descendants</span>.
--- a/tests.js	Mon Jul 11 13:08:29 2011 -0600
+++ b/tests.js	Mon Jul 11 13:53:21 2011 -0600
@@ -2884,6 +2884,7 @@
 
 		'<ol><li><h1>[foo]</h1></ol>',
 		'<ol><li><xmp>[foo]</xmp></li></ol>',
+		'<blockquote><ol><li>foo<div><ol><li>[bar]</ol></div><li>baz</ol></blockquote>',
 	],
 	//@}
 	removeformat: [