From: <cpr...@us...> - 2003-03-02 10:04:57
|
Update of /cvsroot/jungerl/jungerl/lib/ce/src In directory sc8-pr-cvs1:/tmp/cvs-serv27435/src Modified Files: ce_html.erl Log Message: Added ce_html:from_list. Index: ce_html.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ce/src/ce_html.erl,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- ce_html.erl 1 Mar 2003 07:10:21 -0000 1.1 +++ ce_html.erl 2 Mar 2003 10:04:54 -0000 1.2 @@ -38,11 +38,12 @@ %% @end -module(ce_html). --vsn('JUNGERL'). +-vsn('JUNGERL'). -author('ca...@ca...'). --copyright('Copyright (c)2002 Cat`s Eye Technologies. All rights reserved.'). +-copyright('Copyright (c)2003 Cat`s Eye Technologies. All rights reserved.'). -export([escape_html/1, table/4]). +-export([from_list/3]). %% @spec escape_html(string()) -> string() %% @doc Embeds HTML in HTML by escaping HTML metacharacters. @@ -73,30 +74,30 @@ %% is <b>not</b> flattened. table(Headings, _, [], Options) -> ""; -table(Headings, Align, Contents, [{compressed, true} | NewOptions]) -> - {NewHeadings, NewAlign, NewContents} = - compress_table(Headings, Align, Contents), - table(NewHeadings, NewAlign, NewContents, NewOptions); -table(Headings, Align, Contents, Options) -> +table(Headings, Aligns, Contents, [{compressed, true} | NewOptions]) -> + {NewHeadings, NewAligns, NewContents} = + compress_table(Headings, Aligns, Contents), + table(NewHeadings, NewAligns, NewContents, NewOptions); +table(Headings, Aligns, Contents, Options) -> HeadingString = ["<tr>", lists:foldl(fun({Align, Heading}, A) -> [A, "<td align=\"", ce_lib:to_string(Align), "\"><b>", ce_lib:to_string(Heading), "</b></td>"] - end, "", ce_lists:zip(Align, Headings)), "</tr>"], + end, "", ce_lists:zip(Aligns, Headings)), "</tr>"], BodyString = lists:foldl(fun(Row, A) -> - [A, table_row(Row, Align)] + [A, table_row(Row, Aligns)] end, "", Contents), TableString = ["<table ", lists:foldl(fun({Option, Value}, A) -> [A, ce_lib:to_string(Option), "=\"", ce_lib:to_string(Value), "\" "] end, "", Options), ">"], [TableString, HeadingString, BodyString, "</table>"]. -table_row(Row, Align) -> +table_row(Row, Aligns) -> ["<tr>", lists:foldl(fun({Align, Item}, A) -> [A, "<td align=\"", ce_lib:to_string(Align), "\">", ce_lib:to_string(Item), "</td>"] - end, "", ce_lists:zip(Align, Row)), "</tr>"]. + end, "", ce_lists:zip(Aligns, Row)), "</tr>"]. -compress_table(Headings, Align, Contents) -> +compress_table(Headings, Aligns, Contents) -> Columns = ce_lists:zipn(Contents), Compressed = lists:reverse(lists:foldl(fun(X, A) -> [is_empty_column(X) | A] @@ -106,11 +107,11 @@ ({Heading, true}, A) -> A end, [], ce_lists:zip(Headings, Compressed))), - NewAlign = lists:reverse(lists:foldl(fun({Al, false}, A) -> + NewAligns = lists:reverse(lists:foldl(fun({Al, false}, A) -> [Al | A]; ({Al, true}, A) -> A - end, [], ce_lists:zip(Align, Compressed))), + end, [], ce_lists:zip(Aligns, Compressed))), NewContents = lists:reverse(lists:foldl(fun(Row, A) -> [lists:reverse(lists:foldl(fun({Cell, false}, Acc) -> [Cell | Acc]; @@ -118,12 +119,65 @@ Acc end, [], ce_lists:zip(Row, Compressed))) | A] end, [], Contents)), - {NewHeadings, NewAlign, NewContents}. + {NewHeadings, NewAligns, NewContents}. is_empty_column(Column) when tuple(Column) -> is_empty_column(tuple_to_list(Column)); is_empty_column([]) -> true; is_empty_column(["" | T]) -> is_empty_column(T); is_empty_column([H | T]) -> false. + +%% @spec from_list(socket(), module(), html_list()) -> ok +%% @doc Translates an Erlang term into HTML and sends it to a socket. +%% The html_list is a list which starts with an atom, may be followed +%% by zero or more {option, value} tuples, may be followed by zero or +%% more text strings or html_lists. +%% e.g. <code>[html, [body, [h1, "Hello"], [p, {align,right}, "Hi"]]]</code>. +%% Before expanding an atom into an HTML tag, the module is checked and if +%% it has an arity 2 function by the name of the atom, it is invoked instead +%% with the socket as the first argument and the remainder of the list as the +%% second argument. + +from_list(Socket, Module, [get, VarName]) -> + Value = case get(VarName) of + undefined -> ""; + Else -> Else + end, + gen_tcp:send(Socket, ce_lib:to_string(Value)); +from_list(Socket, Module, [Head | Tail]) when atom(Head) -> + case catch Module:Head(Socket, Tail) of + {'EXIT',{undef,_}} -> + gen_tcp:send(Socket, Module, io_lib:fwrite("<~p", [Head])), + Tail0 = write_attr(Socket, Module, Tail), + from_list(Socket, Module, Tail0), + gen_tcp:send(Socket, io_lib:fwrite("</~p>~n", [Head])); + Else -> + Else + end; +from_list(Socket, Module, [Head | Tail]) when is_list(Head), is_integer(hd(Head)) -> + gen_tcp:send(Socket, Head), + from_list(Socket, Module, Tail); +from_list(Socket, Module, [Head | Tail]) when is_list(Head) -> + from_list(Socket, Module, Head), + from_list(Socket, Module, Tail); +from_list(Socket, Module, []) -> + ok. + +write_attr(Socket, Module, [{Option,""} | Tail]) -> + gen_tcp:send(Socket, [" ", ce_lib:to_string(Option), "=\"\""]), + write_attr(Socket, Module, Tail); +write_attr(Socket, Module, [{Option,Value} | Tail]) + when is_list(Value), not is_integer(hd(Value)) -> + gen_tcp:send(Socket, [" ", ce_lib:to_string(Option), "=\""]), + from_list(Socket, Module, Value), + gen_tcp:send(Socket, "\""), + write_attr(Socket, Module, Tail); +write_attr(Socket, Module, [{Option,Value} | Tail]) -> + gen_tcp:send(Socket, io_lib:fwrite(" ~s=~p", + [ce_lib:to_string(Option), ce_lib:to_string(Value)])), + write_attr(Socket, Module, Tail); +write_attr(Socket, Module, List) -> + gen_tcp:send(Socket, ">"), + List. %%% END of ce_html.erl %%% |