Contributing
Architecture
This page explains how adocfmt turns a document into its formatted form, and which package holds each part.
Overview
flowchart LR source[Source] --> parser[Parser] parser --> tree[Block tree] tree --> printer[Printer] printer --> output[Formatted source] parser --> findings[Findings] findings --> refusal[Refusal, no output]
The parser reads the source into a block tree. It reads only as much structure as the rules need, so inline markup, for example, stays text. If it reports findings, adocfmt refuses the document. Otherwise, the printer writes the tree back with the rules applied.
Decision record 0002 explains why the formatter has this shape. Decision record 0003 explains why a document with findings is refused whole. Decision record 0005 explains why adocfmt has its own parser and does not use Asciidoctor’s.
Terms
- Block tree
The parser’s reading of the document. Each node is one block, such as a section title, a paragraph, a list or a delimited block. Metadata lines, such as
[source,go],.Titleor a comment, belong to the block below them. The parser is the only place that decides what kind of block a line belongs to.- Span
The byte range of the source that a node covers. Every byte belongs to exactly one node, so printing the nodes in order gives back the source.
- Gap
The blank lines in front of a node.
- Frozen
A node or gap the printer leaves as it stands: its meaning depends on something the parser does not resolve, such as an include, a conditional or the front matter, or one of its lines means something else once it moves, such as a comment line joined into a paragraph. No rule may add, remove, join or split lines in a frozen node, or change the blank lines of a frozen gap between two nodes.
- Finding
Structure the parser cannot trust, such as a block that never closes, reported with its line number.
Printer and rules
The printer walks the tree once, from top to bottom, with one function per node type. A rule is part of the function for the node type it formats. Some rules need to know more than the node in front of them. For example, the opening fence of a block can only be shortened once every line inside the block is known, but the printer writes the fence first. Such a rule decides for the whole tree in a pass before printing starts, and the printer looks up the decision for each node. A node that no rule formats is copied from the source unchanged, apart from its trailing whitespace.
Rules live in files of internal/printer named after what they format.
In raw mode, the printer walks the tree the same way with every rule off and reproduces the source byte for byte. Only the identity check uses it.
Packages
| Package | Holds |
|---|---|
The command: flags, which files it collects, check mode and writing files back. The CLI reference describes its behavior. | |
| |
The parser and the block tree. | |
The printer and the rules. | |
The sentence splitting behind the one sentence per line rule. | |
The render equivalence checks, used only by tests. | |
Code that finds the golden cases. | |
Code that finds the Asciidoctor cases. | |
Code that finds the repository root, so the tools work from any directory inside it. |