Merge pull request 'first version of outline' (#201) from devel into main
Reviewed-on: #201
This commit is contained in:
commit
1ff4deaa21
2 changed files with 55 additions and 19 deletions
|
@ -3,19 +3,39 @@ defmodule ChiyaWeb.Outline do
|
||||||
@heading_regex ~r/^(#+)\s(.+)$/
|
@heading_regex ~r/^(#+)\s(.+)$/
|
||||||
|
|
||||||
def get(markdown) do
|
def get(markdown) do
|
||||||
headings =
|
@outline_regex
|
||||||
@outline_regex
|
|> Regex.scan(markdown, capture: :all)
|
||||||
|> Regex.scan(markdown, capture: :all)
|
|> List.flatten()
|
||||||
|
|> Enum.map(&into_map/1)
|
||||||
Enum.chunk_by(headings, fn h -> nil end)
|
|> into_tree([])
|
||||||
end
|
|
||||||
|
|
||||||
def level(heading) do
|
|
||||||
Regex.scan(@heading_regex, heading)
|
|
||||||
|> Enum.map(fn [_, level, heading] ->
|
|
||||||
[level_from_string(level), heading]
|
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp level_from_string(string), do: String.length(string)
|
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
|
end
|
||||||
|
|
|
@ -5,16 +5,32 @@ defmodule ChiyaWeb.OutlineTest do
|
||||||
|
|
||||||
describe "extract_outline/1" do
|
describe "extract_outline/1" do
|
||||||
test "extracts headlines from markdown" do
|
test "extracts headlines from markdown" do
|
||||||
markdown = "# Heading\nsome paragraph\n## Sub Heading\n# Second Heading"
|
markdown =
|
||||||
|
"# Heading\nsome paragraph\n## Sub Heading\nsome text\n## Second Sub Heading\nmore text\n# Second Heading"
|
||||||
|
|
||||||
assert [{1, "Heading", [{2, "Sub Heading", []}]}, {1, "Second Heading", []}] =
|
result = [
|
||||||
Outline.get(markdown)
|
%{
|
||||||
|
level: 1,
|
||||||
|
text: "Heading",
|
||||||
|
children: [
|
||||||
|
%{level: 2, text: "Sub Heading", children: []},
|
||||||
|
%{level: 2, text: "Second Sub Heading", children: []}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
%{level: 1, text: "Second Heading", children: []}
|
||||||
|
]
|
||||||
|
|
||||||
|
assert result == Outline.get(markdown)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "outline_level/1" do
|
test "extracts headlines from markdown 2" do
|
||||||
test "extracts outline level" do
|
markdown = "## Second Level"
|
||||||
assert {1, "Heading"} = Outline.level("# Heading")
|
|
||||||
end
|
result = [
|
||||||
|
%{level: 2, text: "Second Level", children: []}
|
||||||
|
]
|
||||||
|
|
||||||
|
assert result == Outline.get(markdown)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue