anchor.diff:              {{data, Data, Whitespace}, S}
       end.
   
  -tokenize_attributes(B, S) ->
  -    tokenize_attributes(B, S, []).
  -
  -tokenize_attributes(B, S=#decoder{offset=O}, Acc) ->
  +tokenize_attributes(B, S, Options) ->
  +    tokenize_attributes(B, S, [], Options).
  +
  +tokenize_attributes(B, S=#decoder{offset=O}, Acc, Options) ->
       case B of
           <<_:O/binary>> ->
               {lists:reverse(Acc), S};
  
positive.code:     ok.
  
  destack_test() ->
      {<<"a">>, [], []} =
          destack([{<<"a">>, [], []}]),
      {<<"a">>, [], [{<<"b">>, [], []}]} =
          destack([{<<"b">>, [], []}, {<<"a">>, [], []}]),
      {<<"a">>, [], [{<<"b">>, [], [{<<"c">>, [], []}]}]} =
       destack([{<<"c">>, [], []}, {<<"b">>, [], []}, {<<"a">>, [], []}]),
      [{<<"a">>, [], [{<<"b">>, [], [{<<"c">>, [], []}]}]}] =
       destack(<<"b">>,
               [{<<"c">>, [], []}, {<<"b">>, [], []}, {<<"a">>, [], []}]),
      [{<<"b">>, [], [{<<"c">>, [], []}]}, {<<"a">>, [], []}] =
       destack(<<"c">>,
               [{<<"c">>, [], []}, {<<"b">>, [], []},{<<"a">>, [], []}]),
      ok.
  
  doctype_test() ->
  
negative.code: tree_data(Rest, AllWhitespace, Acc) ->
      {iolist_to_binary(lists:reverse(Acc)), AllWhitespace, Rest}.
  
  tree([], Stack, _Options) ->
      {destack(Stack), []};
  tree([{end_tag, Tag} | Rest], Stack, Options) ->
      case destack(norm(Tag, Options), Stack, Options) of
          S when is_list(S) ->
              tree(Rest, S, Options);
          Result ->
              {Result, []}
      end;
  tree([{start_tag, Tag, Attrs, true} | Rest], S, Options) ->
      tree(Rest, append_stack_child(norm({Tag, Attrs}, Options), S), Options);
  tree([{start_tag, Tag, Attrs, false} | Rest], S, Options) ->
      tree(Rest, stack(norm({Tag, Attrs}, Options), S, Options), Options);
  tree([T={pi, _Raw} | Rest], S, Options) ->
      tree(Rest, append_stack_child(T, S), Options);
  tree([T={pi, _Tag, _Attrs} | Rest], S, Options) ->
      tree(Rest, append_stack_child(T, S), Options);
  tree([T={comment, _Comment} | Rest], S, Options) ->
      tree(Rest, append_stack_child(T, S), Options);
  tree(L=[{data, _Data, _Whitespace} | _], S, Options) ->
      case tree_data(L, true, []) of
          {_, true, Rest} ->
              tree(Rest, S, Options);
          {Data, false, Rest} ->
              tree(Rest, append_stack_child(Data, S), Options)
      end;
  tree([{doctype, _} | Rest], Stack, Options) ->
      tree(Rest, Stack, Options).
  
  norm({Tag, Attrs}, #{ mode := xml }) ->
      {iolist_to_binary(Tag), [{iolist_to_binary(K), iolist_to_binary(V)} || {K, V} <- Attrs], []};
  norm(Tag, #{ lowercase := true }) when is_binary(Tag); is_list(Tag) ->
      z_string:to_lower(iolist_to_binary(Tag));
  norm(Tag, #{ mode := xml }) ->
      iolist_to_binary(Tag);
  norm({Tag, Attrs}, Options) ->
      {norm(Tag, Options), [{norm(K, Options), iolist_to_binary(V)} || {K, V} <- Attrs], []};
  norm(Tag, _Options) when is_binary(Tag) ->
      Tag;
  norm(Tag, _Options) ->
      BTag = iolist_to_binary(Tag),
      LTag = z_string:to_lower(BTag),
      case is_html_tag(LTag) of
          true -> LTag;
          false -> BTag
      end.
  
  stack(T1, Stack, #{ mode := xml }) ->
      [T1 | Stack];
  stack(T1={TN, _, _}, Stack=[{TN, _, _} | _Rest], Options)
      when       TN =:= <<"li">>
          orelse TN =:= <<"option">> ->
      [T1 | destack(TN, Stack, Options)];
  stack(T1={TN, _, _}, Stack, Options) when TN =:= <<"td">> orelse TN =:= <<"th">> ->
      case find_in_stack([<<"td">>, <<"th">>], <<"table">>, Stack) of
          none -> Stack;
          undefined -> [T1 | Stack];
          Tag -> [T1 | destack(Tag, Stack, Options)]
      end;
  stack(T1={TN, _, _}, Stack, Options)
      when TN =:= <<"tr">> ->
      case find_in_stack([<<"tr">>], <<"table">>, Stack) of
          none -> Stack;
          undefined -> [T1 | Stack];
          Tag -> [T1 | destack(Tag, Stack, Options)]
      end;
  stack(T1={TN, _, _}, Stack, Options)
      when       TN =:= <<"tbody">>
          orelse TN =:= <<"thead">>
          orelse TN =:= <<"tfoot">>
          orelse TN =:= <<"colgroup">> ->
      case find_in_stack([<<"tbody">>, <<"thead">>, <<"tfoot">>, <<"colgroup">>], <<"table">>, Stack) of
          none -> Stack;
          undefined ->
  