Docouture

AsciiDoc basics

Plain AsciiDoc — nothing docouture-specific — every block this page shows is standard Asciidoctor syntax, documented in full in the docouture-writing-docs-pages skill’s reference/language-basics.md. Each subsection below shows the raw markup first, then the same markup rendered live. See Custom AsciiDoc components for this site’s own custom blocks, and Integrations for the build-time capabilities (diagrams, syntax highlighting) mentioned along the way.

One exception: == Includes below uses a plain Asciidoctor directive (include::), but the partial$/example$ targets it points at are Antora’s own resource-family classification, not something core AsciiDoc knows about — noted there, not silently folded in with the rest.

Headings and structure

Sections nest by repeating =, never by skipping a level:

= Page title
== Section
=== Subsection
==== Sub-subsection

This page is itself at the first real section level (==); the next few subsections go one level deeper — the nav/TOC outline you see for this very page is the live rendering of that nesting.

A discrete heading

[discrete]
==== A discrete heading

[discrete] above a heading keeps it out of both the navigation outline and the page’s own TOC — useful for a heading that organizes the page visually without being a real subsection of it.

Text formatting

*bold* and **b*o*ld mid-word**, _italic_ and it__ali__c mid-word, `mono`, `+literal, no
subs+`, #marked text#, [.underline]#a span with a role#. Chemical formula: H~2~0.
Exponent: E = mc^2^. A footnote after this sentencefootnote:[The footnote text itself,
rendered at the bottom of the page.].

bold and b*o*ld mid-word, italic and italic mid-word, mono, literal, no subs, marked text, a span with a role. Chemical formula: H20. Exponent: E = mc2. A footnote after this sentence[1].

Lists

Unordered, with a nested item carrying its own attached paragraph:

* first
* second
** nested
+
Attached via the `+` continuation.
  • first

  • second

    • nested

      Attached via the + continuation.

Ordered, custom numbering:

[upperalpha]
. first
. second
. third
  1. first

  2. second

  3. third

Custom unordered markers:

[square]
* square-marked
* another
  • square-marked

  • another

[circle]
* circle-marked
* another
  • circle-marked

  • another

Description list, then its horizontal variant:

term:: definition
another term:: definition
term

definition

another term

definition

[horizontal]
term:: definition
another term:: definition
term

definition

another term

definition

A checklist:

* [ ] not done yet
* [x] done
  • not done yet

  • done

https://example.com[An external link], https://example.com[same, opened in a new
tab^], link:https://example.com[the explicit macro], mailto:docs@example.com[a mail
link]. Referring to another page on this site: xref:main:guides-adding-a-page.adoc[] —
empty xref text renders that page's own title, so it stays correct if the title
changes. A fragment:
xref:main:guides-adding-a-page.adoc#group-without-a-page-of-its-own[a specific section
on that page].

An external link, same, opened in a new tab, the explicit macro, a mail link. Referring to another page on this site: Adding a page — empty xref text renders that page’s own title, so it stays correct if the title changes. A fragment: a specific section on that page.

Images and icons

.A block image, capped at its own natural size
image::ROOT:hero-placeholder.png[A placeholder image,480]

An inline image sits mid-paragraph: image:ROOT:card-placeholder.png[A small inline
placeholder,20,20] like so. Font icons, keyboard shortcuts and UI paths:
icon:check[] done, kbd:[Ctrl+C] to copy, btn:[Save] to save, menu:File[Save As] to open
the save-as dialog.
A placeholder image
Figure 1. A block image, capped at its own natural size

An inline image sits mid-paragraph: A small inline placeholder like so. Font icons, keyboard shortcuts and UI paths: done, Ctrl+C to copy, Save to save, File  Save As to open the save-as dialog.

Admonitions

Five types exist: NOTE, TIP, IMPORTANT, WARNING, CAUTION — a sixth needs a role plus custom CSS, not a new admonition type. The one-line form is good for a single sentence; the multi-line (delimited) form can hold anything, including another block:

NOTE: The one-line form — good for a single sentence.

[TIP]
====
The multi-line form — anything can go inside, including another block.

[,console]

$ npm run build

====

[IMPORTANT]
====
Five types exist: NOTE, TIP, IMPORTANT, WARNING, CAUTION.
====

[WARNING]
====
Multi-line WARNING.
====

[CAUTION]
====
Multi-line CAUTION.
====
The one-line form — good for a single sentence.

The multi-line form — anything can go inside, including another block.

$ npm run build

Five types exist: NOTE, TIP, IMPORTANT, WARNING, CAUTION. A sixth needs a role plus custom CSS, not a new admonition type.

Multi-line WARNING.

Multi-line CAUTION.

Source code

[,typescript]

const answer: number = 42


const answer: number = 42

A block with no language at all still gets the code surface and copy button, just no syntax colour:

plain text, no highlighting

Callouts, explained in a colon list right after the block:

[,js]

const x = 1 // <1> const y = x + 1 // <2>

<1> Set `x` to `1`.
<2> Derive `y` from it.
const x = 1 (1)
const y = x + 1 (2)
1 Set x to 1.
2 Derive y from it.

The .wrap role lets long lines wrap instead of scrolling horizontally:

const config = { alpha: 1, beta: 2, gamma: 3, delta: 4, epsilon: 5, zeta: 6, eta: 7 }

Tables

A basic table with a header row:

[cols="1,2,1"]
|===
|Name |Description |Default

|`retry.max-attempts`
|Number of times a failed request is retried.
|`3`

|`retry.backoff`
|Base delay between retries; doubles each attempt.
|`200ms`
|===
Name Description Default

retry.max-attempts

Number of times a failed request is retried.

3

retry.backoff

Base delay between retries; doubles each attempt.

200ms

%autowidth shrinks the table to its content instead of filling the column:

[%autowidth]
|===
|Status |Value
|Build |passing
|Coverage |92%
|===

Status

Value

Build

passing

Coverage

92%

%noheader with a percentage width:

[%noheader,width=50%]
|===
|Node.js |`>= 24`
|pnpm |`>= 10`
|===

Node.js

>= 24

pnpm

>= 10

An absolute pixel width via table-width= (bypasses Asciidoctor's own percentage-only width=), with nowrap-cols= pinning specific columns so their tokens never break mid-word:

[table-width=520px,cols="2,1,2",nowrap-cols="1,2"]
|===
|Property |Type |Notes

|`timeout.connect`
|`duration`
|Maximum time to wait for a connection.

|`timeout.read`
|`duration`
|Maximum time to wait for a response once connected.
|===
Property Type Notes

timeout.connect

duration

Maximum time to wait for a connection.

timeout.read

duration

Maximum time to wait for a response once connected.

Column/cell styles (a asciidoc, l literal, m monospace, h header, s strong) and a column span:

[cols="1,1,2"]
|===
|Name |Type |Values

|size
|enum
|`small` \| `medium` \| `large`

2+|spans two columns
|third cell
|===
Name Type Values

size

enum

small | medium | large

spans two columns

third cell

Includes

Content lives once, in its own file, and gets pulled into a page with include::. Antora restricts the target to a resource ID naming one of its content families — partial$ for a reusable AsciiDoc fragment under a module’s own partials/ directory (never rendered as a page of its own), example$ for a file under examples/ (source code, config, fixtures). A relative path (include::../other.adoc[]) or a URL does not work — only these resource-ID families do.

This paragraph lives in its own file under `modules/main/partials/` and is pulled
into whichever page includes it — edit it once, and every page that includes it
picks up the change.

// tag::callout[]
This line is wrapped in a tagged region — a page can include just this part with
`include::partial$example-partial.adoc[tag=callout]`, skipping the paragraph above.
// end::callout[]

A tagged region only, from the same file:

This line is wrapped in a tagged region — a page can include just this part with
`include::partial$example-partial.adoc[tag=callout]`, skipping the paragraph above.

This paragraph lives in its own file under modules/main/partials/ and is pulled into whichever page includes it — edit it once, and every page that includes it picks up the change.

This line is wrapped in a tagged region — a page can include just this part with include::partial$example-partial.adoc[tag=callout], skipping the paragraph above.

A tagged region only, from the same file:

This line is wrapped in a tagged region — a page can include just this part with include::partial$example-partial.adoc[tag=callout], skipping the paragraph above.

Tagged regions are marked in the included file with comments in that file’s own comment syntax (// tag::callout[] / // end::callout[] for AsciiDoc). leveloffset=+1 demotes every section title in an included file that carries its own = heading — required when the included file is a page-shaped fragment rather than a bare partial.

Quotes and sidebars

[quote,Grace Hopper]
____
The most dangerous phrase in the language is, "We've always done it this way."
____

[verse]
____
Two roads diverged in a wood, and I—
I took the one less traveled by.
____

.A sidebar
****
Asides, pull quotes, or background information that supplements the main flow without
interrupting it.
****

The most dangerous phrase in the language is, "We’ve always done it this way."

— Grace Hopper
Two roads diverged in a wood, and I—
I took the one less traveled by.
A sidebar

Asides, pull quotes, or background information that supplements the main flow without interrupting it.

Collapsible

A single, standalone collapsible — for grouping several together with proper role=group semantics and single-open behaviour, see Custom AsciiDoc components's [accordion] block instead.

.Click to expand
[%collapsible]
====
Rendered as a native `<details>` element — works with JavaScript off.
====
Click to expand

Rendered as a native <details> element — works with JavaScript off.


1. The footnote text itself, rendered at the bottom of the page.