Description
Right now each content block produces markdown strings, which requires a lot of string manipulation. For example, the title
block replaces newlines in its value, otherwise, the title would be broken:
# Tiltle with
newline is half-broken
We should use an AST structure closely resembling markdown and use it instead:
func Title(size int, text string) ContentNode
func Text(text string) ContentNode
func List(kind ListKind, items [] ContentNode) ContentNode
// And so on
And use it to avoid repeated validation:
List(Unordered, []ContentNode{Text("list item, but it can contain\n * and not be split into two")})
This also decouples us from markdown, making it possible for data sinks to render a document in a custom format (html
, latex
, or, of course, markdown
...) from our ContentNode structure. Also, this makes the content more easily inspectable and traversable for meta-content providers such as toc
.
I considered using goldmark's AST instead of creating our own, but their AST types are assumed to be valid markdown (since they usually come out of their markdown parser), while ours need to be validated/adjusted before we can pass them as a valid markdown.
Since our AST would be based on markdown it would be straightforward to implement ContentNode
-> goldmark/ast.Node
converter, after which we can use goldmark-markdown to render goldmark AST
back into markdown, built-in renderer to produce HTML or goldmark-latex to produce LaTeX code.