diff --git a/dev/astmacro/index.html b/dev/astmacro/index.html index 8ea3bdf..cdf0e1f 100644 --- a/dev/astmacro/index.html +++ b/dev/astmacro/index.html @@ -10,4 +10,4 @@ Paragraph() do "Some paragraph text" end -end

Strings are interpreted as Text(s) elements.

source +end

Strings are interpreted as Text(s) elements.

source diff --git a/dev/elements/index.html b/dev/elements/index.html index b7aa2cd..1f7251d 100644 --- a/dev/elements/index.html +++ b/dev/elements/index.html @@ -1,2 +1,2 @@ -Markdown AST elements · MarkdownAST

Markdown AST elements

Every node in the Markdown abstract syntax tree (AST) is associated with an element[1], providing semantic information to the node (e.g. that the node is a paragraph, or a inline code snippet). In MarkdownAST, each element is an instance of some subtype of AbstractElement, and may (but does not have to) have fields that contain additional information about how to interpret the element (e.g. the language tag of a code block).

MarkdownAST.AbstractElementType
abstract type AbstractElement

A supertype of all Markdown AST element types.

User-defined elements must not directly inherit this type, but either AbstractBlock or AbstractInline instead.

Interface

  • By default, each element is assumed to be a leaf element that can not contain other elements as children. An iscontainer method can be defined to override this.

  • can_contain can be overridden to constrain what elements can be the direct children of another node. By default, inline container elements can contain any inline element and block container elements can contain any block element.

  • Elements that are implemented as mutable structs should probably implement the equality operator (==), to make sure that two different instances that are semantically the same would be considered equal.

source

If an element does contain some fields, it is usually a mutable type so that it would be possible to update it.

When the Markdown AST is represented using Nodes, the corresponding elements can be accessed via the .element field.

Block and inline nodes

In the Markdown AST, the elements can, broadly, be divided into two categories: block and inline elements. The block elements represent the main, top-level structural elements of a document (e.g. paragraphs, headings, block quotes), whereas inline elements represent components of a paragraph (e.g. bold or plain text, inline math or code snippets). In MarkdownAST, every block and inline element is a subtype of AbstractBlock and AbstractInline, respectively.

Constraints on children

As the AST is a tree, nodes (or elements) can have other nodes or elements as children. However, it does not generally make sense for a node to have arbitrary nodes as children. For this purpose, there are methods to ensure

First, for some elements it does not make sense for them to have any children at all (i.e. they will always be leaf nodes). Whether or not an node is a container node (i.e. whether or not it can have other elements as children) is determined by the iscontainer function.

MarkdownAST.iscontainerFunction
iscontainer(::T) where {T <: AbstractElement} -> Bool

Determines if the particular Markdown element is a container, meaning that is can contain child nodes. Adding child nodes to non-container (leaf) nodes is prohibited.

By default, each user-defined element is assumed to be a leaf node, and each container node should override this method.

source

However, a more fine-grained control over the allowed child nodes is often necessary. For example, while a paragraph can have child nodes, it does not make sense for a paragraph to have another paragraph as a child node, and in fact it should only have inline nodes as children. Such relationships are defined by the can_contain function (e.g. for a Paragraph it only returns true if the child element is an AbstractInline).

MarkdownAST.can_containFunction
can_contain(parent::AbstractElement, child::AbstractElement) -> Bool

Determines if the child element can be a direct child of the parent element.

This is used to constrain the types of valid children for some elements, such as for the elements that are only allowed to have inline child elements or to make sure that Lists only contain Items.

If the parent element is a leaf node (iscontainer(parent) === false)

Extended help

When extending can_contain for custom abstract classes Markdown elements, similar to the AbstractBlock or AbstractInline elements classes, the second argument to can_contain should always be constrained exactly to ::AbstractElement, in order to avoid method ambiguities. I.e. for some abstract type AbstractT <: AbstractElement, the method should be defined as

can_contain(parent::AbstractT, child::AbstractElement) = ...

For concrete parent types T, where the first argument is constrained as parent::T it should then be fine to take advantage of multiple dispatch when implementing can_contain.

source

Usually, the constraint is whether a container node can contain only block elements or only inline elements.

Note

Sometimes it might be desireable to have even more sophisticated constraints on the elements (e.g. perhaps two elements are not allowed to directly follow each other as children of another node). However, it is not practical to over-complicate the APIs here, and simply restricting the child elements of another element seems to strike a good balance.

Instead, in cases where it becomes possible to construct trees that have questionable semantics due to a weird structure that can not be restricted with can_contain, the elements should carefully document how to interpret such problematic trees (e.g. how to interpret a table that has no rows and columns).

CommonMark elements

The CommonMark specification specifies a set of block and inline nodes that can be used to represent Markdown documents.

MarkdownAST.BlockQuoteType
struct BlockQuote <: AbstractBlock

A singleton container element representing a block quote. It must contain other block elements as children.

source
MarkdownAST.CodeType
mutable struct Code <: AbstractInline

Inline element representing an inline code span.

Fields

  • .code :: String: raw code

Constructors

Code(code::AbstractString)
source
MarkdownAST.CodeBlockType
mutable struct CodeBlock <: AbstractBlock

A leaf block representing a code block.

Fields

  • .info :: String: code block info string (e.g. the programming language label)
  • .code :: String: code content of the block
source
MarkdownAST.EmphType
struct Emph <: AbstractInline

Inline singleton element for emphasis (e.g. italic) styling.

source
MarkdownAST.HTMLInlineType
mutable struct HTMLInline <: AbstractInline

Inline leaf element representing raw inline HTML.

Fields

  • .html :: String: inline raw HTML

Constructors

HTMLInline(html::AbstractString)
source
MarkdownAST.HeadingType
mutable struct Heading <: AbstractBlock

Represents a heading of a specific level. Can only contain inline elements as children.

Fields

  • .level :: Int: the level of the heading, must be between 1 and 6.

Constructors

Heading(level :: Integer)
source
MarkdownAST.ImageType
mutable struct Image <: AbstractInline

Inline element representing a link to an image. Can contain other inline nodes that will represent the image description.

Fields

  • .destination :: String: destination URL
  • .title :: String: title attribute of the link

Constructors

Image(destination::AbstractString, title::AbstractString)
source
MarkdownAST.LineBreakType
struct LineBreak <: AbstractInline

Represents a hard line break in a sequence of inline nodes that should lead to a newline when rendered.

source
MarkdownAST.LinkType
mutable struct Link <: AbstractInline

Inline element representing a link. Can contain other inline nodes, but should not contain other Links.

Fields

  • .destination :: String: destination URL
  • .title :: String: title attribute of the link

Constructors

Link(destination::AbstractString, title::AbstractString)
source
MarkdownAST.ListType
mutable struct List <: AbstractBlock

Represents a Markdown list. The children of a List should only be Items, representing individual list items.

Fields

  • .type :: Symbol: determines if this is an ordered (:ordered) or an unordered (:bullet) list.
  • .tight :: Bool: determines if the list should be rendered tight or loose.

Constructors

julia List(type :: Symbol, tight :: Bool)`

source
MarkdownAST.ParagraphType
struct Paragraph <: AbstractBlock

Singleton container representing a paragraph, containing only inline nodes.

source
MarkdownAST.SoftBreakType
struct SoftBreak <: AbstractInline

Represents a soft break which can be rendered as a space instead.

source
MarkdownAST.StrongType
struct Strong <: AbstractInline

Inline singleton element for strong (e.g. bold) styling.

source
MarkdownAST.TextType
mutable struct Text <: AbstractInline

Inline leaf element representing a simply a span of text.

source
MarkdownAST.ThematicBreakType
struct ThematicBreak <: AbstractBlock

A singleton leaf element representing a thematic break (often rendered as a horizontal rule).

source

Julia extension elements

The Julia version of Markdown contains additional elements that do not exists in the CommonMark specification (such as tables or math). However, as MarkdownAST is meant to be interoperable with the Markdown standard library parser, it also supports additional elements to accurately represent the Julia Flavored Markdown documents.

MarkdownAST.AdmonitionType
mutable struct Admonition <: AbstractBlock

A container block representing an admonition. Can contain other block elements as children.

Fields

  • .category :: String: admonition category
  • .title :: String: admonition title

Constructors

Admonition(category :: AbstractString, title :: AbstractString)
source
MarkdownAST.DisplayMathType
mutable struct DisplayMath <: AbstractBlock

Leaf block representing a mathematical display equation.

Fields

  • .math :: String: TeX code of the display equation

Constructors

DisplayMath(math :: AbstractString)
source
MarkdownAST.FootnoteDefinitionType
mutable struct FootnoteDefinition <: AbstractBlock

Container block representing the definition of a footnote, containing the definitions of the footnote as children.

Fields

  • .id :: String: label of the footnote

Constructors

FootnoteDefinition(id :: AbstractString)
source
MarkdownAST.FootnoteLinkType
mutable struct FootnoteLink <: AbstractInline

Inline leaf element representing a link to a footnote.

Fields

  • .id :: String: label of the footnote

Constructors

FootnoteLink(id :: AbstractString)
source
MarkdownAST.InlineMathType
mutable struct InlineMath <: AbstractInline

Leaf inline element representing an inline mathematical expression.

Fields

  • .math :: String: TeX code for the inline equation

Constructors

InlineMath(math::String)
source
MarkdownAST.JuliaValueType
struct JuliaValue <: AbstractInline

Inline leaf element for interpolation of Julia expressions and their evaluated values. Two JuliaValue objects are considered equal if the Julia objects they refer to are equal (even if they originate from different expressions).

Fields

  • .ex :: Any: contains the original Julia expression (e.g. Expr, Symbol, or some literal value)
  • .ref :: Any: stores the Julia object the expression evaluates to

Constructors

JuliaValue(ex, ref = nothing)
source

Tables

Tables are build up from the following elements: Table, TableBody, TableCell, TableHeader, TableRow.

MarkdownAST.TableType
mutable struct Table <: TableComponent

Container block representing a table, an extension of the CommonMark spec, and should be interpreted as a rectangular grid of cells with a fixed number of rows and columns.

Since we can not constrain e.g. the number of children or in what order child nodes can appear in a Markdown tree, it is possible to construct tables that can be difficult to interpret. The following rules should be followed when interpreting tables:

  • The decendants of a Table node should be exactly be a single TableHeader followed by a TableBody.
    • If the first child is a TableBody, the header row is assumed to be a list of empty cells.
    • The rows from any nodes following the first TableBody are interpreted as additional table body rows, even if they are contained in a TableHeader.
    • A Table with no children is interpreted as a table with a single empty header cell.
  • A TableHeader that is the first child of a Table should only contain one TableRow.
    • If a TableHeader that is the first child of a Table contains additional rows, the additional rows are interpreted to be body rows.
    • If a TableHeader that is the first child of a Table is empty, it is assumed to represent a header row with empty cells.
  • Each TableRow of a table should contain the same number of TableCell.
    • Any row that has fewer cells than the longest row should be interpreted as if it is padded with additional empty cells.
source
MarkdownAST.TableBodyType
struct TableBody <: TableComponent

Represents the body of a Markdown table and should only occur as the second child of a Table node. See Table for information on how to handle other circumstances.

It can only contain TableRow elements.

source
MarkdownAST.TableCellType
mutable struct TableCell <: TableComponent

Represents a single cell in a Markdown table. Can contain inline nodes.

  • align :: Symbol: declares the alignment of a cell (can be :left, :right, or :center), and should match the .spec field of the ancestor Table
  • header :: Bool: true if the cell is part of a header row, and should only be true if the cell belongs to a row that is the first
  • column :: Int: the column index of the cell, which should match its position in the Markdown tree

It is possible that the fields of TableCell are inconsistent with the real structure of the Markdown tree, in which case the structure or the .spec field should take precedence when interpreting the elements.

source
MarkdownAST.TableHeaderType
struct TableHeader <: TableComponent

Represents the header portion of a Markdown table and should only occur as the first child of a Table node and should only contain a single TableRow as a child. See Table for information on how to handle other circumstances.

It can only contain TableRow elements.

source

In addition, to help with the complexity of the table structure, the following helper functions can be used when working with Table elements.

MarkdownAST.tablerowsFunction
tablerows(node::Node)

Returns an iterable object containing the all the TableRow elements of a table, bypassing the intermediate TableHeader and TableBody nodes. Requires node to be a Table element.

The first element of the iterator should be interpreted to be the header of the table.

source
MarkdownAST.tablesizeFunction
tablesize(node::Node, [dim])

Similar to size, returns the number of rows and/or columns of a Table element. The optional dim argument can be passed to return just either the number of rows or columns, and must be 1 to obtain the number of rows, and 2 to obtain the number of columns.

Complexity

Determining the number of columns is an $O(n \times m)$ operation in the number of rows and columns, due to the required traversal of the linked nodes. Determining only the number of rows with tablesize(node, 1) is an $O(n)$ operation.

source

Other elements

Document is the root element of a Markdown document.

Index

  • 1This terminology mirrors how each node of the HTML DOM tree is some HTML element.
+Markdown AST elements · MarkdownAST

Markdown AST elements

Every node in the Markdown abstract syntax tree (AST) is associated with an element[1], providing semantic information to the node (e.g. that the node is a paragraph, or a inline code snippet). In MarkdownAST, each element is an instance of some subtype of AbstractElement, and may (but does not have to) have fields that contain additional information about how to interpret the element (e.g. the language tag of a code block).

MarkdownAST.AbstractElementType
abstract type AbstractElement

A supertype of all Markdown AST element types.

User-defined elements must not directly inherit this type, but either AbstractBlock or AbstractInline instead.

Interface

  • By default, each element is assumed to be a leaf element that can not contain other elements as children. An iscontainer method can be defined to override this.

  • can_contain can be overridden to constrain what elements can be the direct children of another node. By default, inline container elements can contain any inline element and block container elements can contain any block element.

  • Elements that are implemented as mutable structs should probably implement the equality operator (==), to make sure that two different instances that are semantically the same would be considered equal.

source

If an element does contain some fields, it is usually a mutable type so that it would be possible to update it.

When the Markdown AST is represented using Nodes, the corresponding elements can be accessed via the .element field.

Block and inline nodes

In the Markdown AST, the elements can, broadly, be divided into two categories: block and inline elements. The block elements represent the main, top-level structural elements of a document (e.g. paragraphs, headings, block quotes), whereas inline elements represent components of a paragraph (e.g. bold or plain text, inline math or code snippets). In MarkdownAST, every block and inline element is a subtype of AbstractBlock and AbstractInline, respectively.

Constraints on children

As the AST is a tree, nodes (or elements) can have other nodes or elements as children. However, it does not generally make sense for a node to have arbitrary nodes as children. For this purpose, there are methods to ensure

First, for some elements it does not make sense for them to have any children at all (i.e. they will always be leaf nodes). Whether or not an node is a container node (i.e. whether or not it can have other elements as children) is determined by the iscontainer function.

MarkdownAST.iscontainerFunction
iscontainer(::T) where {T <: AbstractElement} -> Bool

Determines if the particular Markdown element is a container, meaning that is can contain child nodes. Adding child nodes to non-container (leaf) nodes is prohibited.

By default, each user-defined element is assumed to be a leaf node, and each container node should override this method.

source

However, a more fine-grained control over the allowed child nodes is often necessary. For example, while a paragraph can have child nodes, it does not make sense for a paragraph to have another paragraph as a child node, and in fact it should only have inline nodes as children. Such relationships are defined by the can_contain function (e.g. for a Paragraph it only returns true if the child element is an AbstractInline).

MarkdownAST.can_containFunction
can_contain(parent::AbstractElement, child::AbstractElement) -> Bool

Determines if the child element can be a direct child of the parent element.

This is used to constrain the types of valid children for some elements, such as for the elements that are only allowed to have inline child elements or to make sure that Lists only contain Items.

If the parent element is a leaf node (iscontainer(parent) === false)

Extended help

When extending can_contain for custom abstract classes Markdown elements, similar to the AbstractBlock or AbstractInline elements classes, the second argument to can_contain should always be constrained exactly to ::AbstractElement, in order to avoid method ambiguities. I.e. for some abstract type AbstractT <: AbstractElement, the method should be defined as

can_contain(parent::AbstractT, child::AbstractElement) = ...

For concrete parent types T, where the first argument is constrained as parent::T it should then be fine to take advantage of multiple dispatch when implementing can_contain.

source

Usually, the constraint is whether a container node can contain only block elements or only inline elements.

Note

Sometimes it might be desireable to have even more sophisticated constraints on the elements (e.g. perhaps two elements are not allowed to directly follow each other as children of another node). However, it is not practical to over-complicate the APIs here, and simply restricting the child elements of another element seems to strike a good balance.

Instead, in cases where it becomes possible to construct trees that have questionable semantics due to a weird structure that can not be restricted with can_contain, the elements should carefully document how to interpret such problematic trees (e.g. how to interpret a table that has no rows and columns).

CommonMark elements

The CommonMark specification specifies a set of block and inline nodes that can be used to represent Markdown documents.

MarkdownAST.BlockQuoteType
struct BlockQuote <: AbstractBlock

A singleton container element representing a block quote. It must contain other block elements as children.

source
MarkdownAST.CodeType
mutable struct Code <: AbstractInline

Inline element representing an inline code span.

Fields

  • .code :: String: raw code

Constructors

Code(code::AbstractString)
source
MarkdownAST.CodeBlockType
mutable struct CodeBlock <: AbstractBlock

A leaf block representing a code block.

Fields

  • .info :: String: code block info string (e.g. the programming language label)
  • .code :: String: code content of the block
source
MarkdownAST.EmphType
struct Emph <: AbstractInline

Inline singleton element for emphasis (e.g. italic) styling.

source
MarkdownAST.HTMLInlineType
mutable struct HTMLInline <: AbstractInline

Inline leaf element representing raw inline HTML.

Fields

  • .html :: String: inline raw HTML

Constructors

HTMLInline(html::AbstractString)
source
MarkdownAST.HeadingType
mutable struct Heading <: AbstractBlock

Represents a heading of a specific level. Can only contain inline elements as children.

Fields

  • .level :: Int: the level of the heading, must be between 1 and 6.

Constructors

Heading(level :: Integer)
source
MarkdownAST.ImageType
mutable struct Image <: AbstractInline

Inline element representing a link to an image. Can contain other inline nodes that will represent the image description.

Fields

  • .destination :: String: destination URL
  • .title :: String: title attribute of the link

Constructors

Image(destination::AbstractString, title::AbstractString)
source
MarkdownAST.LineBreakType
struct LineBreak <: AbstractInline

Represents a hard line break in a sequence of inline nodes that should lead to a newline when rendered.

source
MarkdownAST.LinkType
mutable struct Link <: AbstractInline

Inline element representing a link. Can contain other inline nodes, but should not contain other Links.

Fields

  • .destination :: String: destination URL
  • .title :: String: title attribute of the link

Constructors

Link(destination::AbstractString, title::AbstractString)
source
MarkdownAST.ListType
mutable struct List <: AbstractBlock

Represents a Markdown list. The children of a List should only be Items, representing individual list items.

Fields

  • .type :: Symbol: determines if this is an ordered (:ordered) or an unordered (:bullet) list.
  • .tight :: Bool: determines if the list should be rendered tight or loose.

Constructors

julia List(type :: Symbol, tight :: Bool)`

source
MarkdownAST.ParagraphType
struct Paragraph <: AbstractBlock

Singleton container representing a paragraph, containing only inline nodes.

source
MarkdownAST.SoftBreakType
struct SoftBreak <: AbstractInline

Represents a soft break which can be rendered as a space instead.

source
MarkdownAST.StrongType
struct Strong <: AbstractInline

Inline singleton element for strong (e.g. bold) styling.

source
MarkdownAST.TextType
mutable struct Text <: AbstractInline

Inline leaf element representing a simply a span of text.

source
MarkdownAST.ThematicBreakType
struct ThematicBreak <: AbstractBlock

A singleton leaf element representing a thematic break (often rendered as a horizontal rule).

source

Julia extension elements

The Julia version of Markdown contains additional elements that do not exists in the CommonMark specification (such as tables or math). However, as MarkdownAST is meant to be interoperable with the Markdown standard library parser, it also supports additional elements to accurately represent the Julia Flavored Markdown documents.

MarkdownAST.AdmonitionType
mutable struct Admonition <: AbstractBlock

A container block representing an admonition. Can contain other block elements as children.

Fields

  • .category :: String: admonition category
  • .title :: String: admonition title

Constructors

Admonition(category :: AbstractString, title :: AbstractString)
source
MarkdownAST.DisplayMathType
mutable struct DisplayMath <: AbstractBlock

Leaf block representing a mathematical display equation.

Fields

  • .math :: String: TeX code of the display equation

Constructors

DisplayMath(math :: AbstractString)
source
MarkdownAST.FootnoteDefinitionType
mutable struct FootnoteDefinition <: AbstractBlock

Container block representing the definition of a footnote, containing the definitions of the footnote as children.

Fields

  • .id :: String: label of the footnote

Constructors

FootnoteDefinition(id :: AbstractString)
source
MarkdownAST.FootnoteLinkType
mutable struct FootnoteLink <: AbstractInline

Inline leaf element representing a link to a footnote.

Fields

  • .id :: String: label of the footnote

Constructors

FootnoteLink(id :: AbstractString)
source
MarkdownAST.InlineMathType
mutable struct InlineMath <: AbstractInline

Leaf inline element representing an inline mathematical expression.

Fields

  • .math :: String: TeX code for the inline equation

Constructors

InlineMath(math::String)
source
MarkdownAST.JuliaValueType
struct JuliaValue <: AbstractInline

Inline leaf element for interpolation of Julia expressions and their evaluated values. Two JuliaValue objects are considered equal if the Julia objects they refer to are equal (even if they originate from different expressions).

Fields

  • .ex :: Any: contains the original Julia expression (e.g. Expr, Symbol, or some literal value)
  • .ref :: Any: stores the Julia object the expression evaluates to

Constructors

JuliaValue(ex, ref = nothing)
source

Tables

Tables are build up from the following elements: Table, TableBody, TableCell, TableHeader, TableRow.

MarkdownAST.TableType
mutable struct Table <: TableComponent

Container block representing a table, an extension of the CommonMark spec, and should be interpreted as a rectangular grid of cells with a fixed number of rows and columns.

Since we can not constrain e.g. the number of children or in what order child nodes can appear in a Markdown tree, it is possible to construct tables that can be difficult to interpret. The following rules should be followed when interpreting tables:

  • The decendants of a Table node should be exactly be a single TableHeader followed by a TableBody.
    • If the first child is a TableBody, the header row is assumed to be a list of empty cells.
    • The rows from any nodes following the first TableBody are interpreted as additional table body rows, even if they are contained in a TableHeader.
    • A Table with no children is interpreted as a table with a single empty header cell.
  • A TableHeader that is the first child of a Table should only contain one TableRow.
    • If a TableHeader that is the first child of a Table contains additional rows, the additional rows are interpreted to be body rows.
    • If a TableHeader that is the first child of a Table is empty, it is assumed to represent a header row with empty cells.
  • Each TableRow of a table should contain the same number of TableCell.
    • Any row that has fewer cells than the longest row should be interpreted as if it is padded with additional empty cells.
source
MarkdownAST.TableBodyType
struct TableBody <: TableComponent

Represents the body of a Markdown table and should only occur as the second child of a Table node. See Table for information on how to handle other circumstances.

It can only contain TableRow elements.

source
MarkdownAST.TableCellType
mutable struct TableCell <: TableComponent

Represents a single cell in a Markdown table. Can contain inline nodes.

  • align :: Symbol: declares the alignment of a cell (can be :left, :right, or :center), and should match the .spec field of the ancestor Table
  • header :: Bool: true if the cell is part of a header row, and should only be true if the cell belongs to a row that is the first
  • column :: Int: the column index of the cell, which should match its position in the Markdown tree

It is possible that the fields of TableCell are inconsistent with the real structure of the Markdown tree, in which case the structure or the .spec field should take precedence when interpreting the elements.

source
MarkdownAST.TableHeaderType
struct TableHeader <: TableComponent

Represents the header portion of a Markdown table and should only occur as the first child of a Table node and should only contain a single TableRow as a child. See Table for information on how to handle other circumstances.

It can only contain TableRow elements.

source

In addition, to help with the complexity of the table structure, the following helper functions can be used when working with Table elements.

MarkdownAST.tablerowsFunction
tablerows(node::Node)

Returns an iterable object containing the all the TableRow elements of a table, bypassing the intermediate TableHeader and TableBody nodes. Requires node to be a Table element.

The first element of the iterator should be interpreted to be the header of the table.

source
MarkdownAST.tablesizeFunction
tablesize(node::Node, [dim])

Similar to size, returns the number of rows and/or columns of a Table element. The optional dim argument can be passed to return just either the number of rows or columns, and must be 1 to obtain the number of rows, and 2 to obtain the number of columns.

Complexity

Determining the number of columns is an $O(n \times m)$ operation in the number of rows and columns, due to the required traversal of the linked nodes. Determining only the number of rows with tablesize(node, 1) is an $O(n)$ operation.

source

Other elements

Document is the root element of a Markdown document.

Index

  • 1This terminology mirrors how each node of the HTML DOM tree is some HTML element.
diff --git a/dev/index.html b/dev/index.html index 0f75bbd..dcd4a2f 100644 --- a/dev/index.html +++ b/dev/index.html @@ -1,2 +1,2 @@ -Introduction · MarkdownAST

MarkdownAST

The structure of a Markdown file can be represented as an abstract syntax tree. The MarkdownAST package defines a Julia interface for representing such trees to facilitate the interoperability between different packages that deal with Markdown documents in different ways.

While the primary goal is to represent Markdown documents, the tree structure, implemented by the Node type and the AbstractElement subtypes, is intentionally generic and can also be used to represent more general documents.

+Introduction · MarkdownAST

MarkdownAST

The structure of a Markdown file can be represented as an abstract syntax tree. The MarkdownAST package defines a Julia interface for representing such trees to facilitate the interoperability between different packages that deal with Markdown documents in different ways.

While the primary goal is to represent Markdown documents, the tree structure, implemented by the Node type and the AbstractElement subtypes, is intentionally generic and can also be used to represent more general documents.

diff --git a/dev/iteration/index.html b/dev/iteration/index.html index bb681d9..3ee16cd 100644 --- a/dev/iteration/index.html +++ b/dev/iteration/index.html @@ -41,4 +41,4 @@ MarkdownAST.Text("AbstractTrees") MarkdownAST.Text(".") MarkdownAST.Text("The use it, load the package with") -MarkdownAST.CodeBlock("julia", "using AbstractTrees") +MarkdownAST.CodeBlock("julia", "using AbstractTrees") diff --git a/dev/node/index.html b/dev/node/index.html index c8d02a9..9e1ee21 100644 --- a/dev/node/index.html +++ b/dev/node/index.html @@ -1,9 +1,9 @@ -Tree node interface · MarkdownAST

Tree node interface

The Markdown abstract syntax tree (AST) is a tree of Markdown elements. In order to avoid type instabilities when performing basic operations on a tree, such as traversin it, it is implemented by linking together instances of the Node type. Each Node instance functions as a container for some AbstractElement.

The Node type has various properties that can be used to access information about the structure of the tree, but it is generally not possible to set them directly. Changing the structure of a tree (e.g. to adding child nodes), should be done with the help of the various functions and methods to MarkdownAST provides for mutating the tree.

MarkdownAST.NodeType
mutable struct Node{M}

Implements a linked list type representation of a Markdown abstract syntax tree, where each node contains pointers to the children and parent nodes, to make it possible to easily traverse the whole tree in any direction. Each node also contains an "element", which is an instance of some AbstractElement subtype, and can be accessed via the .element property. The element object contains the semantic information about the node (e.g. wheter it is a list or a paragraph).

Optionally, each node can also store additional meta information, which will be an object of type M (see also the .meta property). By default, the node does not contain any extra meta information and M = Nothing.

Constructors

Node(element :: AbstractElement)

Constructs a simple standalone node (not part of any tree) without any additional metadata (M = Nothing) containing the Markdown AST element c.

Node{M}(element :: AbstractElement, meta :: M)

Constructs a simple standalone node (not part of any tree) with the meta information meta, containing the Markdown AST element c.

Extended help

There are various properties that can be used to access the details of a node. Many of them can not be set directly though, as that could lead to an inconsistent tree. Similarly, the underlying fields of the struct should not be accessed directly.

  • .meta :: M: can be used to access or set the extra meta information of the node.
  • .element :: T where {T <: AbstractElement}: can be used to access or set the element corresponding to the node
  • .next :: Union{Node{M},Nothing}: access the next child node after this one, with the value set to nothing if there is no next child
  • .previous :: Union{Node{M},Nothing}: access the previous child node before this one, with the value set to nothing if there is no such node
  • .parent :: Union{Node{M},Nothing}: access the parent node of this node, with the value set to nothing if the node does not have a parent
  • .children: an iterable object of type NodeChildren that can be used to access and modify the child nodes of this node

The .children field is implemented with a wrapper type that implemements the iteration protocol. However, the exact type information etc. is an implementation detail, and one should only rely on the following documented APIs:

Other ways to work with child nodes that do not directly reference .children are:

  • To add new children between others, the insert_after!, insert_before! functions can be used to insert new children relative to a reference child node.
  • To remove a child from a node, the unlink! function can be used on the corresponding child node.

In addition, there are other functions and methods that can be used to work with nodes and trees:

source
Base.:==Method
==(x::Node, y::Node) -> Bool

Determines if two trees are equal by recursively walking through the whole tree (if need be) and comparing each node. Parent nodes are ignored when comparing for equality (so that it would be possible to compare subtrees). If the metadata type does not match, the two trees are not considered equal.

source

Accessing child nodes

Internally, to store the children, a node simply stores the reference to the first and the last child node, and each child stores the references to the next and previous child. The .children property is implemented simply as a lazy iterator of type NodeChildren that traverses the linked list. As such, some operations, such as determining the number of children a node has with length, can have unexpected $O(n)$ complexity.

MarkdownAST.NodeChildrenType
struct NodeChildren

The type of the the .children property of a Node which acts as an iterator over the children of a node. This type is mostly considered to be an implementation detail, and only has the following publicly defined APIs:

  • The name of the type NodeChildren, so that it could be dispatched on.
  • The .parent :: Node field that allows the user to access the parent node of the children.
source
Base.eltypeMethod
eltype(node.children::NodeChildren) = Node{M}

Returns the exact Node type of the tree, corresponding to the type of the elements of the .children iterator.

source
Base.lengthMethod
length(node.children::NodeChildren) -> Int

Returns the number of children of node :: Node.

As the children are stored as a linked list, this method has O(n) complexity. As such, to check there are any children at all, it is generally preferable to use isempty.

source
Base.isemptyMethod
isemtpy(node.children::NodeChildren) -> Bool

Can be called on the .children field of a node :: Node to determine whether or not the node has any child nodes.

source
Base.firstMethod
first(node.children::NodeChildren) -> Node

Returns the first child of the node :: Node, or throws an error if the node has no children.

source
Base.lastMethod
last(node.children::NodeChildren) -> Node

Returns the last child of the node :: Node, or throws an error if the node has no children.

source

Mutating the tree

The following functions and methods can be used to mutate the Markdown AST trees represented using Node objects. When using these methods, the consistency of the tree is preserved (i.e. the references between the affected nodes are correctly updated). Changing the structure of the tree in any other way should generally be avoided, since the code that operates on trees generally assumes a consistent tree, and will likely error or behave in unexpected ways on inconsistent trees.

Mutating the tree while traversing

Mutating the structure of the tree while traversing it with some iterator (e.g. .children or one of the AbstractTrees iterators) can lead to unexpected behavior and should generally be avoided. Updating the .element of a node while traversing, on the other hand, is fine. In general, replace! can be used to mutate a tree in arbitrary ways.

Base.replaceMethod
replace(f::Function, root::Node) -> Node

Creates a copy of the tree where all child nodes of root are recursively (post-order depth-first) replaced by the result of f(child).

The function f(child::Node) must return either a new Node to replace child or a Vector of nodes that will be inserted as siblings, replacing child.

Note that replace does not allow the construction of invalid trees, and element replacements that require invalid parent-child relationships (e.g., a block element as a child to an element expecting inlines) will throw an error.

Example

The following snippet removes links from the given AST. That is, it replaces Link nodes with their link text (which may contain nested inline markdown elements):

new_mdast = replace(mdast) do node
+Tree node interface · MarkdownAST

Tree node interface

The Markdown abstract syntax tree (AST) is a tree of Markdown elements. In order to avoid type instabilities when performing basic operations on a tree, such as traversin it, it is implemented by linking together instances of the Node type. Each Node instance functions as a container for some AbstractElement.

The Node type has various properties that can be used to access information about the structure of the tree, but it is generally not possible to set them directly. Changing the structure of a tree (e.g. to adding child nodes), should be done with the help of the various functions and methods to MarkdownAST provides for mutating the tree.

MarkdownAST.NodeType
mutable struct Node{M}

Implements a linked list type representation of a Markdown abstract syntax tree, where each node contains pointers to the children and parent nodes, to make it possible to easily traverse the whole tree in any direction. Each node also contains an "element", which is an instance of some AbstractElement subtype, and can be accessed via the .element property. The element object contains the semantic information about the node (e.g. wheter it is a list or a paragraph).

Optionally, each node can also store additional meta information, which will be an object of type M (see also the .meta property). By default, the node does not contain any extra meta information and M = Nothing.

Constructors

Node(element :: AbstractElement)

Constructs a simple standalone node (not part of any tree) without any additional metadata (M = Nothing) containing the Markdown AST element c.

Node{M}(element :: AbstractElement, meta :: M)

Constructs a simple standalone node (not part of any tree) with the meta information meta, containing the Markdown AST element c.

Extended help

There are various properties that can be used to access the details of a node. Many of them can not be set directly though, as that could lead to an inconsistent tree. Similarly, the underlying fields of the struct should not be accessed directly.

  • .meta :: M: can be used to access or set the extra meta information of the node.
  • .element :: T where {T <: AbstractElement}: can be used to access or set the element corresponding to the node
  • .next :: Union{Node{M},Nothing}: access the next child node after this one, with the value set to nothing if there is no next child
  • .previous :: Union{Node{M},Nothing}: access the previous child node before this one, with the value set to nothing if there is no such node
  • .parent :: Union{Node{M},Nothing}: access the parent node of this node, with the value set to nothing if the node does not have a parent
  • .children: an iterable object of type NodeChildren that can be used to access and modify the child nodes of this node

The .children field is implemented with a wrapper type that implemements the iteration protocol. However, the exact type information etc. is an implementation detail, and one should only rely on the following documented APIs:

Other ways to work with child nodes that do not directly reference .children are:

  • To add new children between others, the insert_after!, insert_before! functions can be used to insert new children relative to a reference child node.
  • To remove a child from a node, the unlink! function can be used on the corresponding child node.

In addition, there are other functions and methods that can be used to work with nodes and trees:

source
Base.:==Method
==(x::Node, y::Node) -> Bool

Determines if two trees are equal by recursively walking through the whole tree (if need be) and comparing each node. Parent nodes are ignored when comparing for equality (so that it would be possible to compare subtrees). If the metadata type does not match, the two trees are not considered equal.

source

Accessing child nodes

Internally, to store the children, a node simply stores the reference to the first and the last child node, and each child stores the references to the next and previous child. The .children property is implemented simply as a lazy iterator of type NodeChildren that traverses the linked list. As such, some operations, such as determining the number of children a node has with length, can have unexpected $O(n)$ complexity.

MarkdownAST.NodeChildrenType
struct NodeChildren

The type of the the .children property of a Node which acts as an iterator over the children of a node. This type is mostly considered to be an implementation detail, and only has the following publicly defined APIs:

  • The name of the type NodeChildren, so that it could be dispatched on.
  • The .parent :: Node field that allows the user to access the parent node of the children.
source
Base.eltypeMethod
eltype(node.children::NodeChildren) = Node{M}

Returns the exact Node type of the tree, corresponding to the type of the elements of the .children iterator.

source
Base.lengthMethod
length(node.children::NodeChildren) -> Int

Returns the number of children of node :: Node.

As the children are stored as a linked list, this method has O(n) complexity. As such, to check there are any children at all, it is generally preferable to use isempty.

source
Base.isemptyMethod
isemtpy(node.children::NodeChildren) -> Bool

Can be called on the .children field of a node :: Node to determine whether or not the node has any child nodes.

source
Base.firstMethod
first(node.children::NodeChildren) -> Node

Returns the first child of the node :: Node, or throws an error if the node has no children.

source
Base.lastMethod
last(node.children::NodeChildren) -> Node

Returns the last child of the node :: Node, or throws an error if the node has no children.

source

Mutating the tree

The following functions and methods can be used to mutate the Markdown AST trees represented using Node objects. When using these methods, the consistency of the tree is preserved (i.e. the references between the affected nodes are correctly updated). Changing the structure of the tree in any other way should generally be avoided, since the code that operates on trees generally assumes a consistent tree, and will likely error or behave in unexpected ways on inconsistent trees.

Mutating the tree while traversing

Mutating the structure of the tree while traversing it with some iterator (e.g. .children or one of the AbstractTrees iterators) can lead to unexpected behavior and should generally be avoided. Updating the .element of a node while traversing, on the other hand, is fine. In general, replace! can be used to mutate a tree in arbitrary ways.

Base.replaceMethod
replace(f::Function, root::Node) -> Node

Creates a copy of the tree where all child nodes of root are recursively (post-order depth-first) replaced by the result of f(child).

The function f(child::Node) must return either a new Node to replace child or a Vector of nodes that will be inserted as siblings, replacing child.

Note that replace does not allow the construction of invalid trees, and element replacements that require invalid parent-child relationships (e.g., a block element as a child to an element expecting inlines) will throw an error.

Example

The following snippet removes links from the given AST. That is, it replaces Link nodes with their link text (which may contain nested inline markdown elements):

new_mdast = replace(mdast) do node
     if node.element isa MarkdownAST.Link
         return [MarkdownAST.copy_tree(child) for child in node.children]
     else
         return node
     end
-end
source
MarkdownAST.unlink!Function
unlink!(node::Node) -> Node

Isolates and removes the node from the tree by removing all of its links to its neighboring nodes. Returns the updated node, which is now a single, isolate root node.

source
MarkdownAST.insert_before!Function
insert_before!(node::Node, sibling::Node) -> Node

Inserts a new child node sibling as the child right before node. node must not be a root node. If sibling is part of another tree, then it is unlinked from that tree first (see unlink!). Returns the original reference node.

source
MarkdownAST.insert_after!Function
insert_after!(node::Node, sibling::Node) -> Node

Inserts a new child node sibling as the next child after node. node must not be a root node. If sibling is part of another tree, then it is unlinked from that tree first (see unlink!). Returns the original reference node.

source
Base.push!Method
Base.push!(node.children::NodeChildren, child::Node) -> NodeChildren

Adds child as the last child node of node :: Node. If child is part of another tree, then it is unlinked from that tree first (see unlink!). Returns the iterator over children.

source
Base.pushfirst!Method
Base.pushfirst!(node.children::NodeChildren, child::Node) -> NodeChildren

Adds child as the first child node of node :: Node. If child is part of another tree, then it is unlinked from that tree first (see unlink!). Returns the iterator over children.

source
Base.append!Method
append!(node.children::NodeChildren, children) -> NodeChildren

Adds all the elements of the iterable children to the end of the list of children of node. If any of children are part of another tree, then they are unlinked from that tree first (see unlink!). Returns the iterator over children.

Error during an append

The operation is not atomic, and an error during an append! (e.g. due to an element of the wrong type in children) can result in a partial append of the new children, similar to how append! behaves with arrays (see JuliaLang/julia#15868).

source
Base.prepend!Method
prepend!(node.children::NodeChildren, children) -> NodeChildren

Adds all the elements of the iterable children to the beginning of the list of children of node. If any of children are part of another tree, then they are unlinked from that tree first (see unlink!). Returns the iterator over children.

Error during a prepend

The operation is not atomic, and an error during a prepend! (e.g. due to an element of the wrong type in children) can result in a partial prepend of the new children, similar to how append! behaves with arrays (see JuliaLang/julia#15868).

source
Base.empty!Method
empty!(node.children::NodeChildren) -> NodeChildren

Removes all the children of a node.

source
Mutating the .children property

The choice to apparently mutate the .children property when adding child nodes is purely syntactic, and in reality the operation affects the parent Node object. Internally the .children iterator is simply a thin wrapper around the parent node.

Copying trees

The copy_tree function can be used to easily copy a tree.

MarkdownAST.copy_treeFunction
copy_tree(root::Node)
-copy_tree(f, root::Node)

Creates a copy of the tree, starting from node as the root node, and optionally calling f on each of the nodes to determine the corresponding .element in the copied tree.

If node is not the root of its tree, its parent nodes are ignored, and the root node of the copied node corresponds to node.

The function f should have the signature (::Node, ::AbstractElement) -> AbstractElement, and it gets passed the current node being copied and its element. It must return an instance of some AbstractElement, which will then be assigned to the .element field of the copied node. By default, copy_tree performs a deepcopy of both the element (.element) and the node metadata (.meta).

Extended help

For example, to perform a copy instead of deepcopy on the elements, copy_tree can be called as follows

copy_tree((_, e) -> copy(e), node::Node)

Note that copy_tree does not allow the construction of invalid trees, and element replacements that require invalid parent-child relationships (e.g. a block element as a child to an element expecting inlines) will throw an error.

source

This can be particularly useful in circumstances where a tree is passed to other code that while processing the tree also mutates it. As Node is a mutable type, this means that the original tree also mutates. Passing the result from copy_tree can be used to avoid that issue.

Index

+end
source
MarkdownAST.unlink!Function
unlink!(node::Node) -> Node

Isolates and removes the node from the tree by removing all of its links to its neighboring nodes. Returns the updated node, which is now a single, isolate root node.

source
MarkdownAST.insert_before!Function
insert_before!(node::Node, sibling::Node) -> Node

Inserts a new child node sibling as the child right before node. node must not be a root node. If sibling is part of another tree, then it is unlinked from that tree first (see unlink!). Returns the original reference node.

source
MarkdownAST.insert_after!Function
insert_after!(node::Node, sibling::Node) -> Node

Inserts a new child node sibling as the next child after node. node must not be a root node. If sibling is part of another tree, then it is unlinked from that tree first (see unlink!). Returns the original reference node.

source
Base.push!Method
Base.push!(node.children::NodeChildren, child::Node) -> NodeChildren

Adds child as the last child node of node :: Node. If child is part of another tree, then it is unlinked from that tree first (see unlink!). Returns the iterator over children.

source
Base.pushfirst!Method
Base.pushfirst!(node.children::NodeChildren, child::Node) -> NodeChildren

Adds child as the first child node of node :: Node. If child is part of another tree, then it is unlinked from that tree first (see unlink!). Returns the iterator over children.

source
Base.append!Method
append!(node.children::NodeChildren, children) -> NodeChildren

Adds all the elements of the iterable children to the end of the list of children of node. If any of children are part of another tree, then they are unlinked from that tree first (see unlink!). Returns the iterator over children.

Error during an append

The operation is not atomic, and an error during an append! (e.g. due to an element of the wrong type in children) can result in a partial append of the new children, similar to how append! behaves with arrays (see JuliaLang/julia#15868).

source
Base.prepend!Method
prepend!(node.children::NodeChildren, children) -> NodeChildren

Adds all the elements of the iterable children to the beginning of the list of children of node. If any of children are part of another tree, then they are unlinked from that tree first (see unlink!). Returns the iterator over children.

Error during a prepend

The operation is not atomic, and an error during a prepend! (e.g. due to an element of the wrong type in children) can result in a partial prepend of the new children, similar to how append! behaves with arrays (see JuliaLang/julia#15868).

source
Base.empty!Method
empty!(node.children::NodeChildren) -> NodeChildren

Removes all the children of a node.

source
Mutating the .children property

The choice to apparently mutate the .children property when adding child nodes is purely syntactic, and in reality the operation affects the parent Node object. Internally the .children iterator is simply a thin wrapper around the parent node.

Copying trees

The copy_tree function can be used to easily copy a tree.

MarkdownAST.copy_treeFunction
copy_tree(root::Node)
+copy_tree(f, root::Node)

Creates a copy of the tree, starting from node as the root node, and optionally calling f on each of the nodes to determine the corresponding .element in the copied tree.

If node is not the root of its tree, its parent nodes are ignored, and the root node of the copied node corresponds to node.

The function f should have the signature (::Node, ::AbstractElement) -> AbstractElement, and it gets passed the current node being copied and its element. It must return an instance of some AbstractElement, which will then be assigned to the .element field of the copied node. By default, copy_tree performs a deepcopy of both the element (.element) and the node metadata (.meta).

Extended help

For example, to perform a copy instead of deepcopy on the elements, copy_tree can be called as follows

copy_tree((_, e) -> copy(e), node::Node)

Note that copy_tree does not allow the construction of invalid trees, and element replacements that require invalid parent-child relationships (e.g. a block element as a child to an element expecting inlines) will throw an error.

source

This can be particularly useful in circumstances where a tree is passed to other code that while processing the tree also mutates it. As Node is a mutable type, this means that the original tree also mutates. Passing the result from copy_tree can be used to avoid that issue.

Index

diff --git a/dev/search/index.html b/dev/search/index.html index 47a1673..0e40f84 100644 --- a/dev/search/index.html +++ b/dev/search/index.html @@ -1,2 +1,2 @@ -Search · MarkdownAST

Loading search...

    +Search · MarkdownAST

    Loading search...

      diff --git a/dev/stdlib/index.html b/dev/stdlib/index.html index b918330..7b5de0f 100644 --- a/dev/stdlib/index.html +++ b/dev/stdlib/index.html @@ -1,3 +1,3 @@ Conversion to/from Markdown · MarkdownAST

      Conversion to and from Markdown standard library

      The Markdown standard library in Julia provides an alternative representation of the Markdown AST. In particular, the parser and AST there is internally used by Julia for docstrings, and is also used by some of the tooling in the Julia ecosystem that deals with Markdown.

      MarkdownAST supports bi-directional conversion between the two AST representations via the convert function. The conversion, however, is not perfect since there are differences in what and how the two libraries represent the Markdown AST.

      Conversion from standard library representation

      Any AST that is produced by the Markdown standard library parser should parse into MarkdownAST AST. However, as the data structures for the elements in Markdown are pretty loose in what they allow, user-crafted Markdown ASTs may error if it does not exactly follow the conventions of the Markdown parser.

      Base.convertMethod
      convert(::Type{Node}, md::Markdown.MD) -> Node
      -convert(::Type{Node{M}}, md::Markdown.MD, meta=M) where M -> Node{M}

      Converts a standard library Markdown AST into MarkdownAST representation.

      Note that it is not possible to convert subtrees, as only MD objects can be converted. The result will be a tree with Document as the root element.

      When the type argument passed is Node, the resulting tree will be constructed of objects of the default node type Node{Nothing}. However, it is also possible to convert into MarkdownAST trees that have custom metadata field of type M, in which case the M type must have a zero-argument constructor available, which will be called whenever a new Node object gets constructed.

      It is also possible to use a custom function to construct the .meta objects via the `meta argument, which must be a callable object with a zero-argument method, and that then gets called every time a new node is constructed.

      source

      Due to the differences between the Markdown representations, the following things should be kept in mind when converting from the standard library AST into MarkdownAST representation:

      • The standard library parser does not have a dedicated type for representing backslashes, and instead stores them as separate single-character text nodes containing a backslash (i.e. "\\").
      • Soft line breaks are ignored in the standard library parser and represented with a space instead.
      • Strings (or Markdown elements) interpolated into the standard library Markdown (e.g. in docstrings or with the @md_str macro) are indistinguishable from text (or corresponding Markdown) nodes in the standard library AST, and therefore will not be converted into JuliaValues.
      • The standard library allows for block-level interpolation. These get converted into inline JuliaValues wrapped in a Paragraph element.
      • In case the standard library AST contains any inline nodes in block context (e.g. as children for Markdown.MD), the get wrapped in a Paragraph element too.
      • When converting a Markdown.Table, the resulting table will be normalized, such as adding empty cells to rows, to make sure that all rows have the same number of cells.
      • For links and images, the .title attribute is set to an empty string, since the standard library AST does not support parsing titles.

      Conversion to standard library representation

      Any AST that contains only the native MarkdownAST elements can be converted into the standard library representation. The conversion of user-defined elements, however, is not supported and will lead to an error.

      Base.convertMethod
      convert(::Type{Markdown.MD}, node::Node) -> Markdown.MD

      Converts a MarkdownAST representation of a Markdown document into the Markdown standard library representation.

      Note that the root node node must a Document element.

      source

      Due to the differences between the Markdown representations, the following things should be kept in mind when converting from the MarkdownAST representation into the standard library AST:

      • The value from a JuliaValue element (i.e. .ref) gets stored directly in the AST (just like variable interpolation with docstrings and the @md_str macro). This means that, for example, an interpolated string or Markdown element would become a valid AST element, losing the information that it used to be interpolated.
      • The expression information in a JuliaValue element (i.e. the .ex field) gets discarded.
      • The .title attribute of Link and Image elements gets discarded.
      • The standard library does not support storing the child nodes of Image elements (i.e. "alt text", ![alt text]()) as AST, and it is instead reduced to a string with the help of the Markdown.plain function.
      • The standard library AST does not have dedicated elements for SoftBreak and Backslash, and these get converted into strings (i.e. text elements) instead.

      Index

      +convert(::Type{Node{M}}, md::Markdown.MD, meta=M) where M -> Node{M}

      Converts a standard library Markdown AST into MarkdownAST representation.

      Note that it is not possible to convert subtrees, as only MD objects can be converted. The result will be a tree with Document as the root element.

      When the type argument passed is Node, the resulting tree will be constructed of objects of the default node type Node{Nothing}. However, it is also possible to convert into MarkdownAST trees that have custom metadata field of type M, in which case the M type must have a zero-argument constructor available, which will be called whenever a new Node object gets constructed.

      It is also possible to use a custom function to construct the .meta objects via the `meta argument, which must be a callable object with a zero-argument method, and that then gets called every time a new node is constructed.

      source

      Due to the differences between the Markdown representations, the following things should be kept in mind when converting from the standard library AST into MarkdownAST representation:

      Conversion to standard library representation

      Any AST that contains only the native MarkdownAST elements can be converted into the standard library representation. The conversion of user-defined elements, however, is not supported and will lead to an error.

      Base.convertMethod
      convert(::Type{Markdown.MD}, node::Node) -> Markdown.MD

      Converts a MarkdownAST representation of a Markdown document into the Markdown standard library representation.

      Note that the root node node must a Document element.

      source

      Due to the differences between the Markdown representations, the following things should be kept in mind when converting from the MarkdownAST representation into the standard library AST:

      Index