@asciidoc-js/adast
v1.0.0
Published
AsciiDoc Abstract Syntax Tree format
Maintainers
Readme
ADAST
AsciiDoc Abstract Syntax Tree format.
Contents
- Introduction
- Where this specification fits
- Types
- Nodes (abstract)
- Nodes (root)
- Nodes (sections)
- Nodes (compound blocks)
- Nodes (leaf blocks)
- Nodes (void blocks)
- Nodes (lists)
- Nodes (table)
- Nodes (inline — parent)
- Nodes (inline — literal)
- Nodes (inline — void)
- Content model
- Glossary
- Mapping to Asciidoctor
- References
Introduction
This document defines a format for representing AsciiDoc documents as abstract syntax trees. Development of adast started in 2025. This spec is written in a Web IDL-like grammar.
Where this specification fits
adast extends unist, a format for syntax trees, to benefit from its ecosystem of utilities.
adast relates to mdast (Markdown) and hast (HTML) as a sibling specification — all three extend unist but represent different source languages. Converters between the formats (e.g., adast-to-mdast) can live in separate packages.
An adast tree is typically produced by parsing an AsciiDoc document with a tool such as Asciidoctor and can be serialized back to AsciiDoc source, converted to hast for HTML rendering, or processed by any unist utility.
Types
TypeScript types for adast nodes are published as the
adast npm package:
npm install --save-dev @asciidoc-js/adastimport type {Document, Paragraph, Section} from '@asciidoc-js/adast'Nodes (abstract)
adast inherits the abstract node types from unist:
Node
interface Node {
type: string
data: Data?
position: Position?
}The type field is a non-empty string that identifies the node variant.
The data field is an optional object for storing implementation-specific information that does not need to be in the AST.
The position field is an optional object indicating where the node originates in the source document.
Parent
interface Parent <: Node {
children: [Node]
}A node that contains other nodes.
Literal
interface Literal <: Node {
value: string
}A node that contains a text value.
Attributes
dictionary Attributes {
[name: string]: string | number | boolean | null
}A key-value map of AsciiDoc attributes. Present on most block and inline nodes. Attribute names are lowercase strings; values are typically strings.
Nodes (root)
Document
interface Document <: Parent {
type: 'document'
doctype: 'article' | 'book' | 'manpage' | 'inline'?
title: string?
attributes: Attributes?
children: [DocumentContent]
data: DocumentData?
}Document (Parent) represents a complete AsciiDoc document. It is always the root of the tree.
doctype indicates the document type — 'article' (default), 'book',
'manpage', or 'inline'.
title is the resolved document title (level-0 heading), or null if the
document has no title.
attributes holds document-level attributes set with :name: value lines
in the document header.
For example, the AsciiDoc document:
= My Document
Author Name
:toc:
Some introductory text.
== First Section
Content here.Yields:
{
"type": "document",
"doctype": "article",
"title": "My Document",
"attributes": {"toc": ""},
"children": [
{
"type": "preamble",
"children": [
{
"type": "paragraph",
"children": [{"type": "text", "value": "Some introductory text."}]
}
]
},
{
"type": "section",
"depth": 1,
"title": "First Section",
"children": [
{
"type": "paragraph",
"children": [{"type": "text", "value": "Content here."}]
}
]
}
]
}Preamble
interface Preamble <: Parent {
type: 'preamble'
children: [BlockContent]
}Preamble (Parent) represents content between the document header and the first section. A document has at most one preamble, and it is always the first child of the document (when present).
Nodes (sections)
Section
interface Section <: Parent {
type: 'section'
depth: 0 | 1 | 2 | 3 | 4 | 5
title: string
numbered: boolean?
sectname: string?
numeral: string?
id: string?
attributes: Attributes?
children: [Section | BlockContent]
}Section (Parent) represents a document section created by
a heading marker (= through ======).
depth indicates the nesting level: 0 for the document title / part level, 1 through 5 for section levels.
title is the resolved section title text (after substitutions).
sectname classifies the section kind. Standard values:
| Value | Meaning |
| ------------------- | -------------------------------- |
| 'section' | Normal section |
| 'chapter' | Level 1 in book doctype |
| 'part' | Level 0 in multi-part book |
| 'appendix' | Appendix section |
| 'preface' | Preface |
| 'colophon' | Colophon |
| 'dedication' | Dedication |
| 'acknowledgments' | Acknowledgments |
| 'glossary' | Glossary |
| 'bibliography' | Bibliography |
| 'index' | Index |
| 'abstract' | Abstract |
| 'synopsis' | Synopsis (manpage) |
Children of a section can be nested sections (of greater depth) and block content.
For example:
== Introduction
Paragraph text.
=== Background
More details.Yields:
{
"type": "section",
"depth": 1,
"title": "Introduction",
"sectname": "section",
"children": [
{
"type": "paragraph",
"children": [{"type": "text", "value": "Paragraph text."}]
},
{
"type": "section",
"depth": 2,
"title": "Background",
"sectname": "section",
"children": [
{
"type": "paragraph",
"children": [{"type": "text", "value": "More details."}]
}
]
}
]
}Nodes (compound blocks)
Compound blocks contain other block-level nodes as children.
Paragraph
interface Paragraph <: Parent {
type: 'paragraph'
id: string?
attributes: Attributes?
children: [InlineContent]
}Paragraph (Parent) represents a block of prose. Its children are inline content nodes.
Admonition
interface Admonition <: Parent {
type: 'admonition'
name: 'note' | 'tip' | 'important' | 'warning' | 'caution'
textlabel: string?
title: string?
id: string?
attributes: Attributes?
children: [BlockContent]
}Admonition (Parent) represents a call-out block with a severity label.
name identifies the admonition type.
Can be created from a paragraph-style shorthand (NOTE: text) — in which
case children will contain a single Paragraph — or from a delimited block
with admonition style ([NOTE] on an ==== block).
For example:
NOTE: Remember to save your work.Yields:
{
"type": "admonition",
"name": "note",
"textlabel": "Note",
"children": [
{
"type": "paragraph",
"children": [{"type": "text", "value": "Remember to save your work."}]
}
]
}Example
interface Example <: Parent {
type: 'example'
title: string?
caption: string?
id: string?
attributes: Attributes?
children: [BlockContent]
}Example (Parent) represents an example block —
==== delimiters.
Sidebar
interface Sidebar <: Parent {
type: 'sidebar'
title: string?
id: string?
attributes: Attributes?
children: [BlockContent]
}Sidebar (Parent) represents a sidebar block —
**** delimiters.
Quote
interface Quote <: Parent {
type: 'quote'
title: string?
attribution: string?
citetitle: string?
id: string?
attributes: Attributes?
children: [BlockContent]
}Quote (Parent) represents a blockquote — ____ delimiters.
attribution names the quoted person or source. citetitle identifies the source work.
For example:
[quote, Albert Einstein]
____
Imagination is more important than knowledge.
____Yields:
{
"type": "quote",
"attribution": "Albert Einstein",
"children": [
{
"type": "paragraph",
"children": [
{"type": "text", "value": "Imagination is more important than knowledge."}
]
}
]
}Open
interface Open <: Parent {
type: 'open'
style: string?
title: string?
id: string?
attributes: Attributes?
children: [BlockContent]
}Open (Parent) represents an open block — -- delimiters.
The style attribute can morph it into other block types:
'abstract', 'partintro', 'comment', 'example', 'literal',
'listing', 'pass', 'quote', 'sidebar', 'source', 'verse',
'admonition'.
Nodes (leaf blocks)
Leaf blocks contain text content (a value string) rather than child nodes.
Listing
interface Listing <: Literal {
type: 'listing'
value: string
style: 'source'?
language: string?
title: string?
caption: string?
id: string?
attributes: Attributes?
}Listing (Literal) represents a listing block —
---- delimiters.
When style is 'source', the block is a source code block with optional
syntax highlighting via the language field.
For example:
[source,javascript]
----
console.log('Hello, world!')
----Yields:
{
"type": "listing",
"style": "source",
"language": "javascript",
"value": "console.log('Hello, world!')"
}Literal
interface Literal <: Literal {
type: 'literal'
value: string
title: string?
id: string?
attributes: Attributes?
}Literal (Literal) represents a literal block —
.... delimiters or indented lines.
Content is rendered monospace, preserving whitespace. Only special-character substitutions are applied.
Verse
interface Verse <: Literal {
type: 'verse'
value: string
attribution: string?
citetitle: string?
title: string?
id: string?
attributes: Attributes?
}Verse (Literal) represents a verse block — a ____ block
with [verse] style.
Line breaks are preserved as written. Typically used for poetry.
Pass
interface Pass <: Literal {
type: 'pass'
value: string
id: string?
attributes: Attributes?
}Pass (Literal) represents a passthrough block —
++++ delimiters. Content is passed to the output without substitution.
Stem
interface Stem <: Literal {
type: 'stem'
value: string
style: 'asciimath' | 'latexmath'?
id: string?
attributes: Attributes?
}Stem (Literal) represents a STEM (math) block.
style indicates the notation format.
Nodes (void blocks)
Void blocks have no text content and no children.
Image
interface Image <: Node {
type: 'image'
target: string
alt: string?
title: string?
caption: string?
id: string?
attributes: Attributes?
}Image (Node) represents a block image —
image::target[alt].
Audio
interface Audio <: Node {
type: 'audio'
target: string
title: string?
id: string?
attributes: Attributes?
}Audio (Node) represents a block audio macro.
Video
interface Video <: Node {
type: 'video'
target: string
title: string?
id: string?
attributes: Attributes?
}Video (Node) represents a block video macro.
ThematicBreak
interface ThematicBreak <: Node {
type: 'thematicBreak'
}ThematicBreak (Node) represents a horizontal rule — '''.
PageBreak
interface PageBreak <: Node {
type: 'pageBreak'
}PageBreak (Node) represents a page break — <<<.
Toc
interface Toc <: Node {
type: 'toc'
id: string?
attributes: Attributes?
}Toc (Node) represents a table-of-contents macro — toc::[].
FloatingTitle
interface FloatingTitle <: Parent {
type: 'floatingTitle'
depth: 1 | 2 | 3 | 4 | 5
id: string?
attributes: Attributes?
children: [InlineContent]
}FloatingTitle (Parent) represents a discrete heading — a
heading with the [discrete] attribute that does not create a section.
Nodes (lists)
UnorderedList
interface UnorderedList <: Parent {
type: 'unorderedList'
style: string?
title: string?
id: string?
attributes: Attributes?
children: [ListItem]
}UnorderedList (Parent) represents a bullet list —
lines starting with *, -, etc.
OrderedList
interface OrderedList <: Parent {
type: 'orderedList'
style: 'arabic' | 'loweralpha' | 'upperalpha' | 'lowerroman' | 'upperroman' | 'lowergreek'?
start: number?
reversed: boolean?
title: string?
id: string?
attributes: Attributes?
children: [ListItem]
}OrderedList (Parent) represents a numbered list —
lines starting with ., .., etc.
DescriptionList
interface DescriptionList <: Parent {
type: 'descriptionList'
style: string?
title: string?
id: string?
attributes: Attributes?
children: [DescriptionListEntry]
}DescriptionList (Parent) represents a description
(definition) list — term:: description entries.
CalloutList
interface CalloutList <: Parent {
type: 'calloutList'
title: string?
id: string?
attributes: Attributes?
children: [ListItem]
}CalloutList (Parent) represents a callout list — explanations for callout markers in listing/literal blocks.
ListItem
interface ListItem <: Parent {
type: 'listItem'
marker: string?
checked: boolean?
attributes: Attributes?
children: [BlockContent]
}ListItem (Parent) represents a single item in an unordered, ordered, or callout list.
marker is the source marker string (e.g., '*', '.').
checked indicates checkbox state for task list items: true for checked
([x]), false for unchecked ([ ]), undefined for regular items.
DescriptionListEntry
interface DescriptionListEntry <: Parent {
type: 'descriptionListEntry'
children: [DescriptionListTerm | DescriptionListDescription]
}DescriptionListEntry (Parent) groups one or more terms with an optional description in a {@link DescriptionList}.
DescriptionListTerm
interface DescriptionListTerm <: Parent {
type: 'descriptionListTerm'
children: [InlineContent]
}DescriptionListTerm (Parent) is a term in a description list entry.
DescriptionListDescription
interface DescriptionListDescription <: Parent {
type: 'descriptionListDescription'
children: [BlockContent]
}DescriptionListDescription (Parent) is the description part of a description list entry.
Nodes (table)
Table
interface Table <: Parent {
type: 'table'
columns: [TableColumn]
title: string?
caption: string?
id: string?
attributes: Attributes?
children: [TableHead | TableBody | TableFoot]
}Table (Parent) represents a table block — |===.
columns is an array of TableColumn objects describing each column's alignment, width, and default style.
Children are table sections: an optional TableHead, one or more TableBody, and an optional TableFoot.
TableColumn
dictionary TableColumn {
halign: 'left' | 'center' | 'right'?
valign: 'top' | 'middle' | 'bottom'?
width: number?
colpcwidth: number?
style: 'asciidoc' | 'emphasis' | 'header' | 'literal' | 'monospaced' | 'strong'?
}TableColumn is a data object (not a node) that describes default properties for a column.
TableHead
interface TableHead <: Parent {
type: 'tableHead'
children: [TableRow]
}TableHead (Parent) contains the header row(s) of a table.
TableBody
interface TableBody <: Parent {
type: 'tableBody'
children: [TableRow]
}TableBody (Parent) contains the body rows of a table.
TableFoot
interface TableFoot <: Parent {
type: 'tableFoot'
children: [TableRow]
}TableFoot (Parent) contains the footer row(s) of a table.
TableRow
interface TableRow <: Parent {
type: 'tableRow'
children: [TableCell]
}TableRow (Parent) represents a row in a table section.
TableCell
interface TableCell <: Parent {
type: 'tableCell'
colspan: number?
rowspan: number?
halign: 'left' | 'center' | 'right'?
valign: 'top' | 'middle' | 'bottom'?
style: 'asciidoc' | 'emphasis' | 'header' | 'literal' | 'monospaced' | 'strong'?
children: [BlockContent | InlineContent]
}TableCell (Parent) represents a cell in a table row.
When style is 'asciidoc', the cell contains a nested AsciiDoc document
and children are block content. Otherwise children are inline content.
Nodes (inline — parent)
Inline parent nodes contain other inline nodes as children.
Strong
interface Strong <: Parent {
type: 'strong'
id: string?
attributes: Attributes?
children: [InlineContent]
}Strong (Parent) represents bold text — *text* or
**text**.
Emphasis
interface Emphasis <: Parent {
type: 'emphasis'
id: string?
attributes: Attributes?
children: [InlineContent]
}Emphasis (Parent) represents italic text — _text_ or
__text__.
Mark
interface Mark <: Parent {
type: 'mark'
id: string?
attributes: Attributes?
children: [InlineContent]
}Mark (Parent) represents highlighted text — #text# or
##text##.
Superscript
interface Superscript <: Parent {
type: 'superscript'
children: [InlineContent]
}Superscript (Parent) — ^text^.
Subscript
interface Subscript <: Parent {
type: 'subscript'
children: [InlineContent]
}Subscript (Parent) — ~text~.
DoubleQuoted
interface DoubleQuoted <: Parent {
type: 'doubleQuoted'
children: [InlineContent]
}DoubleQuoted (Parent) represents smart/typographic double
quotes — "`text`".
SingleQuoted
interface SingleQuoted <: Parent {
type: 'singleQuoted'
children: [InlineContent]
}SingleQuoted (Parent) represents smart/typographic single
quotes — '`text`'.
Link
interface Link <: Parent {
type: 'link'
url: string
title: string?
id: string?
attributes: Attributes?
children: [InlineContent]
}Link (Parent) represents a hyperlink — link:url[text]
or an auto-detected URL.
CrossReference
interface CrossReference <: Parent {
type: 'crossReference'
target: string
refid: string?
path: string?
fragment: string?
id: string?
attributes: Attributes?
children: [InlineContent]
}CrossReference (Parent) represents a cross-reference to
another location — <<id>> or xref:target[].
target is the raw reference target.
refid is the resolved reference ID (without #).
path and fragment are the path and fragment components for
inter-document references.
Footnote
interface Footnote <: Parent {
type: 'footnote'
identifier: string?
index: number?
children: [InlineContent]
}Footnote (Parent) represents a footnote —
footnote:[text].
Nodes (inline — literal)
Inline literal nodes contain a text value rather than child nodes.
Text
interface Text <: Literal {
type: 'text'
value: string
}Text (Literal) represents plain text content.
Monospaced
interface Monospaced <: Literal {
type: 'monospaced'
value: string
id: string?
attributes: Attributes?
}Monospaced (Literal) represents inline code text —
`text` or ``text``.
InlinePass
interface InlinePass <: Literal {
type: 'inlinePass'
value: string
}InlinePass (Literal) represents an inline passthrough —
+text+ or pass:[text].
Nodes (inline — void)
Void inline nodes have no children and no text value.
Anchor
interface Anchor <: Node {
type: 'anchor'
identifier: string
reftext: string?
}Anchor (Node) represents an inline anchor (bookmark) —
[[id]] or anchor:id[].
BibliographyReference
interface BibliographyReference <: Node {
type: 'bibliographyReference'
identifier: string
label: string?
}BibliographyReference (Node) represents a bibliography
entry — [[[id]]] or [[[id, label]]].
InlineImage
interface InlineImage <: Node {
type: 'inlineImage'
target: string
alt: string?
attributes: Attributes?
}InlineImage (Node) represents an inline image —
image:target[alt].
Icon
interface Icon <: Node {
type: 'icon'
name: string
attributes: Attributes?
}Icon (Node) represents an inline icon — icon:name[].
LineBreak
interface LineBreak <: Node {
type: 'lineBreak'
}LineBreak (Node) represents a hard line break — + at end
of line.
InlineCallout
interface InlineCallout <: Node {
type: 'inlineCallout'
number: number
}InlineCallout (Node) represents a callout marker in a
listing block — <1>, <2>, etc.
Keyboard
interface Keyboard <: Node {
type: 'keyboard'
keys: [string]
}Keyboard (Node) represents a keyboard shortcut —
kbd:[Ctrl+Alt+Del].
Button
interface Button <: Node {
type: 'button'
label: string
}Button (Node) represents a UI button — btn:[Save].
Menu
interface Menu <: Node {
type: 'menu'
menuName: string
submenus: [string]
menuitem: string
}Menu (Node) represents a menu selection —
menu:File[Save As...].
IndexTerm
interface IndexTerm <: Node {
type: 'indexTerm'
terms: [string]
visible: boolean?
}IndexTerm (Node) represents an index entry —
indexterm:[primary, secondary, tertiary] or ((primary)).
Content model
Each node belongs to one or more content categories that constrain where it may appear in the tree.
| Category | Description | | --------------------------- | ----------------------------------------------- | | DocumentContent | Nodes that can be children of Document | | SectionContent | Nodes that can be children of Section | | BlockContent | Block-level nodes for any compound container | | ListContent | Children of lists (ListItem) | | DescriptionListContent | Children of description lists | | TableContent | Children of tables (table sections) | | RowContent | Children of table sections (TableRow) | | InlineContent | Inline (phrasing) content |
DocumentContent
DocumentContent = Preamble | Section | BlockContentSectionContent
SectionContent = Section | BlockContentBlockContent
BlockContent = Paragraph | Admonition | Listing | Literal | Example
| Sidebar | Quote | Verse | Open | Pass | Stem | Table
| Image | Audio | Video | ThematicBreak | PageBreak | Toc
| FloatingTitle | UnorderedList | OrderedList
| DescriptionList | CalloutListInlineContent
InlineContent = Text | Strong | Emphasis | Monospaced | Superscript
| Subscript | Mark | DoubleQuoted | SingleQuoted | Link
| CrossReference | Anchor | BibliographyReference
| InlineImage | Icon | Footnote | LineBreak
| InlineCallout | Keyboard | Button | Menu | IndexTerm
| InlinePassGlossary
- block content — content that participates in the block layout flow (paragraphs, sections, lists, tables, etc.)
- compound block — a block whose content model is
'compound', meaning it contains other blocks as children - inline content — content that participates in the inline (text) flow (formatted text, links, images, etc.)
- leaf block — a block whose content model is
'simple','verbatim', or'raw', meaning it holds text content - void block — a block whose content model is
'empty', meaning it has neither text content nor children
Mapping to Asciidoctor
The following table maps adast node types to Asciidoctor's internal
context values and classes.
| adast type | Asciidoctor context | Asciidoctor class |
| --------------------------- | ---------------------- | ------------------ |
| document | document | Document |
| preamble | preamble | Block |
| section | section | Section |
| paragraph | paragraph | Block |
| admonition | admonition | Block |
| listing | listing | Block |
| literal | literal | Block |
| example | example | Block |
| sidebar | sidebar | Block |
| quote | quote | Block |
| verse | verse | Block |
| open | open | Block |
| pass | pass | Block |
| stem | stem | Block |
| image | image | Block |
| audio | audio | Block |
| video | video | Block |
| thematicBreak | thematic_break | Block |
| pageBreak | page_break | Block |
| toc | toc | Block |
| floatingTitle | floating_title | Block |
| unorderedList | ulist | List |
| orderedList | olist | List |
| descriptionList | dlist | List |
| calloutList | colist | List |
| listItem | list_item | ListItem |
| table | table | Table |
| tableCell | table_cell | Table::Cell |
| strong | quoted (type=strong) | Inline |
| emphasis | quoted (type=emphasis)| Inline |
| monospaced | quoted (type=monospaced)| Inline |
| superscript | quoted (type=superscript)| Inline |
| subscript | quoted (type=subscript)| Inline |
| mark | quoted (type=mark) | Inline |
| doubleQuoted | quoted (type=double) | Inline |
| singleQuoted | quoted (type=single) | Inline |
| link | anchor (type=link) | Inline |
| crossReference | anchor (type=xref) | Inline |
| anchor | anchor (type=ref) | Inline |
| bibliographyReference | anchor (type=bibref) | Inline |
| inlineImage | image (type=image) | Inline |
| icon | image (type=icon) | Inline |
| footnote | footnote | Inline |
| lineBreak | break | Inline |
| inlineCallout | callout | Inline |
| keyboard | kbd | Inline |
| button | button | Inline |
| menu | menu | Inline |
| indexTerm | indexterm | Inline |
| inlinePass | quoted (type=monospaced, subs=none) | Inline |
References
- unist — Universal Syntax Tree format
- mdast — Markdown Abstract Syntax Tree format
- hast — Hypertext Abstract Syntax Tree format
- AsciiDoc — AsciiDoc Language Documentation
- Asciidoctor — AsciiDoc processor
License
MIT © Pablo Angelani [email protected]
