Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add line breaks before ordered and unordered lists. #18

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Empty file modified edown_make 100755 → 100644
Empty file.
Empty file modified make_doc 100755 → 100644
Empty file.
Empty file modified rebar 100755 → 100644
Empty file.
Empty file modified samples/markedoc/make_samples.sh 100755 → 100644
Empty file.
Empty file modified samples/markedoc/test-bsd.sh 100755 → 100644
Empty file.
Empty file modified samples/markedoc/test-linux.sh 100755 → 100644
Empty file.
Empty file modified samples/markedoc/test-macosx.sh 100755 → 100644
Empty file.
562 changes: 281 additions & 281 deletions src/edown_layout.erl

Large diffs are not rendered by default.

257 changes: 131 additions & 126 deletions src/edown_xmerl.erl
Expand Up @@ -17,7 +17,8 @@
%% @copyright 2010 Erlang Solutions Ltd %% @copyright 2010 Erlang Solutions Ltd
%% @end %% @end
%% ============================================================================= %% =============================================================================
%% Modified 2012 by Beads Land-Trujillo: '#text#'/1, brstrip/1 %% Modified 2012 by Beads Land-Trujillo: '#text#'/1, brstrip/1, md_elem/5,
%% '#element#'/5
%% ============================================================================= %% =============================================================================


%% Description : Callback module for exporting XML to Markdown. %% Description : Callback module for exporting XML to Markdown.
Expand All @@ -29,8 +30,8 @@
%% Note: we assume XML data, so all tags are lowercase! %% Note: we assume XML data, so all tags are lowercase!


-export(['#root#'/4, -export(['#root#'/4,
'#element#'/5, '#element#'/5,
'#text#'/1]). '#text#'/1]).


-import(xmerl_lib, [markup/3, find_attribute/2, export_text/1]). -import(xmerl_lib, [markup/3, find_attribute/2, export_text/1]).


Expand All @@ -52,19 +53,22 @@ strip(Str) -> lstrip(rstrip(Str)).
lstrip(Str) -> re:replace(Str,"^\\s","",[]). lstrip(Str) -> re:replace(Str,"^\\s","",[]).
rstrip(Str) -> re:replace(Str, "\\s\$", []). rstrip(Str) -> re:replace(Str, "\\s\$", []).


% Strip double spaces at end of line -- markdown reads as hard return. % Strip double spaces at end of line (markdown reads as hard return).
brstrip(Str) -> re:replace(Str, "\\s+\\s\$", "", [global, multiline]). % Match spaces only. Tabs and newlines are preserved.
brstrip(Str) ->
{ok, MP} = re:compile("\\ +\\ \$", [multiline]),
re:replace(Str, MP, "", [global]).


%% The '#root#' tag is called when the entire structure has been %% The '#root#' tag is called when the entire structure has been
%% exported. It does not appear in the structure itself. %% exported. It does not appear in the structure itself.


'#root#'(Data, Attrs, [], _E) -> '#root#'(Data, Attrs, [], _E) ->
case find_attribute(header, Attrs) of case find_attribute(header, Attrs) of
{value, Hdr} -> {value, Hdr} ->
[lists:flatten(io_lib:fwrite("HEADER: ~p~n", [Hdr])), Data]; [lists:flatten(io_lib:fwrite("HEADER: ~p~n", [Hdr])), Data];
false -> false ->
Data Data
end. end.


%% Note that SGML does not have the <Tag/> empty-element form. %% Note that SGML does not have the <Tag/> empty-element form.
%% Furthermore, for some element types, the end tag may be forbidden - %% Furthermore, for some element types, the end tag may be forbidden -
Expand All @@ -73,152 +77,153 @@ brstrip(Str) -> re:replace(Str, "\\s+\\s\$", "", [global, multiline]).
%% sure that the scope of a markup is not extended by mistake.) %% sure that the scope of a markup is not extended by mistake.)


'#element#'('pre_pre', Data, Attrs, Parents, E) -> '#element#'('pre_pre', Data, Attrs, Parents, E) ->
case re:run(Data, "<a href=", []) of case re:run(Data, "<a href=", []) of
{match, _} -> {match, _} ->
'#element#'(pre, Data, Attrs, Parents, E); '#element#'(pre, Data, Attrs, Parents, E);
nomatch -> nomatch ->
'#element#'(pre, escape_pre(Data), Attrs, Parents, E) '#element#'(pre, escape_pre(Data), Attrs, Parents, E)
end; end;
'#element#'('esc_tt', Data, Attrs, Parents, E) -> '#element#'('esc_tt', Data, Attrs, Parents, E) ->
case within_html(Parents) of case within_html(Parents) of
true -> true ->
'#element#'(tt, escape_pre(Data), Attrs, Parents, E); '#element#'(tt, escape_pre(Data), Attrs, Parents, E);
false -> false ->
'#element#'(tt, Data, Attrs, Parents, E) '#element#'(tt, Data, Attrs, Parents, E)
end; end;
'#element#'('pre', Data, Attrs, Parents, E) ->
xmerl_html:'#element#'('pre', Data, Attrs, Parents, E);
'#element#'('div', Data, _, _Parents, _E) -> '#element#'('div', Data, _, _Parents, _E) ->
%% special case - we use 'div' to enforce html encoding %% special case - we use 'div' to enforce html encoding
Data; Data;
'#element#'('pretext', Data, _Attrs, _Parents, _E) -> '#element#'('pretext', Data, _Attrs, _Parents, _E) ->
Data; Data;
'#element#'(a, Data, Attrs, Parents, E) -> '#element#'(a, Data, Attrs, Parents, E) ->
case edown_lib:redirect_uri(E) of case edown_lib:redirect_uri(E) of
false -> false ->
elem(a, Data, Attrs, Parents, E); elem(a, Data, Attrs, Parents, E);
#xmlElement{attributes = Attrs1, parents = Parents1} = E1 -> #xmlElement{attributes = Attrs1, parents = Parents1} = E1 ->
elem(a, Data, Attrs1, Parents1, E1) elem(a, Data, Attrs1, Parents1, E1)
end; end;
'#element#'(Tag, Data, Attrs, Parents, E) -> '#element#'(Tag, Data, Attrs, Parents, E) ->
elem(Tag, Data, Attrs, Parents, E). elem(Tag, Data, Attrs, Parents, E).


%% the alias_for/5 function is used to force HTML rendering of things we %% the alias_for/5 function is used to force HTML rendering of things we
%% know are likely to cause problems with Markdown. %% know are likely to cause problems with Markdown.
elem(local_defs, Data, Attrs, Parents, E) -> elem(local_defs, Data, Attrs, Parents, E) ->
alias_for(ul, Data, Attrs, Parents, E); alias_for(ul, Data, Attrs, Parents, E);
elem(localdef, Data, Attrs, Parents, E) -> elem(localdef, Data, Attrs, Parents, E) ->
alias_for(li, Data, Attrs, Parents, E); alias_for(li, Data, Attrs, Parents, E);
elem(Tag, Data, Attrs, Parents, E) -> elem(Tag, Data, Attrs, Parents, E) ->
case needs_html(Tag, Attrs) orelse within_html(Parents) of case needs_html(Tag, Attrs) orelse within_html(Parents) of
true -> true ->
html_elem(Tag, Data, Attrs, Parents, E); html_elem(Tag, Data, Attrs, Parents, E);
false -> false ->
md_elem(Tag, Data, Attrs, Parents, E) md_elem(Tag, Data, Attrs, Parents, E)
end. end.


escape_pre(Data) -> escape_pre(Data) ->
re:replace(re:replace(Data, "<", "\\&lt;", [global]), ">", "\\&gt;", [global]). re:replace(re:replace(Data, "<", "\\&lt;", [global]), ">", "\\&gt;", [global]).


alias_for(Tag, Data, Attrs, Parents, E) -> alias_for(Tag, Data, Attrs, Parents, E) ->
xmerl_html:'#element#'(Tag, Data, Attrs, Parents, E#xmlElement{name = Tag}). xmerl_html:'#element#'(Tag, Data, Attrs, Parents, E#xmlElement{name = Tag}).


html_elem(Tag, Data, Attrs, Parents, E) -> html_elem(Tag, Data, Attrs, Parents, E) ->
HTML = fun() -> HTML = fun() ->
xmerl_html:'#element#'(Tag, Data, Attrs, Parents, E) xmerl_html:'#element#'(Tag, Data, Attrs, Parents, E)
end, end,
case within_html(Parents) of case within_html(Parents) of
true -> true ->
HTML(); HTML();
false -> false ->
["\n\n", HTML(), "\n\n"] ["\n\n", HTML(), "\n\n"]
end. end.


md_elem(a, Data, Attrs, _Parents, _E) -> md_elem(a, Data, Attrs, _Parents, _E) ->
%% io:fwrite("A TAG = ~p~nPs = ~p~n", [_E, _Parents]), %% io:fwrite("A TAG = ~p~nPs = ~p~n", [_E, _Parents]),
case lists:keyfind(href, #xmlAttribute.name, Attrs) of case lists:keyfind(href, #xmlAttribute.name, Attrs) of
#xmlAttribute{value = HRef} -> #xmlAttribute{value = HRef} ->
["[", Data, "](", HRef, ")"]; ["[", Data, "](", HRef, ")"];
false -> false ->
case lists:keyfind(name, #xmlAttribute.name, Attrs) of case lists:keyfind(name, #xmlAttribute.name, Attrs) of
#xmlAttribute{} -> #xmlAttribute{} ->
[ %%"\n", [ %%"\n",
xmerl_lib:start_tag(a,Attrs), xmerl_lib:start_tag(a,Attrs),
Data, Data,
xmerl_lib:end_tag(a) xmerl_lib:end_tag(a)
%%"\n"] %%"\n"]
] ]
end end
end; end;
md_elem(img, _Data, Attrs, _Parents, _E) -> md_elem(img, _Data, Attrs, _Parents, _E) ->
#xmlAttribute{value = Src} = lists:keyfind(src,#xmlAttribute.name,Attrs), #xmlAttribute{value = Src} = lists:keyfind(src,#xmlAttribute.name,Attrs),
#xmlAttribute{value = Alt} = lists:keyfind(alt,#xmlAttribute.name,Attrs), #xmlAttribute{value = Alt} = lists:keyfind(alt,#xmlAttribute.name,Attrs),
["![", Alt, "](", Src, ")"]; ["![", Alt, "](", Src, ")"];
md_elem(li, Data, _Attrs, [{ul,_}|_], _E) -> md_elem(li, Data, _Attrs, [{ul,_}|_], _E) ->
["* ", strip(Data), "\n"]; ["* ", strip(Data), "\n"];
md_elem(li, Data, _Attrs, [{ol,_}|_], _E) -> md_elem(li, Data, _Attrs, [{ol,_}|_], _E) ->
["1. ", strip(Data), "\n"]; ["1. ", strip(Data), "\n"];
md_elem(pre, Data, _Attrs, _Parents, _E) ->
{ok, MP} = re:compile("^", [multiline]),
re:replace(Data, MP, "\t", [global, {return, list}]);
md_elem(Tag, Data, Attrs, Parents, E) -> md_elem(Tag, Data, Attrs, Parents, E) ->
case Tag of case Tag of
title -> title ->
%% io:fwrite("TITLE = |~s|~n", [Data]), %% io:fwrite("TITLE = |~s|~n", [Data]),
Str = lists:flatten(Data), Str = lists:flatten(Data),
[Str, "\n", [$= || _ <- to_string(Str)], "\n"]; [Str, "\n", [$= || _ <- to_string(Str)], "\n"];
html -> Data; html -> Data;
body -> Data; body -> Data;
'div' -> Data; 'div' -> Data;
ul -> Data; ul -> [Data];
ol -> Data; ol -> [Data];
p -> ["\n\n", Data]; p -> ["\n\n", Data];
b -> ["__", no_nl(Data), "__"]; b -> ["__", no_nl(Data), "__"];
em -> ["_", no_nl(Data), "_"]; em -> ["_", no_nl(Data), "_"];
i -> ["_", no_nl(Data), "_"]; i -> ["_", no_nl(Data), "_"];
tt -> ["`", no_nl(Data), "`"]; tt -> ["`", no_nl(Data), "`"];
code -> code ->
%% edoc_macros.erl hard-codes expansion of the {@type ...} macro %% edoc_macros.erl hard-codes expansion of the {@type ...} macro
%% as a HTML href inside <code>...</code> %% as a HTML href inside <code>...</code>
case re:run(Data, "<a href=", []) of case re:run(Data, "<a href=", []) of
{match,_} -> {match,_} ->
%% ["<code>", no_nl(Data), "</code>"]; %% ["<code>", no_nl(Data), "</code>"];
["<code>", no_nl(Data), "</code>"]; ["<code>", no_nl(Data), "</code>"];
_ -> _ ->
%% ["`", no_nl(Data), "`"] %% ["`", no_nl(Data), "`"]
%% Don't strip newlines here, as it messes up the specs %% Don't strip newlines here, as it messes up the specs
["`", Data, "`"] ["`", Data, "`"]
end; end;
dl -> Data; dl -> [Data];
dt -> html_elem(dt, Data, Attrs, Parents, E); dt -> html_elem(dt, Data, Attrs, Parents, E);
dd -> html_elem(dd, Data, Attrs, Parents, E); dd -> html_elem(dd, Data, Attrs, Parents, E);
h1 -> ["\n\n#", no_nl(Data), "#\n"]; h1 -> ["\n\n#", no_nl(Data), "#\n"];
h2 -> ["\n\n##", no_nl(Data), "##\n"]; h2 -> ["\n\n##", no_nl(Data), "##\n"];
h3 -> ["\n\n###", no_nl(Data), "##\n"]; h3 -> ["\n\n###", no_nl(Data), "##\n"];
h4 -> ["\n\n####", no_nl(Data), "##\n"]; h4 -> ["\n\n####", no_nl(Data), "##\n"];
hr -> "---------\n"; hr -> "---------\n";
head -> []; head -> [];
_ -> _ ->
["\n", ["\n",
xmerl_lib:start_tag(Tag,Attrs), xmerl_lib:start_tag(Tag,Attrs),
Data, Data,
xmerl_lib:end_tag(Tag), xmerl_lib:end_tag(Tag),
"\n"] "\n"]
end. end.


within_html(Tags) -> within_html(Tags) ->
lists:any(fun({pre,_}) -> true; lists:any(fun({pre,_}) -> true;
({pre_pre,_}) -> true; ({pre_pre,_}) -> true;
({code,_}) -> true; ({code,_}) -> true;
({T,_}) -> needs_html(T) ({T,_}) -> needs_html(T)
end, Tags). end, Tags).


needs_html(T) -> needs_html(T) ->
needs_html(T, []). needs_html(T, []).


needs_html(T, _Attrs) -> needs_html(T, _Attrs) ->
lists:member(T, [table,'div',dd,dt,local_defs,localdef]). lists:member(T, [table,'div',dd,dt,local_defs,localdef]).


no_nl(S) -> no_nl(S) ->
string:strip([C || C <- to_string(S), string:strip([C || C <- to_string(S),
C =/= $\n], both). C =/= $\n], both).


%% attr(#xmlAttribute{name = N, value = V}) -> %% attr(#xmlAttribute{name = N, value = V}) ->
%% "(" ++ atom_to_list(N) ++ "=" ++ [a_val(V)] ++ ")". %% "(" ++ atom_to_list(N) ++ "=" ++ [a_val(V)] ++ ")".
Expand Down