AsciiDoc Validation and Linting

AsciiDoc documents should be validated before committing to ensure consistent formatting and prevent Antora build warnings. This guide documents the available validation tools and rules.

AsciiDoc Linter Script

Location: scripts/adoc-lint.py

A Python-based linter that detects and fixes common AsciiDoc formatting issues that cause Antora build warnings or inconsistent rendering.

Usage

# Report issues only
python scripts/adoc-lint.py ./docs/modules

# Fix issues automatically
python scripts/adoc-lint.py ./docs/modules --fix

# Preview fixes without applying (dry-run)
python scripts/adoc-lint.py ./docs/modules --fix --dry-run

# Verbose output with context
python scripts/adoc-lint.py ./docs/modules --verbose

When to Run

  • Before committing documentation changes

  • As part of CI/CD pipeline validation

  • After generating documentation with AI agents

Supported Rules

Rule Description Auto-Fix

ADOC-001: Bullet List Blank Lines

Bullet list must have blank line before first item (unless after heading)

Yes

ADOC-002: Explicit Numbered Lists

Explicit numbered lists should use auto-numbering

Yes

ADOC-003: Markdown Code Fences

Markdown code fences should use AsciiDoc delimited blocks

Yes

ADOC-004: Unescaped URL Parameters

URL path parameters should be escaped as attributes

No

ADOC-005: Relative Xref Paths

Relative xref paths should use module-relative paths

No

ADOC-001: Bullet List Blank Lines

Severity: Warning
Auto-Fix: Yes

Bullet lists must have a blank line before the first item, unless the list immediately follows a heading.

Incorrect
Some paragraph text.
* First item
* Second item
Correct
Some paragraph text.

* First item
* Second item
Also Correct (after heading)
== Section Heading
* First item
* Second item

ADOC-002: Explicit Numbered Lists

Severity: Warning
Auto-Fix: Yes

Explicit numbered lists (using 1., 2., etc.) should use auto-numbering (.) instead. This prevents Antora "list item index" warnings when list items are separated by blocks.

Incorrect
1. First step
2. Second step
3. Third step
Correct
. First step
. Second step
. Third step

Handling Interrupted Lists

When a numbered list is interrupted by a code block or other content, use list continuation (+) to maintain numbering:

Correct - List Continuation
. First step
. Second step with code:
+
[source,bash]

echo "example"

. Third step continues automatically

If you need to restart numbering from a specific number after a section break, use the [start=N] attribute:

Correct - Explicit Start
[start=5]
. This item is numbered 5
. This item is numbered 6

ADOC-003: Markdown Code Fences

Severity: Warning
Auto-Fix: Yes

Markdown-style code fences (triple backticks) should be converted to AsciiDoc delimited blocks for consistent rendering.

Incorrect
```java
public class Example {}
```
Correct
[source,java]
----
public class Example {}
----

The linter automatically:

  • Detects the language from the opening fence (e.g., ```java)

  • Converts to [source,lang] attribute block

  • Replaces backticks with four dashes (----)

ADOC-004: Unescaped URL Parameters

Severity: Info
Auto-Fix: No (manual fix required)

URL path parameters like {id} or {type} trigger Antora "skipping reference to missing attribute" warnings because Antora interprets curly braces as attribute references.

Problematic
The endpoint `GET /api/users/{id}` returns user details.
Solution

Define escaped attributes at the top of your document:

= API Documentation
:id: \{id\}
:type: \{type\}
:userId: \{userId\}

The endpoint `GET /api/users/{id}` returns user details.

The backslash escapes the opening brace, so {id} defines an attribute named id with the literal value {id}.

Common URL Parameters

Consider defining these common parameters when documenting REST APIs:

:id: \{id\}
:type: \{type\}
:userId: \{userId\}
:eventId: \{eventId\}
:status: \{status\}

ADOC-005: Relative Xref Paths

Severity: Warning
Auto-Fix: No (manual fix required)

Cross-references using relative paths with ../ should use module-relative paths instead. This is critical for files that may be included from other modules via include:: directives.

Why This Matters

When a file in module-a/pages/subdir/file.adoc contains:

xref:../other-page.adoc[Other Page]

And this file is included from module-b:

Unresolved include directive in modules/ROOT/pages/asciidoc-validation.adoc - include::module-a:subdir/file.adoc[]

The ../ resolves relative to module-b, not module-a, causing broken links.

Incorrect
* See xref:../architecture/security-dimensions.adoc[Security Dimensions]
* Review xref:../domain-model/core-entities.adoc[Core Entities]
Correct
* See xref:architecture/security-dimensions.adoc[Security Dimensions]
* Review xref:domain-model/core-entities.adoc[Core Entities]

Module-Relative Path Convention

In Antora, xref paths within the same module are always relative to the pages/ directory:

modules/
└── security/
    └── pages/
        ├── index.adoc
        ├── architecture/
        │   ├── security-dimensions.adoc
        │   └── entity-classification.adoc
        └── domain-model/
            └── core-entities.adoc

From architecture/entity-classification.adoc, reference files as:

Target File Correct Xref

Same directory

architecture/resolution-algorithm.adoc

Different directory

domain-model/core-entities.adoc

Module index

Idealogic Documentation Standards

Cross-Module References

For references to other modules, always use the full module prefix:

* xref:security:architecture/security-dimensions.adoc[Security Dimensions]
* xref:registration-portal:architecture:security.adoc[Portal Security]

External Linting Tools

For more comprehensive linting beyond these rules, consider: