View Source Extractly.Toc (Extractly v0.5.4)
Extract Table Of Contents from a list of lines representing a Markdown document
Summary
Functions
Depending on the options the Table Of Contents extracted from the lines can be rendered in different formats, the default being Markdown
Functions
Depending on the options the Table Of Contents extracted from the lines can be rendered in different formats, the default being Markdown
Markdown
iex(1)> render(["# Hello", "## World"])
["- Hello", " - World"]
Numbered lists can be created too
iex(2)> render(["# Hello", "## World"], type: :ol)
["1. Hello", " 1. World"]
Oftentimes the level of headlines is adapted for output, e.g. ###
for the top
and #####
for the second level.
render
accounts for that
iex(3)> render(["### Alpha", "ignored", "##### Alpha.1", "", "### Beta"])
["- Alpha", " - Alpha.1", "- Beta"]
Remove Gaps
Sometimes there will be gaps in the levels of headlines and these holes might
not reflect semantic but rather stylistic concerns, if this is the case the option
remove_gaps
can be set to true
iex(4)> render(["# First", "### Third (but will go to second level)", "## Second"], remove_gaps: true)
["- First", " - Third (but will go to second level)", " - Second"]
Github README Links
This is all nice, however a TOC is most useful if links are provided.
render
can render Github like links to within the page, here is a real world example
from a Github README.md file
iex(5)> lines = [
...(5)> "## Usage",
...(5)> "### API",
...(5)> "#### EarmarkParser.as_ast/2",
...(5)> "### Support",
...(5)> ]
...(5)> render(lines, gh_links: true)
[
"- [Usage](#usage)",
" - [API](#api)",
" - [EarmarkParser.as_ast/2](#earmarkparseras_ast2)",
" - [Support](#support)",
]
HTML
Sometimes it might be appropriate to generate HTML directly
iex(6)> render(["## One", "### Two"], format: :html)
["<ul>", "<li>One<ul>", "<li>Two</li>", "</ul></li>", "</ul>"]
Exlcuding levels and changing list styles
Let us examine these two options with HTML output, they work too for Markdown of course, but are meaningless with the more raw output formats
So we do not want to include levels greater than, say 3, and we also want to ignore top level headlines, probably because only one top level part has sublevels
iex(7)> document = [
...(7)> "# Ignore",
...(7)> "# Too, but not what's below",
...(7)> "## Synopsis",
...(7)> "## Description",
...(7)> "### API",
...(7)> "#### too detailed",
...(7)> "### Tips & Tricks",
...(7)> "# Ignored again"
...(7)> ]
...(7)> render(document, format: :html, min_level: 2, max_level: 3, start: 5, type: :ol)
[
~S{<ol start="5">},
~S{<li>Synopsis</li>},
~S{<li>Description<ol>},
~S{<li>API</li>},
~S{<li>Tips & Tricks</li>},
~S{</ol></li>},
~S{</ol>},
]
PushList
Either a linear PushList
iex(8)> render(["# I", "## I.1", "## I.2", "### I.2.(i)", "# II", "### II.1.(ii)"], format: :push_list)
["I", :open, "I.1", "I.2", :open, "I.2.(i)", :close, :close, "II", :open, :open, "II.1.(ii)", :close, :close]
AST tree
iex(9)> render(["# I", "## I.1", "## I.2", "### I.2.(i)", "# II", "### II.1.(ii)"], format: :ast)
["I", ["I.1", "I.2", ["I.2.(i)"]], "II", [["II.1.(ii)"]]]
Unsupported Formats
iex(9)> render(["# Does not really matter"], format: :unknown)
{:error, "Unsupported format: unknown in render"}