%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% 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 online at http://www.erlang.org/. %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. %% %% %CopyrightEnd% %% %%%------------------------------------------------------------------ %%% Purpose:Convert Erlang files to html. %%%------------------------------------------------------------------ -module(erl2html2). -export([convert/2, convert/3]). convert([], _Dest) -> % Fake clause. ok; convert(File, Dest) -> %% The generated code uses the BGCOLOR attribute in the %% BODY tag, which wasn't valid until HTML 3.2. Also, %% good HTML should either override all colour attributes %% or none of them -- *never* just a few. %% %% FIXME: The colours should *really* be set with %% stylesheets... Encoding = encoding(File), Header = ["\n" "\n" "\n" "\n" "\n" "", File, "\n" "\n\n" "\n"], convert(File, Dest, Header). convert(File, Dest, Header) -> %% statistics(runtime), case parse_file(File) of {ok,Functions} -> %% {_, Time1} = statistics(runtime), %% io:format("Parsed file in ~.2f Seconds.~n",[Time1/1000]), case file:open(File,[raw,{read_ahead,10000}]) of {ok,SFd} -> case file:open(Dest,[write,raw]) of {ok,DFd} -> file:write(DFd,[Header,"
\n"]),
			    _Lines = build_html(SFd,DFd,Functions),
			    file:write(DFd,["
\n",footer(), "\n\n"]), %% {_, Time2} = statistics(runtime), %% io:format("Converted ~p lines in ~.2f Seconds.~n", %% [_Lines, Time2/1000]), file:close(SFd), file:close(DFd), ok; Error -> Error end; Error -> Error end; Error -> Error end. %%%----------------------------------------------------------------- %%% Parse the input file to get the line numbers for all function %%% definitions. This will be used when creating link targets for each %%% function in build_html/5. %%% %%% All function clauses are also marked in order to allow %%% possibly_enhance/2 to write these in bold. parse_file(File) -> case epp:open(File, [], []) of {ok,Epp} -> Forms = parse_file(Epp,File,false), epp:close(Epp), {ok,Forms}; {error,E} -> {error,E} end. parse_file(Epp,File,InCorrectFile) -> case epp:parse_erl_form(Epp) of {ok,Form} -> case Form of {attribute,_,file,{File,_}} -> parse_file(Epp,File,true); {attribute,_,file,{_OtherFile,_}} -> parse_file(Epp,File,false); {function,L,F,A,[_|C]} when InCorrectFile -> Clauses = [{clause,CL} || {clause,CL,_,_,_} <- C], [{atom_to_list(F),A,L} | Clauses] ++ parse_file(Epp,File,true); _ -> parse_file(Epp,File,InCorrectFile) end; {error,_E} -> parse_file(Epp,File,InCorrectFile); {eof,_Location} -> [] end. %%%----------------------------------------------------------------- %%% Add a link target for each line and one for each function definition. build_html(SFd,DFd,Functions) -> build_html(SFd,DFd,file:read_line(SFd),1,Functions,false). build_html(SFd,DFd,{ok,Str},L,[{F,A,L}|Functions],_IsFuncDef) -> FALink = http_uri:encode(F++"-"++integer_to_list(A)), file:write(DFd,[""]), build_html(SFd,DFd,{ok,Str},L,Functions,true); build_html(SFd,DFd,{ok,Str},L,[{clause,L}|Functions],_IsFuncDef) -> build_html(SFd,DFd,{ok,Str},L,Functions,true); build_html(SFd,DFd,{ok,Str},L,Functions,IsFuncDef) -> LStr = line_number(L), Str1 = line(Str,IsFuncDef), file:write(DFd,[LStr,Str1]), build_html(SFd,DFd,file:read_line(SFd),L+1,Functions,false); build_html(_SFd,_DFd,eof,L,_Functions,_IsFuncDef) -> L. line_number(L) -> LStr = integer_to_list(L), Pred = case length(LStr) of Length when Length < 5 -> lists:duplicate(5-Length,$\s); _ -> [] end, ["",Pred,LStr,": "]. line(Str,IsFuncDef) -> Str1 = htmlize(Str), possibly_enhance(Str1,IsFuncDef). %%%----------------------------------------------------------------- %%% Substitute special characters that should not appear in HTML htmlize([$<|Str]) -> [$&,$l,$t,$;|htmlize(Str)]; htmlize([$>|Str]) -> [$&,$g,$t,$;|htmlize(Str)]; htmlize([$&|Str]) -> [$&,$a,$m,$p,$;|htmlize(Str)]; htmlize([$"|Str]) -> [$&,$q,$u,$o,$t,$;|htmlize(Str)]; htmlize([Ch|Str]) -> [Ch|htmlize(Str)]; htmlize([]) -> []. %%%----------------------------------------------------------------- %%% Write comments in italic and function definitions in bold. possibly_enhance(Str,true) -> case lists:splitwith(fun($() -> false; (_) -> true end, Str) of {_,[]} -> Str; {F,A} -> ["",F,"",A] end; possibly_enhance([$%|_]=Str,_) -> ["",Str--"\n","","\n"]; possibly_enhance([$-|_]=Str,_) -> possibly_enhance(Str,true); possibly_enhance(Str,false) -> Str. %%%----------------------------------------------------------------- %%% End of the file footer() -> "". %%%----------------------------------------------------------------- %%% Read encoding from source file encoding(File) -> Encoding = case epp:read_encoding(File) of none -> epp:default_encoding(); E -> E end, html_encoding(Encoding). html_encoding(latin1) -> "iso-8859-1"; html_encoding(utf8) -> "utf-8".