Skip to content

Commit 67de36c

Browse files
committed
Add gfm_table test suite.
1 parent 12eae21 commit 67de36c

File tree

8 files changed

+6116
-26
lines changed

8 files changed

+6116
-26
lines changed

apps/markdown/src/construct/markdown_construct_gfm_table.erl

Lines changed: 586 additions & 3 deletions
Large diffs are not rendered by default.

apps/markdown/src/construct/markdown_construct_text.erl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,9 @@ resolve(
340340
}
341341
}
342342
) ->
343-
% io:format("\n\n[~w] BEFORE text:resolve\n\n~ts\n\n", [markdown:counter_get(), markdown_debug:rust_debug_string(Tokenizer1)]),
343+
io:format("\n\n[~w] BEFORE text:resolve\n\n~ts\n\n", [
344+
markdown:counter_get(), markdown_debug:rust_debug_string(Tokenizer1)
345+
]),
344346
Tokenizer2 = markdown_construct_partial_whitespace:resolve_whitespace(Tokenizer1, HardBreakTrailing, true),
345347
Tokenizer3 =
346348
case GfmAutolinkLiteral of
@@ -352,5 +354,7 @@ resolve(
352354
#markdown_tokenizer{events = Events3, map = EditMap3} = Tokenizer3,
353355
{EditMap4, Events4} = markdown_edit_map:consume(EditMap3, Events3),
354356
Tokenizer4 = Tokenizer3#markdown_tokenizer{events = Events4, map = EditMap4},
355-
% io:format("\n\n[~w] AFTER text:resolve\n\n~ts\n\n", [markdown:counter_get(), markdown_debug:rust_debug_string(Tokenizer4)]),
357+
io:format("\n\n[~w] AFTER text:resolve\n\n~ts\n\n", [
358+
markdown:counter_get(), markdown_debug:rust_debug_string(Tokenizer4)
359+
]),
356360
{Tokenizer4, {ok, none}}.

apps/markdown/src/html/markdown_html.erl

Lines changed: 188 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -596,11 +596,11 @@ enter(CompileContext1 = #markdown_html_compile_context{events = Events, index =
596596
gfm_footnote_definition -> on_enter_gfm_footnote_definition(CompileContext1);
597597
gfm_footnote_call -> on_enter_gfm_footnote_call(CompileContext1);
598598
gfm_strikethrough -> on_enter_gfm_strikethrough(CompileContext1);
599-
% gfm_table -> on_enter_gfm_table(CompileContext1);
600-
% gfm_table_body -> on_enter_gfm_table_body(CompileContext1);
601-
% gfm_table_cell -> on_enter_gfm_table_cell(CompileContext1);
602-
% gfm_table_head -> on_enter_gfm_table_head(CompileContext1);
603-
% gfm_table_row -> on_enter_gfm_table_row(CompileContext1);
599+
gfm_table -> on_enter_gfm_table(CompileContext1);
600+
gfm_table_body -> on_enter_gfm_table_body(CompileContext1);
601+
gfm_table_cell -> on_enter_gfm_table_cell(CompileContext1);
602+
gfm_table_head -> on_enter_gfm_table_head(CompileContext1);
603+
gfm_table_row -> on_enter_gfm_table_row(CompileContext1);
604604
% gfm_task_list_item_check -> on_enter_gfm_task_list_item_check(CompileContext1);
605605
html_flow -> on_enter_html_flow(CompileContext1);
606606
html_text -> on_enter_html_text(CompileContext1);
@@ -723,11 +723,94 @@ Handle [`Enter`][Kind::Enter]:[`GfmStrikethrough`][Name::GfmStrikethrough].
723723
-spec on_enter_gfm_strikethrough(CompileContext) -> CompileContext when
724724
CompileContext :: markdown_html_compile_context:t().
725725
on_enter_gfm_strikethrough(CompileContext1 = #markdown_html_compile_context{image_alt_inside = false}) ->
726-
CompileContext2 = markdown_html_compile_context:push(CompileContext1, <<"<del>">>),
726+
CompileContext2 = markdown_html_compile_context:push(CompileContext1, <<"<del>"/utf8>>),
727727
CompileContext2;
728728
on_enter_gfm_strikethrough(CompileContext1 = #markdown_html_compile_context{}) ->
729729
CompileContext1.
730730

731+
%% @private
732+
-doc """
733+
Handle [`Enter`][Kind::Enter]:[`GfmTable`][Name::GfmTable].
734+
""".
735+
-spec on_enter_gfm_table(CompileContext) -> CompileContext when CompileContext :: markdown_html_compile_context:t().
736+
on_enter_gfm_table(CompileContext1 = #markdown_html_compile_context{events = Events, index = Index}) ->
737+
Align = markdown_util_infer:gfm_table_align(Events, Index),
738+
CompileContext2 = CompileContext1#markdown_html_compile_context{gfm_table_align = {some, Align}},
739+
CompileContext3 = markdown_html_compile_context:line_ending_if_needed(CompileContext2),
740+
CompileContext4 = markdown_html_compile_context:push(CompileContext3, <<"<table>"/utf8>>),
741+
CompileContext4.
742+
743+
%% @private
744+
-doc """
745+
Handle [`Enter`][Kind::Enter]:[`GfmTableBody`][Name::GfmTableBody].
746+
""".
747+
-spec on_enter_gfm_table_body(CompileContext) -> CompileContext when
748+
CompileContext :: markdown_html_compile_context:t().
749+
on_enter_gfm_table_body(CompileContext1 = #markdown_html_compile_context{}) ->
750+
CompileContext2 = markdown_html_compile_context:push(CompileContext1, <<"<tbody>"/utf8>>),
751+
CompileContext2.
752+
753+
%% @private
754+
-doc """
755+
Handle [`Enter`][Kind::Enter]:[`GfmTableCell`][Name::GfmTableCell].
756+
""".
757+
-spec on_enter_gfm_table_cell(CompileContext) -> CompileContext when
758+
CompileContext :: markdown_html_compile_context:t().
759+
on_enter_gfm_table_cell(
760+
CompileContext1 = #markdown_html_compile_context{
761+
gfm_table_column = Column,
762+
gfm_table_align = {some, Align},
763+
gfm_table_in_head = GfmTableInHead
764+
}
765+
) ->
766+
case Column >= ?markdown_vec_size(Align) of
767+
true ->
768+
%% Capture cell to ignore it.
769+
CompileContext2 = markdown_html_compile_context:buffer(CompileContext1),
770+
CompileContext2;
771+
false ->
772+
Value = markdown_vec:get(Align, Column),
773+
CompileContext2 = markdown_html_compile_context:line_ending_if_needed(CompileContext1),
774+
CompileContext3 =
775+
case GfmTableInHead of
776+
true ->
777+
markdown_html_compile_context:push(CompileContext2, <<"<th"/utf8>>);
778+
false ->
779+
markdown_html_compile_context:push(CompileContext2, <<"<td"/utf8>>)
780+
end,
781+
CompileContext4 =
782+
case Value of
783+
left -> markdown_html_compile_context:push(CompileContext3, <<" align=\"left\""/utf8>>);
784+
right -> markdown_html_compile_context:push(CompileContext3, <<" align=\"right\""/utf8>>);
785+
center -> markdown_html_compile_context:push(CompileContext3, <<" align=\"center\""/utf8>>);
786+
none -> CompileContext3
787+
end,
788+
CompileContext5 = markdown_html_compile_context:push(CompileContext4, <<">"/utf8>>),
789+
CompileContext5
790+
end.
791+
792+
%% @private
793+
-doc """
794+
Handle [`Enter`][Kind::Enter]:[`GfmTableHead`][Name::GfmTableHead].
795+
""".
796+
-spec on_enter_gfm_table_head(CompileContext) -> CompileContext when
797+
CompileContext :: markdown_html_compile_context:t().
798+
on_enter_gfm_table_head(CompileContext1 = #markdown_html_compile_context{}) ->
799+
CompileContext2 = markdown_html_compile_context:line_ending_if_needed(CompileContext1),
800+
CompileContext3 = markdown_html_compile_context:push(CompileContext2, <<"<thead>"/utf8>>),
801+
CompileContext4 = CompileContext3#markdown_html_compile_context{gfm_table_in_head = true},
802+
CompileContext4.
803+
804+
%% @private
805+
-doc """
806+
Handle [`Enter`][Kind::Enter]:[`GfmTableRow`][Name::GfmTableRow].
807+
""".
808+
-spec on_enter_gfm_table_row(CompileContext) -> CompileContext when CompileContext :: markdown_html_compile_context:t().
809+
on_enter_gfm_table_row(CompileContext1 = #markdown_html_compile_context{}) ->
810+
CompileContext2 = markdown_html_compile_context:line_ending_if_needed(CompileContext1),
811+
CompileContext3 = markdown_html_compile_context:push(CompileContext2, <<"<tr>"/utf8>>),
812+
CompileContext3.
813+
731814
%% @private
732815
-doc """
733816
Handle [`Enter`][Kind::Enter]:[`HtmlFlow`][Name::HtmlFlow].
@@ -997,11 +1080,11 @@ exit(CompileContext1 = #markdown_html_compile_context{events = Events, index = I
9971080
gfm_footnote_definition_prefix -> on_exit_gfm_footnote_definition_prefix(CompileContext1);
9981081
gfm_footnote_definition -> on_exit_gfm_footnote_definition(CompileContext1);
9991082
gfm_strikethrough -> on_exit_gfm_strikethrough(CompileContext1);
1000-
% gfm_table -> on_exit_gfm_table(CompileContext1);
1001-
% gfm_table_body -> on_exit_gfm_table_body(CompileContext1);
1002-
% gfm_table_cell -> on_exit_gfm_table_cell(CompileContext1);
1003-
% gfm_table_head -> on_exit_gfm_table_head(CompileContext1);
1004-
% gfm_table_row -> on_exit_gfm_table_row(CompileContext1);
1083+
gfm_table -> on_exit_gfm_table(CompileContext1);
1084+
gfm_table_body -> on_exit_gfm_table_body(CompileContext1);
1085+
gfm_table_cell -> on_exit_gfm_table_cell(CompileContext1);
1086+
gfm_table_head -> on_exit_gfm_table_head(CompileContext1);
1087+
gfm_table_row -> on_exit_gfm_table_row(CompileContext1);
10051088
% gfm_task_list_item_check -> on_exit_gfm_task_list_item_check(CompileContext1);
10061089
% gfm_task_list_item_value_checked -> on_exit_gfm_task_list_item_value_checked(CompileContext1);
10071090
hard_break_escape -> on_exit_break(CompileContext1);
@@ -1553,11 +1636,104 @@ Handle [`Exit`][Kind::Exit]:[`GfmStrikethrough`][Name::GfmStrikethrough].
15531636
-spec on_exit_gfm_strikethrough(CompileContext) -> CompileContext when
15541637
CompileContext :: markdown_html_compile_context:t().
15551638
on_exit_gfm_strikethrough(CompileContext1 = #markdown_html_compile_context{image_alt_inside = false}) ->
1556-
CompileContext2 = markdown_html_compile_context:push(CompileContext1, <<"</del>">>),
1639+
CompileContext2 = markdown_html_compile_context:push(CompileContext1, <<"</del>"/utf8>>),
15571640
CompileContext2;
15581641
on_exit_gfm_strikethrough(CompileContext1 = #markdown_html_compile_context{}) ->
15591642
CompileContext1.
15601643

1644+
%% @private
1645+
-doc """
1646+
Handle [`Exit`][Kind::Exit]:[`GfmTable`][Name::GfmTable].
1647+
""".
1648+
-spec on_exit_gfm_table(CompileContext) -> CompileContext when CompileContext :: markdown_html_compile_context:t().
1649+
on_exit_gfm_table(CompileContext1 = #markdown_html_compile_context{}) ->
1650+
CompileContext2 = CompileContext1#markdown_html_compile_context{gfm_table_align = none},
1651+
CompileContext3 = markdown_html_compile_context:line_ending_if_needed(CompileContext2),
1652+
CompileContext4 = markdown_html_compile_context:push(CompileContext3, <<"</table>"/utf8>>),
1653+
CompileContext4.
1654+
1655+
%% @private
1656+
-doc """
1657+
Handle [`Exit`][Kind::Exit]:[`GfmTableBody`][Name::GfmTableBody].
1658+
""".
1659+
-spec on_exit_gfm_table_body(CompileContext) -> CompileContext when CompileContext :: markdown_html_compile_context:t().
1660+
on_exit_gfm_table_body(CompileContext1 = #markdown_html_compile_context{}) ->
1661+
CompileContext2 = markdown_html_compile_context:line_ending_if_needed(CompileContext1),
1662+
CompileContext3 = markdown_html_compile_context:push(CompileContext2, <<"</tbody>"/utf8>>),
1663+
CompileContext3.
1664+
1665+
%% @private
1666+
-doc """
1667+
Handle [`Exit`][Kind::Exit]:[`GfmTableCell`][Name::GfmTableCell].
1668+
""".
1669+
-spec on_exit_gfm_table_cell(CompileContext) -> CompileContext when CompileContext :: markdown_html_compile_context:t().
1670+
on_exit_gfm_table_cell(
1671+
CompileContext1 = #markdown_html_compile_context{
1672+
gfm_table_column = Column,
1673+
gfm_table_align = {some, Align}
1674+
}
1675+
) ->
1676+
CompileContext2 =
1677+
case Column < ?markdown_vec_size(Align) of
1678+
true ->
1679+
case CompileContext1#markdown_html_compile_context.gfm_table_in_head of
1680+
true ->
1681+
markdown_html_compile_context:push(CompileContext1, <<"</th>"/utf8>>);
1682+
false ->
1683+
markdown_html_compile_context:push(CompileContext1, <<"</td>"/utf8>>)
1684+
end;
1685+
false ->
1686+
%% Stop capturing.
1687+
{CompileContext1_1, _Buffer} = markdown_html_compile_context:resume(CompileContext1),
1688+
CompileContext1_1
1689+
end,
1690+
CompileContext3 = CompileContext2#markdown_html_compile_context{gfm_table_column = Column + 1},
1691+
CompileContext3.
1692+
1693+
%% @private
1694+
-doc """
1695+
Handle [`Exit`][Kind::Exit]:[`GfmTableHead`][Name::GfmTableHead].
1696+
""".
1697+
-spec on_exit_gfm_table_head(CompileContext) -> CompileContext when CompileContext :: markdown_html_compile_context:t().
1698+
on_exit_gfm_table_head(CompileContext1 = #markdown_html_compile_context{}) ->
1699+
CompileContext2 = CompileContext1#markdown_html_compile_context{gfm_table_in_head = false},
1700+
CompileContext3 = markdown_html_compile_context:line_ending_if_needed(CompileContext2),
1701+
CompileContext4 = markdown_html_compile_context:push(CompileContext3, <<"</thead>"/utf8>>),
1702+
CompileContext4.
1703+
1704+
%% @private
1705+
-doc """
1706+
Handle [`Exit`][Kind::Exit]:[`GfmTableRow`][Name::GfmTableRow].
1707+
""".
1708+
-spec on_exit_gfm_table_row(CompileContext) -> CompileContext when CompileContext :: markdown_html_compile_context:t().
1709+
on_exit_gfm_table_row(
1710+
CompileContext1 = #markdown_html_compile_context{
1711+
gfm_table_column = Column,
1712+
gfm_table_align = {some, Align}
1713+
}
1714+
) ->
1715+
%% Add "phantom" cells, for body rows that are shorter than the delimiter
1716+
%% row (which is equal to the head row).
1717+
CompileContext2 = on_exit_gfm_table_row__phantom_cells(CompileContext1, Column, ?markdown_vec_size(Align)),
1718+
CompileContext3 = CompileContext2#markdown_html_compile_context{gfm_table_column = 0},
1719+
CompileContext4 = markdown_html_compile_context:line_ending_if_needed(CompileContext3),
1720+
CompileContext5 = markdown_html_compile_context:push(CompileContext4, <<"</tr>"/utf8>>),
1721+
CompileContext5.
1722+
1723+
%% @private
1724+
-spec on_exit_gfm_table_row__phantom_cells(CompileContext, Column, Len) -> CompileContext when
1725+
CompileContext :: markdown_html_compile_context:t(),
1726+
Column :: non_neg_integer(),
1727+
Len :: non_neg_integer().
1728+
on_exit_gfm_table_row__phantom_cells(CompileContext1 = #markdown_html_compile_context{}, Column, Len) when
1729+
Column < Len
1730+
->
1731+
CompileContext2 = on_enter_gfm_table_cell(CompileContext1),
1732+
CompileContext3 = on_exit_gfm_table_cell(CompileContext2),
1733+
on_exit_gfm_table_row__phantom_cells(CompileContext3, Column + 1, Len);
1734+
on_exit_gfm_table_row__phantom_cells(CompileContext, _Column, _Len) ->
1735+
CompileContext.
1736+
15611737
%% @private
15621738
-doc """
15631739
Handle [`Exit`][Kind::Exit]:[`HeadingAtx`][Name::HeadingAtx].

apps/markdown/src/markdown.erl

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

9292
-spec doc() -> binary().
9393
doc() ->
94-
<<"A call.[^a]\n\n[^a]: whatevs"/utf8>>.
94+
<<"| a |\n| - |\n| b |"/utf8>>.
9595
% <<"[foo [bar](/uri)](/uri)\n"/utf8>>.
9696
% <<"*foo __bar *baz bim__ bam*"/utf8>>.
9797
% <<"[bar](/foo)">>.

apps/markdown/src/mdast/markdown_mdast.erl

Lines changed: 79 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -266,12 +266,15 @@ enter(CompileContext1 = #markdown_mdast_compile_context{events = Events, index =
266266
%% on_enter_gfm_strikethrough
267267
gfm_strikethrough ->
268268
on_enter_gfm_strikethrough(CompileContext1);
269-
% %% on_enter_gfm_table
270-
% gfm_table -> on_enter_gfm_table(CompileContext1);
271-
% %% on_enter_gfm_table_row
272-
% gfm_table_row -> on_enter_gfm_table_row(CompileContext1);
273-
% %% on_enter_gfm_table_cell
274-
% gfm_table_cell -> on_enter_gfm_table_cell(CompileContext1);
269+
%% on_enter_gfm_table
270+
gfm_table ->
271+
on_enter_gfm_table(CompileContext1);
272+
%% on_enter_gfm_table_row
273+
gfm_table_row ->
274+
on_enter_gfm_table_row(CompileContext1);
275+
%% on_enter_gfm_table_cell
276+
gfm_table_cell ->
277+
on_enter_gfm_table_cell(CompileContext1);
275278
%% on_enter_hard_break
276279
hard_break_escape ->
277280
on_enter_hard_break(CompileContext1);
@@ -595,6 +598,60 @@ on_enter_gfm_strikethrough(CompileContext1 = #markdown_mdast_compile_context{})
595598
),
596599
{ok, CompileContext2}.
597600

601+
%% @private
602+
-doc """
603+
Handle [`Enter`][Kind::Enter]:[`GfmTable`][Name::GfmTable].
604+
""".
605+
-spec on_enter_gfm_table(CompileContext) -> {ok, CompileContext} when
606+
CompileContext :: markdown_mdast_compile_context:t().
607+
on_enter_gfm_table(CompileContext1 = #markdown_mdast_compile_context{events = Events, index = Index}) ->
608+
Align = markdown_util_infer:gfm_table_align(Events, Index),
609+
CompileContext2 =
610+
markdown_mdast_compile_context:tail_push(
611+
CompileContext1,
612+
markdown_mdast_node:table(#markdown_mdast_table{
613+
align = Align,
614+
children = markdown_vec:new(),
615+
position = none
616+
})
617+
),
618+
CompileContext3 = CompileContext2#markdown_mdast_compile_context{gfm_table_inside = true},
619+
{ok, CompileContext3}.
620+
621+
%% @private
622+
-doc """
623+
Handle [`Enter`][Kind::Enter]:[`GfmTableRow`][Name::GfmTableRow].
624+
""".
625+
-spec on_enter_gfm_table_row(CompileContext) -> {ok, CompileContext} when
626+
CompileContext :: markdown_mdast_compile_context:t().
627+
on_enter_gfm_table_row(CompileContext1 = #markdown_mdast_compile_context{}) ->
628+
CompileContext2 =
629+
markdown_mdast_compile_context:tail_push(
630+
CompileContext1,
631+
markdown_mdast_node:table_row(#markdown_mdast_table_row{
632+
children = markdown_vec:new(),
633+
position = none
634+
})
635+
),
636+
{ok, CompileContext2}.
637+
638+
%% @private
639+
-doc """
640+
Handle [`Enter`][Kind::Enter]:[`GfmTableCell`][Name::GfmTableCell].
641+
""".
642+
-spec on_enter_gfm_table_cell(CompileContext) -> {ok, CompileContext} when
643+
CompileContext :: markdown_mdast_compile_context:t().
644+
on_enter_gfm_table_cell(CompileContext1 = #markdown_mdast_compile_context{}) ->
645+
CompileContext2 =
646+
markdown_mdast_compile_context:tail_push(
647+
CompileContext1,
648+
markdown_mdast_node:table_cell(#markdown_mdast_table_cell{
649+
children = markdown_vec:new(),
650+
position = none
651+
})
652+
),
653+
{ok, CompileContext2}.
654+
598655
%% @private
599656
-doc """
600657
Handle [`Enter`][Kind::Enter]:[`HardBreakEscape`][Name::HardBreakEscape].
@@ -911,8 +968,9 @@ exit(CompileContext1 = #markdown_mdast_compile_context{events = Events, index =
911968
on_exit_media(CompileContext1);
912969
link ->
913970
on_exit_media(CompileContext1);
914-
% %% on_exit_gfm_table
915-
% gfm_table -> on_exit_gfm_table(CompileContext1);
971+
%% on_exit_gfm_table
972+
gfm_table ->
973+
on_exit_gfm_table(CompileContext1);
916974
% %% on_exit_gfm_task_list_item_value
917975
% gfm_task_list_item_value_unchecked -> on_exit_gfm_task_list_item_value(CompileContext1);
918976
% gfm_task_list_item_value_checked -> on_exit_gfm_task_list_item_value(CompileContext1);
@@ -1381,6 +1439,19 @@ on_exit_gfm_autolink_literal__node_mut_func(
13811439
on_exit_gfm_autolink_literal__node_mut_func(_Node = #markdown_mdast_node{}, {some, _Value}, _Prefix) ->
13821440
?'unreachable!'("expected link on stack", []).
13831441

1442+
%% @private
1443+
-doc """
1444+
Handle [`Exit`][Kind::Exit]:[`GfmTable`][Name::GfmTable].
1445+
""".
1446+
-spec on_exit_gfm_table(CompileContext) -> {ok, CompileContext} | {error, Message} when
1447+
CompileContext :: markdown_mdast_compile_context:t(), Message :: markdown_message:t().
1448+
on_exit_gfm_table(CompileContext1 = #markdown_mdast_compile_context{}) ->
1449+
maybe
1450+
{ok, CompileContext2} ?= on_exit(CompileContext1),
1451+
CompileContext3 = CompileContext2#markdown_mdast_compile_context{gfm_table_inside = false},
1452+
{ok, CompileContext3}
1453+
end.
1454+
13841455
%% @private
13851456
-doc """
13861457
Handle [`Exit`][Kind::Exit]:{[`HardBreakEscape`][Name::HardBreakEscape],[`HardBreakTrailing`][Name::HardBreakTrailing]}.

0 commit comments

Comments
 (0)