%% ``The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved via the world wide web at http://www.erlang.org/. %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See %% the License for the specific language governing rights and limitations %% under the License. %% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB. %% Portions created by Ericsson are Copyright 1999-2000, Ericsson %% Utvecklings AB. All Rights Reserved.'' %% %% $Id$ %% -module(docb_tr_index2html). -export([extension/0, transform/3, rule/2]). extension() -> ".html". transform(_File0, {index, Attrs, [Header| Trees0]}, _Opts) -> Trees1 = prune_flat(Trees0, false), %% %% Now each element of Trees1 is a tree with tag `name' and %% attribute `File', and with one `pcdata' subtree containing the %% name `Func' of the function. We extract `File' and `Func', and %% create new trees. %% %% `File' is attribute CDATA (from an ), and %% `Func' is PCDATA. %% FileFuncs = [{File, RefType, Func} || {name, [{_, _, File}, {_, _, RefType}|_], [{pcdata, [], Func}]} <- Trees1], Trees2 = new_trees(FileFuncs), {index, Attrs, [Header| Trees2]}. %% Remove all elements except those with tag equal to `name'. %% Within `name' remove all elements except those equal to `pcdata'. %% Add attribute `filetype' to `name'. %% %% Refs: appref, comref, cref, erlref, fileref prune_flat([{appref, _Attrs, More}| Rest], _) -> RefType = appref, lists:append(prune_flat(More, RefType), prune_flat(Rest, RefType)); prune_flat([{comref, _Attrs, More}| Rest], _) -> RefType = comref, lists:append(prune_flat(More, RefType), prune_flat(Rest, RefType)); prune_flat([{cref, _Attrs, More}| Rest], _) -> RefType = cref, lists:append(prune_flat(More, RefType), prune_flat(Rest, RefType)); prune_flat([{erlref, _Attrs, More}| Rest], _) -> RefType = erlref, lists:append(prune_flat(More, RefType), prune_flat(Rest, RefType)); prune_flat([{fileref, _Attrs, More}| Rest], _) -> RefType = fileref, lists:append(prune_flat(More, RefType), prune_flat(Rest, RefType)); prune_flat([{name, [Attr0|Attrs0], More}| Rest], RefType) -> Attrs = [Attr0, {"FILETYPE", "CDATA", RefType} | Attrs0], [{name, Attrs, keep_pcdata(More)}| prune_flat(Rest, RefType)]; prune_flat([{pcdata, _, _}| Rest], RefType) -> % special case prune_flat(Rest, RefType); prune_flat([{_Tag, _Attrs, More}| Rest], RefType) -> lists:append(prune_flat(More, RefType), prune_flat(Rest, RefType)); prune_flat([], _) -> []. keep_pcdata(Trees) -> lists:filter(fun({pcdata, _, _}) -> true; (_) -> false end, Trees). new_trees(FileFuncs) -> Files0 = [{File, RefType} || {File, RefType, _} <- FileFuncs], Files1 = lists:usort(Files0), FileEntries = [{reffile, File, RefType, [Fu || {Fi, _, Fu} <- FileFuncs, Fi == File]} || {File, RefType} <- Files1], FuncEntries = [{func, Func, RefType, [File]} || {File, RefType, Func} <- FileFuncs], Entries = FileEntries ++ FuncEntries, SortedEntries = sort_entries(Entries), %% %% We create a tree according to the following "dtd": %% %% element index (reffile | funcdef)* %% element reffile (funcdef2)* %% attribute reffile filename CDATA %% attribute reffile filetype CDATA %% element funcdef2 PCDATA %% attribute funcdef2 filename CDATA %% attribute funcdef2 filetype CDATA %% element funcdef PCDATA %% attribute funcdef filename CDATA %% attribute funcdef filetype CDATA %% %% For example: %% %% %% myfunca(A) %% myfuncb(A, B) %% %% myfunca(A) %% myfuncb(A, B) %% lists:flatmap( fun({reffile, File, RefType, Funcs}) -> %% A reffile tree [{reffile, [{"FILENAME", "CDATA", File}, {"FILETYPE", "CDATA", RefType}], [{funcdef2, [{"FILENAME", "CDATA", File}, {"FILETYPE", "CDATA", RefType}], [{pcdata, [], Func}]} || Func <- Funcs]}]; ({func, Func, RefType, [File]}) -> %% A func tree [{funcdef, [{"FILENAME", "CDATA", File}, {"FILETYPE", "CDATA", RefType}], [{pcdata, [], Func}]}] end, SortedEntries). %% Sorting of entries %% %% The sorting is based on how names of files and functions are %% presented (in a browser). %% Requires conversion to "function/2" etc. %% sort_entries(Entries) -> ExpEntries = lists:map( fun({reffile, File, RefType, Funcs}) -> HFile = filename_sort_order(File), HFuncs = [{funcdef_sort_order(Fu, RefType), Fu} || Fu <- Funcs], {reffile, HFile, File, RefType, lists:sort(HFuncs)}; ({func, Func, RefType, [File]}) -> HFunc = funcdef_sort_order(Func, RefType), HFile = filename_sort_order(File), {func, HFunc, Func, RefType, [{HFile, File}]} end, Entries), SortedExpEntries = lists:keysort(2, ExpEntries), lists:map( fun({Tag, _HName, Name, RefType, Vals}) -> NVals = lists:map(fun({_HVal, Val}) -> Val end, Vals), {Tag, Name, RefType, NVals} end, SortedExpEntries). rule([index| _], _) -> {docb_html_layout:index_top("") ++ "
\n", "
\n" ++ docb_html_layout:index_bot()}; rule([header| _], _) -> {drop, ""}; rule([reffile| _], {_, [File, _RefType|_], _}) -> CFile = docb_html_util:attribute_cdata_to_html(File), {"
" ++ CFile ++ "
\n", ""}; rule([funcdef2| _], {_, [File, RefType|_], [{pcdata, [], FuncDef}]}) -> FFuncDef = lists:flatten(docb_html_util:pcdata_to_html(FuncDef)), TFuncDef = docb_util:trim(FFuncDef), ShortFuncDef = docb_html_util:make_funcdef_short(TFuncDef, RefType), HRef = docb_html_util:make_anchor_href_short(File, TFuncDef, RefType), {drop, "
" ++ ShortFuncDef ++ "
\n"}; rule([funcdef| _], {_, [File, RefType|_], [{pcdata, [], FuncDef}]}) -> FFuncDef = lists:flatten(docb_html_util:pcdata_to_html(FuncDef)), TFuncDef = docb_util:trim(FFuncDef), ShortFuncDef = docb_html_util:make_funcdef_short(TFuncDef, RefType), HRef = docb_html_util:make_anchor_href_short(File, TFuncDef, RefType), CFile = docb_html_util:attribute_cdata_to_html(File), {drop, "
" ++ ShortFuncDef ++ "
\n" "
" ++ CFile ++ "
\n"}; rule(_, _) -> {drop, ""}. filename_sort_order(File) -> docb_html_util:html_latin1_sort_order( lists:flatten( docb_html_util:attribute_cdata_to_html(string:strip(File)))). funcdef_sort_order(FuncDef, RefType) -> docb_html_util:html_latin1_sort_order( docb_html_util:make_anchor_name_short(FuncDef, RefType)).