diff --git a/lib/earmark.ex b/lib/earmark.ex index e726fc25..1b0f2c1c 100644 --- a/lib/earmark.ex +++ b/lib/earmark.ex @@ -260,8 +260,8 @@ defmodule Earmark do `iex` usage. """ def version() do - with {:ok, version} = :application.get_key(:earmark, :vsn), - do: to_string(version) + with {:ok, version} <- :application.get_key(:earmark, :vsn), + do: to_string(version) end defp _as_ast(lines, options) diff --git a/lib/earmark/cli/implementation.ex b/lib/earmark/cli/implementation.ex index 36fe79d7..9ce59372 100644 --- a/lib/earmark/cli/implementation.ex +++ b/lib/earmark/cli/implementation.ex @@ -120,7 +120,7 @@ defmodule Earmark.Cli.Implementation do end defp _format_errors(errors) do - "Illegal options #{errors |> Enum.map(fn {option, _} -> option end) |> Enum.join(", ")}" + "Illegal options #{errors |> Enum.map_join(", ", fn {option, _} -> option end)}" end defp _maybe_to_html!(output, %{file: nil}), do: Earmark.Internal.as_html!(output) @@ -186,8 +186,7 @@ defmodule Earmark.Cli.Implementation do defp _option_related_help do @cli_options - |> Enum.map(&_specific_option_help/1) - |> Enum.join("\n") + |> Enum.map_join("\n", &_specific_option_help/1) end defp _specific_option_help(option) do diff --git a/lib/earmark_parser.ex b/lib/earmark_parser.ex index ce3f7c72..149ec95e 100644 --- a/lib/earmark_parser.ex +++ b/lib/earmark_parser.ex @@ -614,7 +614,7 @@ defmodule Earmark.Parser do end def as_ast(_, options) do - raise ArgumentError, "#{inspect options} not a legal options map or keyword list" + raise ArgumentError, "#{inspect(options)} not a legal options map or keyword list" end defp _as_ast(lines, options) do @@ -627,8 +627,8 @@ defmodule Earmark.Parser do `iex` usage. """ def version() do - with {:ok, version} = :application.get_key(:earmark_parser, :vsn), - do: to_string(version) + with {:ok, version} <- :application.get_key(:earmark_parser, :vsn), + do: to_string(version) end end diff --git a/lib/earmark_parser/helpers/ast_helpers.ex b/lib/earmark_parser/helpers/ast_helpers.ex index 3f5f48f6..7c17a4d2 100644 --- a/lib/earmark_parser/helpers/ast_helpers.ex +++ b/lib/earmark_parser/helpers/ast_helpers.ex @@ -1,5 +1,4 @@ defmodule Earmark.Parser.Helpers.AstHelpers do - @moduledoc false import Earmark.Parser.Ast.Emitter @@ -10,27 +9,33 @@ defmodule Earmark.Parser.Helpers.AstHelpers do @doc false def annotate(node, from_block) def annotate(node, %{annotation: nil}), do: node + def annotate({tag, atts, children, meta}, %{annotation: annotation}), do: {tag, atts, children, Map.put(meta, :annotation, annotation)} + def annotate({tag, atts, children, meta}, annotation), do: {tag, atts, children, Map.put(meta, :annotation, annotation)} @doc false def attrs_to_string_keys(key_value_pair) + def attrs_to_string_keys({k, vs}) when is_list(vs) do {to_string(k), Enum.join(vs, " ")} end + def attrs_to_string_keys({k, vs}) do - {to_string(k),to_string(vs)} + {to_string(k), to_string(vs)} end @doc false def augment_tag_with_ial(tags, ial) - def augment_tag_with_ial([{t, a, c, m}|tags], atts) do - [{t, merge_attrs(a, atts), c, m}|tags] + + def augment_tag_with_ial([{t, a, c, m} | tags], atts) do + [{t, merge_attrs(a, atts), c, m} | tags] end + def augment_tag_with_ial([], _atts) do - [] + [] end @doc false @@ -38,17 +43,23 @@ defmodule Earmark.Parser.Helpers.AstHelpers do classes = ["" | String.split(prefix || "")] |> Enum.map(fn pfx -> "#{pfx}#{language}" end) - {"class", classes |> Enum.join(" ")} + + {"class", classes |> Enum.join(" ")} end @doc false - def codespan(text) do + def codespan(text) do emit("code", text, class: "inline") end @doc false def render_footnote_link(ref, backref, number) do - emit("a", to_string(number), href: "##{ref}", id: backref, class: "footnote", title: "see footnote") + emit("a", to_string(number), + href: "##{ref}", + id: backref, + class: "footnote", + title: "see footnote" + ) end @doc false @@ -73,19 +84,17 @@ defmodule Earmark.Parser.Helpers.AstHelpers do emit("a", text, href: _encode(url)) end - ############################################## # add attributes to the outer tag in a block # ############################################## - @verbatims ~r<%[\da-f]{2}>i defp _encode(url) do url |> String.split(@verbatims, include_captures: true) |> Enum.chunk_every(2) |> Enum.map(&_encode_chunk/1) - |> IO.chardata_to_string + |> IO.chardata_to_string() end defp _encode_chunk([encodable, verbatim]), do: [URI.encode(encodable), verbatim] @@ -94,6 +103,7 @@ defmodule Earmark.Parser.Helpers.AstHelpers do @doc false def merge_attrs(maybe_atts, new_atts) def merge_attrs(nil, new_atts), do: new_atts + def merge_attrs(atts, new) when is_list(atts) do atts |> Enum.into(%{}) @@ -108,13 +118,14 @@ defmodule Earmark.Parser.Helpers.AstHelpers do end defp _value_merger(key, val1, val2) + defp _value_merger(_, val1, val2) when is_list(val1) do val1 ++ [val2] end + defp _value_merger(_, val1, val2) do [val1, val2] end - - end + # SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/helpers/leex_helpers.ex b/lib/earmark_parser/helpers/leex_helpers.ex index 61d8dd75..9afefba3 100644 --- a/lib/earmark_parser/helpers/leex_helpers.ex +++ b/lib/earmark_parser/helpers/leex_helpers.ex @@ -1,31 +1,32 @@ defmodule Earmark.Parser.Helpers.LeexHelpers do - @moduledoc false @doc """ Allows to lex an Elixir string with a leex lexer and returns the tokens as needed for a yecc parser. """ - def lex text, with: lexer do + def lex(text, with: lexer) do case text - |> String.to_charlist() - |> lexer.string() do - {:ok, tokens, _} -> tokens - end + |> String.to_charlist() + |> lexer.string() do + {:ok, tokens, _} -> tokens + end end - def tokenize line, with: lexer do + def tokenize(line, with: lexer) do {:ok, tokens, _} = - line - |> to_charlist() - |> lexer.string() - elixirize_tokens(tokens,[]) + line + |> to_charlist() + |> lexer.string() + + elixirize_tokens(tokens, []) |> Enum.reverse() end defp elixirize_tokens(tokens, rest) defp elixirize_tokens([], result), do: result - defp elixirize_tokens([{token, _, text}|rest], result), do: elixirize_tokens(rest, [{token,to_string(text)}|result]) + defp elixirize_tokens([{token, _, text} | rest], result), + do: elixirize_tokens(rest, [{token, to_string(text)} | result]) end # SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/helpers/pure_link_helpers.ex b/lib/earmark_parser/helpers/pure_link_helpers.ex index 9a471260..fdd595b1 100644 --- a/lib/earmark_parser/helpers/pure_link_helpers.ex +++ b/lib/earmark_parser/helpers/pure_link_helpers.ex @@ -74,7 +74,7 @@ defmodule Earmark.Parser.Helpers.PureLinkHelpers do end end - defp balance_parens(<<_::utf8,rest::binary>>, trailing_paren_count, non_trailing_count) do + defp balance_parens(<<_::utf8, rest::binary>>, trailing_paren_count, non_trailing_count) do balance_parens(rest, trailing_paren_count, non_trailing_count) end end diff --git a/lib/earmark_parser/line_scanner.ex b/lib/earmark_parser/line_scanner.ex index 67cf0de7..b5e898c1 100644 --- a/lib/earmark_parser/line_scanner.ex +++ b/lib/earmark_parser/line_scanner.ex @@ -51,13 +51,14 @@ defmodule Earmark.Parser.LineScanner do when is_boolean(recursive), do: type_of(line, %Options{}, recursive) - def type_of({line, lnb}, options = %Options{annotations: annotations}, recursive) when is_binary(line) do + def type_of({line, lnb}, options = %Options{annotations: annotations}, recursive) + when is_binary(line) do {line1, annotation} = line |> Helpers.expand_tabs() |> Helpers.remove_line_ending(annotations) %{_type_of(line1, options, recursive) | annotation: annotation, lnb: lnb} end def type_of({line, lnb}, _, _) do - raise ArgumentError, "line number #{lnb} #{inspect line} is not a binary" + raise ArgumentError, "line number #{lnb} #{inspect(line)} is not a binary" end defp _type_of(line, options = %Options{}, recursive) do @@ -84,7 +85,7 @@ defmodule Earmark.Parser.LineScanner do lt_four? && Regex.run(~r/\A (?:_\s?){3,} \z/x, content) -> %Line.Ruler{type: "_", indent: indent, line: line} - match = Regex.run(~R/^(#{1,6})\s+(?|(.*?)\s*#*\s*$|(.*))/u, stripped_line) -> + match = Regex.run(~r/^(\#{1,6})\s+(?|(.*?)\s*#*\s*$|(.*))/u, stripped_line) -> [_, level, heading] = match %Line.Heading{ @@ -144,7 +145,7 @@ defmodule Earmark.Parser.LineScanner do match = lt_four? && Regex.run(@id_re, content) -> [_, id, url | title] = match - title = if(length(title) == 0, do: "", else: hd(title)) + title = if(Enum.empty?(title), do: "", else: hd(title)) %Line.IdDef{id: id, url: url, title: title, indent: indent, line: line} match = options.footnotes && Regex.run(~r/\A\[\^([^\s\]]+)\]:\s+(.*)/, line) -> @@ -184,7 +185,9 @@ defmodule Earmark.Parser.LineScanner do line: line } - line |> String.replace(~r/\[\[ .*? \]\]/x, "") |> String.match?(~r/\A (\s*) .* \s \| \s /x) -> + line + |> String.replace(~r/\[\[ .*? \]\]/x, "") + |> String.match?(~r/\A (\s*) .* \s \| \s /x) -> columns = _split_table_columns(line) %Line.TableLine{ @@ -195,7 +198,8 @@ defmodule Earmark.Parser.LineScanner do line: line } - options.gfm_tables && line |> String.replace(~r/\[\[ .*? \]\]/x, "") |> String.match?(~r/\A (\s*) .* \| /x) -> + options.gfm_tables && + line |> String.replace(~r/\[\[ .*? \]\]/x, "") |> String.match?(~r/\A (\s*) .* \| /x) -> columns = _split_table_columns(line) %Line.TableLine{ diff --git a/lib/earmark_parser/parser/link_parser.ex b/lib/earmark_parser/parser/link_parser.ex index d979ebd5..0a4f426b 100644 --- a/lib/earmark_parser/parser/link_parser.ex +++ b/lib/earmark_parser/parser/link_parser.ex @@ -84,7 +84,7 @@ defmodule Earmark.Parser.Parser.LinkParser do defp url(_, _, _, _), do: nil defp bail_out_to_title(ts, result) do - with remaining_text <- ts |> Enum.map(&text_of_token/1) |> Enum.join("") do + with remaining_text <- ts |> Enum.map_join("", &text_of_token/1) do case title(remaining_text) do nil -> nil diff --git a/lib/earmark_parser/parser/list_parser.ex b/lib/earmark_parser/parser/list_parser.ex index e1b48532..c58ff27d 100644 --- a/lib/earmark_parser/parser/list_parser.ex +++ b/lib/earmark_parser/parser/list_parser.ex @@ -12,111 +12,163 @@ defmodule Earmark.Parser.Parser.ListParser do def parse_list(lines, result, options \\ %Options{}) do {items, rest, options1} = _parse_list_items_init(lines, [], options) - list = _make_list(items, _empty_list(items) ) - {[list|result], rest, options1} + list = _make_list(items, _empty_list(items)) + {[list | result], rest, options1} end - defp _parse_list_items_init([item|rest], list_items, options) do - options1 = %{options|line: item.lnb} - _parse_list_items_start(rest, _make_and_prepend_list_item(item, list_items), new(item, options1)) + defp _parse_list_items_init([item | rest], list_items, options) do + options1 = %{options | line: item.lnb} + + _parse_list_items_start( + rest, + _make_and_prepend_list_item(item, list_items), + new(item, options1) + ) end defp _parse_list_items_spaced(input, items, list_info) - defp _parse_list_items_spaced(input, items, %{pending: @not_pending}=list_info) do + + defp _parse_list_items_spaced(input, items, %{pending: @not_pending} = list_info) do _parse_list_items_spaced_np(input, items, list_info) end + defp _parse_list_items_spaced(input, items, list_info) do _parse_list_items_spaced_pdg(input, items, list_info) end - defp _parse_list_items_spaced_np([%Line.Blank{}|rest], items, list_info) do - list_info1 = %{list_info|lines: [""|list_info.lines], options: %{list_info.options|line: list_info.options.line + 1}} + defp _parse_list_items_spaced_np([%Line.Blank{} | rest], items, list_info) do + list_info1 = %{ + list_info + | lines: ["" | list_info.lines], + options: %{list_info.options | line: list_info.options.line + 1} + } + _parse_list_items_spaced_np(rest, items, list_info1) end - defp _parse_list_items_spaced_np([%Line.Ruler{}|_]=lines, items, list_info) do + + defp _parse_list_items_spaced_np([%Line.Ruler{} | _] = lines, items, list_info) do _finish_list_items(lines, items, false, list_info) end - defp _parse_list_items_spaced_np([%Line.ListItem{indent: ii}=item|_]=input, list_items, %{width: w}=list_info) - when ii < w do - if _starts_list?(item, list_items) do - _finish_list_items(input, list_items, false, list_info) - else - {items1, options1} = _finish_list_item(list_items, false, _loose(list_info)) - _parse_list_items_init(input, items1, options1) - end - end - defp _parse_list_items_spaced_np([%Line.Indent{indent: ii}=item|rest], list_items, %{width: w}=list_info) - when ii >= w do - indented = _behead_spaces(item.line, w) - _parse_list_items_spaced(rest, list_items, update_list_info(list_info, indented, item, true)) - end - defp _parse_list_items_spaced_np([%Line.ListItem{}=line|rest], items, list_info) do + + defp _parse_list_items_spaced_np( + [%Line.ListItem{indent: ii} = item | _] = input, + list_items, + %{width: w} = list_info + ) + when ii < w do + if _starts_list?(item, list_items) do + _finish_list_items(input, list_items, false, list_info) + else + {items1, options1} = _finish_list_item(list_items, false, _loose(list_info)) + _parse_list_items_init(input, items1, options1) + end + end + + defp _parse_list_items_spaced_np( + [%Line.Indent{indent: ii} = item | rest], + list_items, + %{width: w} = list_info + ) + when ii >= w do + indented = _behead_spaces(item.line, w) + _parse_list_items_spaced(rest, list_items, update_list_info(list_info, indented, item, true)) + end + + defp _parse_list_items_spaced_np([%Line.ListItem{} = line | rest], items, list_info) do indented = _behead_spaces(line.line, list_info.width) _parse_list_items_start(rest, items, update_list_info(list_info, indented, line)) end + # BUG: Still do not know how much to indent here??? - defp _parse_list_items_spaced_np([%{indent: indent, line: str_line}=line|rest], items, %{width: width}=list_info) when - indent >= width - do - _parse_list_items_spaced(rest, items, update_list_info(list_info, behead(str_line, width), line, true)) + defp _parse_list_items_spaced_np( + [%{indent: indent, line: str_line} = line | rest], + items, + %{width: width} = list_info + ) + when indent >= width do + _parse_list_items_spaced( + rest, + items, + update_list_info(list_info, behead(str_line, width), line, true) + ) end + defp _parse_list_items_spaced_np(input, items, list_info) do - _finish_list_items(input ,items, false, list_info) + _finish_list_items(input, items, false, list_info) end defp _parse_list_items_spaced_pdg(input, items, list_info) - defp _parse_list_items_spaced_pdg([], items, %{pending: {pending, lnb}}=list_info) do + + defp _parse_list_items_spaced_pdg([], items, %{pending: {pending, lnb}} = list_info) do options1 = - add_message(list_info.options, {:warning, lnb, "Closing unclosed backquotes #{pending} at end of input"}) - _finish_list_items([], items, false, %{list_info| options: options1}) + add_message( + list_info.options, + {:warning, lnb, "Closing unclosed backquotes #{pending} at end of input"} + ) + + _finish_list_items([], items, false, %{list_info | options: options1}) end - defp _parse_list_items_spaced_pdg([line|rest], items, list_info) do + + defp _parse_list_items_spaced_pdg([line | rest], items, list_info) do indented = _behead_spaces(line.line, list_info.width) _parse_list_items_spaced(rest, items, update_list_info(list_info, indented, line, true)) end - defp _parse_list_items_start(input, list_items, list_info) - defp _parse_list_items_start(input, list_items, %{pending: @not_pending}=list_info) do + + defp _parse_list_items_start(input, list_items, %{pending: @not_pending} = list_info) do _parse_list_items_start_np(input, list_items, list_info) end + defp _parse_list_items_start(input, list_items, list_info) do _parse_list_items_start_pdg(input, list_items, list_info) end defp _parse_list_items_start_np(input, list_items, list_info) - defp _parse_list_items_start_np([%Line.Blank{}|input], items, list_info) do + + defp _parse_list_items_start_np([%Line.Blank{} | input], items, list_info) do _parse_list_items_spaced(input, items, prepend_line(list_info, "")) end + defp _parse_list_items_start_np([], list_items, list_info) do _finish_list_items([], list_items, true, list_info) end - defp _parse_list_items_start_np([%Line.Ruler{}|_]=input, list_items, list_info) do + + defp _parse_list_items_start_np([%Line.Ruler{} | _] = input, list_items, list_info) do _finish_list_items(input, list_items, true, list_info) end - defp _parse_list_items_start_np([%Line.Heading{}|_]=input, list_items, list_info) do + + defp _parse_list_items_start_np([%Line.Heading{} | _] = input, list_items, list_info) do _finish_list_items(input, list_items, true, list_info) end - defp _parse_list_items_start_np([%Line.ListItem{indent: ii}=item|_]=input, list_items, %{width: w}=list_info) - when ii < w do - if _starts_list?(item, list_items) do - _finish_list_items(input, list_items, true, list_info) - else - {items1, options1} = _finish_list_item(list_items, true, list_info) - _parse_list_items_init(input, items1, options1) - end + + defp _parse_list_items_start_np( + [%Line.ListItem{indent: ii} = item | _] = input, + list_items, + %{width: w} = list_info + ) + when ii < w do + if _starts_list?(item, list_items) do + _finish_list_items(input, list_items, true, list_info) + else + {items1, options1} = _finish_list_item(list_items, true, list_info) + _parse_list_items_init(input, items1, options1) + end end + # Slurp in everything else before a first blank line - defp _parse_list_items_start_np([%{line: str_line}=line|rest], items, list_info) do + defp _parse_list_items_start_np([%{line: str_line} = line | rest], items, list_info) do indented = _behead_spaces(str_line, list_info.width) _parse_list_items_start(rest, items, update_list_info(list_info, indented, line)) end defp _parse_list_items_start_pdg(input, items, list_info) + defp _parse_list_items_start_pdg([], items, list_info) do _finish_list_items([], items, true, list_info) end - defp _parse_list_items_start_pdg([%{line: str_line}=line|rest], items, list_info) do + + defp _parse_list_items_start_pdg([%{line: str_line} = line | rest], items, list_info) do indented = _behead_spaces(str_line, list_info.width) _parse_list_items_start(rest, items, update_list_info(list_info, indented, line)) end @@ -126,7 +178,7 @@ defmodule Earmark.Parser.Parser.ListParser do end # INLINE CANDIDATE - defp _empty_list([%Block.ListItem{loose?: loose?, type: type}|_]) do + defp _empty_list([%Block.ListItem{loose?: loose?, type: type} | _]) do %Block.List{loose?: loose?, type: type} end @@ -139,12 +191,14 @@ defmodule Earmark.Parser.Parser.ListParser do end end - defp _finish_list_item([%Block.ListItem{}=item|items], _at_start?, list_info) do - {blocks, _, _, options1} = list_info.lines - |> Enum.reverse - |> Earmark.Parser.Parser.parse(%{list_info.options|line: item.lnb}, :list) + defp _finish_list_item([%Block.ListItem{} = item | items], _at_start?, list_info) do + {blocks, _, _, options1} = + list_info.lines + |> Enum.reverse() + |> Earmark.Parser.Parser.parse(%{list_info.options | line: item.lnb}, :list) + loose1? = _already_loose?(items) || list_info.loose? - {[%{item | blocks: blocks, loose?: loose1?}|items], options1} + {[%{item | blocks: blocks, loose?: loose1?} | items], options1} end defp _finish_list_items(input, items, at_start?, list_info) do @@ -152,30 +206,41 @@ defmodule Earmark.Parser.Parser.ListParser do {items1, input, options1} end - defp _make_and_prepend_list_item(%Line.ListItem{bullet: bullet, lnb: lnb, type: type}, list_items) do - [%Block.ListItem{bullet: bullet, lnb: lnb, spaced?: false, type: type}|list_items] + defp _make_and_prepend_list_item( + %Line.ListItem{bullet: bullet, lnb: lnb, type: type}, + list_items + ) do + [%Block.ListItem{bullet: bullet, lnb: lnb, spaced?: false, type: type} | list_items] end defp _make_list(items, list) - defp _make_list([%Block.ListItem{bullet: bullet, lnb: lnb}=item], %Block.List{loose?: loose?}=list) do - %{list | blocks: [%{item | loose?: loose?}|list.blocks], - bullet: bullet, - lnb: lnb, - start: _extract_start(item)} + + defp _make_list( + [%Block.ListItem{bullet: bullet, lnb: lnb} = item], + %Block.List{loose?: loose?} = list + ) do + %{ + list + | blocks: [%{item | loose?: loose?} | list.blocks], + bullet: bullet, + lnb: lnb, + start: _extract_start(item) + } end - defp _make_list([%Block.ListItem{}=item|rest], %Block.List{loose?: loose?}=list) do - _make_list(rest, %{list | blocks: [%{item | loose?: loose?}|list.blocks]}) + + defp _make_list([%Block.ListItem{} = item | rest], %Block.List{loose?: loose?} = list) do + _make_list(rest, %{list | blocks: [%{item | loose?: loose?} | list.blocks]}) end defp _already_loose?(items) defp _already_loose?([]), do: false - defp _already_loose?([%{loose?: loose?}|_]), do: loose? + defp _already_loose?([%{loose?: loose?} | _]), do: loose? - defp _loose(list_info), do: %{list_info|loose?: true} + defp _loose(list_info), do: %{list_info | loose?: true} - defp _starts_list?(%{bullet: bullet1}, [%Block.ListItem{bullet: bullet2}|_]) do + defp _starts_list?(%{bullet: bullet1}, [%Block.ListItem{bullet: bullet2} | _]) do String.last(bullet1) != String.last(bullet2) end - end + # SPDX-License-Identifier: Apache-2.0 diff --git a/test/acceptance/earmark/postprocessor/replace_subtree_test.exs b/test/acceptance/earmark/postprocessor/replace_subtree_test.exs index 043160f0..3fda665b 100644 --- a/test/acceptance/earmark/postprocessor/replace_subtree_test.exs +++ b/test/acceptance/earmark/postprocessor/replace_subtree_test.exs @@ -48,10 +48,12 @@ defmodule Test.Acceptance.Earmark.Postprocessor.ReplaceSubtreeTest do defp render_code_node({"code", attrs, _content, meta} = node) do classes = Earmark.AstTools.find_att_in_node(node, "class") || "" - cond do - classes =~ "inline" -> node - true -> {:replace, {"code", attrs, "xxx", meta}} + if classes =~ "inline" do + node + else + {:replace, {"code", attrs, "xxx", meta}} end end end + # SPDX-License-Identifier: Apache-2.0 diff --git a/test/acceptance/transform/map_ast_with_fnchange_test.exs b/test/acceptance/transform/map_ast_with_fnchange_test.exs index 30a72d02..d5cd60dd 100644 --- a/test/acceptance/transform/map_ast_with_fnchange_test.exs +++ b/test/acceptance/transform/map_ast_with_fnchange_test.exs @@ -7,12 +7,21 @@ defmodule Test.Acceptance.Transform.MapAstWithFnchangeTest do describe "change #elixir" do @elixir_home {"a", [{"href", "https://elixir-lang.org"}], ["Elixir"], %{}} @original [ - {"p", [],[ "#elixir"], %{}}, {"bold", [],[ "#elixir"], %{}}, - {"ol", [], [{"li", [],[ "#elixir"], %{}}, {"p", [],[ "elixir"], %{}}, {"p", [], ["#elixir"], %{}}], %{}} + {"p", [], ["#elixir"], %{}}, + {"bold", [], ["#elixir"], %{}}, + {"ol", [], + [{"li", [], ["#elixir"], %{}}, {"p", [], ["elixir"], %{}}, {"p", [], ["#elixir"], %{}}], + %{}} ] @expected [ - {"p", [],[{"a", [{"href", "https://elixir-lang.org"}], ["Elixir"], %{}}], %{}}, {"bold", [],[ "#elixir"], %{}}, - {"ol", [], [{"li", [],[ "#elixir"], %{}}, {"p", [],[ "elixir"], %{}}, {"p", [], [{"a", [{"href", "https://elixir-lang.org"}], ["Elixir"], %{}}], %{}}], %{}} + {"p", [], [{"a", [{"href", "https://elixir-lang.org"}], ["Elixir"], %{}}], %{}}, + {"bold", [], ["#elixir"], %{}}, + {"ol", [], + [ + {"li", [], ["#elixir"], %{}}, + {"p", [], ["elixir"], %{}}, + {"p", [], [{"a", [{"href", "https://elixir-lang.org"}], ["Elixir"], %{}}], %{}} + ], %{}} ] test "transform with function change" do @@ -25,10 +34,13 @@ defmodule Test.Acceptance.Transform.MapAstWithFnchangeTest do expected = [p(@elixir_home), p("hello")] assert map_ast(ast, &main_traverser/1) == expected end + defp main_traverser(element) - defp main_traverser({"p", _, _, _}=para) do + + defp main_traverser({"p", _, _, _} = para) do {&replacer/1, para} end + defp main_traverser(element), do: element defp replacer(element) @@ -37,4 +49,5 @@ defmodule Test.Acceptance.Transform.MapAstWithFnchangeTest do defp replacer(element), do: {&main_traverser/1, element} end end + # SPDX-License-Identifier: Apache-2.0 diff --git a/test/support/gen_html.ex b/test/support/gen_html.ex index 868d7d9a..e8de2f46 100644 --- a/test/support/gen_html.ex +++ b/test/support/gen_html.ex @@ -1,5 +1,4 @@ defmodule Support.GenHtml do - @increment 2 def img(atts), do: para({:img, atts, nil}) @@ -7,7 +6,7 @@ defmodule Support.GenHtml do def gen(list) do list |> _gen(0) - |> IO.iodata_to_binary + |> IO.iodata_to_binary() end def link(children, atts \\ []) do @@ -17,38 +16,39 @@ defmodule Support.GenHtml do def para(elements), do: gen({:p, elements}) defp _gen(input, level) + defp _gen(elements, level) when is_list(elements) do elements |> Enum.map(&_gen1(&1, level)) end + defp _gen(element, level), do: _gen1(element, level) defp _gen1(element, level) defp _gen1(string, level) when is_binary(string), do: _indent(string, level) defp _gen1(symbol, level) when is_atom(symbol), do: _indent("<#{symbol} />", level) defp _gen1({symbol, children}, level), do: _gen1({symbol, [], children}, level) + defp _gen1({symbol, atts, nil}, level) do _indent("<#{symbol}#{_mk_atts(atts)} />", level) end + defp _gen1({symbol, atts, []}, level) do _indent("<#{symbol}#{_mk_atts(atts)}>", level) end + defp _gen1({symbol, atts, children}, level) do - [ _indent("<#{symbol}#{_mk_atts(atts)}>", level), + [ + _indent("<#{symbol}#{_mk_atts(atts)}>", level), _gen(children, level + @increment), - _indent("", level) ] + _indent("", level) + ] end defp _indent(string, level), do: "#{String.duplicate(" ", level)}#{string}\n" defp _mk_atts(atts) defp _mk_atts([]), do: "" - defp _mk_atts(atts) do - " " <> (atts - |> Enum.map(&_mk_att/1) - |> Enum.join(" ")) - end - + defp _mk_atts(atts), do: " " <> (atts |> Enum.map_join(" ", &_mk_att/1)) defp _mk_att({key, value}), do: ~s{#{key}="#{value}"} - end