Migrate from AsciiDoc.py

AsciiDoc.py is the original and legacy Python-based processor for the AsciiDoc language. It has been superseded by Asciidoctor. If you’re currently using AsciiDoc.py to convert your AsciiDoc documents and are ready to switch to Asciidoctor, you’ll need to migrate your legacy AsciiDoc content to the official AsciiDoc syntax defined and supported by Asciidoctor. In doing so, you’ll also benefit from the enhancements that have been added to the AsciiDoc language since Asciidoctor took over development of the language. This page covers those differences and how to migrate.

This documentation specifically covers migration from AsciiDoc.py 8.6.

Processor call

The Asciidoctor processor is a drop-in replacement for AsciiDoc.py. You can replace the call to AsciiDoc.py (asciidoc) with the equivalent call to Asciidoctor (asciidoctor).

$ asciidoctor document.adoc

If your document makes heavy use of the legacy AsciiDoc syntax supported by AsciiDoc.py, you may have better luck enabling compat mode:

$ asciidoctor -a compat-mode document.adoc

However, compat mode is strictly a migration aid. You should only use it as an interim measure while you’re migrating your content. It’s not something you want to rely on long term and is considered deprecated.

Default HTML backend

AsciiDoc.py used XHTML 1.1 as its default output. Asciidoctor’s default output is HTML 5 (i.e., backend=html5) and the html backend maps to html5.


AsciiDoc.py provided a theming mechanism that encapsulated CSS, JavaScript, and images. The --theme option activated one of these themes, which was resolved from your home directory. In Asciidoctor, you control the theme using CSS stylesheets, which you specify using -a stylesheet=<stylesheet>.

If you require more advanced theming, you can inject additional resources using a docinfo file or a postprocessor extension.

Default HTML stylesheet

The Asciidoctor and AsciiDoc.py stylesheets look quite different, but they’re mostly interchangeable since the underlying HTML structure of the two processors is nearly identical.

If you prefer the AsciiDoc.py stylesheet, you can use it by copying it from the AsciiDoc.py stylesheets directory and instructing Asciidoctor to apply it using:

$ asciidoctor -a stylesheet=asciidoc.css document.adoc

Keep in mind that the default stylesheet in Asciidoctor is just that, a default. If you don’t like its appearance, you can customize it.

Unlike AsciiDoc.py, Asciidoctor loads some resources from a CDN. It’s possible to configure Asciidoctor to load all resources from local files. For instance, you can unset the webfonts attribute so that the generated HTML does not use fonts from Google Fonts. There are similar attributes to control how additional resources are resolved.

Updated and deprecated AsciiDoc syntax

As the steward of the AsciiDoc language, Asciidoctor reworked some of the AsciiDoc syntax originally introduced by AsciiDoc.py in an effort to make it more consistent, easier to learn, and, in some cases, more concise. This section outlines those improvements to the modern AsciiDoc syntax and how it differs from the legacy AsciiDoc recognized by AsciiDoc.py.

If a feature or attribute isn’t mentioned in the following tables, then it works in Asciidoctor just like it worked in AsciiDoc.py.

Inline formatting

Feature AsciiDoc.py Asciidoctor Notes

italic text

'italic text' or _italic text_

_italic text_

See Italic.
Reverts to AsciiDoc.py syntax when compat-mode is enabled.

monospace text

+monospace text+

`monospace text` or [x-]+monospace text+

See Monospace.
Reverts to AsciiDoc.py syntax when compat-mode is enabled.

literal monospace text

`literal monospace text`

`+literal monospace text+` or [x-]`literal monospace text`

See Literal monospace.
Reverts to AsciiDoc.py syntax when compat-mode is enabled.

Curved “double quotes”

``double quotes''

"`double quotes`"

See Quotation Marks and Apostrophes.
Reverts to AsciiDoc.py syntax when compat-mode is enabled.

Curved ‘single quotes’

`single quotes'

'`single quotes`'

See Quotation Marks and Apostrophes.
Reverts to AsciiDoc.py syntax when compat-mode is enabled.

Inline role(s)

[role]#text# or [role1 role2]#text#

[.role]#text# or [.role1.role2]#text#

See Text Span and Built-in Roles.
While Asciidoctor still recognizes the bare, space-separated syntax for inline roles, the shorthand-style with the leading dot is preferred.

Font size roles

big, small

user-specified role (e.g., [.details]) with corresponding CSS rules provided by stylesheet

See Using Custom Inline Styles.
The default stylesheet in Asciidoctor still provides CSS for these built-in roles, but they are considered deprecated.

Color roles

aqua, aqua-background, etc.

user-specified role [.brand-primary] with corresponding CSS rules provided by stylesheet

See Using Custom Inline Styles.
The default stylesheet in Asciidoctor still provides CSS for these built-in roles, but they are considered deprecated.

Table of contents

Feature AsciiDoc.py Asciidoctor Notes

Scrollable, left margin TOC


:toc: left

See Position the TOC.

TOC location

toc-placement and toc-position

:toc: <value>

See Position the TOC.

User-specified TOC location

:toc-placement: manual

:toc: macro

See Position the TOC.

Document and section titles

Feature AsciiDoc.py Asciidoctor Notes

Two-line style (setext) document title


= Title

See Document Title.
When Asciidoctor detects the two-line style document title, it switches to compat mode by implicitly setting compat-mode. To revert this behavior, explicitly unset compat-mode.

Underlined section titles

Underline length must match title length +/- 2 characters.

== Level 1 title
=== Level 2 title
==== Level 3 title
===== Level 4 title

See Section Titles and Levels.

Section numbers



See Section Numbers.

Asciidoctor is more careful when deriving automatic IDs for sections from the section title to avoid generating obscure IDs.

  • Asciidoctor removes any start and end HTML/XML tags, whereas AsciiDoc.py does not.

  • Asciidoctor removes any character references (e.g., &copy;), whereas AsciiDoc.py does not (see next rule).

  • Asciidoctor removes any invalid characters (e.g., $), whereas AsciiDoc.py replaces these characters with the value of the idseparator attribute.

  • Asciidoctor automatically generates IDs for discrete headings, whereas AsciiDoc.py does not.

To ensure your IDs have maximum portability, it’s best to define them explicitly if the section title contains special characters or formatting.


Feature AsciiDoc.py Asciidoctor Notes

Table cell

a| or asciidoc|

a| only

See Add Cells and Rows to a Table.

Table cell separator

A Python regular expression.

One or more literal characters or \t for tab.

See Add Cells and Rows to a Table, Table Data Formats, and custom separators.

Horizontal and vertical alignment for tables cells

halign, valign

Column and cell specifiers

See Align Content by Column and Align Content by Cell.

Make tables full page width in DocBook


not implemented


Feature AsciiDoc.py Asciidoctor Notes

Block delimiters

Delimiter lines do not have to match in length.

The length of start and end delimiter lines must match exactly.

See Delimited Blocks.

Default substitutions for passthrough blocks

Applies attributes and macros substitutions to passthrough blocks

Does not apply any substitutions to passthrough blocks

Add [subs="attributes,macros"] above block to restore behavior.


Feature AsciiDoc.py Asciidoctor Notes

Substitute +



See Post Replacement Substitutions.

Suppress inline substitutions and retain block indents when importing large blocks of plain text


not implemented

Close equivalent is a passthrough block or a listing block with the indent attribute.

Mathematical expressions

AsciiDoc.py and Asciidoctor can convert embedded LaTeX and AsciiMath expressions (e.g., asciimath:[expression], latexmath:[expression], etc.). In Asciidoctor, activate STEM support first using the stem attribute.


Feature AsciiDoc.py Asciidoctor Notes

ifeval::[ ]

Evaluates any Python expression.

Evaluates simple logical expressions testing the value of attributes.

See ifeval Directive.

Provide name of current document


not implemented

Provide directory of current document


not implemented

Apply special formatting to named text


not implemented

Replace tabs with spaces in all text, using a default tab size of 8

tabsize (in-document and include directive)

in-document only

Asciidoctor only replaces tabs with spaces in verbatim blocks, and the attribute has no default. In other words, tabs are not expanded in verbatim content blocks unless this attribute is set on the block or the document. For all other text, Asciidoctor tabs are fixed at 4 spaces by the CSS. See normalize block indentation.

docinfo attributes

docinfo attribute values were introduced into AsciiDoc by Asciidoctor 1.5.5 to replace the less descriptive docinfo1 and docinfo2 attributes. Here are the equivalents of the old attributes using the new values:

  • :docinfo: = :docinfo: private

  • :docinfo1: = :docinfo: shared

  • :docinfo2: = :docinfo: shared,private


In AsciiDoc.py, single line comments could be turned into DocBook <remark> elements using showcomments. This feature isn’t implemented in Asciidoctor, but you can send remarks to the output, using an extension, or ifdef directives and passthrough blocks like the example shown below.

<remark>Your comment here</remark>

Compatibility mode

We want to continue to evolve and refine the AsciiDoc syntax, but we also recognize that compatibility is very important. That’s why Asciidoctor provides a compatibility mode (aka compat mode) with AsciiDoc.py (as well as some inline transitional syntax).

Compat mode will help you either stay with or transition away from the legacy AsciiDoc syntax recognized by AsciiDoc.py to the modern AsciiDoc syntax recognized by Asciidoctor. This mode should only be used as a tool to assist with migration, not as a long-term strategy.

If you can’t migrate right now, you can activate compat mode by setting the compat-mode document attribute in the document header or by passing it to the processor:

$ asciidoctor -a compat-mode document.adoc

You can also enable compat mode implicitly by beginning the document with a setext-style (i.e., two-line) document title:

Compat Mode

ifdef::compat-mode[Compat mode is on!]

If you prefer the setext-style document title, but don’t want compat mode to be enabled, you must unset the compat-mode attribute explicitly.

Not Compat Mode

ifndef::compat-mode[Compat mode is not on.]

When compat mode is enabled, Asciidoctor adapts some of its behavior and its interpretation of AsciiDoc to more closely align with AsciiDoc.py. The most noticeable difference is that backticks now only indicate monospace text as opposed to literal monospace. Literal monospace is signified using a compound markup that combines an inline passthrough with monospace formatting.

Feature Source Result




Literal monospace






To learn more about the adaptations that are activated by compat mode, refer to inline formatting.

If you’ve written content to be processed with AsciiDoc.py, and you aren’t yet ready to migrate, or need to ease into that migration, Asciidoctor’s compatibility mode will help ensure that your existing content will continue to work (to the extent possible).

Configuration files

Asciidoctor does not use .conf files or filters, so --conf-file, --dump-conf, and --filter are not applicable. Instead, Asciidoctor provides an extension API that replaces the configuration-based extension and filter mechanisms in AsciiDoc.py.


AsciiDoc.py has built-in .conf files that translated built-in labels. In Asciidoctor, you must define the translations for these labels explicitly. See Localization Support for details.

AsciiDoc.py extensions

The extension mechanism is completely different in Asciidoctor, but most of the standard extensions have been re-implemented, so they should work with minor changes.

AsciiDoc.py Asciidoctor


  • You can choose from a number of source highlighters.

  • Source highlighter values are built-in.

  • src_numbered, src_tab, args are not implemented directly, but check the highlighter you are using for what features it has and how to configure them.


Not implemented.

[latex] block macro

Use a stem block.


Use Asciidoctor Diagram.

Custom extensions

AsciiDoc.py custom extensions are Python commands, so they don’t work with Asciidoctor. Depending on the Asciidoctor processor you choose, you can re-write your extensions in Ruby, Java, or JavaScript.

Extract text

AsciiDoc.py provides a frontend to the DocBook toolchain named a2x.py. This script can produce various output formats from an AsciiDoc document. One of those formats is text (aka “plain text”). In order to extract the text, the DocBook toolchain first converts the AsciiDoc to HTML, then extracts the text from that document using lynx.

There are numerous approaches to extracting text from AsciiDoc in Asciidoctor. One way is to write an Asciidoctor converter mapped to the text backend that converts AsciiDoc to text only. Another approach is to convert the AsciiDoc to HTML, then extract text from the HTML output document using a text-based browser, just like the DocBook toolchain does.

Before continuing, it’s worth noting that there’s no universal definition of “plain text”. It all depends on what information you are trying to extract. That’s why you won’t find a text backend provided by Asciidoctor core. Let’s consider what tools are available.

As an alternative to lynx, the text-based browser w3m does a nice job of extracting text from an HTML document. For example:

$ w3m -dump -cols 120 doc.html > doc.txt

You can set the number of columns so lines aren’t hard wrapped at a fixed line width. The upper bounds for this value is MAX_INT (2147483647). You can retrieve that value dynamically using Perl.

$ w3m -dump -cols $(perl -MPOSIX -e 'print INT_MAX') doc.html > doc.txt

It doesn’t seem possible to configure w3m to preserve markup that indicates headings. However, the text-based browser elinks offers this behavior by default through indentation.

$ elinks -dump 1 -no-references -no-numbering -dump-width 50000 doc.html > doc.txt

Yet another option is the html-to-text module for Node.js, which parses HTML and returns beautiful text.

If you want to extract the text during AsciiDoc conversion, you can do so using an Asciidoctor postprocessor extension.

require 'open3'

Asciidoctor::Extensions.register do
  postprocessor do
    process do |doc, output|
      outfile = (doc.attr 'outfile').sub %r/\.\S+$/, '.txt'
      Open3.popen2 'elinks -dump 1 -no-references -no-numbering' do |is, os|
        is.print output
        File.write outfile, os.read

This extension will write a file with a .txt extension adjacent to the document written by the converter.


AsciiDoc.py --doctest ran its unit tests. See the contributing guide to learn how to run the Asciidoctor unit tests. Asciidoctor also has a doctest tool which you can use when creating custom HTML or XML-based converters.

Help topics

In both AsciiDoc.py and Asciidoctor, the --help CLI option shows the command usage by default. It can also show a syntax crib sheet using --help syntax or the man page using --help manpage.

In AsciiDoc.py, the --help manpage option emits a plaintext version of the man page. Asciidoctor, on the other hand, outputs the formatted man page so you can use it with a man pager. To view it, you need to pipe the result to the man command as follows:

$ asciidoctor --help manpage | man /dev/stdin


$ asciidoctor --help manpage | man -l -

If you want to view the plaintext version with Asciidoctor, you can route the output through the col command as follows:

$ asciidoctor --help manpage | man -l - | col -bx

Alternately, you can view the man page for Asciidoctor online at asciidoctor(1).