[ANN] MarkdownAST.jl: abstract syntax trees of Markdown documents

Motivated by the desire to have a better representation of Markdown documents in Julia for Documenter, I am happy to announce a package for working with Markdown abstract syntax trees (ASTs).

Its goal is to provide an API for working with Markdown ASTs and also to function as a relatively lightweight interface package for sharing Markdown trees between different packages (like parsers and document generators).

To give a sense of what the package does, the following small Markdown document

# Markdown document

Hello [world](https://example.com/)!

can be constructed as the following tree using the MarkdownAST @ast macro DSL

using MarkdownAST: @ast, Document, Heading, Paragraph, Link
@ast Document() do
    Heading(1) do
        "Markdown document"
    Paragraph() do
        "Hello "
        Link("https://example.com/", "") do

Each node of the tree is a Node object that wraps an element (giving each node its semantic meaning; like Link or Paragraph) and references other Nodes (parent, sibling, and child nodes). Unlike the Markdown standard library AST, this provides a type-stable way of traversing ASTs, and it also implements the AbstractTrees.jl interface.

  • A lot of the core design is derived from @mike’s CommonMark.jl (in large parts, I just documented the design and added additional APIs for working with the trees). Currently, MarkdownAST is staying pretty close to CommonMark, and once MarkdownAST is stable, I hope we can switch CommonMark over to it internally.
  • The package can also convert to and from the Markdown standard library AST.
  • The current API is preliminary, and there will likely be a few breaking iterations to it. With that in mind, I would be very keen to get feedback on the design from anyone who might want to use MarkdownAST — please do open an issue (or a PR), or chime in on some of the existing ones.
  • In the long run, I hope this package is a step towards replacing the current Markdown standard library (see also JuliaLang/julia#37337).

Finally, I would like to acknowledge the funding from the Julia project (via NumFOCUS) that enabled this work!