From b77055c6bd81f3e10695c6eff0187cbbedb8cb90 Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Fri, 16 Feb 2024 21:14:24 -0700 Subject: [PATCH 01/25] look_for_alignments/1 Consolidated two Enum.map together; other changes are incidental whitespace formatting --- lib/earmark_parser/parser.ex | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/lib/earmark_parser/parser.ex b/lib/earmark_parser/parser.ex index 727f873..a9957c1 100644 --- a/lib/earmark_parser/parser.ex +++ b/lib/earmark_parser/parser.ex @@ -1,5 +1,4 @@ defmodule EarmarkParser.Parser do - @moduledoc false alias EarmarkParser.{Block, Line, LineScanner, Options} @@ -41,7 +40,7 @@ defmodule EarmarkParser.Parser do end def parse_markdown(lines, _) do - raise ArgumentError, "#{inspect lines} not a binary, nor a list of binaries" + raise ArgumentError, "#{inspect(lines)} not a binary, nor a list of binaries" end def parse(text_lines, options = %Options{}, recursive) do @@ -59,7 +58,6 @@ defmodule EarmarkParser.Parser do {blocks, footnotes, options} = lines |> remove_trailing_blank_lines() |> lines_to_blocks(options, recursive) - links = links_from_blocks(blocks) {blocks, links, footnotes, options} end @@ -268,7 +266,13 @@ defmodule EarmarkParser.Parser do {code_lines, rest} = Enum.split_while(list, &indent_or_blank?/1) code_lines = remove_trailing_blank_lines(code_lines) code = for line <- code_lines, do: properly_indent(line, 1) - _parse([%Line.Blank{}|rest], [%Block.Code{lines: code, lnb: lnb} | result], options, recursive) + + _parse( + [%Line.Blank{} | rest], + [%Block.Code{lines: code, lnb: lnb} | result], + options, + recursive + ) end ############### @@ -447,7 +451,6 @@ defmodule EarmarkParser.Parser do ) end - ####################################################### # Assign attributes that follow a block to that block # ####################################################### @@ -463,10 +466,16 @@ defmodule EarmarkParser.Parser do end defp _check_closing_fence(rest, lnb, delimiter, options) + defp _check_closing_fence([], lnb, delimiter, options) do - {[], add_message(options, {:error, lnb, "Fenced Code Block opened with #{delimiter} not closed at end of input"})} + {[], + add_message( + options, + {:error, lnb, "Fenced Code Block opened with #{delimiter} not closed at end of input"} + )} end - defp _check_closing_fence([_|rest], _lnb, _delimiter, options) do + + defp _check_closing_fence([_ | rest], _lnb, _delimiter, options) do {rest, options} end @@ -523,8 +532,9 @@ defmodule EarmarkParser.Parser do defp look_for_alignments([_first, second | _rest]) do if Enum.all?(second, fn row -> row =~ ~r{^:?-+:?$} end) do second - |> Enum.map(fn row -> Regex.replace(~r/-+/, row, "-") end) |> Enum.map(fn row -> + row = Regex.replace(~r/-+/, row, "-") + case row do ":-:" -> :center ":-" -> :left From d1d337a7d3f6dbcc950f76046448e056a3aee852 Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Fri, 16 Feb 2024 21:18:49 -0700 Subject: [PATCH 02/25] _split_table_columns/1: combined two Enum.map function calls --- lib/earmark_parser/line_scanner.ex | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/earmark_parser/line_scanner.ex b/lib/earmark_parser/line_scanner.ex index 2e85b5a..87e9ce0 100644 --- a/lib/earmark_parser/line_scanner.ex +++ b/lib/earmark_parser/line_scanner.ex @@ -51,13 +51,14 @@ defmodule EarmarkParser.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 @@ -184,7 +185,9 @@ defmodule EarmarkParser.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 EarmarkParser.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{ @@ -303,8 +307,10 @@ defmodule EarmarkParser.LineScanner do defp _split_table_columns(line) do line |> String.split(~r{(? Enum.map(&String.trim/1) - |> Enum.map(fn col -> Regex.replace(~r{\\\|}, col, "|") end) + |> Enum.map(fn col -> + col = String.trim(col) + Regex.replace(~r{\\\|}, col, "|") + end) end end From 47250203e15920335887bebdf3b26315522d4f5e Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Fri, 16 Feb 2024 21:40:59 -0700 Subject: [PATCH 03/25] refactored some conditionals to pattern matching --- lib/earmark_parser/ast_renderer.ex | 61 ++++++++++++++---------------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/lib/earmark_parser/ast_renderer.ex b/lib/earmark_parser/ast_renderer.ex index 8857676..4ab70d3 100644 --- a/lib/earmark_parser/ast_renderer.ex +++ b/lib/earmark_parser/ast_renderer.ex @@ -87,7 +87,8 @@ defmodule EarmarkParser.AstRenderer do emit( "h#{level}", context1.value |> Enum.reverse(), - attrs) + attrs + ) ] end ) @@ -107,32 +108,26 @@ defmodule EarmarkParser.AstRenderer do ######### # Table # ######### + defp render_block( - %Block.Table{lnb: lnb, header: header, rows: rows, alignments: aligns, attrs: attrs}, + %Block.Table{lnb: lnb, header: nil, rows: rows, alignments: aligns, attrs: attrs}, context, _loose? ) do - header_offset = - if header do - 2 # 1 line for header text, 1 line for header separator - else - 0 - end - - {rows_ast, context1} = render_rows(rows, lnb + header_offset, aligns, context) - - {rows_ast1, context2} = - if header do - {header_ast, context3} = render_header(header, lnb, aligns, context1) - {[header_ast | rows_ast], context3} - else - {rows_ast, context1} - end + {rows_ast, context} = render_rows(rows, lnb, aligns, context) + prepend(clear_value(context), emit("table", rows_ast, attrs)) + end - prepend( - clear_value(context2), - emit("table", rows_ast1, attrs) - ) + defp render_block( + %Block.Table{lnb: lnb, header: header, rows: rows, alignments: aligns, attrs: attrs}, + context, + _loose? + ) do + header_offset = 2 + {rows_ast, context} = render_rows(rows, lnb + header_offset, aligns, context) + {header_ast, context} = render_header(header, lnb, aligns, context) + {rows_ast, context} = {[header_ast | rows_ast], context} + prepend(clear_value(context), emit("table", rows_ast, attrs)) end ######## @@ -188,6 +183,7 @@ defmodule EarmarkParser.AstRenderer do _loose? ) do context1 = render(blocks, clear_value(context), loose?) + prepend( context, emit("li", context1.value, attrs), @@ -199,15 +195,16 @@ defmodule EarmarkParser.AstRenderer do # Text # ######## - defp render_block(%Block.Text{line: line, lnb: lnb}, context, loose?) do - context1 = convert(line, lnb, clear_value(context)) - ast = context1.value |> Enum.reverse() + defp render_block(%Block.Text{line: line, lnb: lnb}, context, true = _loose?) do + context = convert(line, lnb, clear_value(context)) + ast = context.value |> Enum.reverse() + modify_value(context, fn _ -> [emit("p", ast)] end) + end - if loose? do - modify_value(context1, fn _ -> [emit("p", ast)] end) - else - modify_value(context1, fn _ -> ast end) - end + defp render_block(%Block.Text{line: line, lnb: lnb}, context, false = _loose?) do + context = convert(line, lnb, clear_value(context)) + ast = context.value |> Enum.reverse() + modify_value(context, fn _ -> ast end) end ################## @@ -215,13 +212,14 @@ defmodule EarmarkParser.AstRenderer do ################## @empty_set MapSet.new([]) - defp render_block(%Block.FnList{}=fn_list, context, _loose?) do + defp render_block(%Block.FnList{} = fn_list, context, _loose?) do if MapSet.equal?(context.referenced_footnote_ids, @empty_set) do context else render_defined_fns(fn_list, context) end end + ####################################### # Isolated IALs are rendered as paras # ####################################### @@ -261,7 +259,6 @@ defmodule EarmarkParser.AstRenderer do start1 -> start1 end end - end # SPDX-License-Identifier: Apache-2.0 From 9f3ef38de38a389ee3e1d3815a3aa3508922f949 Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Sat, 17 Feb 2024 18:24:43 -0700 Subject: [PATCH 04/25] undo Enum.map refactor --- lib/earmark_parser/line_scanner.ex | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/earmark_parser/line_scanner.ex b/lib/earmark_parser/line_scanner.ex index 87e9ce0..3bcb41b 100644 --- a/lib/earmark_parser/line_scanner.ex +++ b/lib/earmark_parser/line_scanner.ex @@ -307,10 +307,8 @@ defmodule EarmarkParser.LineScanner do defp _split_table_columns(line) do line |> String.split(~r{(? Enum.map(fn col -> - col = String.trim(col) - Regex.replace(~r{\\\|}, col, "|") - end) + |> Enum.map(&String.trim/1) + |> Enum.map(fn col -> Regex.replace(~r{\\\|}, col, "|") end) end end From e9ae60f827144fa0e931623d5d1a9ba9b0610aca Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Mon, 17 Mar 2025 15:47:30 -0600 Subject: [PATCH 05/25] consolidated block modules into a single file, add types for Line and Block modules. --- lib/earmark_parser/block.ex | 126 +++++++++++++++++++++++ lib/earmark_parser/block/block_quote.ex | 6 -- lib/earmark_parser/block/code.ex | 6 -- lib/earmark_parser/block/fn_def.ex | 6 -- lib/earmark_parser/block/fn_list.ex | 6 -- lib/earmark_parser/block/heading.ex | 6 -- lib/earmark_parser/block/html.ex | 6 -- lib/earmark_parser/block/html_comment.ex | 6 -- lib/earmark_parser/block/html_oneline.ex | 6 -- lib/earmark_parser/block/ial.ex | 6 -- lib/earmark_parser/block/id_def.ex | 6 -- lib/earmark_parser/block/list.ex | 18 ---- lib/earmark_parser/block/list_item.ex | 13 --- lib/earmark_parser/block/para.ex | 6 -- lib/earmark_parser/block/ruler.ex | 6 -- lib/earmark_parser/block/table.ex | 10 -- lib/earmark_parser/block/text.ex | 6 -- lib/earmark_parser/line.ex | 19 ++++ 18 files changed, 145 insertions(+), 119 deletions(-) create mode 100644 lib/earmark_parser/block.ex delete mode 100644 lib/earmark_parser/block/block_quote.ex delete mode 100644 lib/earmark_parser/block/code.ex delete mode 100644 lib/earmark_parser/block/fn_def.ex delete mode 100644 lib/earmark_parser/block/fn_list.ex delete mode 100644 lib/earmark_parser/block/heading.ex delete mode 100644 lib/earmark_parser/block/html.ex delete mode 100644 lib/earmark_parser/block/html_comment.ex delete mode 100644 lib/earmark_parser/block/html_oneline.ex delete mode 100644 lib/earmark_parser/block/ial.ex delete mode 100644 lib/earmark_parser/block/id_def.ex delete mode 100644 lib/earmark_parser/block/list.ex delete mode 100644 lib/earmark_parser/block/list_item.ex delete mode 100644 lib/earmark_parser/block/para.ex delete mode 100644 lib/earmark_parser/block/ruler.ex delete mode 100644 lib/earmark_parser/block/table.ex delete mode 100644 lib/earmark_parser/block/text.ex diff --git a/lib/earmark_parser/block.ex b/lib/earmark_parser/block.ex new file mode 100644 index 0000000..adec157 --- /dev/null +++ b/lib/earmark_parser/block.ex @@ -0,0 +1,126 @@ +defmodule EarmarkParser.Block do + @moduledoc false + + @type t :: + %__MODULE__.BlockQuote{} + | %__MODULE__.Code{} + | %__MODULE__.FnDef{} + | %__MODULE__.FnList{} + | %__MODULE__.Heading{} + | %__MODULE__.Html{} + | %__MODULE__.HtmlComment{} + | %__MODULE__.HtmlOneline{} + | %__MODULE__.Ial{} + | %__MODULE__.IdDef{} + | %__MODULE__.ListItem{} + | %__MODULE__.List{} + | %__MODULE__.Para{} + | %__MODULE__.Ruler{} + | %__MODULE__.Table{} + | %__MODULE__.Text{} + + defmodule BlockQuote do + @moduledoc false + defstruct lnb: 0, annotation: nil, attrs: nil, blocks: [] + end + + defmodule Code do + @moduledoc false + defstruct lnb: 0, annotation: nil, attrs: nil, lines: [], language: nil + end + + defmodule FnDef do + @moduledoc false + defstruct lnb: 0, annotation: nil, attrs: nil, id: nil, number: nil, blocks: [] + end + + defmodule FnList do + @moduledoc false + defstruct lnb: 0, annotation: nil, attrs: ".footnotes", blocks: [] + end + + defmodule Heading do + @moduledoc false + defstruct lnb: 0, annotation: nil, attrs: nil, content: nil, level: nil + end + + defmodule HtmlComment do + @moduledoc false + defstruct lnb: 0, annotation: nil, attrs: nil, lines: [] + end + + defmodule HtmlOneline do + @moduledoc false + defstruct lnb: 0, annotation: nil, attrs: nil, html: "" + end + + defmodule Html do + @moduledoc false + defstruct lnb: 0, annotation: nil, attrs: nil, html: [], tag: nil + end + + defmodule Ial do + @moduledoc false + defstruct lnb: 0, annotation: nil, attrs: nil, content: nil, verbatim: "" + end + + defmodule IdDef do + @moduledoc false + defstruct lnb: 0, annotation: nil, attrs: nil, id: nil, url: nil, title: nil + end + + defmodule ListItem do + @moduledoc false + defstruct attrs: nil, + blocks: [], + bullet: "", + lnb: 0, + annotation: nil, + loose?: false, + spaced?: true, + type: :ul + end + + defmodule List do + @moduledoc false + + defstruct annotation: nil, + attrs: nil, + blocks: [], + lines: [], + bullet: "-", + indent: 0, + lnb: 0, + loose?: false, + pending: {nil, 0}, + spaced?: false, + start: "", + type: :ul + end + + defmodule Para do + @moduledoc false + defstruct lnb: 0, annotation: nil, attrs: nil, lines: [] + end + + defmodule Ruler do + @moduledoc false + defstruct lnb: 0, annotation: nil, attrs: nil, type: nil + end + + defmodule Table do + @moduledoc false + defstruct lnb: 0, annotation: nil, attrs: nil, rows: [], header: nil, alignments: [] + + def new_for_columns(n) do + %__MODULE__{alignments: Elixir.List.duplicate(:left, n)} + end + end + + defmodule Text do + @moduledoc false + defstruct attrs: nil, lnb: 0, annotation: nil, line: "" + end +end + +# SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/block/block_quote.ex b/lib/earmark_parser/block/block_quote.ex deleted file mode 100644 index 6cb001e..0000000 --- a/lib/earmark_parser/block/block_quote.ex +++ /dev/null @@ -1,6 +0,0 @@ -defmodule EarmarkParser.Block.BlockQuote do - @moduledoc false - defstruct lnb: 0, annotation: nil, attrs: nil, blocks: [] -end - -# SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/block/code.ex b/lib/earmark_parser/block/code.ex deleted file mode 100644 index 820dc36..0000000 --- a/lib/earmark_parser/block/code.ex +++ /dev/null @@ -1,6 +0,0 @@ -defmodule EarmarkParser.Block.Code do - @moduledoc false - defstruct lnb: 0, annotation: nil, attrs: nil, lines: [], language: nil -end - -# SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/block/fn_def.ex b/lib/earmark_parser/block/fn_def.ex deleted file mode 100644 index 5d26767..0000000 --- a/lib/earmark_parser/block/fn_def.ex +++ /dev/null @@ -1,6 +0,0 @@ -defmodule EarmarkParser.Block.FnDef do - @moduledoc false - defstruct lnb: 0, annotation: nil, attrs: nil, id: nil, number: nil, blocks: [] -end - -# SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/block/fn_list.ex b/lib/earmark_parser/block/fn_list.ex deleted file mode 100644 index 173a0d2..0000000 --- a/lib/earmark_parser/block/fn_list.ex +++ /dev/null @@ -1,6 +0,0 @@ -defmodule EarmarkParser.Block.FnList do - @moduledoc false - defstruct lnb: 0, annotation: nil, attrs: ".footnotes", blocks: [] -end - -# SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/block/heading.ex b/lib/earmark_parser/block/heading.ex deleted file mode 100644 index 2ef0405..0000000 --- a/lib/earmark_parser/block/heading.ex +++ /dev/null @@ -1,6 +0,0 @@ -defmodule EarmarkParser.Block.Heading do - @moduledoc false - defstruct lnb: 0, annotation: nil, attrs: nil, content: nil, level: nil -end - -# SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/block/html.ex b/lib/earmark_parser/block/html.ex deleted file mode 100644 index ba01b0d..0000000 --- a/lib/earmark_parser/block/html.ex +++ /dev/null @@ -1,6 +0,0 @@ -defmodule EarmarkParser.Block.Html do - @moduledoc false - defstruct lnb: 0, annotation: nil, attrs: nil, html: [], tag: nil -end - -# SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/block/html_comment.ex b/lib/earmark_parser/block/html_comment.ex deleted file mode 100644 index 63dfd90..0000000 --- a/lib/earmark_parser/block/html_comment.ex +++ /dev/null @@ -1,6 +0,0 @@ -defmodule EarmarkParser.Block.HtmlComment do - @moduledoc false - defstruct lnb: 0, annotation: nil, attrs: nil, lines: [] -end - -# SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/block/html_oneline.ex b/lib/earmark_parser/block/html_oneline.ex deleted file mode 100644 index ef6a429..0000000 --- a/lib/earmark_parser/block/html_oneline.ex +++ /dev/null @@ -1,6 +0,0 @@ -defmodule EarmarkParser.Block.HtmlOneline do - @moduledoc false - defstruct lnb: 0, annotation: nil, attrs: nil, html: "" -end - -# SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/block/ial.ex b/lib/earmark_parser/block/ial.ex deleted file mode 100644 index 5a397b0..0000000 --- a/lib/earmark_parser/block/ial.ex +++ /dev/null @@ -1,6 +0,0 @@ -defmodule EarmarkParser.Block.Ial do - @moduledoc false - defstruct lnb: 0, annotation: nil, attrs: nil, content: nil, verbatim: "" -end - -# SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/block/id_def.ex b/lib/earmark_parser/block/id_def.ex deleted file mode 100644 index 9e860cb..0000000 --- a/lib/earmark_parser/block/id_def.ex +++ /dev/null @@ -1,6 +0,0 @@ -defmodule EarmarkParser.Block.IdDef do - @moduledoc false - defstruct lnb: 0, annotation: nil, attrs: nil, id: nil, url: nil, title: nil -end - -# SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/block/list.ex b/lib/earmark_parser/block/list.ex deleted file mode 100644 index e7e4f9a..0000000 --- a/lib/earmark_parser/block/list.ex +++ /dev/null @@ -1,18 +0,0 @@ -defmodule EarmarkParser.Block.List do - @moduledoc false - - defstruct annotation: nil, - attrs: nil, - blocks: [], - lines: [], - bullet: "-", - indent: 0, - lnb: 0, - loose?: false, - pending: {nil, 0}, - spaced?: false, - start: "", - type: :ul -end - -# SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/block/list_item.ex b/lib/earmark_parser/block/list_item.ex deleted file mode 100644 index de9d682..0000000 --- a/lib/earmark_parser/block/list_item.ex +++ /dev/null @@ -1,13 +0,0 @@ -defmodule EarmarkParser.Block.ListItem do - @moduledoc false - defstruct attrs: nil, - blocks: [], - bullet: "", - lnb: 0, - annotation: nil, - loose?: false, - spaced?: true, - type: :ul -end - -# SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/block/para.ex b/lib/earmark_parser/block/para.ex deleted file mode 100644 index 4e35d7d..0000000 --- a/lib/earmark_parser/block/para.ex +++ /dev/null @@ -1,6 +0,0 @@ -defmodule EarmarkParser.Block.Para do - @moduledoc false - defstruct lnb: 0, annotation: nil, attrs: nil, lines: [] -end - -# SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/block/ruler.ex b/lib/earmark_parser/block/ruler.ex deleted file mode 100644 index 17c8a30..0000000 --- a/lib/earmark_parser/block/ruler.ex +++ /dev/null @@ -1,6 +0,0 @@ -defmodule EarmarkParser.Block.Ruler do - @moduledoc false - defstruct lnb: 0, annotation: nil, attrs: nil, type: nil -end - -# SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/block/table.ex b/lib/earmark_parser/block/table.ex deleted file mode 100644 index fb9b90b..0000000 --- a/lib/earmark_parser/block/table.ex +++ /dev/null @@ -1,10 +0,0 @@ -defmodule EarmarkParser.Block.Table do - @moduledoc false - defstruct lnb: 0, annotation: nil, attrs: nil, rows: [], header: nil, alignments: [] - - def new_for_columns(n) do - %__MODULE__{alignments: Elixir.List.duplicate(:left, n)} - end -end - -# SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/block/text.ex b/lib/earmark_parser/block/text.ex deleted file mode 100644 index a0a2d8d..0000000 --- a/lib/earmark_parser/block/text.ex +++ /dev/null @@ -1,6 +0,0 @@ -defmodule EarmarkParser.Block.Text do - @moduledoc false - defstruct attrs: nil, lnb: 0, annotation: nil, line: "" -end - -# SPDX-License-Identifier: Apache-2.0 diff --git a/lib/earmark_parser/line.ex b/lib/earmark_parser/line.ex index df4d142..cecc888 100644 --- a/lib/earmark_parser/line.ex +++ b/lib/earmark_parser/line.ex @@ -1,6 +1,25 @@ defmodule EarmarkParser.Line do @moduledoc false + @type t :: + %__MODULE__.Blank{} + | %__MODULE__.Ruler{} + | %__MODULE__.Heading{} + | %__MODULE__.BlockQuote{} + | %__MODULE__.Indent{} + | %__MODULE__.Fence{} + | %__MODULE__.HtmlOpenTag{} + | %__MODULE__.HtmlCloseTag{} + | %__MODULE__.HtmlComment{} + | %__MODULE__.HtmlOneLine{} + | %__MODULE__.IdDef{} + | %__MODULE__.FnDef{} + | %__MODULE__.ListItem{} + | %__MODULE__.SetextUnderlineHeading{} + | %__MODULE__.TableLine{} + | %__MODULE__.Ial{} + | %__MODULE__.Text{} + defmodule Blank do @moduledoc false defstruct(annotation: nil, lnb: 0, line: "", indent: -1, content: "") From cadc78e4e554ca1ed46bb05b5c778916de586297 Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Mon, 17 Mar 2025 17:52:15 -0600 Subject: [PATCH 06/25] EarmarkParser.Message typing edits --- lib/earmark_parser/message.ex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/earmark_parser/message.ex b/lib/earmark_parser/message.ex index 97ef10e..dec9534 100644 --- a/lib/earmark_parser/message.ex +++ b/lib/earmark_parser/message.ex @@ -4,9 +4,9 @@ defmodule EarmarkParser.Message do alias EarmarkParser.Context alias EarmarkParser.Options - @type message_type :: :error | :warning - @type t :: {message_type, number, binary} - @type ts :: list(t) + @type message_type :: :error | :warning | :deprecated + @type t :: {message_type, non_neg_integer(), String.t()} + @type ts :: MapSet.t(t()) @type container_type :: Options.t() | Context.t() def add_messages(container, messages) do From f5dd60cc5db3db1607f59d2d7e0602e9158ee220 Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Mon, 17 Mar 2025 17:57:48 -0600 Subject: [PATCH 07/25] applied pre-existing alias, renamed nv -> new_value --- lib/earmark_parser/context.ex | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/earmark_parser/context.ex b/lib/earmark_parser/context.ex index ec139ac..83c75ef 100644 --- a/lib/earmark_parser/context.ex +++ b/lib/earmark_parser/context.ex @@ -3,14 +3,14 @@ defmodule EarmarkParser.Context do alias EarmarkParser.Options @type t :: %__MODULE__{ - options: EarmarkParser.Options.t(), + options: Options.t(), links: map(), footnotes: map(), referenced_footnote_ids: MapSet.t(String.t()), value: String.t() | [String.t()] } - defstruct options: %EarmarkParser.Options{}, + defstruct options: %Options{}, links: Map.new(), rules: nil, footnotes: Map.new(), @@ -23,8 +23,8 @@ defmodule EarmarkParser.Context do @doc false def modify_value(%__MODULE__{value: value} = context, fun) do - nv = fun.(value) - %{context | value: nv} + new_value = fun.(value) + %{context | value: new_value} end @doc false From 2211317505baef036eaf59077b23ac38df9aeb2c Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Mon, 17 Mar 2025 18:31:32 -0600 Subject: [PATCH 08/25] Options.t edits: renderer and math were missing. normalize/1 lets the annotation be a regex --- lib/earmark_parser/options.ex | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/earmark_parser/options.ex b/lib/earmark_parser/options.ex index d447efe..20a1882 100644 --- a/lib/earmark_parser/options.ex +++ b/lib/earmark_parser/options.ex @@ -32,6 +32,7 @@ defmodule EarmarkParser.Options do timeout: nil @type t :: %__MODULE__{ + renderer: module(), all: boolean(), gfm: boolean(), gfm_tables: boolean(), @@ -42,18 +43,19 @@ defmodule EarmarkParser.Options do parse_inline: boolean(), # allow for annotations - annotations: nil | binary(), + annotations: nil | binary() | Regex.t(), # additional prefies for class of code blocks code_class_prefix: nil | binary(), # Filename and initial line number of the markdown block passed in # for meaningful error messages file: binary(), - line: number(), + line: non_neg_integer(), # [{:error|:warning, lnb, text},...] - messages: MapSet.t(), + messages: MapSet.t(Message.t()), pure_links: boolean(), sub_sup: boolean(), + math: boolean(), # deprecated pedantic: boolean(), From dfe67c52a910c0dbad918c9300cc55b1b914164f Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Mon, 17 Mar 2025 21:28:17 -0600 Subject: [PATCH 09/25] `new/2` type specification with aliases for EarmarkParser.Options and EarmarkParser.Line --- lib/earmark_parser/parser/list_info.ex | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/earmark_parser/parser/list_info.ex b/lib/earmark_parser/parser/list_info.ex index 78435fb..7c74563 100644 --- a/lib/earmark_parser/parser/list_info.ex +++ b/lib/earmark_parser/parser/list_info.ex @@ -1,4 +1,7 @@ defmodule EarmarkParser.Parser.ListInfo do + + alias EarmarkParser.{Options, Line} + import EarmarkParser.Helpers.LookaheadHelpers, only: [opens_inline_code: 1, still_inline_code: 2] @moduledoc false @@ -14,7 +17,8 @@ defmodule EarmarkParser.Parser.ListInfo do width: 0 ) - def new(%EarmarkParser.Line.ListItem{initial_indent: ii, list_indent: width} = item, options) do + @spec new(Line.ListItem.t(), Options.t()) :: t() + def new(%Line.ListItem{initial_indent: ii, list_indent: width} = item, options) do pending = opens_inline_code(item) %__MODULE__{indent: ii, lines: [item.content], options: options, pending: pending, width: width} end From adc96fc59a491432184b46d760c083fd481797d7 Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Mon, 17 Mar 2025 23:46:26 -0600 Subject: [PATCH 10/25] ListInfo.t type definition --- lib/earmark_parser/parser/list_info.ex | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/earmark_parser/parser/list_info.ex b/lib/earmark_parser/parser/list_info.ex index 7c74563..077512f 100644 --- a/lib/earmark_parser/parser/list_info.ex +++ b/lib/earmark_parser/parser/list_info.ex @@ -16,6 +16,14 @@ defmodule EarmarkParser.Parser.ListInfo do options: %EarmarkParser.Options{}, width: 0 ) + @type t :: %__MODULE__{ + indent: non_neg_integer(), + lines: list(), + loose?: boolean(), + pending: {nil | String.t(), non_neg_integer()}, + options: Options.t(), + width: non_neg_integer() + } @spec new(Line.ListItem.t(), Options.t()) :: t() def new(%Line.ListItem{initial_indent: ii, list_indent: width} = item, options) do From 19c70cae88d9a3aecf3cb65b41340f61a711baef Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Mon, 17 Mar 2025 23:55:32 -0600 Subject: [PATCH 11/25] added EarmarkParser.{Options, Line}; added type specifications for EarmarkParser.Parser.ListInfo --- lib/earmark_parser/parser/list_info.ex | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/earmark_parser/parser/list_info.ex b/lib/earmark_parser/parser/list_info.ex index 077512f..27ef9fb 100644 --- a/lib/earmark_parser/parser/list_info.ex +++ b/lib/earmark_parser/parser/list_info.ex @@ -1,6 +1,6 @@ defmodule EarmarkParser.Parser.ListInfo do - alias EarmarkParser.{Options, Line} + alias EarmarkParser.{Options, Line, Line.ListItem} import EarmarkParser.Helpers.LookaheadHelpers, only: [opens_inline_code: 1, still_inline_code: 2] @@ -8,33 +8,36 @@ defmodule EarmarkParser.Parser.ListInfo do @not_pending {nil, 0} - defstruct( + defstruct [ indent: 0, lines: [], loose?: false, pending: @not_pending, - options: %EarmarkParser.Options{}, + options: %Options{}, width: 0 - ) + ] + @type t :: %__MODULE__{ indent: non_neg_integer(), - lines: list(), + lines: [String.t()], loose?: boolean(), pending: {nil | String.t(), non_neg_integer()}, options: Options.t(), width: non_neg_integer() } - @spec new(Line.ListItem.t(), Options.t()) :: t() - def new(%Line.ListItem{initial_indent: ii, list_indent: width} = item, options) do + @spec new(ListItem.t(), Options.t()) :: t() + def new(%ListItem{initial_indent: ii, list_indent: width} = item, options) do pending = opens_inline_code(item) %__MODULE__{indent: ii, lines: [item.content], options: options, pending: pending, width: width} end + @spec update_list_info(t(), String.t(), Line.t(), boolean()) :: t() def update_list_info(list_info, line, pending_line, loose? \\ false) do prepend_line(list_info, line) |> _update_rest(pending_line, loose?) end + @spec prepend_line(t(), String.t()) :: t() def prepend_line(%__MODULE__{lines: lines} = list_info, line) do %{list_info | lines: [line | lines]} end From 85d7c1e0a762cba2636d5a7c365eb585f766d5c4 Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Tue, 18 Mar 2025 00:22:24 -0600 Subject: [PATCH 12/25] refactor from case to pattern matching; added new helper function `_normalize_annotations/1` --- lib/earmark_parser/options.ex | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/earmark_parser/options.ex b/lib/earmark_parser/options.ex index 20a1882..eaa3d23 100644 --- a/lib/earmark_parser/options.ex +++ b/lib/earmark_parser/options.ex @@ -107,22 +107,12 @@ defmodule EarmarkParser.Options do ...(1)> options.annotations ~r{\A(.*)(%%.*)} """ + @spec normalize(t() | keyword()) :: t() def normalize(options) def normalize(%__MODULE__{} = options) do - case options.annotations do - %Regex{} -> - options - - nil -> - options - - _ -> - %{ - options - | annotations: Regex.compile!("\\A(.*)(#{Regex.escape(options.annotations)}.*)") - } - end + options + |> _normalize_annotations() |> _set_all_if_applicable() |> _deprecate_old_messages() end @@ -131,6 +121,18 @@ defmodule EarmarkParser.Options do struct(__MODULE__, options) |> normalize() end + defp _normalize_annotations(%__MODULE__{annotations: %Regex{}} = options) do + options + end + + defp _normalize_annotations(%__MODULE__{annotations: nil} = options) do + options + end + + defp _normalize_annotations(%__MODULE__{annotations: annotations} = options) do + %{options | annotations: Regex.compile!("\\A(.*)(#{Regex.escape(annotations)}.*)")} + end + defp _deprecate_old_messages(options) defp _deprecate_old_messages(%__MODULE__{messages: %MapSet{}} = options) do From 4b6e1ee78d4ad86517b51f66a19b42d7e365c192 Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Tue, 18 Mar 2025 00:32:26 -0600 Subject: [PATCH 13/25] type specification for `parse_markdown/2` --- lib/earmark_parser/parser.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/earmark_parser/parser.ex b/lib/earmark_parser/parser.ex index 9b1e874..c4e1e32 100644 --- a/lib/earmark_parser/parser.ex +++ b/lib/earmark_parser/parser.ex @@ -1,6 +1,6 @@ defmodule EarmarkParser.Parser do @moduledoc false - alias EarmarkParser.{Block, Line, LineScanner, Options} + alias EarmarkParser.{Block, Line, LineScanner, Options, Context} import EarmarkParser.Helpers.{AttrParser, LineHelpers, ReparseHelpers} @@ -19,6 +19,7 @@ defmodule EarmarkParser.Parser do The options are a `%EarmarkParser.Options{}` structure. See `as_html!` for more details. """ + @spec parse_markdown([String.t()] | String.t(), Options.t()) :: {[Block.t()], Context.t()} def parse_markdown(lines, options) def parse_markdown(lines, options = %Options{}) when is_list(lines) do From 293e60092392b06ba26ae3640333fecbd1f73ff4 Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Tue, 18 Mar 2025 00:37:54 -0600 Subject: [PATCH 14/25] type specification for `parse_list/3` --- lib/earmark_parser/parser/list_parser.ex | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/earmark_parser/parser/list_parser.ex b/lib/earmark_parser/parser/list_parser.ex index cbe356f..88d8d3e 100644 --- a/lib/earmark_parser/parser/list_parser.ex +++ b/lib/earmark_parser/parser/list_parser.ex @@ -10,6 +10,7 @@ defmodule EarmarkParser.Parser.ListParser do @not_pending {nil, 0} + @spec parse_list([Line.t()], [Block.t()], Options.t()) :: {[Block.t()], [Line.t()], Options.t()} def parse_list(lines, result, options \\ %Options{}) do {items, rest, options1} = _parse_list_items_init(lines, [], options) list = _make_list(items, _empty_list(items)) From ce89aa64c38e2411276de5d34ca4383d4e68cb3d Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Tue, 18 Mar 2025 00:46:41 -0600 Subject: [PATCH 15/25] EarmarkParser.AstRenderer.render type specification --- lib/earmark_parser/ast_renderer.ex | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/earmark_parser/ast_renderer.ex b/lib/earmark_parser/ast_renderer.ex index d339ba2..0b4e9d6 100644 --- a/lib/earmark_parser/ast_renderer.ex +++ b/lib/earmark_parser/ast_renderer.ex @@ -12,6 +12,7 @@ defmodule EarmarkParser.AstRenderer do @moduledoc false + @spec render([Block.t()], Context.t(), boolean()) :: Context.t() def render(blocks, context = %Context{options: %Options{}}, loose? \\ true) do _render(blocks, context, loose?) end From 6074cb0946af8369189f3742283b6310026bc864 Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Tue, 18 Mar 2025 01:24:08 -0600 Subject: [PATCH 16/25] Fixed dialyzer warnings: lib/earmark_parser/parser/list_info.ex:29:21:unknown_type Unknown type: EarmarkParser.Line.ListItem.t/0. lib/earmark_parser/options.ex:55:37:unknown_type Unknown type: Message.t/0. --- lib/earmark_parser/line.ex | 13 +++++++++++++ lib/earmark_parser/options.ex | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/earmark_parser/line.ex b/lib/earmark_parser/line.ex index cecc888..5881e1c 100644 --- a/lib/earmark_parser/line.ex +++ b/lib/earmark_parser/line.ex @@ -94,6 +94,19 @@ defmodule EarmarkParser.Line do initial_indent: 0, list_indent: 0 ) + + @type t :: %__MODULE__{ + annotation: nil | String.t(), + ial: nil | String.t(), + lnb: non_neg_integer(), + type: :ul | :ol, + line: String.t(), + indent: non_neg_integer(), + bullet: String.t(), + content: String.t(), + initial_indent: non_neg_integer(), + list_indent: non_neg_integer() + } end defmodule SetextUnderlineHeading do diff --git a/lib/earmark_parser/options.ex b/lib/earmark_parser/options.ex index eaa3d23..3f726bb 100644 --- a/lib/earmark_parser/options.ex +++ b/lib/earmark_parser/options.ex @@ -52,7 +52,7 @@ defmodule EarmarkParser.Options do file: binary(), line: non_neg_integer(), # [{:error|:warning, lnb, text},...] - messages: MapSet.t(Message.t()), + messages: MapSet.t(EarmarkParser.Message.t()), pure_links: boolean(), sub_sup: boolean(), math: boolean(), From 817c738608dd55f4cc5a30721d7045aa3e2c14a3 Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Tue, 18 Mar 2025 01:25:09 -0600 Subject: [PATCH 17/25] EarmarkParser.Helpers.LookaheadHelpers type specification --- lib/earmark_parser/helpers/lookahead_helpers.ex | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/earmark_parser/helpers/lookahead_helpers.ex b/lib/earmark_parser/helpers/lookahead_helpers.ex index 7b66c0c..d713440 100644 --- a/lib/earmark_parser/helpers/lookahead_helpers.ex +++ b/lib/earmark_parser/helpers/lookahead_helpers.ex @@ -3,6 +3,8 @@ defmodule EarmarkParser.Helpers.LookaheadHelpers do import EarmarkParser.Helpers.LeexHelpers + @type backtix :: String.t() + @doc """ Indicates if the _numbered_line_ passed in leaves an inline code block open. @@ -11,6 +13,7 @@ defmodule EarmarkParser.Helpers.LookaheadHelpers do Otherwise `{nil, 0}` is returned """ + @spec opens_inline_code(EarmarkParser.Line.t()) :: {backtix | nil, non_neg_integer()} def opens_inline_code(%{line: line, lnb: lnb}) do case tokenize(line, with: :earmark_parser_string_lexer) |> has_still_opening_backtix(nil) do nil -> {nil, 0} @@ -26,6 +29,7 @@ defmodule EarmarkParser.Helpers.LookaheadHelpers do opening backtix """ # (#{},{_,_}) -> {_,_} + @spec still_inline_code(EarmarkParser.Line.t(), {backtix, non_neg_integer()}) :: {backtix, non_neg_integer()} def still_inline_code(%{line: line, lnb: lnb}, old = {pending, _pending_lnb}) do case tokenize(line, with: :earmark_parser_string_lexer) |> has_still_opening_backtix({:old, pending}) do nil -> {nil, 0} From 784f13a64a0335f586730556368f43084ca07649 Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Tue, 18 Mar 2025 01:42:11 -0600 Subject: [PATCH 18/25] Type specifications for EarmarkParser.Message functions; fixed ts() type: it's a list not a MapSet; change type container_type to container --- lib/earmark_parser/message.ex | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/earmark_parser/message.ex b/lib/earmark_parser/message.ex index dec9534..8aba6f6 100644 --- a/lib/earmark_parser/message.ex +++ b/lib/earmark_parser/message.ex @@ -6,13 +6,15 @@ defmodule EarmarkParser.Message do @type message_type :: :error | :warning | :deprecated @type t :: {message_type, non_neg_integer(), String.t()} - @type ts :: MapSet.t(t()) - @type container_type :: Options.t() | Context.t() + @type ts :: [t()] + @type container :: Options.t() | Context.t() + @spec add_messages(container, ts()) :: container def add_messages(container, messages) do Enum.reduce(messages, container, &add_message(&2, &1)) end + @spec add_message(container, t()) :: container def add_message(container, message) def add_message(options = %Options{}, message) do @@ -23,6 +25,7 @@ defmodule EarmarkParser.Message do %{context | options: add_message(context.options, message)} end + @spec get_messages(container) :: ts() def get_messages(container) def get_messages(%Context{options: %{messages: messages}}) do @@ -32,6 +35,7 @@ defmodule EarmarkParser.Message do @doc """ For final output """ + @spec sort_messages(container) :: [t()] def sort_messages(container) do container |> get_messages() From 48514f6dac7ef755ee5c30a5d2983e31803101d8 Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Tue, 18 Mar 2025 13:43:59 -0600 Subject: [PATCH 19/25] type spec fix --- lib/earmark_parser/helpers/lookahead_helpers.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/earmark_parser/helpers/lookahead_helpers.ex b/lib/earmark_parser/helpers/lookahead_helpers.ex index d713440..61e89a9 100644 --- a/lib/earmark_parser/helpers/lookahead_helpers.ex +++ b/lib/earmark_parser/helpers/lookahead_helpers.ex @@ -29,7 +29,7 @@ defmodule EarmarkParser.Helpers.LookaheadHelpers do opening backtix """ # (#{},{_,_}) -> {_,_} - @spec still_inline_code(EarmarkParser.Line.t(), {backtix, non_neg_integer()}) :: {backtix, non_neg_integer()} + @spec still_inline_code(EarmarkParser.Line.t(), {backtix, non_neg_integer()}) :: {backtix | nil, non_neg_integer()} def still_inline_code(%{line: line, lnb: lnb}, old = {pending, _pending_lnb}) do case tokenize(line, with: :earmark_parser_string_lexer) |> has_still_opening_backtix({:old, pending}) do nil -> {nil, 0} From 2237e35318bde9c90fc02a31807bccb98088600b Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Tue, 18 Mar 2025 13:57:49 -0600 Subject: [PATCH 20/25] mix format --- lib/earmark_parser/line.ex | 22 +++++++++---------- lib/earmark_parser/parser/list_info.ex | 29 ++++++++++++-------------- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/lib/earmark_parser/line.ex b/lib/earmark_parser/line.ex index 5881e1c..f8ea838 100644 --- a/lib/earmark_parser/line.ex +++ b/lib/earmark_parser/line.ex @@ -96,17 +96,17 @@ defmodule EarmarkParser.Line do ) @type t :: %__MODULE__{ - annotation: nil | String.t(), - ial: nil | String.t(), - lnb: non_neg_integer(), - type: :ul | :ol, - line: String.t(), - indent: non_neg_integer(), - bullet: String.t(), - content: String.t(), - initial_indent: non_neg_integer(), - list_indent: non_neg_integer() - } + annotation: nil | String.t(), + ial: nil | String.t(), + lnb: non_neg_integer(), + type: :ul | :ol, + line: String.t(), + indent: non_neg_integer(), + bullet: String.t(), + content: String.t(), + initial_indent: non_neg_integer(), + list_indent: non_neg_integer() + } end defmodule SetextUnderlineHeading do diff --git a/lib/earmark_parser/parser/list_info.ex b/lib/earmark_parser/parser/list_info.ex index 27ef9fb..bb39cad 100644 --- a/lib/earmark_parser/parser/list_info.ex +++ b/lib/earmark_parser/parser/list_info.ex @@ -1,5 +1,4 @@ defmodule EarmarkParser.Parser.ListInfo do - alias EarmarkParser.{Options, Line, Line.ListItem} import EarmarkParser.Helpers.LookaheadHelpers, only: [opens_inline_code: 1, still_inline_code: 2] @@ -8,23 +7,21 @@ defmodule EarmarkParser.Parser.ListInfo do @not_pending {nil, 0} - defstruct [ - indent: 0, - lines: [], - loose?: false, - pending: @not_pending, - options: %Options{}, - width: 0 - ] + defstruct indent: 0, + lines: [], + loose?: false, + pending: @not_pending, + options: %Options{}, + width: 0 @type t :: %__MODULE__{ - indent: non_neg_integer(), - lines: [String.t()], - loose?: boolean(), - pending: {nil | String.t(), non_neg_integer()}, - options: Options.t(), - width: non_neg_integer() - } + indent: non_neg_integer(), + lines: [String.t()], + loose?: boolean(), + pending: {nil | String.t(), non_neg_integer()}, + options: Options.t(), + width: non_neg_integer() + } @spec new(ListItem.t(), Options.t()) :: t() def new(%ListItem{initial_indent: ii, list_indent: width} = item, options) do From 2a61c7e97bf5cc3a972bd40ca6f8b1dd718dc4a4 Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Wed, 19 Mar 2025 14:09:40 -0600 Subject: [PATCH 21/25] https://github.com/RobertDober/earmark_parser/pull/168#discussion_r2002669145 Replaced binary() with String,t() --- lib/earmark_parser.ex | 12 ++++++------ lib/earmark_parser/options.ex | 6 +++--- lib/earmark_parser/parser.ex | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/earmark_parser.ex b/lib/earmark_parser.ex index 49ef870..6936e41 100644 --- a/lib/earmark_parser.ex +++ b/lib/earmark_parser.ex @@ -1,15 +1,15 @@ defmodule EarmarkParser do @type ast_meta :: map() - @type ast_tag :: binary() - @type ast_attribute_name :: binary() - @type ast_attribute_value :: binary() + @type ast_tag :: String.t() + @type ast_attribute_name :: String.t() + @type ast_attribute_value :: String.t() @type ast_attribute :: {ast_attribute_name(), ast_attribute_value()} @type ast_attributes :: list(ast_attribute()) @type ast_tuple :: {ast_tag(), ast_attributes(), ast(), ast_meta()} - @type ast_node :: binary() | ast_tuple() + @type ast_node :: String.t() | ast_tuple() @type ast :: list(ast_node()) - @type error :: {atom(), non_neg_integer(), binary()} + @type error :: {atom(), non_neg_integer(), String.t()} @type errors :: list(error()) @type t :: {:ok, ast(), []} | {:error, ast(), errors()} @@ -615,7 +615,7 @@ defmodule EarmarkParser do The AST is exposed in the spirit of [Floki's](https://hex.pm/packages/floki). """ - @spec as_ast(binary() | list(binary()), any()) :: t() + @spec as_ast(String.t() | list(String.t()), any()) :: t() def as_ast(lines, options \\ %Options{}) def as_ast(lines, %Options{} = options) do diff --git a/lib/earmark_parser/options.ex b/lib/earmark_parser/options.ex index 3f726bb..8242c7d 100644 --- a/lib/earmark_parser/options.ex +++ b/lib/earmark_parser/options.ex @@ -43,13 +43,13 @@ defmodule EarmarkParser.Options do parse_inline: boolean(), # allow for annotations - annotations: nil | binary() | Regex.t(), + annotations: nil | String.t() | Regex.t(), # additional prefies for class of code blocks - code_class_prefix: nil | binary(), + code_class_prefix: nil | String.t(), # Filename and initial line number of the markdown block passed in # for meaningful error messages - file: binary(), + file: String.t(), line: non_neg_integer(), # [{:error|:warning, lnb, text},...] messages: MapSet.t(EarmarkParser.Message.t()), diff --git a/lib/earmark_parser/parser.ex b/lib/earmark_parser/parser.ex index c4e1e32..0adfdd4 100644 --- a/lib/earmark_parser/parser.ex +++ b/lib/earmark_parser/parser.ex @@ -514,7 +514,7 @@ defmodule EarmarkParser.Parser do # Consolidate multiline inline code blocks into an element # ############################################################ @not_pending {nil, 0} - # ([#{},...]) -> {[#{}],[#{}],{'nil' | binary(),number()}} + # ([#{},...]) -> {[#{}],[#{}],{'nil' | String.t(),number()}} # @spec consolidate_para( ts ) :: { ts, ts, {nil | String.t, number} } defp consolidate_para(lines) do _consolidate_para(lines, [], @not_pending, nil) From a6cef10a0fd553c3d15ff42665b38af12e9b8ae1 Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Wed, 19 Mar 2025 14:10:26 -0600 Subject: [PATCH 22/25] updated @void_tag to make list comprehensive --- lib/earmark_parser/line_scanner/rgx.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/earmark_parser/line_scanner/rgx.ex b/lib/earmark_parser/line_scanner/rgx.ex index dfc8185..b201162 100644 --- a/lib/earmark_parser/line_scanner/rgx.ex +++ b/lib/earmark_parser/line_scanner/rgx.ex @@ -159,7 +159,7 @@ defmodule EarmarkParser.LineScanner.Rgx do Regex.run(~r/\A (?:_\s?){3,} \z/x, content) end - @void_tags ~w{area br hr img wbr} + @void_tags ~w{area base br col embed hr img input link meta param source track wbr} def void_tag_rgx do ~r''' ^<( #{Enum.join(@void_tags, "|")} ) From 8483cfeff7e794a9a2b51c3768a7fec3cc71c4a2 Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Wed, 19 Mar 2025 14:11:42 -0600 Subject: [PATCH 23/25] https://github.com/RobertDober/earmark_parser/pull/168#discussion_r2002682723 Added natural type --- lib/earmark_parser/helpers/lookahead_helpers.ex | 2 +- lib/earmark_parser/line.ex | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/earmark_parser/helpers/lookahead_helpers.ex b/lib/earmark_parser/helpers/lookahead_helpers.ex index 61e89a9..32d1391 100644 --- a/lib/earmark_parser/helpers/lookahead_helpers.ex +++ b/lib/earmark_parser/helpers/lookahead_helpers.ex @@ -3,7 +3,7 @@ defmodule EarmarkParser.Helpers.LookaheadHelpers do import EarmarkParser.Helpers.LeexHelpers - @type backtix :: String.t() + @type natural :: non_neg_integer() @doc """ Indicates if the _numbered_line_ passed in leaves an inline code block open. diff --git a/lib/earmark_parser/line.ex b/lib/earmark_parser/line.ex index f8ea838..afd347c 100644 --- a/lib/earmark_parser/line.ex +++ b/lib/earmark_parser/line.ex @@ -95,17 +95,19 @@ defmodule EarmarkParser.Line do list_indent: 0 ) + @type natural :: non_neg_integer() + @type t :: %__MODULE__{ annotation: nil | String.t(), ial: nil | String.t(), - lnb: non_neg_integer(), + lnb: natural, type: :ul | :ol, line: String.t(), - indent: non_neg_integer(), + indent: natural, bullet: String.t(), content: String.t(), - initial_indent: non_neg_integer(), - list_indent: non_neg_integer() + initial_indent: natural, + list_indent: natural } end From 3850a9028d0d4f05b90aa258e62c0e98f0f511ec Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Wed, 19 Mar 2025 14:12:56 -0600 Subject: [PATCH 24/25] https://github.com/RobertDober/earmark_parser/pull/168#discussion_r2002789798 _t isn't idiomatic; I'm going to guess someone has spent a lot of time in C :) --- lib/earmark_parser/helpers/lookahead_helpers.ex | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/earmark_parser/helpers/lookahead_helpers.ex b/lib/earmark_parser/helpers/lookahead_helpers.ex index 32d1391..dd4d2fc 100644 --- a/lib/earmark_parser/helpers/lookahead_helpers.ex +++ b/lib/earmark_parser/helpers/lookahead_helpers.ex @@ -3,9 +3,10 @@ defmodule EarmarkParser.Helpers.LookaheadHelpers do import EarmarkParser.Helpers.LeexHelpers + @type backtix_string :: String.t() @type natural :: non_neg_integer() - @doc """ +@doc """ Indicates if the _numbered_line_ passed in leaves an inline code block open. If so returns a tuple where the first element is the opening sequence of backticks, @@ -13,7 +14,7 @@ defmodule EarmarkParser.Helpers.LookaheadHelpers do Otherwise `{nil, 0}` is returned """ - @spec opens_inline_code(EarmarkParser.Line.t()) :: {backtix | nil, non_neg_integer()} + @spec opens_inline_code(EarmarkParser.Line.t()) :: {backtix_string | nil, natural} def opens_inline_code(%{line: line, lnb: lnb}) do case tokenize(line, with: :earmark_parser_string_lexer) |> has_still_opening_backtix(nil) do nil -> {nil, 0} @@ -29,7 +30,7 @@ defmodule EarmarkParser.Helpers.LookaheadHelpers do opening backtix """ # (#{},{_,_}) -> {_,_} - @spec still_inline_code(EarmarkParser.Line.t(), {backtix, non_neg_integer()}) :: {backtix | nil, non_neg_integer()} + @spec still_inline_code(EarmarkParser.Line.t(), {backtix_string, natural}) :: {backtix_string | nil, natural} def still_inline_code(%{line: line, lnb: lnb}, old = {pending, _pending_lnb}) do case tokenize(line, with: :earmark_parser_string_lexer) |> has_still_opening_backtix({:old, pending}) do nil -> {nil, 0} From 9a2cd28164b91aa4624fab8e553648b4a1d15929 Mon Sep 17 00:00:00 2001 From: Brad Hanks Date: Wed, 19 Mar 2025 14:15:01 -0600 Subject: [PATCH 25/25] mix format --- lib/earmark_parser/helpers/lookahead_helpers.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/earmark_parser/helpers/lookahead_helpers.ex b/lib/earmark_parser/helpers/lookahead_helpers.ex index dd4d2fc..d610435 100644 --- a/lib/earmark_parser/helpers/lookahead_helpers.ex +++ b/lib/earmark_parser/helpers/lookahead_helpers.ex @@ -6,7 +6,7 @@ defmodule EarmarkParser.Helpers.LookaheadHelpers do @type backtix_string :: String.t() @type natural :: non_neg_integer() -@doc """ + @doc """ Indicates if the _numbered_line_ passed in leaves an inline code block open. If so returns a tuple where the first element is the opening sequence of backticks,