anchor.diff:                                  {myframeid, [{sort, 1, ascending}]}],
                                  "myframeid.3")).
   
  +linewrap_test() ->
  +    ?assertEqual("abcdefghij" ++ ?HTML_LINEBRK ++
  +                 "klmnopqrst" ++ ?HTML_LINEBRK ++ "uvwxyz",
  +                 linewrap("abcdefghijklmnopqrstuvwxyz", 10)),
  +    ?assertEqual("abcd&quot;fghij" ++ ?HTML_LINEBRK ++
  +                 "klmnopqrs&#1234;" ++ ?HTML_LINEBRK ++ "uvwxyz",
  +                 linewrap("abcd&quot;fghijklmnopqrs&#1234;uvwxyz", 10)).
  +
   html_test() ->
       ?assertEqual("<br>", html(br)),
       ?assertEqual("<body></body>", html({body, [], []})),
  -    ?assertEqual("<table width=\"100%\" cellspacing=\"0\"></table>",
  -                 html({table, [{width, "100%"}, {cellspacing, 0}], []})),
  +    ?assertEqual("<table width=\"100%\" cellspacing=\"0\">"
  +                 "<tr bgcolor=\"#123456\">"
  +                 "<td align=\"left\">Cell</td>"
  +                 "<td>I&#39;m&nbsp;valid&nbsp;&amp;&nbsp;&nbsp;encoded!</td>"
  +                 "</tr></table>",
  +                 html({table, [{width, "100%"}, {cellspacing, 0}],
  +                       [{tr, [{bgcolor, "#123456"}],
  +                         [{td, [{align, left}], [{str, "Cell"}]},
  +                          {td, [], [{str, "I'm valid &  encoded!"}]}]}]})),
       ?assertEqual("<html><body bgcolor=\"#123456\" align=\"left\">"
                    "<table cellpadding=\"0\"><hr><br></table></body></html>",
                    html({html, [],
  
positive.code: attr_to_str({Attr, Value}) -> lists:concat([Attr, "=\"", Value, "\""]);
  attr_to_str(Attr) -> lists:concat([Attr]).
  
  html_esc(C) when is_integer(C) -> C;
  html_esc(S) -> html_esc(lists:flatten(S), []).
  
  html_esc([], Acc) -> lists:flatten(lists:reverse(Acc));
  html_esc([$< | T], Acc) -> html_esc(T, ["&lt;" | Acc]);
  html_esc([$> | T], Acc) -> html_esc(T, ["&gt;" | Acc]);
  html_esc([$& | T], Acc) -> html_esc(T, ["&amp;" | Acc]);
  html_esc([$" | T], Acc) -> html_esc(T, ["&quot;" | Acc]);
  html_esc([$' | T], Acc) -> html_esc(T, ["&#39;" | Acc]);
  html_esc([$  | T], Acc) -> html_esc(T, ["&nbsp;" | Acc]);
  html_esc([$\n | T], Acc) -> html_esc(T, ["<br>" | Acc]);
  html_esc([H|T], Acc) -> html_esc(T, [H|Acc]).
  
  %% Tests
  -ifdef(TEST).
  
negative.code: invert_dir(descending) -> ascending.
  
  %% Generate a HTML-encoded string from a data structure encoding HTML.
  %%
  %% HTML is represented as a recursive data structure:
  %%   {Tag, Attributes, Contents}
  %% where Tag is an atom;
  %%       Attributes is a list of {Attr, Value}, and
  %%       Contents is a list of children tags.
  %%
  %% Special 'terminal' tags {raw, Str}, {str, Str} and {term, Term}
  %% produce direct output with different degrees of processing.
  html({raw, Str}) -> Str;
  html({str, Str}) -> html_encode(Str);
  html({term, Term}) ->
      RawStr = io_lib:format("~40p", [Term]),
      Str = nl_encode(linewrap(html_encode(RawStr), 42)),
      html({code, [], [{raw, Str}]});
  html(Tags) when is_list(Tags) -> lists:concat([html(T) || T <- Tags]);
  html(Tag) when is_atom(Tag) -> lists:concat(["<", Tag, ">"]);
  html({Tag, Attributes, Contents}) ->
  