Did we miss something ?

Working quite hard these days on nested lists, I wonder if all the SGML/XML gurus and fans, including myself, who have always preached in favor of a clean model for lists aren't just wrong... Basically, here's the model for HTML lists. All DTDs before HTML used a similar model of nesting.

<!ELEMENT UL - - (LI)+ -- unordered list -->
<!ELEMENT LI - O (%flow;)* -- list item -->
<!ENTITY % flow "%block; | %inline;">
<!ENTITY % block "P | %heading; | %list; | %preformatted; | DL | DIV | NOSCRIPT |
                  BLOCKQUOTE | FORM | HR | TABLE | FIELDSET | ADDRESS">
<!ENTITY % list "UL | OL">
...

So a list item can contain almost everything in the HTML model but a list item. In particular, sublists are contained in list items and can't be the child of another list. So let's consider a simple and valid HTML example :

<ol>
  <li>this is a first list item</li>
  <li>a second one
    <p>it contains a paragraph too</p>
    <ol>
      <li>and this is the first sublist item</li>
      <li>the second sublist item</li>
    </ol>
    <ol>
      <li>another sublist item, but not in same sublist</li>
    </ol>
  </li>
  <li>and a third list item in outermost list</li>
</ol>

Imagine you are a software developer and you have to implement the two buttons "indent" and "outdent". You can place the caret wherever you want in the markup above and you can even extend the selection from one element to another, from the middle of an element to the middle of another one. Then you press on indent or outdent, what happens ?

Answer is easy : you fall in a programming nightmare. Here's why :

Imagine the selection starts in the same anonymous content and ends in the paragraph just after it. All sub-elements of the list item but sub-lists are totally or partly selected, we want to make a new sublist item with these nodes. To do that, we have to :

  1. check if the first top list item ends with a sublist
    1. if does not, append a new sublist
  2. create a new list item in the sublist ending the first top list item
  3. move all the promoted selection inside that new sublist item
  4. ooops, we now have a top list item (the one we are indenting) having a sublist as first child and that causes ugly renderings, thanks to legacy browsers + HTML + CSS ! That's a proof of existence of the devil and we can't let it be ! We need to move all the children of our list item into the previous one (the first top list item)...
  5. and we have to merge the sublist at the end of first top list item and the sublist at beginning of second top list item ; of course, don't merge the second sublist of the second top list item
  6. the second top list item is now empty, remove it
  7. of course, that's the simple case... There's no other element, not a list, after the second sublist in the second top list item, and all the lists and sublists are ordered. It could even be more complex than that, but I see you already need an aspirin so that will be enough for today.

The more I list (sic) simple cases like the one above, the more I think that the Structured Documentation Gurus' model of nested lists is rotten and that what we have always called "the invalid" model for nested lists is the best one. Sublists and top list items should be at same level.

<!ELEMENT LIST     - - (LISTITEM, LIST*)+ >
<!ELEMENT LISTITEM - - (%flow;)* - (LIST) >

Our markup becomes :

<ol>
  <li>this is a first list item</li>
  <li>a second one
    <p>it contains a paragraph too</p>
  </li>
  <ol>
    <li>and this is the first sublist item</li>
    <li>the second sublist item</li>
  </ol>
  <ol>
    <li>another sublist item, but not in same sublist</li>
  </ol>
  <li>and a third list item in outermost list</li>
</ol>

And here is what we have to do :

  1. detect that our top second list item is followed by a sublist
  2. move the top list item into that sublist, in first child's position

The default presentation would imply a CSS counter on LIST elements, incremented only on LISTITEMs. The HTML example above becomes trivial to implement and in fact all the examples I can think of become trivial to implement. On the other hand, all the examples I can think of in the "valid" HTML model make me think I should call four dozens of ambulances and invite the whole HTML WG, passed and present members (don't flame me, I'm on the list too), to a peaceful retreat in a psychiatric hospital unit, faaaaar away from any computer and standardization committee.

Well, it's late and the nurses at the hospital won't be happy if I'm late for my injection of tranquilizers. Please don't tell them I used a computer, I don't want that camisole again.