<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>src/main/scala/knockoff2/ListItem.scala</filename>
    </added>
    <added>
      <filename>src/main/scala/knockoff2/OrderedItem.scala</filename>
    </added>
    <added>
      <filename>src/main/scala/knockoff2/UnorderedItem.scala</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1 +1,8 @@
 knockoff.tmproj
+lib
+lib_managed
+target
+project/boot
+*/project/boot
+src_managed
+test-output</diff>
      <filename>.gitignore</filename>
    </modified>
    <modified>
      <diff>@@ -13,7 +13,7 @@ class KnockoffLiterablePluginProject(info: ProjectInfo) extends PluginProject(in
     val knockoff    = &quot;com.tristanhunt&quot; % &quot;knockoff&quot; % &quot;0.4.1&quot;
     val site_step   = &quot;com.tristanhunt&quot; % &quot;site_step&quot; % &quot;0.4.0&quot;
     val literable   = &quot;com.tristanhunt&quot; % &quot;literable&quot; % &quot;0.4.5&quot;
-    val sbt_plugin  = &quot;com.tristanhunt&quot; % &quot;literable_sbt_plugin&quot; % &quot;0.4.5&quot;
+    val sbt_plugin  = &quot;com.tristanhunt&quot; % &quot;literable_sbt_plugin&quot; % &quot;0.4.4&quot;
     
     override def managedStyle = ManagedStyle.Maven
     val publishTo = &quot;tristanhunt releases&quot; at &quot;http://tristanhunt.com:8081/content/repositories/releases/&quot;</diff>
      <filename>literable_plugin/project/build/src/KnockoffLiterablePluginProject.scala</filename>
    </modified>
    <modified>
      <diff>@@ -1,8 +1,8 @@
-#Project properties
-#Mon Jun 01 11:35:54 CEST 2009
-project.organization=com.tristanhunt
+#Project Properties
+#Sat Oct 03 10:42:23 CEST 2009
 project.name=knockoff
+project.organization=com.tristanhunt
 sbt.version=0.5.5
-project.version=0.5.0-SNAPSHOT
 scala.version=2.7.5
+project.version=0.5.0-SNAPSHOT
 project.initialize=false</diff>
      <filename>project/build.properties</filename>
    </modified>
    <modified>
      <diff>@@ -5,7 +5,7 @@ extends DefaultProject( info )
 with    knockoff.Literable {
   
   override def compileOptions = {
-    List( MaxCompileErrors( 10 ), CompileOption(&quot;-unchecked&quot;) ) :::
+    List( MaxCompileErrors( 5 ), CompileOption(&quot;-unchecked&quot;) ) :::
     super.compileOptions.toList
   }
   </diff>
      <filename>project/build/src/KnockoffProject.scala</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,3 @@
 #Project properties
-#Wed Sep 30 22:26:34 CEST 2009
+#Sat Oct 03 10:50:24 CEST 2009
 plugin.uptodate=true</diff>
      <filename>project/plugins/project/build.properties</filename>
    </modified>
    <modified>
      <diff>@@ -52,7 +52,7 @@ In some other cases, the block is a pretty complex thing:
         val children : Seq[ Block ]
         val span = new SpanSeq{ def theSeq = children.flatMap( _.span ) }
         def theSeq = children
-        def childrenMarkdown = children.map( _.markdown ).mkString(&quot;\n&quot;)
+        def childrenMarkdown = children.map( _.markdown ).mkString(&quot;\n&quot;) + &quot;\n&quot;
         def childrenXML = children.map( _.xml )
     }
 
@@ -401,103 +401,89 @@ In implementation terms, we don't have a single list.
 &gt; the spec wants blocks as consistent within the list. Not hard, either
 &gt; way.
 
-    // In knockoff2/SimpleItem.scala
+    // In knockoff2/ListItem.scala
     package knockoff2
     
     import scala.util.parsing.input.Position
+    import scala.xml.Node
     
-    trait PrefixedItem { self : ComplexBlock =&gt;
-      def itemPrefix : String
-      
-      /** Create a new unordered item ... */
-      def + ( b : Block ) : UnorderedItem
-      
-    }
-    
-    class OrderedItem(
+    abstract class ListItem(
       val children : BlockSeq,
       val position : Position
-    ) extends ComplexBlock with PrefixedItem {
-      
-      def itemPrefix = &quot;1. &quot;
-      
+    )
+    extends ComplexBlock {
+
+      def itemPrefix : String
       
-    }
-        
-    class UnorderedItem(
-      val children : BlockSeq,
-      val position : Position
-    ) extends PrefixedItem with ComplexBlock {
+      def markdown : String = {
+        if ( children.isEmpty ) return &quot;&quot;
+
+        return (
+          ( itemPrefix + children.first.markdown + &quot;  \n&quot; ) +
+          children.drop(1).map( &quot;    &quot; + _.markdown + &quot;  \n&quot; ).mkString( &quot;&quot; )
+        )
+      }
       
-      def this( s : SpanSeq, p : Position ) =
-        this(
+      def xml( complex : Boolean ) : Node = &lt;li&gt;{
+        if ( isComplex )
+          children.first.span.toXML
+        else
+          childrenXML 
+      }&lt;/li&gt;
       
-      def itemPrefix = &quot;* &quot;
+      def xml : Node = xml( isComplex )
       
+      def isComplex = children.length &gt; 1
       
-      // TODO toString, equals, hashCode (yay)
+      // See the ListItem toString, equals, hashCode implementation
     }
+      
+### `OrderedItem`
 
-    abstract class SimpleItem (
-      val span     : SpanSeq,
-      val position : Position   
-    )
-    extends SimpleBlock
-    with    PrefixedItem {
-        
-      def xml = &lt;li&gt;{ span.toXML }&lt;/li&gt;
+    // In knockoff2/OrderedItem.scala
+    package knockoff2
+
+    import scala.util.parsing.input.Position
+    
+    class OrderedItem( children : BlockSeq, position : Position )
+    extends ListItem( children, position ) {
+
+      def this( block : Block, position : Position ) =
+        this( new BlockSeq{ val theSeq = Seq( block ) }, position )
       
-      def markdown = itemPrefix + span.toMarkdown
+      def itemPrefix = &quot;1. &quot;
       
-      // See the SimpleItem toString, equals, hashCode implementations
+      def + ( b : Block ) : OrderedItem =
+        new OrderedItem( children, children.first.position )        
     }
-    
-    class   OrderedSimpleItem( span : SpanSeq, position : Position )
-    extends SimpleItem( span, position )
-    with    OrderedItem
-    
-    class   UnorderedSimpleItem( span : SpanSeq, position : Position )
-    extends SimpleItem( span, position )
-    with    UnorderedItem
 
-#### `ComplexItem`
+### `UnorderedItem`
 
-    // In knockoff2/ComplexItem.scala
+    // In knockoff2/UnorderedItem.scala
     package knockoff2
     
     import scala.util.parsing.input.Position
-    
-    abstract class ComplexItem(
-      val children : BlockSeq,
-      val position : Position
-    )
-    extends ComplexBlock
-    with    PrefixedItem {
         
-      def xml = &lt;li&gt;{ childrenXML }&lt;/li&gt;
+    class UnorderedItem( children : BlockSeq, position : Position )
+    extends ListItem( children, position ) {
       
-      def markdown : String = {
-        if ( children.isEmpty ) return &quot;&quot;
-
-        return (
-          ( itemPrefix + children.first.markdown + &quot;  \n&quot; ) +
-          children.drop(1).map( &quot;    &quot; + _.markdown + &quot;  \n&quot; ).mkString( &quot;&quot; )
-        )
-      }
+      def this( block : Block, position : Position ) =
+        this( new BlockSeq{ val theSeq = Seq( block ) }, position )
+      
+      def itemPrefix = &quot;* &quot;
       
-      // See the ComplexItem toString, equals, hashCode implementations
+      def + ( b : Block ) : UnorderedItem =
+        new UnorderedItem( children, children.first.position )
     }
-    
-    class   OrderedComplexItem( children : BlockSeq, position : Position )
-    extends ComplexItem( children, position )
-    with    OrderedItem
 
-    class   UnorderedComplexItem( children : BlockSeq, position : Position )
-    extends ComplexItem( children, position )
-    with    UnorderedItem
-    
 #### `MarkdownList`
 
+Lists just contain items, and are either ordered or unordered.
+
+The position of a list is a little spurious: the start of the list should be
+the position of the first item, however, it's elements may not contain the
+entire content; whitespace will be missing in complex cases.
+
     // In knockoff2/MarkdownList.scala
     package knockoff2
     
@@ -510,7 +496,7 @@ In implementation terms, we don't have a single list.
     abstract class MarkdownList(
       val children : BlockSeq
     ) extends ComplexBlock {
-        
+      
       val position = children.firstOption match {
         case None =&gt; NoPosition
         case Some( child ) =&gt; child.position
@@ -526,11 +512,8 @@ In implementation terms, we don't have a single list.
      
       def xml = &lt;ol&gt;{ childrenXML }&lt;/ol&gt;
       
-      def + ( item : OrderedSimpleItem ) : OrderedList =
-        new OrderedList( new GroupBlock( children ++ Seq( item ) ) )
-      
-      def + ( item : OrderedComplexItem ) : OrderedList =
-        new OrderedList( new GroupBlock( children ++ Seq( item ) ) )
+      def + ( item : OrderedItem ) : OrderedList =
+        new OrderedList( new GroupBlock( children ++ Seq( item ) ) )      
     }
     
     class UnorderedList( children : BlockSeq )
@@ -538,10 +521,7 @@ In implementation terms, we don't have a single list.
      
       def xml = &lt;ul&gt;{ childrenXML }&lt;/ul&gt;
       
-      def + ( item : UnorderedSimpleItem ) : UnorderedList =
-        new UnorderedList( new GroupBlock( children ++ Seq( item ) ) )
-      
-      def + ( item : UnorderedComplexItem ) : UnorderedList =
+      def + ( item : UnorderedItem ) : UnorderedList =
         new UnorderedList( new GroupBlock( children ++ Seq( item ) ) )
     }
     
@@ -820,65 +800,32 @@ In implementation terms, we don't have a single list.
 
     def canEqual( t : HorizontalRule ) : Boolean = t.getClass == getClass
 
-### `SimpleItem`
 
-#### `SimpleItem` - Package and Imports
+### `ListItem`
 
-    // The SimpleItem package and imports
-    package knockoff2
+#### `ListItem` - `toString`, `equals`, `hashCode`
 
-    import scala.xml.{ Node, Unparsed }
-    import scala.io.Source
-    import scala.util.parsing.input.Position
-
-#### `SimpleItem` - `toString`, `equals`, `hashCode`
-
-    // The SimpleItem toString, equals, hashCode implementations
-    override def toString = &quot;SimpleItem(&quot; + markdown + &quot;)&quot;
-
-    override def hashCode : Int = position.hashCode + 47
+    // The ListItem toString, equals, hashCode implementations
+    override def toString = &quot;ListItem(&quot; + markdown + &quot;)&quot;
 
-    override def equals( rhs : Any ) : Boolean = rhs match {
-      case t : SimpleItem =&gt; t.canEqual( this ) &amp;&amp; ( this sameElements t )
-      case _ =&gt; false
-    }
-    
-    def sameElements( si : SimpleItem ) : Boolean = {
-      ( span == si.span ) &amp;&amp;
-      ( position == si.position )
+    override def hashCode : Int =  {
+      ( 11 /: children )( (total, child) =&gt; total + 51 + 3 * child.hashCode ) +
+      position.hashCode + 47
     }
 
-    def canEqual( t : SimpleItem ) : Boolean = t.getClass == getClass
-
-### `ComplexItem`
-
-#### `ComplexItem` - Package and Imports
-
-    // The ComplexItem package and imports
-    package knockoff2
-
-    import scala.xml.{ Node, Unparsed }
-    import scala.io.Source
-    import scala.util.parsing.input.Position
-
-#### `ComplexItem` - `toString`, `equals`, `hashCode`
-
-    // The ComplexItem toString, equals, hashCode implementations
-    override def toString = &quot;ComplexItem(&quot; + markdown + &quot;)&quot;
-
-    override def hashCode : Int = position.hashCode + 47
-
     override def equals( rhs : Any ) : Boolean = rhs match {
-      case t : ComplexItem =&gt; t.canEqual( this ) &amp;&amp; ( this sameElements t )
+      case t : ListItem =&gt; t.canEqual( this ) &amp;&amp; ( this sameElements t )
       case _ =&gt; false
     }
     
-    def sameElements( ci : ComplexItem ) : Boolean = {
+    def sameElements( ci : ListItem ) : Boolean = {
       ( children == ci.children ) &amp;&amp;
       ( position == ci.position )
     }
 
-    def canEqual( t : ComplexItem ) : Boolean = t.getClass == getClass
+    def canEqual( t : ListItem ) : Boolean = t.getClass == getClass
+
+
 
 ### `MarkdownList`
 
@@ -895,7 +842,10 @@ In implementation terms, we don't have a single list.
     // The MarkdownList toString, equals, hashCode implementations
     override def toString = &quot;MarkdownList(&quot; + markdown + &quot;)&quot;
 
-    override def hashCode : Int = position.hashCode + 47
+    override def hashCode : Int = {
+      ( 13 /: children )( (total, child) =&gt; total + 51 + 3 * child.hashCode ) +
+      position.hashCode + 47
+    }
 
     override def equals( rhs : Any ) : Boolean = rhs match {
       case t : MarkdownList =&gt; t.canEqual( this ) &amp;&amp; ( t sameElements this )</diff>
      <filename>src/main/markdown/30-Implementation/02-Block_Elements.markdown</filename>
    </modified>
    <modified>
      <diff>@@ -50,10 +50,10 @@ customizing the `ElementFactory` is pretty simple. You create a subtype of
 
       // Block Elements
       
-      def para( s : Span, p : Position ) =
+      def para( s : SpanSeq, p : Position ) =
         new Paragraph( s, p )
       
-      def head( l : Int, s : Span, p : Position ) =
+      def head( l : Int, s : SpanSeq, p : Position ) =
         new Header( l, s, p )
         
       def hr( p : Position ) =
@@ -68,29 +68,31 @@ customizing the `ElementFactory` is pretty simple. You create a subtype of
       def htmlBlock( h : String, p : Position ) : HTMLBlock =
         new HTMLBlock( h, p )
       
-      def simpleOL( osis : OrderedSimpleItem * ) : MarkdownList =
-        new OrderedList( new BlockSeq{ def theSeq = osis } )
+      def codeBlock( s : String, p : Position ) : CodeBlock =
+        codeBlock( text(s), p )
       
-      def complexOL( ocis : OrderedComplexItem * ) : MarkdownList =
-        new OrderedList( new BlockSeq{ def theSeq = ocis } )
+      def codeBlock( t : Text, p : Position ) : CodeBlock =
+        new CodeBlock( t, p )
       
-      def simpleUL( usis : UnorderedSimpleItem * ) : MarkdownList =
-        new UnorderedList( new BlockSeq{ def theSeq = usis } )
-
-      def complexUL( ucis : UnorderedComplexItem * ) : MarkdownList =
-        new UnorderedList( new BlockSeq{ def theSeq = ucis } )
+      def olist( olis : OrderedItem * ) : OrderedList = new OrderedList(
+        if ( olis.length == 1 ) olis.first else new GroupBlock( olis )
+      )
       
-      def osi( s : Span, p : Position ) : OrderedSimpleItem =
-        new OrderedSimpleItem( s, p )
+      def ulist( ulis : UnorderedItem * ) : UnorderedList = new UnorderedList(
+        if ( ulis.length == 1 ) ulis.first else new GroupBlock( ulis )
+      )
       
-      def oci( b : BlockSeq, p : Position ) : OrderedComplexItem =
-        new OrderedComplexItem( b, p )
+      def uli( b : Block, p : Position ) : UnorderedItem =
+        new UnorderedItem( b, p )
+  
+      def uli( bs : BlockSeq, p : Position ) : UnorderedItem =
+        new UnorderedItem( bs, p )
 
-      def usi( s : Span, p : Position ) : UnorderedSimpleItem =
-        new UnorderedSimpleItem( s, p )
+      def oli( b : Block, p : Position ) : OrderedItem =
+        new OrderedItem( b, p )
 
-      def uci( b : BlockSeq, p : Position ) : UnorderedComplexItem =
-        new UnorderedComplexItem( b, p )
+      def oli( bs : BlockSeq, p : Position ) : OrderedItem =
+        new OrderedItem( bs, p )
       
       
       // Span Elements</diff>
      <filename>src/main/markdown/30-Implementation/04-ElementFactory.markdown</filename>
    </modified>
    <modified>
      <diff>@@ -14,7 +14,8 @@ part separately from the expressions here.
       override def skipWhitespace = false
       
       def chunk : Parser[ Chunk ] = {
-        horizontalRule | bulletLead | numberedLead | header | textBlock | emptyLines
+        horizontalRule | bulletLead | numberedLead | indentedChunk | 
+        header | textBlock | emptyLines
       }
       
       def emptyLines : Parser[ Chunk ] =
@@ -70,6 +71,13 @@ part separately from the expressions here.
         }
       }
       
+      def indentedChunk : Parser[ Chunk ] = 
+        rep1( indentedLine ) ^^ ( lines =&gt; IndentedChunk( foldedString( lines ) ) )
+      
+      def indentedLine : Parser[ Chunk ] =
+        &quot;&quot;&quot;\t|[ ]{4}&quot;&quot;&quot;.r ~&gt; ( textLine | emptyLine )
+      
+      
       
       // Utility Methods
       </diff>
      <filename>src/main/markdown/30-Implementation/10-Parsing/11-ChunkParsers.markdown</filename>
    </modified>
    <modified>
      <diff>@@ -62,16 +62,19 @@ This is more of a reference to the typing of chunks.
         spans    : SpanSeq,
         position : Position
       )( elementFactory : ElementFactory ) {
-        val li = elementFactory.usi( elementFactory.toSpan(spans), position )
+        val li = elementFactory.uli(
+          elementFactory.para(spans, position),
+          position
+        )
         if ( list.isEmpty ) {
-          list += elementFactory.simpleUL( li )
+          list += elementFactory.ulist( li )
         } else {
           list.last match {
             case ul : UnorderedList =&gt; {
               val appended = ul + li
               list.update( list.length - 1, appended )
             }
-            case _ =&gt; list += elementFactory.simpleUL( li )
+            case _ =&gt; list += elementFactory.ulist( li )
           }
         }
       }
@@ -84,16 +87,19 @@ This is more of a reference to the typing of chunks.
         spans    : SpanSeq,
         position : Position
       )( elementFactory : ElementFactory ) {
-        val li = elementFactory.osi( elementFactory.toSpan(spans), position )
+        val li = elementFactory.oli(
+          elementFactory.para(spans, position),
+          position
+        )
         if ( list.isEmpty ) {
-          list += elementFactory.simpleOL( li )
+          list += elementFactory.olist( li )
         } else {
           list.last match {
             case ol : OrderedList =&gt; {
               val appended = ol + li
               list.update( list.length - 1, appended )
             }
-            case _ =&gt; list += elementFactory.simpleOL( li )
+            case _ =&gt; list += elementFactory.olist( li )
           }
         }
       }
@@ -127,6 +133,18 @@ This is more of a reference to the typing of chunks.
         spans    : SpanSeq,
         position : Position
       )( elementFactory : ElementFactory ) {
-        
+        list.last match {
+          case ml : MarkdownList =&gt; {
+            list += elementFactory.para( spans, position )
+          }
+          case _ =&gt; {
+            spans.first match {
+              case text : Text =&gt;
+                list += elementFactory.codeBlock( text, position )
+              case s : Span =&gt;
+                error( &quot;Expected Text(code) for code block addition, not &quot; + s )
+            }
+          }
+        }
       }
     }</diff>
      <filename>src/main/markdown/30-Implementation/10-Parsing/12-Chunk_Types.markdown</filename>
    </modified>
    <modified>
      <diff>@@ -62,7 +62,12 @@ of that span.
       /**
         The SpanConverter is a map method from Chunk to SpanSeq
       */
-      def apply( chunk : Chunk ) : SpanSeq = convert( chunk.content, Nil )
+      def apply( chunk : Chunk ) : SpanSeq = {
+        chunk match {
+          case IndentedChunk( content ) =&gt; new Text( content )
+          case _ =&gt; convert( chunk.content, Nil )
+        }
+      }
       
       /**
         Tail-recursive method halts when the content argument is empty.</diff>
      <filename>src/main/markdown/30-Implementation/10-Parsing/20-Span_Conversion.markdown</filename>
    </modified>
    <modified>
      <diff>@@ -7,7 +7,8 @@ class ChunkParser extends RegexParsers with StringExtras {
   override def skipWhitespace = false
   
   def chunk : Parser[ Chunk ] = {
-    horizontalRule | bulletLead | numberedLead | header | textBlock | emptyLines
+    horizontalRule | bulletLead | numberedLead | indentedChunk | 
+    header | textBlock | emptyLines
   }
   
   def emptyLines : Parser[ Chunk ] =
@@ -63,6 +64,13 @@ class ChunkParser extends RegexParsers with StringExtras {
     }
   }
   
+  def indentedChunk : Parser[ Chunk ] = 
+    rep1( indentedLine ) ^^ ( lines =&gt; IndentedChunk( foldedString( lines ) ) )
+  
+  def indentedLine : Parser[ Chunk ] =
+    &quot;&quot;&quot;\t|[ ]{4}&quot;&quot;&quot;.r ~&gt; ( textLine | emptyLine )
+  
+  
   
   // Utility Methods
   </diff>
      <filename>src/main/scala/knockoff2/ChunkParsers.scala</filename>
    </modified>
    <modified>
      <diff>@@ -57,16 +57,19 @@ case class BulletLineChunk( val content : String ) extends Chunk {
     spans    : SpanSeq,
     position : Position
   )( elementFactory : ElementFactory ) {
-    val li = elementFactory.usi( elementFactory.toSpan(spans), position )
+    val li = elementFactory.uli(
+      elementFactory.para(spans, position),
+      position
+    )
     if ( list.isEmpty ) {
-      list += elementFactory.simpleUL( li )
+      list += elementFactory.ulist( li )
     } else {
       list.last match {
         case ul : UnorderedList =&gt; {
           val appended = ul + li
           list.update( list.length - 1, appended )
         }
-        case _ =&gt; list += elementFactory.simpleUL( li )
+        case _ =&gt; list += elementFactory.ulist( li )
       }
     }
   }
@@ -79,16 +82,19 @@ case class NumberedLineChunk( val content : String ) extends Chunk {
     spans    : SpanSeq,
     position : Position
   )( elementFactory : ElementFactory ) {
-    val li = elementFactory.osi( elementFactory.toSpan(spans), position )
+    val li = elementFactory.oli(
+      elementFactory.para(spans, position),
+      position
+    )
     if ( list.isEmpty ) {
-      list += elementFactory.simpleOL( li )
+      list += elementFactory.olist( li )
     } else {
       list.last match {
         case ol : OrderedList =&gt; {
           val appended = ol + li
           list.update( list.length - 1, appended )
         }
-        case _ =&gt; list += elementFactory.simpleOL( li )
+        case _ =&gt; list += elementFactory.olist( li )
       }
     }
   }
@@ -104,3 +110,36 @@ case class HeaderChunk( val level : Int, val content : String ) extends Chunk {
     list += elementFactory.head( level, elementFactory.toSpan(spans), position )
   }
 }
+
+/**
+  This represents a group of lines that have at least 4 spaces/1 tab preceding
+  the line.
+*/
+case class IndentedChunk( val content : String ) extends Chunk {
+  
+  lazy val lines = io.Source.fromString( content ).getLines.toList
+  
+  /**
+    If the block before is a list, we append this to the end of that list.
+    Otherwise, append it as a new block item.
+  */
+  def appendNewBlock(
+    list     : ListBuffer[ Block ],
+    spans    : SpanSeq,
+    position : Position
+  )( elementFactory : ElementFactory ) {
+    list.last match {
+      case ml : MarkdownList =&gt; {
+        list += elementFactory.para( spans, position )
+      }
+      case _ =&gt; {
+        spans.first match {
+          case text : Text =&gt;
+            list += elementFactory.codeBlock( text, position )
+          case s : Span =&gt;
+            error( &quot;Expected Text(code) for code block addition, not &quot; + s )
+        }
+      }
+    }
+  }
+}</diff>
      <filename>src/main/scala/knockoff2/ChunkTypes.scala</filename>
    </modified>
    <modified>
      <diff>@@ -4,6 +4,6 @@ trait ComplexBlock extends Block {
     val children : Seq[ Block ]
     val span = new SpanSeq{ def theSeq = children.flatMap( _.span ) }
     def theSeq = children
-    def childrenMarkdown = children.map( _.markdown ).mkString(&quot;\n&quot;)
+    def childrenMarkdown = children.map( _.markdown ).mkString(&quot;\n&quot;) + &quot;\n&quot;
     def childrenXML = children.map( _.xml )
 }</diff>
      <filename>src/main/scala/knockoff2/ComplexBlock.scala</filename>
    </modified>
    <modified>
      <diff>@@ -7,10 +7,10 @@ class ElementFactory {
 
   // Block Elements
   
-  def para( s : Span, p : Position ) =
+  def para( s : SpanSeq, p : Position ) =
     new Paragraph( s, p )
   
-  def head( l : Int, s : Span, p : Position ) =
+  def head( l : Int, s : SpanSeq, p : Position ) =
     new Header( l, s, p )
     
   def hr( p : Position ) =
@@ -25,29 +25,31 @@ class ElementFactory {
   def htmlBlock( h : String, p : Position ) : HTMLBlock =
     new HTMLBlock( h, p )
   
-  def simpleOL( osis : OrderedSimpleItem * ) : MarkdownList =
-    new OrderedList( new BlockSeq{ def theSeq = osis } )
+  def codeBlock( s : String, p : Position ) : CodeBlock =
+    codeBlock( text(s), p )
   
-  def complexOL( ocis : OrderedComplexItem * ) : MarkdownList =
-    new OrderedList( new BlockSeq{ def theSeq = ocis } )
+  def codeBlock( t : Text, p : Position ) : CodeBlock =
+    new CodeBlock( t, p )
   
-  def simpleUL( usis : UnorderedSimpleItem * ) : MarkdownList =
-    new UnorderedList( new BlockSeq{ def theSeq = usis } )
-
-  def complexUL( ucis : UnorderedComplexItem * ) : MarkdownList =
-    new UnorderedList( new BlockSeq{ def theSeq = ucis } )
+  def olist( olis : OrderedItem * ) : OrderedList = new OrderedList(
+    if ( olis.length == 1 ) olis.first else new GroupBlock( olis )
+  )
   
-  def osi( s : Span, p : Position ) : OrderedSimpleItem =
-    new OrderedSimpleItem( s, p )
+  def ulist( ulis : UnorderedItem * ) : UnorderedList = new UnorderedList(
+    if ( ulis.length == 1 ) ulis.first else new GroupBlock( ulis )
+  )
   
-  def oci( b : BlockSeq, p : Position ) : OrderedComplexItem =
-    new OrderedComplexItem( b, p )
+  def uli( b : Block, p : Position ) : UnorderedItem =
+    new UnorderedItem( b, p )
+
+  def uli( bs : BlockSeq, p : Position ) : UnorderedItem =
+    new UnorderedItem( bs, p )
 
-  def usi( s : Span, p : Position ) : UnorderedSimpleItem =
-    new UnorderedSimpleItem( s, p )
+  def oli( b : Block, p : Position ) : OrderedItem =
+    new OrderedItem( b, p )
 
-  def uci( b : BlockSeq, p : Position ) : UnorderedComplexItem =
-    new UnorderedComplexItem( b, p )
+  def oli( bs : BlockSeq, p : Position ) : OrderedItem =
+    new OrderedItem( bs, p )
   
   
   // Span Elements</diff>
      <filename>src/main/scala/knockoff2/ElementFactory.scala</filename>
    </modified>
    <modified>
      <diff>@@ -9,7 +9,7 @@ import scala.util.parsing.input.{ NoPosition, Position }
 abstract class MarkdownList(
   val children : BlockSeq
 ) extends ComplexBlock {
-    
+  
   val position = children.firstOption match {
     case None =&gt; NoPosition
     case Some( child ) =&gt; child.position
@@ -19,7 +19,10 @@ abstract class MarkdownList(
   
   override def toString = &quot;MarkdownList(&quot; + markdown + &quot;)&quot;
   
-  override def hashCode : Int = position.hashCode + 47
+  override def hashCode : Int = {
+    ( 13 /: children )( (total, child) =&gt; total + 51 + 3 * child.hashCode ) +
+    position.hashCode + 47
+  }
   
   override def equals( rhs : Any ) : Boolean = rhs match {
     case t : MarkdownList =&gt; t.canEqual( this ) &amp;&amp; ( t sameElements this )
@@ -38,11 +41,8 @@ extends MarkdownList( children ) {
  
   def xml = &lt;ol&gt;{ childrenXML }&lt;/ol&gt;
   
-  def + ( item : OrderedSimpleItem ) : OrderedList =
-    new OrderedList( new GroupBlock( children ++ Seq( item ) ) )
-  
-  def + ( item : OrderedComplexItem ) : OrderedList =
-    new OrderedList( new GroupBlock( children ++ Seq( item ) ) )
+  def + ( item : OrderedItem ) : OrderedList =
+    new OrderedList( new GroupBlock( children ++ Seq( item ) ) )      
 }
 
 class UnorderedList( children : BlockSeq )
@@ -50,9 +50,6 @@ extends MarkdownList( children ) {
  
   def xml = &lt;ul&gt;{ childrenXML }&lt;/ul&gt;
   
-  def + ( item : UnorderedSimpleItem ) : UnorderedList =
-    new UnorderedList( new GroupBlock( children ++ Seq( item ) ) )
-  
-  def + ( item : UnorderedComplexItem ) : UnorderedList =
+  def + ( item : UnorderedItem ) : UnorderedList =
     new UnorderedList( new GroupBlock( children ++ Seq( item ) ) )
 }</diff>
      <filename>src/main/scala/knockoff2/MarkdownList.scala</filename>
    </modified>
    <modified>
      <diff>@@ -16,7 +16,12 @@ with    StringExtras {
   /**
     The SpanConverter is a map method from Chunk to SpanSeq
   */
-  def apply( chunk : Chunk ) : SpanSeq = convert( chunk.content, Nil )
+  def apply( chunk : Chunk ) : SpanSeq = {
+    chunk match {
+      case IndentedChunk( content ) =&gt; new Text( content )
+      case _ =&gt; convert( chunk.content, Nil )
+    }
+  }
   
   /**
     Tail-recursive method halts when the content argument is empty.</diff>
      <filename>src/main/scala/knockoff2/SpanConverter.scala</filename>
    </modified>
    <modified>
      <diff>@@ -1,11 +1,9 @@
 Subject: Things I have To Do
 
+* Complete code vs list item attachment
 
-* Each of the list elements should just simply be capable of having shit attached
-  via an append method. You don't know what that will be until then, but...
-
-* OK, the ChunkParser step may have to also be recursive. This is for cases like
-  blockquotes. Mmm... but how to manipulate position?
+* OK, the ChunkParser step may have to also be recursive. This is for cases
+  like blockquotes. Mmm... but how to manipulate position?
 
 * I need the &lt;hr&gt; and header stuff sorted before I complete the list tests
 </diff>
      <filename>tickets/waiting/0003-To_Do.mail</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>src/main/scala/knockoff2/ComplexItem.scala</filename>
    </removed>
    <removed>
      <filename>src/main/scala/knockoff2/SimpleItem.scala</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>752025dcaa25a7d57f1407fae6ced3e43ed78188</id>
    </parent>
  </parents>
  <author>
    <name>Tristan Juricek</name>
    <email>juricek@emarsys.com</email>
  </author>
  <url>http://github.com/tristanjuricek/knockoff/commit/f7e12944bef4bd99b5a3c4b180d8d6c94e092640</url>
  <id>f7e12944bef4bd99b5a3c4b180d8d6c94e092640</id>
  <committed-date>2009-10-03T05:39:26-07:00</committed-date>
  <authored-date>2009-10-03T05:39:26-07:00</authored-date>
  <message>Implemented a new list system that makes it easier to combine them on the fly. The code blocks were implemented to the point where Horizontal Rule tests now work.</message>
  <tree>cbaa20d3412c98eb02071cf476faa0509ca623be</tree>
  <committer>
    <name>Tristan Juricek</name>
    <email>juricek@emarsys.com</email>
  </committer>
</commit>
