chiya/lib/chiya_web/outline.ex
2023-07-10 23:11:56 +02:00

41 lines
1.1 KiB
Elixir

defmodule ChiyaWeb.Outline do
@outline_regex ~r/\#{1,6}\s.+/
@heading_regex ~r/^(#+)\s(.+)$/
def get(markdown) do
@outline_regex
|> Regex.scan(markdown, capture: :all)
|> List.flatten()
|> Enum.map(&into_map/1)
|> into_tree([])
end
defp level_from_string(string), do: String.length(string)
defp into_map(heading) do
[[_, level, heading]] = Regex.scan(@heading_regex, heading)
%{level: level_from_string(level), text: heading, children: []}
end
defp into_tree([], result), do: result
defp into_tree([head | tail], result) do
level = head.level
# Split the remaining items (tail) at the next
# same level element as the current (head)
# The first list will be the children of the head,
# the second list will be the new list
{children, new_list} =
Enum.split_while(tail, fn heading ->
level < heading.level
end)
# add the children to the current item
head = Map.put(head, :children, children)
# call again with new list and current item
# added to result
into_tree(new_list, result ++ [head])
end
end