summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/erl_docgen/priv/bin/chunk.escript27
-rw-r--r--lib/stdlib/src/shell_docs.erl61
2 files changed, 53 insertions, 35 deletions
diff --git a/lib/erl_docgen/priv/bin/chunk.escript b/lib/erl_docgen/priv/bin/chunk.escript
index d31da2853e..2fb397b627 100644
--- a/lib/erl_docgen/priv/bin/chunk.escript
+++ b/lib/erl_docgen/priv/bin/chunk.escript
@@ -320,9 +320,20 @@ transform([{list,Attr,Content}|T],Acc) ->
transform([{taglist,Attr,Content}|T],Acc) ->
transform([transform_taglist(Attr,Content)|T],Acc);
-%% transform <c><anno>text</anno></c> to <anno>text</anno>
-transform([{c,[],[{anno,[],AnnoContent}]}|T],Acc) ->
- transform(T,[{a,[{type,anno}],AnnoContent}|Acc]);
+%% remove <anno> as it is only used to validate specs vs xml src
+transform([{anno,[],Content}|T],Acc) ->
+ transform([Content|T],Acc);
+
+%% transform <c> to <code>
+transform([{c,[],Content}|T],Acc) ->
+ transform(T, [{code,[],transform(Content,[])}|Acc]);
+
+%% transform <code> to <pre><code>
+transform([{code,Attr,Content}|T],Acc) ->
+ transform(T, [{pre,[],[{code,Attr,transform(Content,[])}]}|Acc]);
+%% transform <pre> to <pre><code>
+transform([{pre,Attr,Content}|T],Acc) ->
+ transform(T, [{pre,[],[{code,Attr,transform(Content,[])}]}|Acc]);
%% transform <funcs> with <func> as children
transform([{funcs,_Attr,Content}|T],Acc) ->
@@ -388,7 +399,7 @@ transform([{d,[],Content}|T],Acc) ->
transform(T, [{li,[{class,"description"}],transform(Content,[])}|Acc]);
transform([Tag = {seealso,_Attr,_Content}|T],Acc) ->
- transform(T,[transform_seealso(Tag)|Acc]);
+ transform([transform_seealso(Tag)|T],Acc);
transform([{term,Attr,[]}|T],Acc) ->
transform([list_to_binary(proplists:get_value(id,Attr))|T],Acc);
@@ -440,9 +451,9 @@ transform_types(Dom,Acc) ->
transform_taglist(Attr,Content) ->
Items =
lists:map(fun({tag,A,C}) ->
- {dt,A,transform(C, [])};
+ {dt,A,C};
({item,A,C}) ->
- {dd,A,transform(C, [])}
+ {dd,A,C}
end, Content),
{dl,Attr,Items}.
@@ -587,8 +598,8 @@ transform_datatype(Dom,_Acc) ->
{signature,Signature}],ContentsNoName}
end || N = {name,_,_} <- Dom].
-transform_seealso(_S = {seealso,_Attr,_Content}) ->
- _Content.
+transform_seealso({seealso,Attr,_Content}) ->
+ {a, Attr, _Content}.
to_chunk(Dom, Source, Module, AST) ->
[{module,MAttr,Mcontent}] = Dom,
diff --git a/lib/stdlib/src/shell_docs.erl b/lib/stdlib/src/shell_docs.erl
index 69bed465a1..25bf7cb69f 100644
--- a/lib/stdlib/src/shell_docs.erl
+++ b/lib/stdlib/src/shell_docs.erl
@@ -35,9 +35,19 @@
io_columns = element(2,io:columns())
}).
--define(ALL_TAGS,[a,anno,p,h1,h2,h3,c,i,br,em,pre,code,ul,ol,li,dl,dt,dd]).
--type chunk_element_type() :: a | anno | p | c | i | br | em | pre |
- code | ul | ol | li | dl | dt | dd.
+-define(ALL_ELEMENTS,[a,p,h1,h2,h3,i,br,em,pre,code,ul,ol,li,dl,dt,dd]).
+%% inline elements are:
+-define(INLINE,[i,br,em,code,a]).
+-define(IS_INLINE(ELEM),(((ELEM) =:= a) orelse ((ELEM) =:= code)
+ orelse ((ELEM) =:= i) orelse ((ELEM) =:= br)
+ orelse ((ELEM) =:= em))).
+%% non-inline elements are:
+-define(BLOCK,[p,pre,ul,ol,li,dl,dt,dd,h1,h2,h3]).
+-define(IS_BLOCK(ELEM),not ?IS_INLINE(ELEM)).
+-define(IS_PRE(ELEM),(((ELEM) =:= pre))).
+
+-type chunk_element_type() :: a | p | i | br | em | pre | code | ul |
+ ol | li | dl | dt | dd.
-type chunk_element_attr() :: {atom(),unicode:chardata()}.
-type chunk_element_attrs() :: [chunk_element_attr()].
-type chunk_element() :: {chunk_element_type(),chunk_element_attrs(),
@@ -54,6 +64,13 @@ validate(Module) when is_atom(Module) ->
{ok, Doc} = code:get_doc(Module),
validate(Doc);
validate(#docs_v1{ module_doc = MDocs, docs = AllDocs }) ->
+
+ %% Check some macro in-variants
+ AE = lists:sort(?ALL_ELEMENTS),
+ AE = lists:sort(?INLINE ++ ?BLOCK),
+ true = lists:all(fun(Elem) -> ?IS_INLINE(Elem) end, ?INLINE),
+ true = lists:all(fun(Elem) -> ?IS_BLOCK(Elem) end, ?BLOCK),
+
_ = maps:map(fun(_Key,MDoc) -> validate(binary_to_term(MDoc)) end, MDocs),
lists:map(fun({_,_Anno, Sig, Docs, _Meta}) ->
case lists:all(fun erlang:is_binary/1, Sig) of
@@ -66,7 +83,7 @@ validate([H|T]) when is_tuple(H) ->
_ = validate(H),
validate(T);
validate({Tag,Attr,Content}) ->
- case lists:member(Tag,?ALL_TAGS) of
+ case lists:member(Tag,?ALL_ELEMENTS) of
false ->
throw({invalid_tag,Tag});
true ->
@@ -101,9 +118,8 @@ normalize_trim(Bin,true) when is_binary(Bin) ->
re:replace(NoNewLine,"\\s+"," ",[global,{return,binary}]);
normalize_trim(Bin,false) when is_binary(Bin) ->
Bin;
-normalize_trim([{Tag,Attr,Content}|T],Trim) when Tag =:= pre;
- Tag =:= code ->
- [{Tag,Attr,normalize_trim(Content,false)} | normalize_trim(T,Trim)];
+normalize_trim([{pre,Attr,Content}|T],Trim) ->
+ [{pre,Attr,normalize_trim(Content,false)} | normalize_trim(T,Trim)];
normalize_trim([{Tag,Attr,Content}|T],Trim) ->
[{Tag,Attr,normalize_trim(Content,Trim)} | normalize_trim(T,Trim)];
normalize_trim([<<>>|T],Trim) ->
@@ -119,17 +135,6 @@ normalize_trim([],_Trim) ->
%% cross into other inline elements.
%% For non-inline elements we just need to make sure that any
%% leading or trailing spaces are stripped.
-%%
-%% inline elements are:
--define(INLINE,[c,anno,c,i,br,em]).
--define(IS_INLINE(ELEM),(((ELEM) =:= a) orelse ((ELEM) =:= c)
- orelse ((ELEM) =:= anno) orelse ((ELEM) =:= c)
- orelse ((ELEM) =:= i) orelse ((ELEM) =:= br)
- orelse ((ELEM) =:= em))).
-%% non-inline elements are:
--define(BLOCK,[p,pre,code,ul,ol,li,dl,dt,dd,h1,h2,h3]).
--define(IS_BLOCK(ELEM),not ?IS_INLINE(ELEM)).
--define(IS_PRE(ELEM),(((ELEM) =:= pre) orelse ((ELEM) =:= code))).
normalize_space([{Pre,Attr,Content}|T]) when ?IS_PRE(Pre) ->
[{Pre,Attr,trim_first_and_last(Content,$\n)} | normalize_space(T)];
normalize_space([{Block,Attr,Content}|T]) when ?IS_BLOCK(Block) ->
@@ -328,10 +333,10 @@ get_local_doc({F,A}, Docs) ->
get_local_doc(unicode:characters_to_binary(io_lib:format("~tp/~p",[F,A])), Docs);
get_local_doc(_Missing, #{ <<"en">> := Docs }) ->
%% English if it exists
- binary_to_term(Docs);
+ normalize(binary_to_term(Docs));
get_local_doc(_Missing, ModuleDoc) when map_size(ModuleDoc) > 0 ->
%% Otherwise take first alternative found
- binary_to_term(maps:get(hd(maps:keys(ModuleDoc)), ModuleDoc));
+ normalize(binary_to_term(maps:get(hd(maps:keys(ModuleDoc)), ModuleDoc)));
get_local_doc(Missing, hidden) ->
[{p,[],[<<"The documentation for ">>,Missing,
<<" is hidden. This probably means that it is internal "
@@ -431,11 +436,11 @@ render_element({IgnoreMe,_,Content}, State, Pos, Ind,D)
%% Catch h1, h2 and h3 before the padding is done as there reset padding
render_element({h1,_,Content},State,0 = Pos,_Ind,D) ->
- trimnlnl(render_element({c,[],[{em,[],Content}]}, State, Pos, 0, D));
+ trimnlnl(render_element({code,[],[{em,[],Content}]}, State, Pos, 0, D));
render_element({h2,_,Content},State,0 = Pos,_Ind,D) ->
trimnlnl(render_element({em,[],Content}, State, Pos, 0, D));
render_element({h3,_,Content},State,Pos,_Ind,D) when Pos =< 2 ->
- trimnlnl(render_element({c,[],Content}, State, Pos, 2, D));
+ trimnlnl(render_element({code,[],Content}, State, Pos, 2, D));
render_element({p,_Attr,_Content} = E,State,Pos,Ind,D) when Pos > Ind ->
{Docs,NewPos} = render_element(E,State,0,Ind,D),
@@ -452,9 +457,12 @@ render_element(Elem,State,Pos,Ind,D) when Pos < Ind ->
{[pad(Ind - Pos), Docs],NewPos};
-render_element({c,_,Content},State,Pos,Ind,D) ->
+render_element({code,_,Content},[pre|_] = State,Pos,Ind,D) ->
+ %% When code is within a pre we don't emit any underline
+ render_docs(Content, [code|State], Pos, Ind,D);
+render_element({code,_,Content},State,Pos,Ind,D) ->
Underline = sansi(underline),
- {Docs, NewPos} = render_docs(Content, [c|State], Pos, Ind,D),
+ {Docs, NewPos} = render_docs(Content, [code|State], Pos, Ind,D),
{[Underline,Docs,ransi(underline)], NewPos};
render_element({i,_,Content},State,Pos,Ind,D) ->
@@ -469,9 +477,8 @@ render_element({em,_,Content},State,Pos,Ind,D) ->
{Docs, NewPos} = render_docs(Content, State, Pos, Ind,D),
{[Bold,Docs,ransi(bold)], NewPos};
-render_element({PreCode,_,Content},State,Pos,Ind,D)
- when PreCode =:= pre; PreCode =:= code ->
- %% For pre we make sure to respect the newlines in code and pre
+render_element({pre,_,Content},State,Pos,Ind,D) ->
+ %% For pre we make sure to respect the newlines in pre
trimnlnl(render_docs(Content, [pre|State], Pos, Ind+2, D));
render_element({ul,[{class,"types"}],Content},State,_Pos,Ind,D) ->