anchor.diff:      p1(T, Urls, Imgs, Stack, ["<h6>" ++ string:strip(P) ++ "</h6>" | Acc]);
   %% unordered lists
   p1([{{ul, _P}, _} | _T] = List, Urls, Imgs, Stack, Acc) ->
  -    {Rest, NewAcc} = parse_ol(List, Urls, Imgs, []),
  -    p1(Rest, Urls, Imgs, Stack, [NewAcc | Acc]);
  +    {Rest, NewAcc} = parse_list(ul, List, Urls, Imgs, []),
  +    p1(Rest, Urls, Imgs, Stack, ["<ul>" ++ NewAcc ++ "</ul>" | Acc]);
  +%% unordered lists
  +p1([{{ol, _P}, _} | _T] = List, Urls, Imgs, Stack, Acc) ->
  +    {Rest, NewAcc} = parse_list(ol, List, Urls, Imgs, []),
  +    p1(Rest, Urls, Imgs, Stack, ["<ol>" ++ NewAcc ++ "</ol>" | Acc]);
  +%% codeblock
  +p1([{{codeblock, P}, _} | T], Urls, Imgs, Stack, Acc) ->
  +    p1(T, Urls, Imgs, Stack, ["<pre><code>" ++ make_str(P) ++ "</code></pre>" | Acc]);
  +
   p1([{br, P} | T], Urls, Imgs, Stack, Acc) ->
       p1(T, Urls, Imgs, Stack, [P | Acc]).
   
   %% this is a bit messy because of the way that hard lines are treated...
   %% If your li's have a blank line between them the item gets wrapped in a para,
   %% if not, they don't
  -parse_ol([], _Urls, _Imgs, Acc) ->
  -    {[], "<ul>" ++ reverse(Acc) ++ "</ul>"};
  -%% if the '<li>' is followed by a blank then wrap it, throw the blank back onto the tail
  -parse_ol([{{ul, P}, _}, {blank, _} = B | T], _Urls, _Imgs, Acc) ->
  -    parse_ol([B | T], _Urls, _Imgs, ["<li><p>" ++ P ++ "</p></li>" | Acc]);
  +parse_list(_Type, [], _Urls, _Imgs, A) ->
  +    {[], reverse(A)};
  +%% if the '<li>' is followed by a blank then wrap it, throw the blank
  +%% back onto the tail
  +parse_list(Type, [{{Type, P}, _}, {blank, _} = B | T], _Urls, _Imgs, A) ->
  +     parse_list(Type, [B | T], _Urls, _Imgs, ["<li><p>" ++ P ++ "</p></li>" | A]);
   %% this is the partner of the previous line...
  -parse_ol([{blank, _}, {{ul, P}, _} | T], _Urls, _Imgs, Acc) ->
  -    parse_ol(T, _Urls, _Imgs, ["<li><p>" ++ P ++ "</p></li>" | Acc]);
  +parse_list(Type, [{blank, _}, {{Type, P}, _} | T], _Urls, _Imgs, A) ->
  +    {Rest, NewP} = grab(T, []),
  +    parse_list(Type, Rest, _Urls, _Imgs, ["<li><p>" ++ P ++ NewP ++"</p></li>" | A]);
  +
   %% this is a plain old '<li>'
  -parse_ol([{{ul, P}, _} | T], _Urls, _Imgs, Acc) ->
  -    parse_ol(T, _Urls, _Imgs, ["<li>" ++ P ++ "</li>" | Acc]);
  -%% parse_ol(List, _Urls, _Imgs, Acc) ->
  -%%    {List, "<ul" ++ reverse(Acc) ++ "</ul>"};
  -parse_ol(List, _Urls, _Imgs, Acc) ->
  -    {List, "<ul" ++ reverse(Acc) ++ "</ul>"}.
  -    
  +parse_list(Type, [{{Type, P}, _} | T], _Urls, _Imgs, A) ->
  +    {Rest, NewP} = grab(T, []),
  +    parse_list(Type, Rest, _Urls, _Imgs, ["<li>" ++ P ++ NewP ++ "</li>" | A]);
  +parse_list(_Type, List, _Urls, _Imgs, A) ->
  +    {List, reverse(A)}.
  +
  +%% grab grabs normals and double codeblocks
  +grab([{{codeblock, _}, S} | T] = List, Acc) ->
  +    case is_blockquote(S, T) of
  +        {{true, R1}, T2}       -> grab(T2, ["</blockquote>",% Putting Tags
  +                                            make_str(R1),   % on backwards!
  +                                            "<blockquote>"
  +                                            | Acc]);
  +        {{esc_false, R1}, _T2} -> {R1, reverse(Acc)};       % escaped >
  +        {false, T2}            -> 
  +            case is_double_indent(S) of  % try codeblock
  +                false      -> {List, reverse(Acc)};
  +                {true, R2} -> grab(T2, [make_str(R2), "<br />" | Acc])
  +            end
  +    end;
  +grab([{normal, P} | T], Acc) -> grab(T, [make_str(P) | Acc]);
  +grab(List, Acc)              -> {List, reverse(Acc)}.
  +
  +is_double_indent(List) -> is_double_indent1(List, 0).
  +
  +%% double indent is any combination of tabs and spaces that add
  +%% up to 8
  +is_double_indent1([], _N)                  -> false;
  +is_double_indent1(Rest, N) when N > 7      -> {true, Rest};
  +is_double_indent1([{{ws, sp}, _} | T], N)  -> is_double_indent1(T, N + 1);
  +is_double_indent1([{{ws, tab}, _} | T], N) -> is_double_indent1(T, N + 4);
  +is_double_indent1(_List, _N)               -> false.
  +
  +is_blockquote(List, T) ->
  +    case is_bq1(List, 0) of
  +        false          -> {false, T};
  +        {esc_false, R} -> {{esc_false, R}, T};
  +        {true, R}      -> {NewT, NewR} = grab2(T, R),
  +                          {{true, NewR}, NewT}
  +    end.
  +        
  +is_bq1([], _N)                            -> false;
  +is_bq1([{{ws, sp}, _} | T], N)            -> is_bq1(T, N + 1);
  +is_bq1([{{ws, tab}, _} | T], N)           -> is_bq1(T, N + 4);
  +is_bq1([{{md, gt}, _},
  +        {{ws, _}, _} | T], N) when N > 3  -> {true, T};
  +is_bq1([{{punc, backslash}, _},
  +        {{md, gt}, GT},
  +        {{ws, _}, WS} | T], N) when N > 3 -> {esc_false, [GT, WS | T]};
  +is_bq1(_List, _N)                         -> false.
  +
  +grab2(List, R) -> gb2(List, reverse(R)).
  +
  +gb2([], Acc)               -> {[], flatten(reverse(Acc))};
  +gb2([{blank, _} | T], Acc) -> {T, flatten(reverse(Acc))};
  +gb2([{_Type, P} | T], Acc) -> gb2(T, [P | Acc]).
  +             
   
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   %%%
  
positive.code:      ?_assert(conv("###### blahblah")  == "<h6>blahblah</h6>"),
       ?_assert(conv("####### blahblah") == "<h6>blahblah</h6>"),
       ?_assert(conv("# blahblah ###")   == "<h1>blahblah</h1>"),
       ?_assert(conv("> blah")           == "<p>&gt; blah</p>"),
       ?_assert(conv("bleh\n> blah")     == "<p>bleh</p><blockquote><p>blah</p></blockquote>"),
       ?_assert(conv("bleh  \n> blah")   == "<p>bleh</p><br /><blockquote><p>blah</p></blockquote>"),
       ?_assert(conv("bleh  \n> > blah") == "<p>bleh</p><br /><blockquote><p>&gt; blah</p></blockquote>"),
       ?_assert(conv("+ blah")           == "<ul><li>blah</li></ul>"),
       ?_assert(conv("+blah")            == "<p>+blah</p>"),
       ?_assert(conv("* blah")           == "<ul><li>blah</li></ul>"),
       ?_assert(conv("*blah")            == "<p><em>blah</em></p>"),
       ?_assert(conv("- blah")           == "<ul><li>blah</li></ul>"),
       ?_assert(conv("-blah")            == "<p>-blah</p>"),
       ?_assert(conv("- a\n+ b\n- c")    == "<ul><li>a </li><li>b </li><li>c</li></ul>"),   
       ?_assert(conv("- a\n\n+ b")       == "<ul><li><p>a </p></li><li><p>b</p></li></ul>"),    
       ?_assert(conv("- a\n\n+ b\n\n+ c\n* d") == "<ul><li><p>a </p></li><li><p>b </p></li>" ++
                "<li><p>c </p></li><li>d</li></ul>"),   
       ?_assert(conv("- blah\nblah")           == "<ul><li>blah blah</li></ul>")
      ].
  
negative.code: l1([], A1, A2)             -> l1([], [], [l2(A1) | A2]);
  %% these two heads capture opening and closing tags
  l1([$<, $/|T], A1, A2)     -> {Tag, NewT} = closingdiv(T, []),
                                l1(NewT, [], [Tag, l2(A1) | A2]);
  l1([$< | T], A1, A2)       -> {Tag, NewT} = openingdiv(T),
                                l1(NewT, [], [Tag , l2(A1) | A2]);
  %% these clauses are the normal lexer clauses
  l1([$= | T], A1, A2)       -> l1(T, [], [{{md, eq}, "="}, l2(A1) | A2]);
  l1([$- | T], A1, A2)       -> l1(T, [], [{{md, dash}, "-"}, l2(A1) | A2]);
  