From 112f38e3c7ba6cb5f8aa2ed4c7601ba098e68627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Mon, 11 Jun 2018 22:26:00 +0200 Subject: Many fixes based on reading the HTML renders of Cowboy docs --- src/asciideck_block_parser.erl | 13 +++++++--- src/asciideck_inline_pass.erl | 17 +++++++++++++ src/asciideck_to_html.erl | 58 ++++++++++++++++++++++++++++++++---------- 3 files changed, 71 insertions(+), 17 deletions(-) diff --git a/src/asciideck_block_parser.erl b/src/asciideck_block_parser.erl index e0faceb..09d3f1a 100644 --- a/src/asciideck_block_parser.erl +++ b/src/asciideck_block_parser.erl @@ -1018,12 +1018,13 @@ para(St) -> fold_para(eof) -> done; -fold_para(Line0) -> - case trim(Line0) of +fold_para(Line) -> + case trim(Line) of <<>> -> done; <<"+">> -> done; + <<"//", _/bits>> -> done; %% @todo Detect delimited block or list. - Line -> {more, Line} + _ -> {more, Line} end. -ifdef(TEST). @@ -1042,6 +1043,12 @@ para_test() -> [{paragraph, _, LoremIpsum, _}] = parse(<< LoremIpsum/binary, "\n">>), %% Paragraph followed by end of file with no trailing line break.. [{paragraph, _, LoremIpsum, _}] = parse(LoremIpsum), + %% Paragraph followed by list continuation. + [{paragraph, _, LoremIpsum, _}, {list_item_continuation, _, _, _}] + = parse(<>), + %% Paragraph followed by comment. + [{paragraph, _, LoremIpsum, _}, {comment_line, _, <<"@todo Double check.">>, _}] + = parse(<>), %% Two paragraphs. [{paragraph, _, LoremIpsum, _}, {paragraph, _, LoremIpsum, _}] = parse(<< diff --git a/src/asciideck_inline_pass.erl b/src/asciideck_inline_pass.erl index 3ed79b1..469c9f3 100644 --- a/src/asciideck_inline_pass.erl +++ b/src/asciideck_inline_pass.erl @@ -170,7 +170,10 @@ direct_link(Data, Prefix) -> {Target0, Rest0} = while(fun(C) -> (C =/= $[) andalso (C =/= $\s) andalso (C =/= $\t) andalso (C =/= $\r) andalso (C =/= $\n) + andalso (C =/= $,) end, Data), + %% The link must be more than just the prefix. + false = Target0 =:= <<>>, Target = <>, %% It is optionally followed by a caption. Otherwise %% the link itself is the caption. @@ -191,6 +194,13 @@ direct_link(Data, Prefix) -> -ifdef(TEST). http_link_test() -> + <<"Incomplete http: link">> = inline(<<"Incomplete http: link">>), + [ + {link, #{ + target := <<"http://example.org:8080">> + }, <<"http://example.org:8080">>, _}, + <<", continued">> + ] = inline(<<"http://example.org:8080, continued">>), [ <<"If you have ">>, {link, #{ @@ -221,6 +231,13 @@ https_link(<<"https:", Rest/bits>>, Prev) when ?IS_BOUNDARY(Prev) -> -ifdef(TEST). https_link_test() -> + <<"Incomplete https: link">> = inline(<<"Incomplete https: link">>), + [ + {link, #{ + target := <<"https://example.org:8080">> + }, <<"https://example.org:8080">>, _}, + <<", continued">> + ] = inline(<<"https://example.org:8080, continued">>), [ <<"If you have ">>, {link, #{ diff --git a/src/asciideck_to_html.erl b/src/asciideck_to_html.erl index b904f3a..6f8a393 100644 --- a/src/asciideck_to_html.erl +++ b/src/asciideck_to_html.erl @@ -71,21 +71,42 @@ ast_node(Node={Type, _, _, _}) -> listing_block -> listing_block(Node); list -> list(Node); table -> table(Node); + block_macro -> block_macro(Node); comment_line -> comment_line(Node); - _ -> - io:format("Ignored AST node ~p~n", [Node]), - [] + _ -> ast_error({unknown_type, Node}) end - catch _:_ -> - io:format("Ignored AST node ~p~n", [Node]), - [] + catch C:E -> + ast_error({crash, C, E, erlang:get_stacktrace(), Node}) end. +ast_error(Error) -> + [ + "

", + html_encode(unicode:characters_to_binary(io_lib:format("~p", [Error]))), + "

" + ]. + %% Section titles. -section_title({section_title, #{level := Level}, Title, _}) -> +section_title({section_title, Attrs=#{level := Level}, Title, _}) -> LevelC = $1 + Level, - ["", inline(Title), "\n"]. + ID = case Attrs of + #{<<"id">> := ID0} -> ID0; + _ -> id_from_title(Title) + end, + ["", inline(Title), "\n"]. + +%% Asciidoc User Guide 8.4.2 +%% @todo Handle cases where the title is repeated in the same document. +id_from_title(Title) -> + ID0 = unicode:characters_to_binary(string:to_lower(unicode:characters_to_list(Title))), + ID1 = <= $a, C =< $z -> <>; + C >= $0, C =< $9 -> <>; + true -> <<$_>> + end || <> <= ID0>>, + ID = string:strip(unicode:characters_to_list(ID1), both, $_), + [$_, unicode:characters_to_binary(ID)]. %% Paragraphs. @@ -129,11 +150,10 @@ bulleted_list_item({list_item, _, [{paragraph, _, Text, _}|AST], _}) -> "\n" ]. -labeled_list_item({list_item, #{label := Label}, [{paragraph, _, Text, _}|AST], _}) -> +labeled_list_item({list_item, #{label := Label}, AST, _}) -> [ "
", inline(Label), "
\n", "
", - inline(Text), "\n", ast(AST), "
\n" ]. @@ -160,6 +180,13 @@ table_body_cells(Cells) -> [["", inline(Text), "\n"] || {cell, _, Text, _} <- Cells]. +%% Block macros. + +block_macro({block_macro, #{name := <<"image">>, + target := Target, 1 := Caption}, _, _}) -> + [""]. + %% Comment lines are printed in the generated file %% but are not visible in viewers. @@ -170,9 +197,10 @@ comment_line({comment_line, _, Text, _}) -> inline(Text) when is_binary(Text) -> html_encode(Text); -inline({Link, #{target := Target}, Text, _}) - when Link =:= link; Link =:= xref -> +inline({link, #{target := Target}, Text, _}) -> ["", html_encode(Text), ""]; +inline({xref, #{id := ID}, Text, _}) -> + ["", html_encode(Text), ""]; inline({emphasized, _, Text, _}) -> ["", inline(Text), ""]; inline({strong, _, Text, _}) -> @@ -187,5 +215,7 @@ html_encode(Text) -> $& -> <<"&">>; $< -> <<"<">>; $> -> <<">">>; - _ -> <> - end || <> <= Text>>. + $" -> <<""">>; + $' -> <<"'">>; + _ -> <> + end || <> <= Text>>. -- cgit v1.2.3