%% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% %% Copyright (c) 2001-2016 Richard Carlsson. Parts written by Ericsson %% are Copyright (c) Ericsson AB 2001-2017. All Rights Reserved. %% -module(docgen_edoc_xml_cb). %% This is the EDoc callback module for creating erlref %% documents (man pages) in XML format, and also a chapter %% document based on "overview.edoc". %% %% edoc:file(File, [{layout,docgen_edoc_xml_cb},{file_suffix,".xml"}, %% {preprocess,true}]). %% %% The origin of this file is the edoc module otpsgml_layout.erl %% written by Richard Carlsson and Kenneth Lundin. -export([module/2, overview/2]). -include("xmerl.hrl"). -define(NL, "\n"). %%-User interface------------------------------------------------------- %% ERLREF module(Element, Opts) -> SortP = proplists:get_value(sort_functions, Opts, true), XML = layout_module(Element, SortP), RootAttributes = root_attributes(Element, Opts), xmerl:export_simple([XML], docgen_xmerl_xml_cb, RootAttributes). %% CHAPTER overview(Element, Opts) -> XML = layout_chapter(Element), RootAttributes = root_attributes(Element, Opts), xmerl:export_simple([XML], docgen_xmerl_xml_cb, RootAttributes). %%--Internal functions-------------------------------------------------- layout_module(#xmlElement{name = module, content = Es}=E, SortP) -> Name = get_attrval(name, E), Desc = get_content(description, Es), ShortDesc = text_only(get_content(briefDescription, Desc)), FullDesc = otp_xmlify(get_content(fullDescription, Desc)), Types0 = get_content(typedecls, Es), Types1 = lists:sort([{type_name(Et), Et} || Et <- Types0]), Functions = case SortP of true -> lists:sort([{function_name(Ef), Ef} || Ef <- get_content(functions, Es)]); false -> [{function_name(Ef), Ef} || Ef <- get_content(functions, Es)] end, Header = {header, [ ?NL,{title, [Name]}, ?NL,{prepared, [""]}, ?NL,{responsible, [""]}, ?NL,{docno, ["1"]}, ?NL,{approved, [""]}, ?NL,{checked, [""]}, ?NL,{date, [""]}, ?NL,{rev, ["A"]}, ?NL,{file, [Name++".xml"]} ]}, Module = {module, [Name]}, ModuleSummary = {modulesummary, ShortDesc}, Description = {description, [?NL|FullDesc]}, Types = case Types1 of [] -> []; _ -> [?NL, {section,[{title,["DATA TYPES"]}, {marker,[{id,"types"}],[]}, ?NL|types(Types1)]}] end, Funcs = functions(Functions), See = seealso_module(Es), Authors = {authors, authors(Es)}, {erlref, [?NL,Header, ?NL,Module, ?NL,ModuleSummary, ?NL,Description] ++ Types ++ [?NL,Funcs, ?NL,See, ?NL,Authors] }. root_attributes(Element, Opts) -> Encoding = case get_attrval(encoding, Element) of "" -> DefaultEncoding = epp:default_encoding(), proplists:get_value(encoding, Opts, DefaultEncoding); Enc -> Enc end, [#xmlAttribute{name=encoding, value=reformat_encoding(Encoding)}]. %% epp:default_encoding/0 returns 'utf8' reformat_encoding(utf8) -> "UTF-8"; reformat_encoding(List) when is_list(List) -> case string:lowercase(List) of "utf8" -> "UTF-8"; _ -> List end; reformat_encoding(Other) -> Other. layout_chapter(#xmlElement{name=overview, content=Es}) -> Title = get_text(title, Es), Header = {header, [ ?NL,{title,[Title]}, ?NL,{prepared,[""]}, ?NL,{docno,[""]}, ?NL,{date,[""]}, ?NL,{rev,[""]}, ?NL,{file, ["chapter.xml"]} ]}, DescEs = get_content(description, Es), FullDescEs = get_content(fullDescription, DescEs), Sections = chapter_ify(FullDescEs, first), {chapter, [?NL, Header, ?NL | Sections]}. chapter_ify([], _) -> []; chapter_ify(Es, first) -> %% Everything up to the first section should be made into %% plain paragraphs -- or if no first section is found, everything %% should be made into one case find_next(h3, Es) of {Es, []} -> SubSections = subchapter_ify(Es, first), [{section, [?NL,{title,["Overview"]}, ?NL | SubSections]}]; {FirstEs, RestEs} -> otp_xmlify(FirstEs) ++ chapter_ify(RestEs, next) end; chapter_ify([#xmlElement{name=h3} = E | Es], next) -> {SectionEs, RestEs} = find_next(h3, Es), SubSections = subchapter_ify(SectionEs, first), {Marker, Title} = chapter_title(E), [{section, [?NL,{marker,[{id,Marker}],[]}, ?NL,{title,[Title]}, ?NL | SubSections]} | chapter_ify(RestEs, next)]. subchapter_ify([], _) -> []; subchapter_ify(Es, first) -> %% Everything up to the (possible) first subsection should be %% made into plain paragraphs {FirstEs, RestEs} = find_next(h4, Es), otp_xmlify(FirstEs) ++ subchapter_ify(RestEs, next); subchapter_ify([#xmlElement{name=h4} = E | Es], next) -> {SectionEs, RestEs} = find_next(h4, Es), Elements = otp_xmlify(SectionEs), {Marker, Title} = chapter_title(E), [{section, [?NL,{marker,[{id,Marker}],[]}, ?NL,{title,[Title]}, ?NL | Elements]} | subchapter_ify(RestEs, next)]. chapter_title(#xmlElement{content=Es}) -> % name = h3 | h4 case Es of [#xmlElement{name=a} = E] -> {get_attrval(name, E), get_text(E)} end. %%--XHTML->XML transformation------------------------------------------- %% otp_xmlify(Es1) -> Es2 %% Es1 = Es2 = [#xmlElement{} | #xmlText{}] %% Fix things that are allowed in XHTML but not in chapter/erlref DTDs. %% 1) lists (