Reference

Formatting rules

adocfmt applies the rules on this page and leaves the rest of the document as it is.

Guarantees

  • A byte that no rule covers is written back unchanged.

  • Line endings keep their form: a file with Windows line endings keeps them. A line that a rule writes ends the same way as the rest of the file.

  • Front matter, the block of YAML that some static site generators put at the top of a file, is left alone.

  • Lines whose meaning depends on an include or a conditional lose only their trailing whitespace. No other rule changes them, because their content is known only after Asciidoctor resolves the directive.

  • adocfmt refuses a document that it cannot read reliably. It reports what it found and writes nothing.

  • Formatting a formatted document changes nothing.

  • No rule changes what the rendered document shows. The rendering that counts is Asciidoctor’s, the reference implementation of AsciiDoc. The testing strategy describes how every rule is checked against Asciidoctor.

Trailing whitespace

Spaces and tabs at the end of a line are removed, including inside code and literal blocks. So are the rarer characters that Asciidoctor strips there too, such as a form feed. A line that holds nothing but whitespace becomes empty.

· marks a space.

BeforeAfter
Text.··
Line +··
Text.
Line +

AsciiDoc forces a line break by ending a line with a space and a +. That space is part of the break and stays. Only the whitespace after the + is removed.

Left alone:

  • Front matter. It is YAML, where trailing whitespace can be part of a value.

Heading markers

A one-line section title is written with = signs followed by a single space. A closing marker at the end of the line is removed.

BeforeAfter
## Section ##

==   Other
== Section

== Other

The document title is written the same way. The author, revision and attribute lines below it keep their content.

Left alone:

  • A document title written on two lines. It turns on compat-mode. With a one-line title, the same document would render its inline markup differently.

  • A title that the rewrite would change. A closing marker counts only when it matches the opening marker. So ## Title == has the title Title ==, but == Title == would have the title Title.

  • A document header that an include or a conditional reaches, including its title. Which lines are the author and revision lines is known only after Asciidoctor resolves the directive.

  • A title right below an include, a conditional or front matter, with no blank line between. Asciidoctor may read it as part of a paragraph above it. That paragraph can come from the lines that the directive brings in. Without the skip-front-matter attribute, Asciidoctor reads front matter and the lines below it, down to the first blank line, as one paragraph.

Setext headings

A section title written as a line of text with an underline below it moves onto one line.

BeforeAfter
Section
-------
== Section

The underline character sets the level: = is level 0, - is level 1, ~ is level 2, ^ is level 3, and + is level 4.

Left alone:

  • An indented title. A one-line title cannot keep the indentation, because Asciidoctor skips the whitespace between the marker and the title.

  • A two-line title at the very top of a document. That title is the document title, not a section title. It stays on two lines; see Heading markers.

  • A title right below an include, a conditional or front matter, with no blank line between; see Heading markers.

  • A two-line title whose first line reads as a list item, such as <1> Title. Block attribute lines between a description list and such a line stay in the list, because Asciidoctor keeps them only above a list item. On one line, the title would take them over.

Blank lines

One blank line separates two blocks, and two terms of a description list. No blank line stands between a metadata line and its block, or between the items of any other list. The file starts with no blank line and ends with a single line ending.

BeforeAfter
= Title
:toc:

== Section
.Listing

----
code
----
term:: one
other:: two

text



* one

* two
= Title
:toc:

== Section

.Listing
----
code
----

term:: one

other:: two

text

* one
* two

Two terms on consecutive lines share one description, so no blank line goes between them.

Example

Asciidoctor renders colour and color above the one description. With a blank line between them, colour would look as if it had no description.

BeforeAfter
colour::
color:: The wavelength.
next:: Text.
colour::
color:: The wavelength.

next:: Text.

Asciidoctor renders a block, or a description list term, the same with or without a blank line in front of it. That is why adocfmt can insert the separating line safely. In a few places, a blank line is syntax, not spacing. There, adocfmt keeps the blank lines it finds.

Left alone:

  • Blank lines between a list item and the blocks attached to it. A blank line there decides what still belongs to the item, so adocfmt neither adds nor removes one.

    Example

    A callout list, the <1> line, directly under a listing in an item belongs to that item. After a blank line, it becomes a list of its own below the item list.

    Part of the itemA list of its own
    * An item
    +
    ----
    code (1)
    ----
    <1> a note
    * An item
    +
    ----
    code (1)
    ----
    
    <1> a note
  • The blank line after an item that ends in indented text. Indented text in an item is a literal paragraph. The item takes every line from there down to the next blank line, even a block right under the paragraph. Without that blank line, the next item becomes part of the item above. For the same reason, adocfmt adds no blank line among those lines.

    Example

    On the left, * two shows as text inside the literal paragraph. On the right, the blank line ends the paragraph, and * two is a second item.

    Part of the indented textAn item of its own
    * one
    
      indented text
    * two
    * one
    
      indented text
    
    * two
  • The blank lines around a + on a line of its own. In a list, such a + is a list continuation: it attaches the block below it to a list item. The blank lines above it decide which item the block attaches to, and the blank lines below it decide whether the block attaches at all. Outside a list, the + attaches nothing, and a blank line below it splits one paragraph into two.

    Example

    Outside a list, Asciidoctor reads the + and the text below it as one paragraph. With a blank line below the +, they are two paragraphs.

    One paragraphTwo paragraphs
    Text.
    
    +
    More text.
    Text.
    
    +
    
    More text.
  • Two or more blank lines in a row under a term with nothing after its ::. Asciidoctor reads the line after them as the start of the term’s description, even a delimiter or a block attribute line. After one blank line, such a line ends the description list instead.

  • Two or more blank lines in a row between a term’s description and a list with a block attribute line above it. After one blank line, the list belongs to the description. After two, it is a list of its own below the description list.

    Example

    With one blank line, the list belongs to the description of term. With two, it is a list of its own below the description list.

    Part of the descriptionA list of its own
    term:: text
    
    [.role]
    * item
    term:: text
    
    
    [.role]
    * item
  • The blank line under a comment. Asciidoctor drops comments before it renders, so nothing ties a comment to the block beneath it. Removing that blank line would make a comment that stands on its own read as a comment about the block below it.

  • The blank line under an attribute entry whose last line still ends in \ or +. The value runs on to the next blank line. Removing that blank line would make the block below part of the attribute value instead of rendering it.

  • The lines below front matter, down to the first blank line: adocfmt adds no blank line between them. Asciidoctor skips front matter only when it is told to. Otherwise, it reads everything from the opening fence to that blank line as one paragraph. So a blank line there changes what the document title below the front matter becomes.

    Example
    Read as textA section title
    ---
    layout: post
    ---
    = Title
    ---
    layout: post
    ---
    
    = Title
  • A blank line at the top of a file whose first line of content is a ---. Front matter counts only when its fence is the very first line. Removing that blank line would turn lines that are not front matter into front matter.

  • Blank lines inside a listing, a literal block or a table. Each of these counts as one block.

Block delimiters

A delimited block opens and closes with a delimiter line, its fence. Both fences are written as short as the block allows: four characters, unless a line inside the block needs a longer fence.

BeforeAfter
--------
code
--------
----
code
----

A table fence is shortened the same way. Its first character picks how the rows are read, so that character stays: |======= becomes |===, and ,======= becomes ,===.

A block ends at the first line that matches its opening fence. So the new fence is the shortest one that matches no line inside the formatted block.

BeforeAfter
--------
----
code
--------
-----
----
code
-----

This includes lines inside nested blocks, because a line that matches the outer fence closes the outer block even there.

Example

The ==== sits inside a listing, but it would still close an example block fenced with ====. So the fence of the example block shrinks only to five characters, not four.

BeforeAfter
======
----
====
----
======
=====
----
====
----
=====

Left alone:

  • An open block and a Markdown fence. Each has only one valid length: two dashes for an open block and three backticks for a Markdown fence. So there is nothing to shorten.

  • A comment block, which //// opens. A comment block is a block of its own only where it stands alone. Otherwise, it is part of the metadata of the block below it. So a rewrite would depend on where the comment block sits rather than on what it holds. A [comment] makes a comment block only out of an open block. Above any other fence, Asciidoctor drops the style and reads the block that the delimiter names.

  • A block that an include or a conditional reaches, inside its body or on the line above it. The directive may bring in exactly the line that a shorter fence would close on.

List markers

A list is written with one marker per kind: * for a bullet and . for a number. One space separates the marker from the text.

BeforeAfter
1.  first
2.  second

-	one
-	two
. first
. second

* one
* two

The numbers themselves carry no meaning. Asciidoctor counts the items and only warns where the numbers differ from that count. So 3. 4. 5. renders like . . .. To start at another number, set the start attribute, which this rule leaves alone.

Left alone:

  • A list whose new marker is already used by a list around it or a list inside it. AsciiDoc tells nested lists apart by their markers, so the two lists would become one.

    Example

    The * list is nested inside the - list because the marker changes. Once both lists use the same marker, nested becomes a second item of the outer list. Lists on the other side of a delimited block’s fence do not count, because a list that is open outside the block is not open inside it.

    Two levelsOne level
    - one
    * nested
    * one
    * nested
  • a., A., i), I), the • bullet, description terms and callouts. Each of them expresses something that a * or a . cannot.

    Example
    BeforeAfter
    a.   alpha
    
    term::   text
    a. alpha
    
    term:: text
  • A list that an include or a conditional reaches, next to the list or inside one of its items. Nothing marks the end of a list, so the items that a directive brings in may still belong to it. Their markers are known only after Asciidoctor resolves the directive.

  • The first line of a list, where a shorter line would read as a section title. The rest of the list keeps that line’s marker.

    Example

    A section title can be written over two lines. Asciidoctor takes the second line as the underline when its length is within one character of the first line.

    A listA section title
    -   item
    ~~~~~~
    * item
    ~~~~~~

One sentence per line

The lines of a paragraph are joined and split again, so that every sentence starts on a line of its own.

BeforeAfter
First sentence
continues here. Second one.
First sentence continues here.
Second one.

A sentence ends at a ., ! or ? followed by whitespace and a word that starts with an uppercase letter. Closing quotes, brackets and formatting marks after it belong to the sentence. A period does not end a sentence after a digit, a single letter or a common English or German abbreviation such as Dr., e.g., z. B. or Nr.. An ellipsis does not end a sentence either. A line that ends in a ., !, ? or : keeps its line break, even after a number, an abbreviation or …​. So a sentence may start with a lowercase word, code or a macro such as link:. A hard line break stays where it is. So does a line break inside code, a passthrough or a macro.

Left alone:

  • The text of a list item, including a description list entry. A paragraph attached to an item with a + is reflowed like any other.

    Example
    BeforeAfter
    * This item has
    two lines. They stay.
    +
    This paragraph
    is attached. It is reflowed.
    * This item has
    two lines. They stay.
    +
    This paragraph is attached.
    It is reflowed.
  • A paragraph in a list, when one of its lines starts like a list item. Asciidoctor takes that line for the start of a nested list and leaves a + below it to that list, so the page shows the + as text. Joined into the line above, the + would attach the next paragraph again.

    Example

    The - or line keeps the + below it on the page. Reflowed, the + would disappear from the page.

    Left aloneReflowed
    * Install the tool.
    +
    Pass the path as an argument
    - or set it in the config file.
    +
    Then run it.
    * Install the tool.
    +
    Pass the path as an argument - or set it in the config file.
    +
    Then run it.
  • A paragraph whose line breaks show on the page. Verse and literal paragraphs show every line break. So does a paragraph with the hardbreaks option, set on the paragraph or for the whole document. A paragraph with its own subs can pass raw HTML through, and raw HTML can show a line break.

    Example

    A verse paragraph keeps its line breaks on the page, so joining its lines would change what the page shows.

    [verse]
    Roses are red. Violets
    are blue.
  • A paragraph below :attribute-missing: drop-line, which sets how Asciidoctor treats missing attributes. Asciidoctor then drops every line that refers to a missing attribute, so the line breaks decide which sentences the page shows.

  • A paragraph that holds a comment line. Joining its lines would pull the comment into the text, where it shows.

  • A paragraph right below an include, a conditional or front matter, with no blank line between. Asciidoctor may read it as part of a paragraph above it; see Heading markers. When the directive brings in a literal paragraph, the line breaks show.

  • A block that an extension may read in its own way. That is a block with a style Asciidoctor does not know, such as [mermaid], and a paragraph that starts with a block macro it does not know, such as plantuml::diagram.puml[]. Which extensions are loaded depends on the build, which adocfmt cannot see.

  • A paragraph that a joined or a split line would turn into something else. A line that starts like a list item, an attribute line or an admonition label is syntax, not text.

    Example
    A paragraphAn admonition
    NOTE:
    the label stands alone.
    NOTE: the label stands alone.

View the source on GitHub