footnote_parser.ex (1917B)
1 defmodule EarmarkParser.Parser.FootnoteParser do 2 alias EarmarkParser.{Block, Enum.Ext, Line} 3 4 @moduledoc false 5 def parse_fn_defs([fn_def | rest], result, options) do 6 acc = 7 {[fn_def.content], [%Block.FnList{blocks: [_block_fn_def(fn_def)]} | result], %{}, options} 8 9 rest 10 |> Ext.reduce_with_end(acc, &_parse_fn_def_reduce/2) 11 end 12 13 defp _parse_fn_def_reduce(ele_or_end, acc) 14 15 defp _parse_fn_def_reduce({:element, %Line.FnDef{content: content}=fn_def}, acc) do 16 {result1, footnotes, options1} = _complete_fn_def_block(acc, fn_def) 17 {[content], result1, footnotes, options1} 18 end 19 20 defp _parse_fn_def_reduce({:element, %{line: line}}, acc) do 21 _prepend_to_first_in4(line, acc) 22 end 23 24 defp _parse_fn_def_reduce(:end, acc) do 25 {[fn_list | rest], footnotes, options} = _complete_fn_def_block(acc) 26 {[%{fn_list | blocks: Enum.reverse(fn_list.blocks)} | rest], footnotes, options} 27 end 28 29 defp _prepend_to_first_in4(element, {a, b, c, d}) do 30 {[element | a], b, c, d} 31 end 32 33 defp _block_fn_def(%Line.FnDef{} = fn_def) do 34 %Block.FnDef{id: fn_def.id, lnb: fn_def.lnb} 35 end 36 37 defp _complete_fn_def_block( 38 {input, [%Block.FnList{blocks: [open_fn | closed_fns]} | rest], footnotes, options}, 39 new_fn_def \\ nil 40 ) do 41 # `_footnotes1` should be empty but let us not change the shape of parse depending 42 # on options or the value of recursive? 43 {inner_blocks, _links, _footnotes1, options1} = EarmarkParser.Parser.parse(Enum.reverse(input), options, true) 44 closed_fn = %{open_fn | blocks: inner_blocks} 45 footnotes1 = Map.put(footnotes, closed_fn.id, closed_fn) 46 47 fn_blocks = 48 if new_fn_def do 49 [_block_fn_def(new_fn_def), closed_fn | closed_fns] 50 else 51 [closed_fn | closed_fns] 52 end 53 54 {[%Block.FnList{blocks: fn_blocks} | rest], footnotes1, options1} 55 end 56 57 end 58 # SPDX-License-Identifier: Apache-2.0