Skip to content

Commit

Permalink
Refs: #288; Adding metadata for parsed html to AST and adapting Trans…
Browse files Browse the repository at this point in the history
…form WIP [amend-me]

  - Some tests with manually annotated ast transformations
  • Loading branch information
RobertDober committed Oct 14, 2019
1 parent 06b6884 commit 6abcf1c
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 48 deletions.
7 changes: 4 additions & 3 deletions lib/earmark/helpers/html_parser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ defmodule Earmark.Helpers.HtmlParser do
# Iterate over lines inside a tag
# -------------------------------

@verbatim %{meta: %{verbatim: true}}
defp _parse_rest(rest, tag_tpl, lines)
# Hu? That should never have happened but let us return some
# sensible data, allowing rendering after the corruped block
Expand All @@ -74,9 +75,9 @@ defmodule Earmark.Helpers.HtmlParser do
end
defp _parse_rest([last_line], {tag, _}=tag_tpl, lines) do
case Regex.run(~r{\A</#{tag}>\s*(.*)}, last_line) do
nil -> tag_tpl |> Tuple.append(Enum.reverse([last_line|lines]))
[_, ""] -> tag_tpl |> Tuple.append(Enum.reverse(lines))
[_, suffix] -> [tag_tpl |> Tuple.append(Enum.reverse(lines)), suffix]
nil -> tag_tpl |> Tuple.append(Enum.reverse([last_line|lines])) |> Tuple.append(@verbatim)
[_, ""] -> tag_tpl |> Tuple.append(Enum.reverse(lines)) |> Tuple.append(@verbatim)
[_, suffix] -> [tag_tpl |> Tuple.append(Enum.reverse(lines)) |> Tuple.append(@verbatim), suffix]
end
end
defp _parse_rest([inner_line|rest], tag_tpl, lines) do
Expand Down
46 changes: 32 additions & 14 deletions lib/earmark/transform.ex
Original file line number Diff line number Diff line change
Expand Up @@ -41,51 +41,69 @@ defmodule Earmark.Transform do
_to_html(ast, options, Map.get(options, :initial_indent, 0)) |> IO.iodata_to_binary
end

defp _to_html(ast, options, level)
defp _to_html(elements, options, level) when is_list(elements) do
defp _to_html(ast, options, level, verbatim \\ false)
defp _to_html(elements, options, level, verbatim) when is_list(elements) do
elements
|> Enum.map(&_to_html(&1, options, level))
|> Enum.map(&_to_html(&1, options, level, verbatim))
end
defp _to_html(element, options, level) when is_binary(element) do
defp _to_html(element, options, level, false) when is_binary(element) do
escape(element, options, level)
end
defp _to_html(element, options, level, true) when is_binary(element) do
[make_indent(options, level), element]
end
# Void tags: `area`, `br`, `hr`, `img`, and `wbr` are rendered slightly differently
defp _to_html({"area", _, _}=tag, options, level), do: void_tag(tag, options, level)
defp _to_html({"br", _, _}=tag, options, level), do: void_tag(tag, options, level)
defp _to_html({"hr", _, _}=tag, options, level), do: void_tag(tag, options, level)
defp _to_html({"img", _, _}=tag, options, level), do: void_tag(tag, options, level)
defp _to_html({"wbr", _, _}=tag, options, level), do: void_tag(tag, options, level)
defp _to_html({:comment, _, children}, options, level) do
defp _to_html({"area", _, _}=tag, options, level, _verbatim), do: void_tag(tag, options, level)
defp _to_html({"br", _, _}=tag, options, level, _verbatim), do: void_tag(tag, options, level)
defp _to_html({"hr", _, _}=tag, options, level, _verbatim), do: void_tag(tag, options, level)
defp _to_html({"img", _, _}=tag, options, level, _verbatim), do: void_tag(tag, options, level)
defp _to_html({"wbr", _, _}=tag, options, level, _verbatim), do: void_tag(tag, options, level)
defp _to_html({:comment, _, children}, options, level, _verbatim) do
indent = make_indent(options, level)
[ indent,
"<!--", Enum.intersperse(children, ["\n", indent, " "]), "-->"]
end
defp _to_html({tag, atts, []}, options, level) do
defp _to_html({tag, atts, []}, options, level, _verbatim) do
[ make_indent(options, level),
open_tag(tag, atts),
"</",
tag,
">\n" ]
end
defp _to_html({"code", atts, children}, options, level) do
defp _to_html({"code", atts, children}, options, level, _verbatim) do
[ make_indent(options, 0),
open_tag("code", atts),
Enum.join(children, "\n")|>Earmark.Helpers.escape(),
"</code>"]
end
defp _to_html({"pre", atts, children}, options, level) do
defp _to_html({"pre", atts, children}, options, level, _verbatim) do
[ make_indent(options, level),
open_tag("pre", atts),
_to_html(children, options, level),
"</pre>\n"]
end
defp _to_html({tag, atts, children}, options, level) do
defp _to_html({"pre", atts, children, meta}, options, level, _verbatim) do
verbatim = Map.get(meta, :meta, %{}) |> Map.get(:verbatim, false)
[ make_indent(options, level),
open_tag("pre", atts),
_to_html(children, options, level, verbatim),
"</pre>\n"]
end
defp _to_html({tag, atts, children}, options, level, _verbatim) do
[ make_indent(options, level),
open_tag(tag, atts),
"\n",
_to_html(children, options, level+1),
close_tag(tag, options, level)]
end
defp _to_html({tag, atts, children, meta}, options, level, _verbatim) do
verbatim = Map.get(meta, :meta, %{}) |> Map.get(:verbatim, false)
[ make_indent(options, level),
open_tag(tag, atts),
"\n",
_to_html(children, options, level+1, verbatim),
close_tag(tag, options, level)]
end

defp close_tag(tag, options, level) do
[make_indent(options, level), "</", tag, ">\n"]
Expand Down
26 changes: 14 additions & 12 deletions test/acceptance/ast/html_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ defmodule Acceptance.Ast.HtmlBlocksTest do

@moduletag :ast

@verbatim %{meta: %{verbatim: true}}

describe "HTML blocks" do
test "tables are just tables again (or was that mountains?)" do
markdown = "<table>\n <tr>\n <td>\n hi\n </td>\n </tr>\n</table>\n\nokay.\n"
ast = [
{"table", [], [" <tr>", " <td>", " hi", " </td>", " </tr>"]},
{"table", [], [" <tr>", " <td>", " hi", " </td>", " </tr>"], @verbatim},
{"p", [], ["okay."]}]
messages = []

Expand All @@ -18,23 +20,23 @@ defmodule Acceptance.Ast.HtmlBlocksTest do

test "div (ine?)" do
markdown = "<div>\n *hello*\n <foo><a>\n</div>\n"
ast = [{"div", [], [" *hello*", " <foo><a>"]}]
ast = [{"div", [], [" *hello*", " <foo><a>"], @verbatim}]
messages = []

assert as_ast(markdown) == {:ok, ast, messages}
end

test "we are leaving html alone" do
markdown = "<div>\n*Emphasized* text.\n</div>"
ast = [{"div", [], ["*Emphasized* text."]}]
ast = [{"div", [], ["*Emphasized* text."], @verbatim}]
messages = []

assert as_ast(markdown) == {:ok, ast, messages}
end

test "even block elements" do
markdown = "<div>\n```elixir\ndefmodule Mine do\n```\n</div>"
ast = [{"div", [], ["```elixir", "defmodule Mine do", "```"]}]
ast = [{"div", [], ["```elixir", "defmodule Mine do", "```"], @verbatim}]
messages = []

assert as_ast(markdown) == {:ok, ast, messages}
Expand Down Expand Up @@ -190,57 +192,57 @@ defmodule Acceptance.Ast.HtmlBlocksTest do
describe "multiple tags in closing line" do
test "FTF" do
markdown = "<div class=\"my-div\">\nline\n</div>"
ast = [{"div", [{"class", "my-div"}], ["line"]}]
ast = [{"div", [{"class", "my-div"}], ["line"], @verbatim}]
messages = []

assert as_ast(markdown) == {:ok, ast, messages}
end
test "this is not closing" do
markdown = "<div>\nline\n</hello></div>"
ast = [{"div", [], ["line", "</hello></div>"]}]
ast = [{"div", [], ["line", "</hello></div>"], @verbatim}]
messages = [{:warning, 1, "Failed to find closing <div>"}]

assert as_ast(markdown) == {:error, ast, messages}
end
test "therefore the div continues" do
markdown = "<div>\nline\n</hello></div>\n</div>"
ast = [{"div", [], ["line", "</hello></div>"]}]
ast = [{"div", [], ["line", "</hello></div>"], @verbatim}]
messages = []

assert as_ast(markdown) == {:ok, ast, messages}
end
test "...nor is this" do
markdown = "<div>\nline\n<hello></div>"
ast = [{"div", [], ["line", "<hello></div>"]}]
ast = [{"div", [], ["line", "<hello></div>"], @verbatim}]
messages = [{:warning, 1, "Failed to find closing <div>"},
{:warning, 3, "Failed to find closing <hello>"}]

assert as_ast(markdown) == {:error, ast, messages}
end
test "however, this closes and keeps the garbage" do
markdown = "<div>\nline\n</div><hello>"
ast = [{"div", [], ["line"]}, "<hello>"]
ast = [{"div", [], ["line"], @verbatim}, "<hello>"]
messages = []

assert as_ast(markdown) == {:ok, ast, messages}
end
test "however, this closes and keeps **whatever** garbage" do
markdown = "<div>\nline\n</div> `garbage`"
ast = [{"div", [], ["line"]}, "`garbage`"]
ast = [{"div", [], ["line"], @verbatim}, "`garbage`"]
messages = []

assert as_ast(markdown) == {:ok, ast, messages}
end
test "however, this closes and keeps not even warnings" do
markdown = "<div>\nline\n</div> `garbage"
ast = [{"div", [], ["line"]}, "`garbage"]
ast = [{"div", [], ["line"], @verbatim}, "`garbage"]
messages = []

assert as_ast(markdown) == {:ok, ast, messages}
end
test "however, this closes and kept garbage is not even inline formatted" do
markdown = "<div>\nline\n</div> _garbage_"
ast = [{"div", [], ["line"]}, "_garbage_"]
ast = [{"div", [], ["line"], @verbatim}, "_garbage_"]
messages = []

assert as_ast(markdown) == {:ok, ast, messages}
Expand Down
22 changes: 3 additions & 19 deletions test/acceptance/html1/html_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,25 @@ defmodule Acceptance.Html1.Html1BlocksTest do
@moduletag :html1

describe "HTML blocks" do
@tag :wip
test "tables are just tables again (or was that mountains?)" do
markdown = "<table>\n <tr>\n <td>\n hi\n </td>\n </tr>\n</table>\n\nokay.\n"
html = construct([
{:table, nil, {:tr, nil, {:td, nil, " hi"}}},
{:p, nil, "okay."} ])
html = "<table>\n <tr> <td> hi </td> </tr></table>\n<p>\n okay.\n</p>\n"
messages = []

assert to_html1(markdown) == {:ok, html, messages}
end

test "div (ine?)" do
markdown = "<div>\n *hello*\n <foo><a>\n</div>\n"
html = construct({:div, nil, [" *hello*", " &lt;foo&gt;&lt;a&gt;"]})

html = "<div>\n *hello* <foo><a></div>\n"
messages = []

assert to_html1(markdown) == {:ok, html, messages}
end

test "we are leaving html alone" do
markdown = "<div>\n*Emphasized* text.\n</div>"
html = construct({:div, nil, "*Emphasized* text."})
html ="<div>\n *Emphasized* text.</div>\n"
messages = []

assert to_html1(markdown) == {:ok, html, messages}
Expand Down Expand Up @@ -159,18 +155,6 @@ defmodule Acceptance.Html1.Html1BlocksTest do
assert to_html1(markdown) == {:ok, html, messages}
end

@tag :wip
test "block elements close para" do
markdown = "alpha\n<div></div>beta"
html = construct([
{:p, nil, "alpha"},
"<div></div>beta"
])
messages = []

assert to_html1(markdown) == {:ok, html, messages}
end

test "block elements close para, atts do not matter" do
markdown = "alpha\n<div class=\"first\"></div>beta"
html = "<p>alpha</p>\n<div class=\"first\"></div>beta"
Expand Down

0 comments on commit 6abcf1c

Please sign in to comment.