Skip to content

Commit 4186072

Browse files
committed
Add gfm_autolink_literal test suite.
1 parent 8d1e145 commit 4186072

18 files changed

+5527
-375
lines changed

apps/markdown/src/construct/markdown_construct_gfm_autolink_literal.erl

Lines changed: 668 additions & 1 deletion
Large diffs are not rendered by default.

apps/markdown/src/construct/markdown_construct_text.erl

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -333,23 +333,22 @@ resolve(
333333
parse_state = #markdown_parse_state{
334334
options = #markdown_parse_options{
335335
constructs = #markdown_construct_options{
336-
hard_break_trailing = HardBreakTrailing, gfm_autolink_literal = _GfmAutolinkLiteral
336+
gfm_autolink_literal = GfmAutolinkLiteral,
337+
hard_break_trailing = HardBreakTrailing
337338
}
338339
}
339340
}
340341
}
341342
) ->
342343
% io:format("\n\n[~w] BEFORE text:resolve\n\n~ts\n\n", [markdown:counter_get(), markdown_debug:rust_debug_string(Tokenizer1)]),
343344
Tokenizer2 = markdown_construct_partial_whitespace:resolve_whitespace(Tokenizer1, HardBreakTrailing, true),
344-
Tokenizer3 = Tokenizer2,
345-
%% TODO: gfm_autolink_literal
346-
% Tokenizer3 =
347-
% case GfmAutolinkLiteral of
348-
% true ->
349-
% resolve_gfm_autolink_literal(Tokenizer2);
350-
% false ->
351-
% Tokenizer2
352-
% end,
345+
Tokenizer3 =
346+
case GfmAutolinkLiteral of
347+
true ->
348+
markdown_construct_gfm_autolink_literal:resolve(Tokenizer2);
349+
false ->
350+
Tokenizer2
351+
end,
353352
#markdown_tokenizer{events = Events3, map = EditMap3} = Tokenizer3,
354353
{EditMap4, Events4} = markdown_edit_map:consume(EditMap3, Events3),
355354
Tokenizer4 = Tokenizer3#markdown_tokenizer{events = Events4, map = EditMap4},

apps/markdown/src/html/markdown_html.erl

Lines changed: 80 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -705,11 +705,11 @@ exit(CompileContext1 = #markdown_html_compile_context{events = Events, index = I
705705
definition_title_string -> on_exit_definition_title_string(CompileContext1);
706706
emphasis -> on_exit_emphasis(CompileContext1);
707707
frontmatter -> on_exit_frontmatter(CompileContext1);
708-
% gfm_autolink_literal_email -> on_exit_gfm_autolink_literal_email(CompileContext1);
709-
% gfm_autolink_literal_mailto -> on_exit_gfm_autolink_literal_mailto(CompileContext1);
710-
% gfm_autolink_literal_protocol -> on_exit_gfm_autolink_literal_protocol(CompileContext1);
711-
% gfm_autolink_literal_www -> on_exit_gfm_autolink_literal_www(CompileContext1);
712-
% gfm_autolink_literal_xmpp -> on_exit_gfm_autolink_literal_xmpp(CompileContext1);
708+
gfm_autolink_literal_email -> on_exit_gfm_autolink_literal_email(CompileContext1);
709+
gfm_autolink_literal_mailto -> on_exit_gfm_autolink_literal_mailto(CompileContext1);
710+
gfm_autolink_literal_protocol -> on_exit_gfm_autolink_literal_protocol(CompileContext1);
711+
gfm_autolink_literal_www -> on_exit_gfm_autolink_literal_www(CompileContext1);
712+
gfm_autolink_literal_xmpp -> on_exit_gfm_autolink_literal_xmpp(CompileContext1);
713713
% gfm_footnote_call -> on_exit_gfm_footnote_call(CompileContext1);
714714
% gfm_footnote_definition_label_string -> on_exit_gfm_footnote_definition_label_string(CompileContext1);
715715
% gfm_footnote_definition_prefix -> on_exit_gfm_footnote_definition_prefix(CompileContext1);
@@ -1014,6 +1014,81 @@ on_exit_frontmatter(CompileContext1 = #markdown_html_compile_context{}) ->
10141014
CompileContext3 = CompileContext2#markdown_html_compile_context{slurp_one_line_ending = true},
10151015
CompileContext3.
10161016

1017+
%% @private
1018+
-doc """
1019+
Handle [`Exit`][Kind::Exit]:[`GfmAutolinkLiteralEmail`][Name::GfmAutolinkLiteralEmail].
1020+
""".
1021+
-spec on_exit_gfm_autolink_literal_email(CompileContext) -> CompileContext when
1022+
CompileContext :: markdown_html_compile_context:t().
1023+
on_exit_gfm_autolink_literal_email(
1024+
CompileContext1 = #markdown_html_compile_context{bytes = Bytes, events = Events, index = Index}
1025+
) ->
1026+
Position = markdown_position:from_exit_event(Events, Index),
1027+
Slice = markdown_slice:from_position(Bytes, Position),
1028+
SliceBytes = markdown_slice:as_binary(Slice),
1029+
CompileContext2 = generate_autolink(CompileContext1, {some, <<"mailto:">>}, SliceBytes, true),
1030+
CompileContext2.
1031+
1032+
%% @private
1033+
-doc """
1034+
Handle [`Exit`][Kind::Exit]:[`GfmAutolinkLiteralMailto`][Name::GfmAutolinkLiteralMailto].
1035+
""".
1036+
-spec on_exit_gfm_autolink_literal_mailto(CompileContext) -> CompileContext when
1037+
CompileContext :: markdown_html_compile_context:t().
1038+
on_exit_gfm_autolink_literal_mailto(
1039+
CompileContext1 = #markdown_html_compile_context{bytes = Bytes, events = Events, index = Index}
1040+
) ->
1041+
Position = markdown_position:from_exit_event(Events, Index),
1042+
Slice = markdown_slice:from_position(Bytes, Position),
1043+
SliceBytes = markdown_slice:as_binary(Slice),
1044+
CompileContext2 = generate_autolink(CompileContext1, none, SliceBytes, true),
1045+
CompileContext2.
1046+
1047+
%% @private
1048+
-doc """
1049+
Handle [`Exit`][Kind::Exit]:[`GfmAutolinkLiteralProtocol`][Name::GfmAutolinkLiteralProtocol].
1050+
""".
1051+
-spec on_exit_gfm_autolink_literal_protocol(CompileContext) -> CompileContext when
1052+
CompileContext :: markdown_html_compile_context:t().
1053+
on_exit_gfm_autolink_literal_protocol(
1054+
CompileContext1 = #markdown_html_compile_context{bytes = Bytes, events = Events, index = Index}
1055+
) ->
1056+
Position = markdown_position:from_exit_event(Events, Index),
1057+
Slice = markdown_slice:from_position(Bytes, Position),
1058+
SliceBytes = markdown_slice:as_binary(Slice),
1059+
CompileContext2 = generate_autolink(CompileContext1, none, SliceBytes, true),
1060+
CompileContext2.
1061+
1062+
%% @private
1063+
-doc """
1064+
Handle [`Exit`][Kind::Exit]:[`GfmAutolinkLiteralWww`][Name::GfmAutolinkLiteralWww].
1065+
""".
1066+
-spec on_exit_gfm_autolink_literal_www(CompileContext) -> CompileContext when
1067+
CompileContext :: markdown_html_compile_context:t().
1068+
on_exit_gfm_autolink_literal_www(
1069+
CompileContext1 = #markdown_html_compile_context{bytes = Bytes, events = Events, index = Index}
1070+
) ->
1071+
Position = markdown_position:from_exit_event(Events, Index),
1072+
Slice = markdown_slice:from_position(Bytes, Position),
1073+
SliceBytes = markdown_slice:as_binary(Slice),
1074+
CompileContext2 = generate_autolink(CompileContext1, {some, <<"http://">>}, SliceBytes, true),
1075+
CompileContext2.
1076+
1077+
%% @private
1078+
-doc """
1079+
Handle [`Exit`][Kind::Exit]:[`GfmAutolinkLiteralXmpp`][Name::GfmAutolinkLiteralXmpp].
1080+
""".
1081+
-spec on_exit_gfm_autolink_literal_xmpp(CompileContext) -> CompileContext when
1082+
CompileContext :: markdown_html_compile_context:t().
1083+
on_exit_gfm_autolink_literal_xmpp(
1084+
CompileContext1 = #markdown_html_compile_context{bytes = Bytes, events = Events, index = Index}
1085+
) ->
1086+
Position = markdown_position:from_exit_event(Events, Index),
1087+
Slice = markdown_slice:from_position(Bytes, Position),
1088+
SliceBytes = markdown_slice:as_binary(Slice),
1089+
CompileContext2 = generate_autolink(CompileContext1, none, SliceBytes, true),
1090+
CompileContext2.
1091+
10171092
%% @private
10181093
-doc """
10191094
Handle [`Exit`][Kind::Exit]:[`GfmStrikethrough`][Name::GfmStrikethrough].

apps/markdown/src/markdown.erl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ counter_reset() ->
9191

9292
-spec doc() -> binary().
9393
doc() ->
94-
<<"[foo [bar](/uri)](/uri)\n"/utf8>>.
94+
<<"[email protected]"/utf8>>.
95+
% <<"[foo [bar](/uri)](/uri)\n"/utf8>>.
9596
% <<"*foo __bar *baz bim__ bam*"/utf8>>.
9697
% <<"[bar](/foo)">>.
9798
% %% erlfmt-ignore

apps/markdown/src/markdown_point.erl

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,17 @@ The interface for the location in the document comes from unist
2020
-compile(warn_missing_spec_all).
2121
-oncall("whatsapp_clr").
2222

23+
-include_lib("markdown/include/markdown_const.hrl").
2324
-include_lib("markdown/include/markdown_parser.hrl").
2425
-include_lib("markdown/include/markdown_util.hrl").
2526

27+
-include_lib("stdlib/include/assert.hrl").
28+
2629
%% API
2730
-export([
2831
fmt/1,
2932
new/4,
33+
shift_to/3,
3034
to_index/1,
3135
to_unist/1
3236
]).
@@ -75,6 +79,20 @@ new(Line, Column, Offset, Virtual) when
7579
->
7680
#markdown_point{line = Line, column = Column, offset = Offset, virtual = Virtual}.
7781

82+
-doc """
83+
Create a new point, that is shifted from the close earlier current
84+
point, to `index`.
85+
""".
86+
-spec shift_to(Point, Bytes, Index) -> NewPoint when
87+
Point :: t(), Bytes :: binary(), Index :: non_neg_integer(), NewPoint :: t().
88+
shift_to(Point = #markdown_point{}, Bytes, Index) when
89+
is_binary(Bytes) andalso ?is_non_neg_integer(Index)
90+
->
91+
%% BEGIN: assertions
92+
?assert(Index > Point#markdown_point.offset, "expected to shift forward"),
93+
%% END: assertions
94+
shift_to_loop(Point, Bytes, Index).
95+
7896
-spec to_index(Point) -> Index when Point :: t(), Index :: markdown_index:t().
7997
to_index(Point = #markdown_point{}) ->
8098
#markdown_index{offset = Point#markdown_point.offset, virtual = Point#markdown_point.virtual}.
@@ -85,3 +103,46 @@ Create a unist point.
85103
-spec to_unist(Point) -> UnistPoint when Point :: t(), UnistPoint :: markdown_unist_point:t().
86104
to_unist(Point = #markdown_point{}) ->
87105
markdown_unist_point:new(Point#markdown_point.line, Point#markdown_point.column, Point#markdown_point.offset).
106+
107+
%%%-----------------------------------------------------------------------------
108+
%%% Internal functions
109+
%%%-----------------------------------------------------------------------------
110+
111+
%% @private
112+
-compile({inline, [mod/2]}).
113+
-spec mod(Base, Modulus) -> Result when Base :: integer(), Modulus :: integer(), Result :: integer().
114+
mod(B, M) ->
115+
(B rem M + M) rem M.
116+
117+
%% @private
118+
-spec shift_to_loop(Point, Bytes, TargetIndex) -> NewPoint when
119+
Point :: t(), Bytes :: binary(), TargetIndex :: non_neg_integer(), NewPoint :: t().
120+
shift_to_loop(Point = #markdown_point{offset = Offset, column = Column}, Bytes, TargetIndex) when
121+
Offset < TargetIndex
122+
->
123+
case binary:at(Bytes, Offset) of
124+
$\n ->
125+
?'unreachable!'("cannot move past line endings", []);
126+
$\r ->
127+
?'unreachable!'("cannot move past line endings", []);
128+
$\t ->
129+
Remainder = mod(Column, ?TAB_SIZE),
130+
Vs =
131+
case Remainder of
132+
0 -> 0;
133+
_ -> ?TAB_SIZE - Remainder
134+
end,
135+
NextPoint = Point#markdown_point{
136+
offset = Offset + 1,
137+
column = Column + 1 + Vs
138+
},
139+
shift_to_loop(NextPoint, Bytes, TargetIndex);
140+
_ ->
141+
NextPoint = Point#markdown_point{
142+
offset = Offset + 1,
143+
column = Column + 1
144+
},
145+
shift_to_loop(NextPoint, Bytes, TargetIndex)
146+
end;
147+
shift_to_loop(Point = #markdown_point{}, _Bytes, _TargetIndex) ->
148+
Point.

0 commit comments

Comments
 (0)