如果你在文档中发现了错误或疏漏, 请不要犹豫 提交一个issue或发起一个带有修复的pull request。 我们也欢迎你在 邮件列表 或 聊天室 中提问和讨论项目的各个方面。 欢迎新贡献者！

# Asciidoctor简介

## 1. 什么是Asciidoctor?

Asciidoctor是一个用于转换AsciiDoc内容为 HTML5，EPUB3，PDF，DocBook 5 （或4.5），幻灯片及其他格式的 快速 文本处理器和出版工具链。 Asciidoctor使用Ruby编写，打包为RubyGem发布在 RubyGems.org 。 Gem还打包在几个Linux发行版中，包括Fedora，Debian和Ubuntu。 Asciidoctor是开源的 托管在GitHub上 ，并使用MIT协议发布。

### 1.1. 整体概览

Asciidoctor读取书写的纯文本内容，如下图左侧面板所示，并将其转换为HTML5，如右侧面板所示。 如图所示，Asciidoctor为HTML5添加了默认样式，以提供舒适的开箱即用体验。

### 1.3. Asciidoctor.js

Asciidoctor也能够在JavaScript中使用。 Opal 用来将Ruby代码转换为JavaScript来生成 Asciidoctor.js ，可以用在任何可运行JavaScript的地方，如浏览器或Node.js等。

### 1.4. Asciidoctor的主要优势

Asciidoctor使用一组内置的ERB模板生成HTML 5和DocBook输出其结构和AsciiDoc生成的相同。 所有这些模板都可以用Ruby生态系统中可用的任意模板语言编写的自定义模板替换。 自定义模板的渲染由 Tilt 模板抽象库处理。 Tilt是Ruby生态系统中最受流行的gem包之一。

Beyond Ruby

Asciidoctor的使用并不只限于Ruby生态内。 感谢 JRuby，它是一个纯Java实现的Ruby解释器，让Asciidoctor也可以在Java应用中使用。 Apache MavenGradle，和 Rewrite 都有可用插件。 这些插件基于使用AsciidoctorJ的Asciidoctor。

Asciidoctor还有一个命令行接口（CLI）。 Asciidoctor命令行接口 asciidoctor，是AsciiDoc Python发行版中 asciidoc.py 脚本的替代。

#### 1.4.1. AsciiDoc语法处理

Asciidoctor读取并解析按AsciiDoc语法编写的文本内容，然后将解析树输入到一组内置模板中来生成HTML5，PDF，DocBook 5等。 你也可以选择编写自己的转换器或提供 Tilt 支持的模板来自定义生成的输出或生成其他格式。

 Asciidoctor是原AsciiDoc Python处理器（asciidoc.py）的替代。 Asciidoctor有超过1500个测试用例，来确保与AsciiDoc语法的完全兼容。

### 1.5. 与Markdown对比

#### 1.5.1. 开始使用Markdown

 IETF已经声明“没有“无效”Markdown这一说法” 详见 This Is Markdown! Or: Markup and Its Discontents。

AsciiDoc提供了一个更健全的替代方案。 AsciiDoc的语法比Markdown更（至少同样简单）简单。 同时AsciiDoc提供强大的功能和灵活性，不用在为如表格、描述列表、警示（提示、注释、警告等）、目录等基本语法使用HTML或不同“风格”的实现。

#### 1.5.3. 举例比较

**bold**
*bold*

**b**old
**b**old

*italic*
_italic_

n/a

__i__talic

monospace
monospace

monospace
monospace

[AsciiDoc](http://asciidoc.org)
http://asciidoc.org[AsciiDoc]

[user guide](user-guide.html)
link:user-guide.html[user guide]
xref:user-guide.adoc[user guide]

[get the PDF]({% raw %}{{ site.url }}{% endraw %}/assets/mydoc.pdf)
link:{site-url}/assets/mydoc.pdf[get the PDF]

See link:#_usage[Usage].

<h2 id="_usage">Usage</h2>
See <<_usage>>.

== Usage

<h2 id="usage">Usage</h2>
[#usage]
== Usage

n/a

. [[step-1]]Download the software

![Logo](/images/logo.png)
image:logo.png[Logo]

n/a

image::logo.png[Logo]

## Heading 2
== Heading 2

> Quoted text.
>
> Another paragraph in quote.
____
Quoted text.

Another paragraph in quote.
____

    $gem install asciidoctor Indented (by 1 or more spaces) $ gem install asciidoctor
Delimited
....
$gem install asciidoctor .... 代码块* java public class Person { private String name; public Person(String name) { this.name = name; } }  [source,java] ---- public class Person { private String name; public Person(String name) { this.name = name; } } ---- 无序列表 * apples * orange * temple * navel * bananas * apples * oranges ** temple ** navel * bananas 有序列表 1. first 2. second 3. third . first . second . third 主題分割 (水平线)* *** * * * --- - - - ___ _ _ _ ''' Typographic quotes (aka “smart quotes”) Enabled through an extension switch, but offer little control in how they are applied. The '90s popularized a new form of music known as "grunge" rock. Its influence extended well beyond music. Document header Slapped on as “front matter” --- layout: docs title: Writing posts prev_section: defining-frontmatter next_section: creating-pages permalink: /docs/writing-posts/ --- Native support! = Writing posts :awestruct-layout: base :showtitle: :prev_section: defining-frontmatter :next_section: creating-pages Admonitions n/a TIP: You can add line numbers to source listings by adding the word numbered in the attribute list after the language name. Sidebars n/a Lightweight Markup Writing languages that let you type less and express more. Block titles n/a Grocery list • Milk • Eggs • Bread Includes n/a include::intro.adoc[] URI reference [home]: https://example.org "Home" Go [home]. :home: https://example.org Go {home}[Home]. Custom CSS classes n/a [.path]_Gemfile_ * Asciidoctor also supports the Markdown syntax for this language feature. You can see that AsciiDoc has the following advantages over Markdown: • AsciiDoc uses the same number of markup characters or less when compared to Markdown in nearly all cases. • AsciiDoc uses a consistent formatting scheme (i.e., it has consistent patterns). • AsciiDoc can handle all permutations of nested inline (and block) formatting, whereas Markdown often falls down. • AsciiDoc handles cases that Markdown doesn’t, such as a proper approach to inner-word markup, source code blocks and block-level images.  Certain Markdown flavors, such as Markdown Extra, support additional features such as tables and description lists. However, since these features don’t appear in “plain” Markdown, they’re not included in the comparison table. But they’re supported natively by AsciiDoc. Asciidoctor, which is used for converting AsciiDoc on GitHub and GitLab, emulates “the good parts” of the Markdown syntax, like headings, blockquotes and fenced code blocks, making migration from Markdown to AsciiDoc fairly simple. For details about migration, see Markdown Compatibility. To read more about the shortcomings of Markdown, see these opinion pieces: # Quick Starts ## 2. Using the Command Line Interface Asciidoctor’s command line interface (CLI) is a drop-in replacement for the asciidoc.py command from the Python implementation. If the Asciidoctor gem installed successfully, the asciidoctor command line interface (CLI) will be available on your PATH. To confirm that Asciidoctor is available, execute: $ asciidoctor --version

The following information should be output in your terminal:

Asciidoctor 1.5.6.2 [https://asciidoctor.org]

To invoke Asciidoctor from the CLI and convert an .adoc file, execute:

$asciidoctor <asciidoc_file> This will use the built-in defaults for options and create a new file in the same directory as the input file, with the same base name, but with the .html extension. There are many other options available, listed in CLI Options. Full help is provided in the man page or via: $ asciidoctor --help

There is also an asciidoctor-safe command, which turns on safe mode by default, preventing access to files outside the parent directory of the source file. This mode is very similar to the safe mode of asciidoc.py.

## 3. Using the Ruby API

In addition to the command line interface, Asciidoctor provides a Ruby API. The API is intended for integration with other software projects and is suitable for server-side applications, such as Rails, Sinatra and GitHub.

Asciidoctor also has a Java API that mirrors the Ruby API. The Java API calls through to the Ruby API using an embedded JRuby runtime. See the AsciidoctorJ project for more information.

To use Asciidoctor in your application, you first need to require the gem:

require 'asciidoctor'

This statement makes all of the public APIs in Asciidoctor available to your script or application. You are now ready to start processing AsciiDoc documents.

The main entry points in the Asciidoctor API are the static methods to load or convert AsciiDoc documents, which we’ll cover the next two chapters.

To parse a file into an Asciidoctor::Document object:

doc = Asciidoctor.load_file 'mysample.adoc'

You can get information about the document:

puts doc.doctitle
puts doc.attributes

More than likely, you will want to convert the document. To convert a file containing AsciiDoc markup to HTML 5, use:

Asciidoctor.convert_file 'mysample.adoc'

The command will output to the file mysample.html in the same directory.

You can convert the file to DocBook 5.0 by setting the :backend option to 'docbook':

Asciidoctor.convert_file 'mysample.adoc', backend: 'docbook'

The command will output to the file mysample.xml in the same directory. If you’re on Linux, you can view the file using Yelp.

You can also use the API to convert strings and load custom templates.

# Getting Started

## 4. System Requirements

Asciidoctor works on Linux, macOS and Windows.

Asciidoctor requires one of the following implementations of Ruby:

• Ruby 1.8.7

• Ruby 1.9.3

• Ruby 2 (2.0.0 or better)

• JRuby 1.7 (Ruby 1.8 and 1.9 modes)

• JRuby 9000

• Rubinius 2.0 (Ruby 1.8 and 1.9 modes)

• Opal (Javascript)

We expect Asciidoctor to work with other versions of Ruby as well. We welcome your help testing those versions if you are interested in seeing them supported.

## 5. Installing the Asciidoctor Ruby Gem

Asciidoctor can be installed using the gem command, Bundler or a Linux package manager.

### 5.1. Install using gem

To install Asciidoctor using the gem command:

1. Open a terminal

2. Type the following gem command

$gem install asciidoctor If the Asciidoctor gem installed successfully, the asciidoctor command line interface (CLI) will be available on your PATH. To confirm that Asciidoctor is available, execute: $ asciidoctor --version

The following output should appear in your terminal:

Asciidoctor 1.5.6.2 [https://asciidoctor.org]
Runtime Environment (ruby 2.3.0p0 [x86_64-linux]) (lc:UTF-8 fs:UTF-8 in:- ex:UTF-8)

### 5.2. Install using Bundler

To install Asciidoctor for a project using Bundler:

2. Add the asciidoctor gem using:

gem 'asciidoctor'
3. Save the Gemfile

4. Open a terminal

5. Install the gem using the bundle command:

$bundle ### 5.3. Install on Fedora To install Asciidoctor on Fedora (or RHEL via EPEL) using the rubygem-asciidoctor package: 1. Open a terminal 2. Run the installation command on Fedora: $ sudo dnf install asciidoctor

The benefit of installing the gem using this method is that the package manager will also install Ruby and RubyGems if not already on your machine.

### 5.4. Install on Debian or Ubuntu

To install Asciidoctor on Debian or Ubuntu:

1. Open a terminal

2. Type the following apt-get command using sudo:

$sudo apt-get install asciidoctor The benefit of installing the gem via apt-get is that the package manager will also install Ruby and RubyGems if not already on your machine. ### 5.5. Install on Alpine Linux To install Asciidoctor on Alpine Linux using the asciidoctor package: 1. Open a terminal 2. Type the following apk command using sudo: $ sudo apk add asciidoctor

The benefit of installing the gem via apk is that the package manager will also install Ruby and RubyGems if not already on your machine.

## 6. Upgrading the Asciidoctor Ruby Gem

If you have an earlier version of Asciidoctor installed, you can update the gem using the gem command:

$gem update asciidoctor  If you accidentally use gem install instead of gem update, then you’ll end up with both versions installed. To remove the older version, use the following gem command: $ gem cleanup asciidoctor

On Fedora, you can update the package using:

$sudo dnf update asciidoctor  Your Fedora system may be configured to automatically update packages, in which case no further action is required by you. Refer to the Fedora docs if you are unsure. On Debian or Ubuntu, you can update the package using: $ sudo apt-get upgrade asciidoctor

On Alpine Linux, you can update the package using:

$sudo apk add --upgrade asciidoctor  The Linux packages may not be available right away after a release of the gem. It may take several weeks for the packages to be updated. If you need to upgrade to the latest version immediately, use the gem install option documented above. ## 7. Extensions and Integrations See Extensions. # Terms and Concepts All of the content in an Asciidoctor document, including lines of text, predefined styles, and processing commands, is classified as either a block or an inline element. Within each of these elements are an array of styles, options, and functions that can be applied to your content. This section will provide you with an overview of what each of these elements and sub-elements are and the basic syntax and rules for using them. ## 8. Elements One or more lines of text in a document are defined as a block element. Block elements can be nested within block elements. A document can include the following block elements: • Header • Title • Author Info • First Name • Middle Name • Last Name • Email Address • Revision Info • Revision Number • Revision Date • Revision Remark • Attribute Entry • Preamble • Section Title • Section Body • BlockId • Block Title • Block Macro • Block • Paragraph • Delimited Block • Table • List • Bulleted List • Numbered List • Description List • Callout List • List Entry • List Label • List Item • Item Text • List Paragraph • List Continuation An inline element performs an operation on a subset of the content within a block element. Inline elements include: • Quotes • Replacements • Special characters • Special words • Attribute references • Inline macros ## 9. Formatting Marks There are two categories of formatting marks for applying styles (i.e., formatting) to text, constrained and unconstrained. These formatting marks are referred to as quotes in the AsciiDoc syntax. This section covers their purpose, their differences and how to apply them. ### 9.1. Constrained quotes In short, “constrained” means around a word or sequence of words. Constrained quotes are single characters (often symbols) placed around a word. The “around” is defined by the fact that word characters do not appear immediately outside the enclosing marks. You use this form to format a word that stands alone, When the word stands alone That is *strong* stuff! to format a sequence of words, When there are multiple words That is *really strong* stuff! or to format a word adjacent to punctuation, like an exclamation mark. When the word is adjacent to punctuation This stuff sure is *strong*! ### 9.2. Unconstrained quotes In short, “unconstrained” means anywhere, including within a word. Unconstrained quotes are repeated characters (often symbols) placed anywhere in the text, including within a word. The “within” is defined by the fact that a word character may appear directly outside one of the enclosing marks. Unconstrained formatting She spells her name with an "h", as in Sara**h**. ### 9.3. When should I use unconstrained quotes? Consider the following questions: • Is there a letter, number, underscore directly outside the formatting marks (on either side)? • Is there a colon, semi-colon, or closing curly bracket directly before the starting formatting mark? • Is there a space directly inside of the formatting mark? If you answered “yes” to any of these questions, you need to switch to unconstrained (double formatting) quotes. To help you determine whether a particular syntax pattern requires unconstrained quotes, consider the following scenarios: Constrained or Unconstrained? AsciiDoc Result Quote type Reason Sara__h__ Sarah Unconstrained The a is directly adjacent to (the left of) a formatting mark. **B**old Bold Unconstrained The o is directly adjacent to (the right of) a formatting mark. &ndash;**2016** 2016 Unconstrained ; is directly adjacent to (the left of) a formatting mark. ** bold ** bold Unconstrained There are spaces directly inside the formatting marks. *2016*&ndash; 2016 Constrained The adjacent & is not a letter, number, underscore, colon, or semi-colon. *9*-to-*5* 9-to-5 Constrained The adjacent hyphen is not a letter, number, underscore, colon, or semi-colon. ### 9.4. Unconstrained formatting edge cases There are cases when it might seem logical to use constrained quotes, however unconstrained quotes are required. This happens because of the way the Asciidoctor parser (and the AsciiDoc Python parser) currently handles substitutions. Substitutions may be applied by the parser before getting to the formatting marks, in which case the characters adjacent to those marks may not be what you see in the original source. One such example is enclosing a monospaced phrase (i.e., codespan) inside typographic quotation marks, such as “endpoints”. Here’s how you would enter that: A monospaced phrase inside typographic quotes "endpoints" You might start with the following syntax: "endpoints" That only gives you “endpoints”, thought. The backticks contribute to making the typographic quotes. Adding another set of backticks isn’t enough because the phrase now calls for unconstrained formatting marks. As a result, the parser ignores the inner set of backticks and instead interprets them as literal characters. "endpoints" So you have to unconstrained monospace inside the typographic quotes (three sets of backticks in total) to coerce the parser into formatting the phrase as monospace. "endpoints" Although more rare, if what you’re after is to surround the monospaced phrase with normal double quotes, such as "endpoints", then you need to interrupt the typographic quote syntax by applying a role to monospaced phrase or escaping the typographic quote. For example: A monospaced phase inside normal quotes "[.code]endpoints" or \"endpoints" Another example is a possessive, monospaced phrase that ends in an “s”. In this case, you must switch the monospaced phrase to unconstrained formatting. The class' static methods make it easy to operate on files and directories. Rendered possessive, monospaced phrase The class’ static methods make it easy to operate on files and directories. Alternately, you could encode the typographic apostrophe directly in the AsciiDoc source to get the same result without the need to use unconstrained formatting. The class’ static methods make it easy to operate on files and directories.  This situation may improve in the future when Asciidoctor is switched to using a parsing expression grammar for inline formatting instead of the current regular expression-based strategy. For details, follow issue #61. ### 9.5. Escaping unconstrained quotes Unconstrained quotes are meant to match anywhere in the text, context free. However, that means you catch them formatting when you don’t intend them to. Admittedly, these symbols are a bit tricky to type literally when the content calls for it. But being able to do so is just a matter of knowing the tricks, which this section will cover. Let’s assume you are typing the following two lines: The __kernel qualifier can be used with the __attribute__ keyword... #CB###2# and #CB###3# In the first sentence, you aren’t looking for any text formatting, but you’re certainly going to get it. Double underscore is an unconstrained formatting mark. In the second sentence, you might expect CB###2 and CB###3 to be formatted in monospace and highlighted. However, what you get is a scrambled mess. The mix of constrained and unconstrained formatting marks in the line is ambiguous. There are two (reliable) solutions for escaping unconstrained formatting marks: • Use an attribute reference to insert the unconstrained formatting mark verbatim • Wrap the text you don’t want formatted in an inline passthrough The attribute reference is preferred because it’s the easiest to read: :dbl_: __ :3H: ### The {dbl_}kernel qualifier can be used with the {dbl_}attribute{dbl_} keyword... #CB{3H}2# and #CB{3H}3# This works because attribute expansion is performed after text formatting (i.e., quotes substitution) under normal substitution order. (Recall that backticks around text format the text in monospace but permit the use of attribute references). Here’s how you’d write these lines using the inline passthrough to escape the unconstrained formatting marks instead: The +__kernel+ qualifier can be used with the +__attribute__+ keyword... #+CB###2+# and #+CB###3+# Notice the addition of the plus symbols. That’s the closest thing to a text formatting escape. Everything between the plus symbols is escaped from interpolation (attribute references, text formatting, etc). However, the text still receives proper output escaping for HTML (e.g., < becomes &lt;). The enclosure +TEXT+ (text enclosed in pluses surrounded by backticks) is a special formatting combination in Asciidoctor. It means to format TEXT as monospace, but don’t interpolate formatting marks or attribute references in TEXT. It’s roughly equivalent to Markdown’s backticks. Since AsciiDoc offers more advanced formatting, the double enclosure is necessary. The more brute-force solution to the inline passthrough approach is to use the pass:c[] macro, which is a more verbose (and flexible) version of the plus formatting marks. The pass:c[__kernel] qualifier can be used with the pass:c[__attribute__] keyword... #pass:c[CB###2]# and #pass:c[CB###3]# As you can see, however, the macro is not quite as elegant or concise. In case you’re wondering, the c in the target slot of the pass:c[] macro applies output escaping for HTML. Though not always required, it’s best to include this flag so you don’t forget to when it is needed. Backslashes for escaping aren’t very reliable in AsciiDoc. While they can be used, they have to be placed so strategically that they are rather finicky. ## 10. Attributes Attributes are one of the features that sets Asciidoctor apart from other lightweight markup languages. Attributes can activate features (behaviors, styles, integrations, etc) or hold replacement (i.e., variable) content. In Asciidoctor, attributes are classified as: ### 10.1. Attribute Restrictions All attributes have a name and a value (though the value may be implicit). The attribute name: • must be at least one character long, • must begin with a word character (A-Z, a-z, 0-9 or _) and • must only contain word characters and hyphens. In other words, the name cannot contain dots or spaces. Although uppercase characters are permitted in an attribute entry (the place where an attribute is defined), the attribute name is converted to lowercase before being stored. The attribute name in an attribute reference is also converted to lowercase before the attribute is resolved. For example, URI, Uri and uRI are all treated as uri. (See issue #509 for a proposed change to this restriction). A best practice is to only use lowercase for letters in the name and avoid starting the name with a number. The attribute value: • can be any inline content and • can only contain line breaks if an explicit line continuation is used. Certain attributes have a restricted range of allowable values. See the entries in the Catalog of Document Attributes for details. ### 10.2. Attribute Assignment Precedence The attribute assignment precedence, listed from highest to lowest, is as follows: • An attribute defined using the API or CLI • An attribute defined in the document • The default value of the attribute, if applicable Let’s use the imagesdir attribute to show how precedence works. The default value for the imagesdir attribute is an empty string. Therefore, if the imagesdir attribute is not assigned a value (either in the document, API, or CLI), the processor will assign it the default value of empty string. If the imagesdir attribute is set in the document (meaning assigned a new value, such as images), that value will override the default value. Finally, if a value is assigned to the imagesdir attribute via the API or CLI, that value will override both the default value and the value assigned in the document. It’s possible to alter this order of precedence using a modifier, covered in the next section. #### 10.2.1. Altering the Attribute Assignment Precedence You can allow the document to reassign an attribute that is defined via the API or CLI by adding the @ precedence modifier to the end of the attribute value (or, since 1.5.7, the end of the attribute name). Adding this modifier lowers the precedence so that an assignment in the document still wins out. We sometimes refer to this as “soft setting” the attribute. This feature can be useful for assigning default values for attribute, but still letting the document control its own fate.  The @ modifier is removed before the assignment is made. Here’s an example that shows how to set the imagesdir from the CLI with a lower precedence: $ asciidoctor -a [email protected] doc.adoc

Since 1.5.7, you can place the modifier at the end of the attribute name:

$gem install pygments.rb (2)  1 Install Python using your package manager 2 Install the pygments.rb gem Once you’ve installed these libraries, assign pygments to the source-highlighter attribute in your document’s header. :source-highlighter: pygments You can further customize the source block output with additional Pygments attributes. pygments-style Sets the name of the color theme Pygments uses. To see the list of available style names, see Available Pygments style names. Default: pastie. pygments-css Controls what method is used for applying CSS to the tokens. Can be class (CSS classes) or style (inline styles). See Pygments stylesheet to learn more about how the value class is handled. Default: class. pygments-linenums-mode Controls how line numbers are arranged when line numbers are enabled on the source block. Can be table or inline. If line wrapping is enabled on preformatted blocks (i.e., prewrap), and you want to use line numbering on source blocks, you must set the value of this attribute to inline in order for the numbers to line up properly with their target lines. Default: table. Customizing a source block with Pygments attributes :source-highlighter: pygments :pygments-style: manni :pygments-linenums-mode: inline [source,ruby,linenums] ---- ORDERED_LIST_KEYWORDS = { 'loweralpha' => 'a', 'lowerroman' => 'i', 'upperalpha' => 'A', 'upperroman' => 'I' #'lowergreek' => 'a' #'arabic' => '1' #'decimal' => '1' } ---- Result: Source block using inline line numbers and the manni theme #### 46.4.1. Highlight Select Lines Not to be confused with syntax highlighting, you can configure Pygments to highlight (i.e., emphasize) select lines in order to call attention to them. This feature is activated on a source block if the highlight attribute is defined. The highlight attribute accepts a comma or semi-colon delimited list of line ranges. A line range is represented by two numbers separated by a double period (e.g., 2..5). These numbers correspond to the line numbers of the source block, inclusive, where the first line is 1. Highlight select lines in a source block :source-highlighter: pygments [source,ruby,highlight=2..5] ---- ORDERED_LIST_KEYWORDS = { 'loweralpha' => 'a', 'lowerroman' => 'i', 'upperalpha' => 'A', 'upperroman' => 'I', } ---- #### 46.4.2. Available Pygments style names To list the available Pygments styles, run the following command in a terminal: $ $(dirname$(gem which pygments.rb))/../vendor/pygments-main/pygmentize -L styles

The pygments.rb gem uses a bundled version of Pygments (often ahead of the latest release). This command ensures that you are invoking the pygmentize command from the Pygments used by that gem.

#### 46.4.3. Using a custom Pygments installation

If you already have Pygments installed on your system, you want to use your own fork, or you want to customize how Pygments is configured, you can get Asciidoctor to use a custom version of Pygments instead of the one bundled with the pygments.rb gem.

First, install your own version of Pygments. You can do this, for instance, by cloning the upstream Pygments repository:

$hg clone https://bitbucket.org/birkenfeld/pygments-main pygments Find the directory that contains the file pygmentize or the Makefile. That’s your Pygments installation path. Make note of it. Next, create a script to run before invoking Asciidoctor for the first time. Let’s call it pygments_init.rb. Populate the script with the following content: pygments_init.rb require 'pygments' # use a custom Pygments installation (directory that contains pygmentize) Pygments.start '/path/to/pygments' # example of registering a missing or additional lexer #Pygments::Lexer.create name: 'Turtle', aliases: ['turtle'], # filenames: ['*.ttl'], mimetypes: ['text/turtle', 'application/x-turtle']  You could enhance this script to read the Pygments installation path from an environment variable (or configuration file). Now just require this script before your invoke Asciidoctor the first time. When using the asciidoctor command, pass the script using the -r flag: $ asciidoctor -r ./pygments_init.rb document.adoc

When using the Asciidoctor API, require the script using require or require_relative:

require 'asciidoctor'
require_relative './pygments_init.rb'

Asciidoctor.convert_file 'document.adoc', safe: :safe

Now Asciidoctor is using your custom installation of Pygments instead of the one bundled with the pygments.rb gem.

### 46.5. CodeRay

CodeRay is an encoding-aware, syntax highlighter that supports the languages listed below.

 C C++ Clojure CSS Delphi diff ERB Go Groovy HAML HTML Java JavaScript JSON Lua PHP Python Ruby Sass SQL Taskpaper XML YAML

In order to use CodeRay with Asciidoctor, you need the coderay RubyGem. You can use one of the following methods to install CodeRay.

Install using gem (all systems)
$gem install coderay Install using apt-get (Debian-based systems) $ sudo apt-get install coderay
Install using dnf (Fedora-based systems)
sudo dnf install rubygem-coderay Once you’ve installed the RubyGem, assign the coderay value to the source-highlighter attribute in the document header to activate it. :source-highlighter: coderay You can further customize the source block output with additional CodeRay attributes. coderay-css Controls what method is used for applying CSS to the tokens. Can be class or style. Default: class. coderay-linenums-mode Controls how line numbers are laid out. Can be table or inline. If line wrapping is enabled on preformatted blocks (i.e., prewrap), and you want to use line numbering on source blocks, you must set the value of this attribute to inline in order for the numbers to line up properly with their target lines. Default: table. Customizing a source block with CodeRay line numbers :source-highlighter: coderay :coderay-linenums-mode: inline [source,ruby,linenums] ---- ORDERED_LIST_KEYWORDS = { 'loweralpha' => 'a', 'lowerroman' => 'i', 'upperalpha' => 'A', 'upperroman' => 'I' #'lowergreek' => 'a' #'arabic' => '1' #'decimal' => '1' } ---- See the CodeRay stylesheet section to learn about the coderay-css attribute. #### 46.5.1. Highlight Select Lines Not to be confused with syntax highlighting, you can configure CodeRay to highlight (i.e., emphasize) select lines in order to call attention to them. This feature is activated on a source block if the following conditions are met: • Line numbering is enabled (i.e., the linenums option). (In CodeRay, the highlight feature is coupled with line numbering). • The highlight attribute is defined. The highlight attribute accepts a comma or semi-colon delimited list of line ranges. A line range is represented by two numbers separated by a double period (e.g., 2..5). These numbers correspond to the line numbers of the source block, inclusive, where the first line is 1. Highlight select lines in a source block :source-highlighter: coderay [source,ruby,linenums,highlight=2..5] ---- ORDERED_LIST_KEYWORDS = { 'loweralpha' => 'a', 'lowerroman' => 'i', 'upperalpha' => 'A', 'upperroman' => 'I', } ---- ### 46.6. highlight.js Highlight.js is a popular client-side syntax highlighter that supports a broad range of languages. To use highlight.js, simply add the following attribute entry to the header of your AsciiDoc file: :source-highlighter: highlightjs By default, Asciidoctor will link to the highlight.js library and stylesheet hosted on cdnjs. The version of the highlight.js library hosted on cdnjs only includes the basic language bundle. To enable support for a wider range of languages (or to use a different version), follow these steps: 1. Create your custom bundle on the download page. 2. Download and unpack the zip into a folder called highlight adjacent to your AsciiDoc file (or in the output directory, if different) 3. Rename highlight/highlight.pack.js to highlight/highlight.min.js 4. Rename highlight/styles/github.css to highlight/styles/github.min.css • Replace github with the name of the highlightjs-theme you are using, if different. 5. Add the attribute entry :highlightjsdir: highlight to the header of your AsciiDoc file. • Alternatively, you can pass the -a highlightjsdir=highlight flag when invoking the Asciidoctor CLI. The output file will use your personal copy of the highlight.js library and stylesheet instead of the one hosted on cdnjs. ## 47. Callouts Callout numbers (aka callouts) provide a means to add annotations to lines in a verbatim block. Each callout number used in a verbatim block must appear twice. The first use, which goes within the verbatim block, marks the line being annotated (i.e., the target). The second use, which goes below the verbatim block, defines the annotation text. Multiple callout numbers may be used on a single line.  The callout number (at the target) must be placed at the end of the line. Here’s a basic example of a verbatim block that uses callouts: [source,ruby] ---- require 'sinatra' <1> get '/hi' do <2> <3> "Hello World!" end ---- <1> Library import <2> URL mapping <3> Response block Here’s how this example gets rendered: require 'sinatra' (1) get '/hi' do (2) (3) "Hello World!" end  1 Library import 2 URL mapping 3 Response block Since callout number can interfere with the syntax of the code they are annotating, Asciidoctor provides several features to hide the callout numbers from both the source and the converted document. The sections that follow detail these features. ### 47.1. Copy and Paste Friendly Callouts In versions prior to Asciidoctor 0.1.4, when a reader visiting an HTML page generated by Asciidoctor selected source code from a listing that contained callouts and copied it, the callout numbers would get caught up in the copied text. If the reader pasted that code and tried to run it, likely the extra characters from the callouts would cause compile or runtime errors. Asciidoctor uses CSS to prevent callouts from being selected. On the other side of the coin, you don’t want the callout annotations or CSS messing up your raw source code either. You can tuck your callouts neatly behind line comments. Asciidoctor will recognize the line comments characters in front of a callout number, optionally offset by a space, and remove them when converting the document. Here are the line comments that are supported: ---- line of code // <1> line of code # <2> line of code ;; <3> ---- <1> A callout behind a line comment for C-style languages. <2> A callout behind a line comment for Ruby, Python, Perl, etc. <3> A callout behind a line comment for Clojure. Here’s how it looks when rendered: line of code (1) line of code (2) line of code (3)  1 A callout behind a line comment for C-style languages. 2 A callout behind a line comment for Ruby, Python, Perl, etc. 3 A callout behind a line comment for Clojure. #### 47.1.1. XML Callouts XML doesn’t have line comments, so our “tuck the callout behind a line comment” trick doesn’t work here. To use callouts in XML, you must place the callout’s angled brackets around the the XML comment and callout number. Here’s how it appears in a listing: [source,xml] ---- <section> <title>Section Title</title> <!--1--> </section> ---- <1> The section title is required. Here’s how it looks when rendered: <section> <title>Section Title</title> (1) </section>  1 The section title is required. Notice the comment has been replaced with a circled number that cannot be selected (if not using font icons it will be rendered differently and selectable). Now both you and the reader can copy and paste XML source code containing callouts without worrying about errors. ### 47.2. Callout Icons The font icons setting also enables callout icons drawn using CSS. = Document Title :icons: font (1) NOTE: Asciidoctor now supports font-based admonition icons, powered by Font Awesome! (2)  1 Activates the font-based icons in the HTML5 backend. 2 Admonition block that uses a font-based icon. ## 48. Conditional Preprocessor Directives You can include or exclude lines of text in your document using one of the following conditional preprocessor directives: • ifdef • ifndef • ifeval These directives tell the processor whether to include the enclosed content based on certain conditions. The conditions are based on the presence or value of document attributes. For example, say you want to include a certain section of content only when converting to HTML. Conditional preprocessor directives make this possible. You simply check for the presence of the basebackend-html attribute using an ifdef directive. Details of this example, as well as others, are described in the following sections. ### 48.1. Processing Although a conditional preprocessor directive looks like a block macro, it’s not a macro and therefore not processed like one. Instead, it’s a preprocessor directive, just like include. It’s important to understand the distinction. A preprocessor directive is processed when the lines are read, but before the document structure is parsed. Therefore, it’s not aware of the surrounding document structure. A preprocessor directive merely adds lines to the reader or takes lines away. The conditional preprocessor directives determine which lines to add and which ones to take away based on the condition. If you don’t want a conditional preprocessor directive to be processed, you must escape it using a backslash. \ifdef::just-an-example[] Escaping the directive is necessary even if it appears in a verbatim block since it’s not aware of the surrounding document structure. ### 48.2. ifdef Directive Content between the ifdef and endif directives gets included if the specified attribute is set: ifdef example ifdef::env-github[] This content is for GitHub only. endif::[] The syntax of the start directive is ifdef::<attribute>[], where <attribute> is the name of an attribute. Keep in mind that the content is not limited to a single line. You can have any amount of content between the ifdef and endif directives. If you have a large amount of content inside the ifdef directive, you may find it more readable to use the long-form version of the directive, in which the attribute (aka condition) is referenced again in the endif directive. ifdef long-form example ifdef::env-github[] This content is for GitHub only. So much content in this section, I'd get confused reading the source without the closing ifdef directive. It isn't necessary for short blocks, but if you are conditionally including a section it may be something worth considering. Other readers reviewing your docs source code may go cross-eyed when reading your source docs if you don't. endif::env-github[]  A great example of long-form conditional formatting is the source of this user manual! We use it to show and hide entire sections when building individual content for separate guides. If you’re only dealing with a single line of text, you can put the content directly inside the square brackets and drop the endif directive. ifdef single line example ifdef::revnumber[This document has a version number of {revnumber}.] The single-line block above is equivalent to this formal ifdef directive: ifdef::revnumber[] This document has a version number of {revnumber}. endif::[] ### 48.3. ifndef Directive ifndef is the logical opposite of ifdef. Content between ifndef and endif gets included only if the specified attribute is not set: ifndef Example ifndef::env-github[] This content is not shown on GitHub. endif::[] The syntax of the start directive is ifndef::<attribute>[], where <attribute> is the name of an attribute. The ifndef directive supports the same single-line and long-form variants as ifdef. ### 48.4. Checking multiple attributes (ifdef and ifndef only) Both the ifdef and ifndef directives accept multiple attribute names. The combinator can be “and” or “or”. Any attribute (or) Multiple comma-separated (,) directive names evaluate to true, allowing the content to be included, if one or more of the directives is defined. Otherwise the content is not included. Any attribute example ifdef::backend-html5,backend-docbook5[Only shown when converting to HTML5 or DocBook 5.] All attributes (and) Multiple plus-separated (+) directive names evaluate to true, allowing the content to be included, if all of the directives are defined. Otherwise the content is not included. All attributes example ifdef::env-github+backend-html5[Only shown when converting to HTML5 on GitHub.] The ifndef directive negates the results of the expression.  Starting in Asciidoctor 1.5.6, the operator logic in the ifndef directive changed to align with the behavior of AsciiDoc Python. Specifically, when attributes are separated by commas, content is only included if none of the attributes are defined. When attributes are separated by pluses, content is included if at least one of the attributes is undefined. See issue #1983 to find the discussion about this behavior and the rationale for the change. ### 48.5. ifeval directive Content between ifeval and endif gets included if the expression inside the square brackets evaluates to true. ifeval example ifeval::[{sectnumlevels} == 3] If the sectnumlevels attribute has the value 3, this sentence is included. endif::[] The ifeval directive does not have a single-line or long-form variant like ifdef and ifndef. #### 48.5.1. Anatomy The expression consists of a left-hand value and a right-hand value with an operator in between. ifeval expression examples ifeval::[2 > 1] ... endif::[] ifeval::["{backend}" == "html5"] ... endif::[] ifeval::[{sectnumlevels} == 3] ... endif::[] // the value of outfilesuffix includes a leading period (e.g., .html) ifeval::["{docname}{outfilesuffix}" == "master.html"] ... endif::[] #### 48.5.2. Values Each expression value can reference the name of zero or more AsciiDoc attribute using the attribute reference syntax (for example, {backend}). Attribute references are resolved (substituted) first. Once attributes references have been resolved, each value is coerced to a recognized type. When the expected value is a string (i.e., a string of characters), we recommend that you enclose the expression in quotes. The following values types are recognized: number Either an integer or floating-point value. quoted string Enclosed in either single (') or double (") quotes. boolean Literal value of true or false. ##### How value type coercion works If a value is enclosed in quotes, the characters between the quotes are preserved and coerced to a string. If a value is not enclosed in quotes, it is subject to the following type coercion rules: • an empty value becomes nil (aka null). • a value of true or false becomes a boolean value. • a value of only repeating whitespace becomes a single whitespace string. • a value containing a period becomes a floating-point number. • any other value is coerced to an integer value. #### 48.5.3. Operators The value on each side is compared using the operator to derive an outcome. == Checks if the two values are equal. != Checks if the two values are not equal. < Checks whether the left-hand side is less than the right-hand side. <= Checks whether the left-hand side is less than or equal to the right-hand side. > Checks whether the left-hand side is greater than the right-hand side. >= Checks whether the left-hand side is greater than or equal to the right-hand side.  The operators follow the same rules as operators in Ruby. ## 49. Docinfo Files You can add custom content to the head or footer of an output document using docinfo files. Docinfo files are useful for injecting auxiliary metadata, stylesheet, and script information into the output not added by the converter. Different docinfo files get used depending on whether you are converting to HTML or DocBook (but don’t yet apply when converting to PDF). ### 49.1. Head docinfo files The content of head docinfo files gets injected into the top of the document. For HTML, the content is append to the <head> element. For DocBook, the content is appended to the root <info> element. The docinfo file for HTML output may contain valid elements to populate the HTML <head> element, including: • <base> • <link> • <meta> • <noscript> • <script> • <style>  Use of the  element is not recommend as it’s already emitted by the converter. You do not need to include the enclosing <head> tag as it’s assumed to be the envelop. Here’s an example: A head docinfo file for HTML output <meta name="keywords" content="open source, documentation"> <meta name="description" content="The dangerous and thrilling adventures of an open source documentation team."> <link rel="stylesheet" href="basejump.css"> <script src="map.js"></script> Docinfo files for HTML output must be saved with the .html file extension. See Naming docinfo files for more details. The docinfo file for DocBook 5.0 output may include any of the <info> element’s children, such as: • <address> • <copyright> • <edition> • <keywordset> • <publisher> • <subtitle> • <revhistory> The following example shows some of the content a docinfo file for DocBook might contain. A docinfo file for DocBook 5.0 output <author> <personname> <firstname>Karma</firstname> <surname>Chameleon</surname> </personname> <affiliation> <jobtitle>Word SWAT Team Leader</jobtitle> </affiliation> </author> <keywordset> <keyword>open source</keyword> <keyword>documentation</keyword> <keyword>adventure</keyword> </keywordset> <printhistory> <para>April, 2019. Twenty-sixth printing.</para> </printhistory> Docinfo files for DocBook output must be saved with the .xml file extension. See Naming docinfo files for more details. To see a real-world example of a docinfo file for DocBook, checkout the RichFaces Developer Guide docinfo file. Footer docinfo files are differentiated from head docinfo files by the addition of -footer to the file name. In the HTML output, the footer content is inserted immediately after the footer div (i.e., <div id="footer">). In the DocBook output, the footer content is inserted immediately before the ending tag (e.g., </article> or </book>).  One possible use of the footer docinfo file is to completely replace the default footer in the standard stylesheet. Just set the attribute nofooter, then apply a custom footer docinfo file. ### 49.3. Naming docinfo files The file that gets selected to provide the docinfo depends on which converter is in use (html, docbook, etc) and whether the docinfo scope is configured for a specific document (“private”) or for all documents in the same directory (“shared”). The file extension of the docinfo file must match the file extension of the output file (as specified by the outfilesuffix attribute, a value which always begins with a period (.)). Docinfo file naming Mode Location Behavior Docinfo file name Private Head Adds content to <head>/<info> for <docname>.adoc files. <docname>-docinfo<outfilesuffix> Footer Adds content to end of document for <docname>.adoc files. <docname>-docinfo-footer<outfilesuffix> Shared Head Adds content to <head>/<info> for any document in same directory. docinfo<outfilesuffix> Footer Adds content to end of document for any document in same directory. docinfo-footer<outfilesuffix> To specify which file(s) you want to apply, set the docinfo attribute to any combination of these values: • private-head • private-footer • private (alias for private-head,private-footer) • shared-head • shared-footer • shared (alias for shared-head,shared-footer) Setting docinfo with no value is equivalent to setting the value to private. For example: :docinfo: shared,private-footer This docinfo configuration will apply the shared docinfo head and footer files, if they exist, as well as the private footer file, if it exists.  docinfo attribute values were introduced in 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 Let’s apply this to an example: You have two AsciiDoc documents, adventure.adoc and insurance.adoc, saved in the same folder. You want to add the same content to the head of both documents when they’re converted to HTML. 1. Create a docinfo file containing <head> elements. 2. Save it as docinfo.html. 3. Set the docinfo attribute in adventure.adoc and insurance.adoc to shared. You also want to include some additional content, but only to the head of adventure.adoc. 1. Create another docinfo file containing <head> elements. 2. Save it as adventure-docinfo.html. 3. Set the docinfo attribute in adventure.adoc to shared,private-head If other AsciiDoc files are added to the same folder, and docinfo is set to shared in those files, only the docinfo.html file will be added when converting those files. ### 49.4. Locating docinfo files By default, docinfo files are searched for in the same folder as the document file. If you want to keep them anywhere else, set the docinfodir attribute to their location: :docinfodir: common/meta Note that if you use this attribute, only the specified folder will be searched; docinfo files in the document folder will no longer be found. ### 49.5. Attribute substitution in docinfo files Docinfo files may include attribute references. Which substitutions get applied is controlled by the docinfosubs attribute, which takes a comma-separated list of substitution names. The value of this attribute defaults to attributes. For example, if you created the following docinfo file: Docinfo file containing a revnumber attribute reference <edition>{revnumber}</edition> And this source document: Source document including a revision number = Document Title Author Name v1.0, 2019-06-01 :doctype: book :backend: docbook :docinfo: Then the converted DocBook output would be: <?xml version="1.0" encoding="UTF-8"?> <book xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" lang="en"> <info> <title>Document Title</title> <date>2019-06-01</date> <author> <personname> <firstname>Author</firstname> <surname>Name</surname> </personname> </author> <authorinitials>AN</authorinitials> <revhistory> <revision> <revnumber>1.0</revnumber> (1) <date>2019-06-01</date> <authorinitials>AN</authorinitials> </revision> </revhistory> </info> </book>  1 The revnumber attribute reference was replaced by the source document’s revision number in the converted output. ## 50. Counters Counters are used to store and display ad-hoc sequences of numbers or latin characters. They are designed for simple use cases. Possible uses include inline itemized lists, paragraph numbers and serial item numbers. A counter is implemented as a specialized document attribute. You declare and display a counter using an augmented attribute reference, in which the attribute name is prefixed with counter: (e.g., {counter:name}). Since counters are attributes, counter names follow the same rules as attribute names. The most important rule to note is that letters in counter names must be lowercase. The counter value is incremented and displayed every time the counter: attribute reference is used. The term increment means advance to the next value in the sequence. If the counter value is an integer, add 1. If the counter value is a character, move to the next letter in the Latin alphabet. The default start value of a counter is 1. To create a sequence starting at 1, use the simple form {counter:name} as shown here: The salad calls for {counter:seq1}) apples, {counter:seq1}) oranges and {counter:seq1}) pears. Here’s the resulting output: The salad calls for 1) apples, 2) oranges and 3) pears. To increment the counter without displaying it (i.e., to skip an item in the sequence), use the counter2 prefix instead: {counter2:seq1}  A counter2 attribute reference on a line by itself will produce an empty paragraph. You’ll need to adjoin it to the nearest content to avoid this side effect. To display the current value of the counter without incrementing it, reference the counter name as you would any other attribute: {counter2:pnum}This is paragraph {pnum}. To create a character sequence, or start a number sequence with a value other than 1, specify a start value by appending it to the first use of the counter: Dessert calls for {counter:seq1:A}) mangoes, {counter:seq1}) grapes and {counter:seq1}) cherries.  Character sequences either run from a,b,c,…​x,y,z,{,|…​ or A,B,C,…​,X,Y,Z,[,…​ depending on the start value. Therefore, they aren’t really useful for more than 26 items. The start value of a counter is only recognized if the counter is unset at that point in the document. Otherwise, the start value is ignored. To reset a counter attribute, unset the corresponding attribute using an attribute entry. The attribute entry must be adjacent to a block or else it is ignored. The salad calls for {counter:seq1:1}) apples, {counter:seq1}) oranges and {counter:seq1}) pears. :!seq1: Dessert calls for {counter:seq1:A}) mangoes, {counter:seq1}) grapes and {counter:seq1}) cherries. This gives: The salad calls for 1) apples, 2) oranges and 3) pears. Dessert calls for A) mangoes, B) grapes and C) cherries. Here’s a full example that shows how to use a counter for part numbers in a table. [caption=""] .Parts{counter2:index:0} |=== |Part Id |Description |PX-{counter:index} |Description of PX-{index} |PX-{counter:index} |Description of PX-{index} |=== Here’s the output of that table: Parts Part Id Description PX-1 Description of PX-1 PX-2 Description of PX-2 # Structuring, Navigating, and Referencing Your Content Asciidoctor provides macros or attributes for the specialized frontmatter and backmatter sections commonly found in journal articles, academic papers, and books. In the following sections, you’ll learn the dependency, structure, and output rules for the special section macros and attributes and how to use them. ## 51. Colophon Book colophons list information such as the ISBN, publishing house, edition and copyright dates, legal notices and disclaimers, cover art, design, and book layout credits, and any significant production notes. In most mass market books, the colophon is on the verso (back side) of the title page, but it can also be located at the end of the book. [colophon] = Colophon The Asciidoctor Press, Ceres and Denver (C) 2018 by The Asciidoctor Press Published in the Milky Way Galaxy This book is designed by Dagger Flush, Denver, Colorado. The types are handset Chinchilla and Dust, designed by Leeloo. Leeloo designed the typefaces to soften the bluntness of documentation. Created in Asciidoctor and Fedora 27. The printing and binding is by Ceres Lithographing, Inc., Ceres, Milky Way. ## 52. Table of Contents A table of contents (TOC) is an index of section and subsection titles that can be automatically generated from the document’s structure when converting a document with Asciidoctor. To enable the auto-generated TOC, you must set the toc attribute. The toc attribute can be specified via the command line (-a toc), TOC enabled via the CLI  asciidoctor -a toc adventure.adoc

or in the document header (:toc:).

TOC enabled via the document header
= The Dangerous and Thrilling Documentation Chronicles
Kismet Chameleon
:toc:

This journey begins on a bleary...

== Cavern Glow

The river rages through the cavern, rattling its content...

When no other options are specified, the TOC is inserted directly below the document header (document title, author, and revision lines), it has the title Table of Contents, and contains section 1 and section 2 level titles only.

Result: Setting the toc attribute

Asciidoctor allows you to customize the layout, placement, and title of the table of contents. However, not all customizations are supported by all converters. See the Table of Contents Summary to find out which customizations are available to each backend.

### 52.1. In-Document Placement

toc values of auto (the default), preamble, and macro place the TOC in the main document area.

When the value of toc attribute is unspecified or auto, the TOC is inserted directly below the document header (document title, author and revision lines).

When toc is set to preamble, the TOC is placed immediately below the preamble.

 When using the preamble placement, the TOC will not appear if your document does not have a preamble. To fix this problem, just set the toc attribute to an empty value (or auto).

To place the TOC anywhere else in the document, set the toc attribute to macro. Then, put the block toc macro (toc::[]) at the location in the document where you want the TOC to appear. The toc macro should appear at most once in any document.

If toc is not set to macro, any toc macro in the document will be silently ignored.

Setting toc value to macro and using the block toc macro
= The Dangerous and Thrilling Documentation Chronicles
Kismet Chameleon
:toc: macro (1)

This journey begins on a bleary...

== Cavern Glow

toc::[] (2)

The river rages through the cavern, rattling its content...
 1 The toc attribute must be set to macro in order to enable the use of the toc macro. 2 In this example, the toc macro is placed below the first section’s title, indicating that this is the location where the TOC will be displayed once the document is rendered.
Result: Setting toc value to macro and using the block toc macro

### 52.2. Side Column Placement

When converting to HTML, you can position the TOC to the left or right of the main content column by assigning the value left or right to the toc attribute, respectively. In this case, the sidebar column containing the TOC is both fixed and scrollable.

Assigning the left value to toc
= The Dangerous and Thrilling Documentation Chronicles
Kismet Chameleon
:toc: left

This journey begins on a bleary...

== Cavern Glow

The river rages through the cavern, rattling its content...

== The Ravages of Writing

Her finger socks had been vaporized by crystalline nuggets of...

=== A Recipe for Potion

Two fresh Burdockian leaves, harvested by the light of the teal moons...
Result: Assigning the left value to toc

This positioning is achieved using CSS, which means it depends on support from the stylesheet. However, it’s only honored if there’s sufficient room on the screen for a sidebar column. If there isn’t sufficient room available (i.e., the screen width falls below a certain breakpoint), the TOC will automatically shift back to the center, appearing directly below the document title.

 The TOC is always placed in the center in an embeddable HTML document, regardless of the value of the toc attribute.

### 52.3. Title

The toc-title attribute allows you to change the title of the TOC.

Defining a new TOC title
= The Dangerous and Thrilling Documentation Chronicles
Kismet Chameleon
:toc: (1)

This journey begins on a bleary...

== Cavern Glow

The river rages through the cavern, rattling its content...
 1 The toc attribute must be set in order to use toc-title. 2 toc-title is set and assigned the value Table of Adventures in the document’s header.
Result: Defining a new TOC title

### 52.4. Levels

By default, the TOC will display level 1 and level 2 section titles. You can set a different depth with the toclevels attribute.

Defining a new toclevels value
= The Dangerous and Thrilling Documentation Chronicles
Kismet Chameleon
:toc: (1)
:toclevels: 4 (2)

This journey begins on a bleary...

== Cavern Glow

The river rages through the cavern, rattling its content...

== The Ravages of Writing

Her finger socks had been vaporized by crystalline nuggets of...

=== A Recipe for Potion

Two fresh Burdockian leaves, harvested by the light of the teal moons...

==== Searching for Burdockian

Crawling through the twisted understory...
 1 The toc attribute must be set in order to use toclevels. 2 toclevels is set and assigned the value 4 in the document’s header. The TOC will list the titles of the section 1, 2, 3, and 4 levels when the document is rendered.
Result: Defining a new toclevels value

### 52.5. Using a TOC with Embeddable HTML

When AsciiDoc is converted to embeddable HTML (i.e., the header_footer option is false), there are only three valid values for the toc attribute:

• auto (or unspecified value)

• preamble

• macro

All of the following environments convert AsciiDoc to embeddable HTML:

• the file viewer on GitHub and GitLab

• the AsciiDoc preview in an editor like Atom, Brackets or AsciidocFX

• the Asciidoctor browser extensions

 The side column placement (left or right) isn’t available in this mode. That’s because the embeddable HTML doesn’t have the outer framing (or the CSS) necessary to support a side column TOC.

Attribute Values Example Syntax Comments Backends

toc

auto, left, right, macro, preamble

:toc: left

Not set by default. Defaults to auto if value is unspecified.

html

auto, macro, preamble

:toc: macro

Not set by default. Defaults to auto if value is unspecified.

html (embeddable)

auto

:toc:

Not set by default. The table of contents is placed after the title page (See issue #233 for developments).

pdf

auto

:toc:

Not set by default. The placement and styling of the table of contents is determined by the DocBook toolchain configuration.

docbook

toclevels

1–5

:toclevels: 4

Default value is 2.

html, pdf

toc-title

<text>

:toc-title: Contents

html, pdf

## 53. Abstract

An abstract is a concise overview of an article or of a chapter in a book. They are frequently found in the frontmatter of academic, research, and analytical papers. A complete (i.e., informative) abstract states the key topics and findings while a limited (i.e., descriptive) abstract briefly describes the structure of the content.

The abstract may be written using a section, open block, or paragraph and must bear the abstract style. If used, the abstract must appear before the first section of an article (at the start of the preamble) or at the start of a chapter in a book. An abstract may not be used before a part or chapter in a book.

Here’s an example of an abstract at the beginning of an article, defined using a section:

= Article Title

[abstract]
== Abstract

Documentation is a distillation of many long, squiggly adventures.

== First Section

Here’s an example of the same abstract defined using a paragraph:

= Article Title

[abstract]
.Abstract
Documentation is a distillation of many long, squiggly adventures.

== First Section

In the book doctype, the abstract section must be a level below the chapter.

== Chapter Title

[abstract]
=== Chapter Abstract

Documentation is a distillation of many long, squiggly adventures.

=== First Section

An abstract defined using an open block or paragraph does not require a title and does not depend on a subsequent section to terminate.

= Article Title

[abstract]
.Optional Abstract Title
--

Beyond that, where you go is up to you.
--

Your journey begins here.
 To include a quote at the beginning of a chapter in a book, wrap the quote block inside an abstract block.

## 54. Preface

The preface is a special section of a book that precedes the first part or chapter of the book (or the first chapter of a part). The preface can contain subsections.

An author explains how the idea behind her book manifested and developed in the preface. The preface can include acknowledgments and may be signed by the author with her name, writing date and location.

For multi-part books, the preface must be defined as a level-0 section and any subsections must start at level 2.

= Book Title
:doctype: book

[preface]
= Documentation Preface

The basis for this documentation germinated when I awoke one morning and was confronted by the dark and stormy eyes of the chinchilla.
She had conquered the mountain of government reports that, over the course of six months, had eroded into several minor foothills and a creeping alluvial plain of loose papers.

=== Acknowledgments in Preface

I'd like to thank the Big Bang and String Theory.
Would we be without them?

= Part 1

...

For books without parts, the preface must be defined as a level-1 section and any subsections must start at level 2.

= Book Title
:doctype: book

[preface]
== Documentation Preface

The basis for this documentation germinated when I awoke one morning and was confronted by the dark and stormy eyes of the chinchilla.
She had conquered the mountain of government reports that, over the course of six months, had eroded into several minor foothills and a creeping alluvial plain of loose papers.

=== Acknowledgments in Preface

I'd like to thank the Big Bang and String Theory.
Would we be without them?

== Chapter 1

...

The same structure can be used to define a preface for a part.

As an alternative to a special section, Asciidoctor will automatically promote the preamble to a preface. The title of the preface is set using the preface-title document attribute. When defined this way, the preface may not contain subsections.

= Book Title
:doctype: book
:preface-title: Documentation Preface

The basis for this documentation germinated when I awoke one morning and was confronted by the dark and stormy eyes of the chinchilla.
She had conquered the mountain of government reports that, over the course of six months, had eroded into several minor foothills and a creeping alluvial plain of loose papers.

== Chapter 1

...

The special section is the preferred way of defining a preface.

## 55. Dedication

The dedication page is where the author expresses gratitude toward a person.

[dedication]
= Dedication

For S.S.T.--

thank you for the plague of archetypes.

## 56. Book Parts and Chapters

You may group the sections of your document into parts when you set the doctype to book. In fact, parts can only be used when the doctype is book.

When a document has its doctype set to book and contains at least one part, it implicitly becomes a multi-part book. There is no dedicated doctype value for a multi-part book to distinguish it from a regular book. That distinction is made by the content.

Part titles are specified with a single equals sign (=), the equivalent to the structure of a document title (i.e., level-0 section). Each part must contain at least one section (a chapter or special section). Immediately after the part title, you may insert an optional introduction, which is designated by the partintro style.

[partintro]
.Optional part introduction title
--
Optional part introduction goes here.
--

A part can also include its own preface, bibliography, glossary and index.

= Title of Part 1

[partintro]
--
This is the introduction to the first part of our mud-encrusted journey.
--

== Chapter 1

There was mud...

== Chapter 2

Great gobs of mud...

[glossary]
== Part 1 Glossary

[glossary]
mud:: wet, cold dirt

= Part 2

[preface]
== Part 2 Preface

This part was written because...

== Chapter 1

The mud had turned to cement...

When using the PDF converter (i.e., Asciidoctor PDF), the value of the chapter-label attribute (followed by a space) is automatically added to the beginning of the chapter title. A chapter title is a level-1 section title when the doctype is book.

You can modify this prefix by redefining the chapter-label attribute.

:chapter-label: Chapter ~

To use no prefix, set the value to blank.

## 57. Appendix

You can indicate that a section, part, or chapter is an appendix by adding an [appendix] line above the section title.

[appendix]
== Copyright and License

While the AsciiDoc structure allows appendices to be placed anywhere, it’s customary to place them at the end of the document, after all other sections.

Sections marked as appendix have a different title, which is built as follows:

• A fixed prefix (taken from the value of the appendix-caption attribute, which defaults to “Appendix”)

• A letter that represents the number of this appendix within the sequence of appendices (A, B, C, …​)

• A colon

• The original section title

For example:

Appendix A: Copyright and License

The prefix can be modified by defining the appendix-caption attribute. This value can be changed using:

:appendix-caption: Appx

Or it can be unset using:

:appendix-caption!:

Appendices can have subsections. However, there are some rules to follow depending on which type of document you are creating.

For articles, the appendix must be defined as a level-1 section. (If a level-0 section is used, a level-1 section is implied). For example:

= Article Title
:appendix-caption: Appx
:sectnums:
:toc:

== First Section

=== Subsection

[appendix]
== First Appendix

=== First Subsection

=== Second Subsection

[appendix]
== Second Appendix

1. First Section
1.1. Subsection
Appx A: First Appendix
1.1. First Subsection
1.2. Second Subsection
Appx B: Second Appendix

For books, the appendix must be defined as a level-1 section if you want the appendix to be a adjacent to other chapters (and in the current part if the book has multiple parts). In a multi-part book, if you want the appendix to be adjacent to other parts, the appendix must be defined as a level-0 section. In either case, the first subsection of the appendix must be a level-3 section, not a level-2 section. That’s because an appendix cannot contain chapters.

The following example shows how to define an appendix for a multi-book (take away the part title if you’re creating a simple book):

= Book Title
:doctype: book
:appendix-caption: Appx
:sectnums:
:toc:

= First Part

== First Chapter

=== Subsection

[appendix]
= First Appendix

=== First Subsection

=== Second Subsection

[appendix]
= Second Appendix

First Part
1. First Chapter
1.1. Subsection
Appx A: First Appendix
1.1. First Subsection
1.2. Second Subsection
Appx B: Second Appendix

## 58. Glossary

You can include a glossary of definitions by including the [glossary] marker before the section header and before the first definition.

[glossary]
== Glossary

[glossary]
mud:: wet, cold dirt
rain::
water falling from the sky

## 59. Bibliography

AsciiDoc has basic support for bibliographies. AsciiDoc doesn’t concern itself with the structure of the bibliography entry itself, which is entirely freeform. What it does is provide a way to make references to the entries from the same document and output the bibliography with proper semantics for processing by other toolchains (such as DocBook).

In order to reference a bibliography entry, you need to assign a non-numeric label to the entry. To assign this label, prefix the entry with the label enclosed in a pair of triple square brackets (e.g., [[[label]]]). We call this a bibliography anchor. Using this label, you can then reference the entry from anywhere above the bibliography in the same document using the normal cross reference syntax (e.g., <<label>>).

By default, the bibliography anchor and reference to the bibliography entry is converted to [<label>], where <label> is the ID of the entry. If you specify xreftext on the bibliography anchor (e.g., [[[label,xreftext]]]), the bibliography anchor and reference to the bibliography entry converts to [<xreftext>] instead.

If you want the bibliography anchor and reference to appear as a number, assign the number of the entry using the xreftext. For example, [[[label,1]]] will be converted to [1].

The bibliography entries themselves are declared as items in an unordered list. You promote a normal unordered list to a bibliography list by adding the bibliography style. However, to be conforming, bibliography lists must be contained inside a bibliography section. A bibliography section is a section with the special bibliography style. By adding the bibliography style to the section, you implicitly add it to each unordered list in that section.

 If the bibliography style is used on an unordered list outside of a bibliography section, the resulting behavior is undefined.

Let’s consider an example.

Bibliography with inbound references
_The Pragmatic Programmer_ <<pp>> should be required reading for all developers.
To learn all about design patterns, refer to the book by the "Gang of Four" <<gof>>.

[bibliography]
== References

- [[[pp]]] Andy Hunt & Dave Thomas. The Pragmatic Programmer:
From Journeyman to Master. Addison-Wesley. 1999.
- [[[gof,2]]] Erich Gamma, Richard Helm, Ralph Johnson & John Vlissides. Design Patterns:
Elements of Reusable Object-Oriented Software. Addison-Wesley. 1994.

This renders as:

The Pragmatic Programmer [pp] should be required reading for all developers. To learn all about design patterns, refer to the book by the “Gang of Four” [2].

## References

• [pp] Andy Hunt & Dave Thomas. The Pragmatic Programmer: From Journeyman to Master. Addison-Wesley. 1999.

• [2] Erich Gamma, Richard Helm, Ralph Johnson & John Vlissides. Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley. 1994.

If you want more advanced features such as automatic numbering and custom citation styles, try the asciidoctor-bibtex project.

 To escape a bibliography anchor anywhere in the text, use the syntax [[[word]]]. This prevents the anchor from being matched as a bibliography anchor or a normal anchor.

## 60. Index

You can mark index terms explicitly in AsciiDoc content. Index terms form a controlled vocabulary that can be used to navigate the document by keyword starting from an index.

### 60.1. Index Terms

There are two types of index terms in AsciiDoc:

flow index term

indexterm2:[<primary>] or ((<primary>))

An index term that appears in the flow of text (i.e., a visible term) and in the index. This type of index term can only be used to define a primary entry.

concealed index term

indexterm:[<primary>, <secondary>, <tertiary>] or (((<primary>, <secondary>, <tertiary>)))

A group of index terms that appear only in the index. This type of index term can be used to define a primary entry as well as optional secondary and tertiary entries.

Here’s an example that shows the two forms in use.

The Lady of the Lake, her arm clad in the purest shimmering samite,
held aloft Excalibur from the bosom of the water,
signifying by divine providence that I, ((Arthur)), (1)
was to carry Excalibur (((Sword, Broadsword, Excalibur))). (2)
That is why I am your king. Shut up! Will you shut up?!
Burn her anyway! I'm not a witch.
Look, my liege! We found them.

indexterm2:[Lancelot] was one of the Knights of the Round Table. (3)
indexterm:[knight, Knight of the Round Table, Lancelot] (4)
 1 The double parenthesis form adds a primary index term and includes the term in the generated output. 2 The triple parenthesis form allows for an optional second and third index term and does not include the terms in the generated output (i.e., concealed index term). 3 The inline macro indexterm2:[primary] is equivalent to the double parenthesis form. 4 The inline macro indexterm:[primary, secondary, tertiary] is equivalent to the triple parenthesis form.

If you’re defining a concealed index term (i.e., the indexterm macro), and one of the terms contains a comma, you must surround that segment in double quotes so the comma is treated as content. For example:

I, King Arthur.
indexterm:[knight, "Arthur, King"]

or

I, King Arthur.
(((knight, "Arthur, King")))

### 60.2. Index Catalog

Although index terms are always processed, only Asciidoctor PDF and the DocBook toolchain support creating an index catalog automatically. To create an index, define a level-1 section marked with the style index at the end of your document.

[index]
== Index

Both Asciidoctor PDF and the DocBook toolchain will automatically populate an index into this seed section.

 The built-in HTML5 converter in Asciidoctor does not currently generate an index. Follow issue #450 to track the progress of this feature.

## 61. Footnotes

A footnote is created with the footnote macro (footnote:[]). If you plan to reference a footnote more than once, use the footnote macro with a target (footnote:id[]).

Footnote syntax
The hail-and-rainbow protocol can be initiated at five levels: double, tertiary, supernumerary, supermassive, and apocalyptic party.footnote:[The double hail-and-rainbow level makes my toes tingle.]  (1) (2)
A bold statement!footnote:disclaimer[Opinions are my own.] (3)

Another outrageous statement.footnote:disclaimer[] (4)
 1 Insert the footnote macro directly after any punctuation. Note that the footnote macro only uses a single colon (:). 2 Insert the footnote’s content within the square brackets ([]). The text may span several lines. 3 If you plan to reuse a footnote, specify a unique ID in the target position. 4 To reference an existing footnote, you only need to insert the ID in the target slot (leaving the text in the square brackets empty).

The footnotes will be numbered consecutively throughout the article.

Rendered footnotes
 The hail-and-rainbow protocol can be initiated at five levels: double, tertiary, supernumerary, supermassive, and apocalyptic party.[2] A bold statement![3] Another outrageous statement.[3] 2. The double hail-and-rainbow level makes my toes tingle. 3. Opinions are my own.

If you use a footnote in a heading, you’ll likely find that the footnote sequence is wrong. That’s because headings (section titles and discrete headings) get converted out of document order for the purpose of generating IDs and setting up cross references.

To resolve this problem, you must assign an explicit ID and reftext to any heading that contains a footnote. For example:

See <<heading>>.

== Heading{blank}footnote:[This is a heading with a footnote]

Not only will this prevent the footnote from being processed out of document order (and thus assigned the wrong number in the sequence), it will also prevent the footnote number from reappearing in the text of an xref.

While the AsciiDoc syntax is designed to be readable in raw form, the intended audience for that format are writers and editors. Readers aren’t going to appreciate the raw text nearly as much. Aesthetics matter. You’ll want to apply nice typography with font sizes that adhere to the golden ratio, colors, icons and images to give it the respect it deserves. That’s where converters, backends, and themes come into play.

## 62. Selecting an Output Format

The Asciidoctor processor is typically used to parse an AsciiDoc document and convert it to a variety of formats, such as HTML, DocBook, or PDF. This section describes how to specify the output format.

The processor generates the output format using a converter. Each converter is mapped to the name of a backend. You specify the backend—​and, in turn, the converter—​using the -b (--backend) command line option or backend API option. If no backend is specified, the processor uses the converter for the default backend (html5).

Asciidoctor provides several built-in converters, which are mapped to the following backend names:

html (or html5)

HTML 5, styled with CSS3 (default).

xhtml (or xhtml5)

The XHTML variant of the output from html5.

docbook (or docbook5)

DocBook 5.0 XML.

docbook45

DocBook 4.5 XML.

manpage

Manual pages for Unix and Unix-like operating systems.

Asciidoctor also has several add-on converters, which can be plugged in by adding the appropriate library to the runtime path (e.g., -r asciidoctor-pdf). These converters are mapped to the following backend names:

pdf

PDF, a portable document format. Requires the asciidoctor-pdf gem.

epub3

EPUB3, a distribution and interchange format standard for digital publications and documents. Requires the asciidoctor-epub3 gem.

latex

LaTeX, a document preparation system for high-quality typesetting. Requires the asciidoctor-latex gem.

mallard

Mallard 1.0 XML. Requires the asciidoctor-mallard gem (not yet released).

There are also converters available for HTML5 presentation systems such as reveal.js and Bespoke.js. Those converters are still in development and will be documented once releases become available.

## 63. HTML

Asciidoctor’s default output format is HTML.

html5

HTML 5 markup styled with CSS3.

### 63.1. Using the Command Line

In this section, we’ll create a sample document, then process and convert it with Asciidoctor’s html5 converter.

1. Create an AsciiDoc file like the one below

2. Save the file as mysample.adoc

= My First Experience with the Dangers of Documentation

In my world, we don't have to worry about mutant, script-injecting warlocks.
No.
We have something far worse.
We're plagued by Wolpertingers.

== Origins

You may not be familiar with these https://en.wikipedia.org/wiki/Wolpertinger[ravenous beasts], but, trust me, they'll eat your shorts and suck the loops from your code.

To convert mysample.adoc to HTML from the command line:

1. Open a console

2. Switch to the directory that contains the mysample.adoc document

3. Call the Asciidoctor processor with the asciidoctor command, followed by the name of the document you want to convert

$asciidoctor mysample.adoc Remember, Asciidoctor’s default converter is html5, so it isn’t necessary to specify it with the -b command. You won’t see any messages printed to the console. If you type ls or view the directory in a file manager, there is a new file named mysample.html. $ ls
mysample.adoc  mysample.html

Asciidoctor derives the name of the output document from the name of the input document.

The document’s text, titles, and link is styled by the default Asciidoctor stylesheet, which is embedded in the HTML output. As a result, you could save mysample.html to any computer and it will look the same.

### 63.2. Using the Ruby API

Asciidoctor also includes a Ruby API that lets you generate an HTML document directly from a Ruby application.

require 'asciidoctor'

Asciidoctor.convert_file 'mysample.adoc'

Alternatively, you can capture the HTML output in a variable instead of writing it to a file.

html = Asciidoctor.convert_file 'mysample.adoc', to_file: false, header_footer: true
puts html

The convert methods also accept a map of options. Use of this map is described in Ruby API Options.

### 63.3. Styling the HTML with CSS

Asciidoctor uses CSS for HTML document styling and JavaScript for generating document attributes such as a table of contents and footnotes. It comes bundled with a stylesheet, named asciidoctor.css. When you generate a document with the html5 backend, the asciidoctor.css stylesheet is embedded into the HTML output by default (when the safe mode is less than SECURE).

You have the option of linking to the stylesheet instead of embedding it. This is the mandatory behavior when the safe mode is SECURE. If your stylesheet is being linked when you expect it to be embedded, lower the safe mode (safe is the recommend value).

To have your document link to the stylesheet, set the linkcss attribute in the document’s header.

= My First Experience with the Dangers of Documentation

In my world, we don't have to worry about mutant, script-injecting warlocks.
No.
We have something far worse.
We're plagued by Wolpertingers.

== Origins

You may not be familiar with these https://en.wikipedia.org/wiki/Wolpertinger[ravenous beasts], but, trust me, they'll eat your shorts and suck the loops from your code.

You can also set linkcss with the CLI.

$asciidoctor -a linkcss mysample.adoc Now, when you view the directory, you should see the file asciidoctor.css in addition to mysample.adoc and mysample.html. The linkcss attribute automatically copies asciidoctor.css to the output directory. Additionally, you can inspect mysample.html in your browser and see <link rel="stylesheet" href="./asciidoctor.css"> inside the <head> tags. If you don’t want any styles applied to the HTML output of your document, unset the stylesheet attribute. $ asciidoctor -a stylesheet! mysample.adoc

One of Asciidoctor’s strengths is the ease in which you can swap the default stylesheet for an alternative Asciidoctor theme or use your own custom stylesheet.

### 63.4. Managing Images

Images are not embedded in the HTML output by default. If you have image references in your document, you’ll have to save the image files in the same directory as your converted document.

As an alternative, you can embed the images directly into the document by setting the data-uri document attribute.

$asciidoctor -a data-uri mysample.adoc = My First Experience with the Dangers of Documentation :imagesdir: myimages :data-uri: In my world, we don't have to worry about mutant, script-injecting warlocks. No. We have something far worse. We're plagued by Wolpertingers. == Origins [.left.text-center] image::wolpertinger.jpg[Wolpertinger] You may not be familiar with these https://en.wikipedia.org/wiki/Wolpertinger[ravenous beasts], but, trust me, they'll eat your shorts and suck the loops from your code. If the target of one or more images in the document is a URI, you must also set the allow-uri-read attribute securely and run Asciidoctor in SECURE mode or less. $ asciidoctor -a data-uri -a allow-uri-read mysample.adoc

The same is true when converting the document to PDF using Asciidoctor PDF, even if the allow-uri-read attribute is not set (since the behavior is implied).

### 63.5. CodeRay and Pygments Stylesheets

Asciidoctor will also embed the theme stylesheet for the CodeRay or Pygments syntax highlighter.

CodeRay

If the source-highlighter attribute is coderay and the coderay-css attribute is class, the CodeRay stylesheet is:

• embedded by default

• copied to the file asciidoctor-coderay.css inside the stylesdir folder within the output directory if linkcss is set

Pygments

If the source-highlighter attribute is pygments and the pygments-css attribute is class, the Pygments stylesheet is:

• embedded by default

• copied to the file asciidoctor-pygments.css inside the stylesdir folder within the output directory if linkcss is set

## 64. XHTML

To convert AsciiDoc to XHTML, set the backend to xhtml5.

Produce XHTML using the built-in HTML converter
asciidoctor -b xhtml5 document.adoc

To produce XHTML instead of HTML when using converter templates, set the htmlsyntax attribute to xml in addition to the backend option:

Produce XHTML using custom templates
asciidoctor -T /path/to/templates -b slides -a htmlsyntax=xml document.adoc
Black Box Decoded: XHTML and htmlsyntax

XHTML output is a special mode of the built-in HTML5 converter. It is activated by prefixing the backend value with x (e.g., xhtml or xhtml5). This hint implicitly assigns the htmlsyntax attribute to the value xml, which normally has the value html.

For all other converters, the htmlsyntax attribute is not set explicitly. If you want a converter template that’s written in Slim or Haml to output XHTML instead of the default HTML, you simply need to set the htmlsyntax attribute to xml explicitly. Asciidoctor will pass on this preference to the Slim or Haml template engine by setting the :format option to :html5.

## 65. DocBook

Asciidoctor can produce DocBook 5.0 and 4.5 output. Since the AsciiDoc syntax was designed with DocBook output in mind, the conversion is very good. There’s a corresponding DocBook element for each markup in the AsciiDoc syntax.

To convert the mysample.adoc document to DocBook 5.0 format, call the processor with the backend flag set to docbook.

$asciidoctor -b docbook mysample.adoc A new XML document, named mysample.xml, will now be present in the current directory. $ ls
mysample.adoc  mysample.html  mysample.xml

Here’s a snippet of the XML generated by the DocBook converter.

XML generated from AsciiDoc
<?xml version="1.0" encoding="UTF-8"?>
<article xmlns="http://docbook.org/ns/docbook"
<info>
<title>Hello, AsciiDoc!</title>
<date>2013-09-03</date>
<author>
<personname>
<firstname>Doc</firstname>
<surname>Writer</surname>
</personname>
<email>[email protected]</email>
</author>
<authorinitials>DW</authorinitials>
</info>
<simpara>
</simpara>
<section xml:id="_first_section">
<title>First Section</title>
<itemizedlist>
<listitem>
<simpara>item 1</simpara>
</listitem>
<listitem>
<simpara>item 2</simpara>
</listitem>
</itemizedlist>
</section>
</article>
 By default, the xmlns attribute is not added to the root element of the DocBook 4.5 document. To enable it, assign an empty value to the xmlns attribute.

If you’re on Linux, you can view the DocBook file with Yelp.

$yelp mysample.xml And of course, if you’re using the Asciidoctor Ruby API, you can generate a DocBook document directly from your application. Generate DocBook output from the API Asciidoctor.convert_file 'mysample.adoc', backend: 'docbook' By default, the docbook converter produces DocBook 5.0 output that is compliant to the DocBook 5.0 specification. A summary of the differences are as follows: • XSD declarations are used on the document root instead of a DTD • <info> elements for document info instead of <articleinfo> and <bookinfo> • elements that hold the author’s name are wrapped in a <personname> element • the id for an element is defined using an xml:id attribute • <link> is used for links instead of <ulink> • the URL for a link is defined using the xl:href attribute Refer to What’s new in DocBook v5.0? for more details about how DocBook 5.0 differs from DocBook 4.5. If you need to output DocBook 4.5, set the backend to docbook45. $ asciidoctor -b docbook45 mysample.adoc

## 66. Man Pages

One of the more specialized uses of AsciiDoc is to serve as a shorthand for generating man pages (short for manual pages) for Unix and Unix-like operating systems.

A man page is coded in the roff typesetting language. By adhering to a specific structure in the man page file, the man command can parse the content and present a formatted document in a textual (command line) pager. Manual pages provide a unified help catalog for all commands in the system. For a full description, see the roff man page (or type man roff or man 7 man).

Asciidoctor can produce roff-formatted man pages if the structure of the AsciiDoc document adheres to the manpage doctype structure (described later in this section).

To produce a roff-formatted man page from an AsciiDoc file that declares the manpage doctype, run:

asciidoctor -b manpage source.adoc Note that the man page converter sets the output file name to progname.1, where progname is the name of the command and 1 is the volume number, as defined by the doctitle of the source document. When converting to the man page format, Asciidoctor uppercases the titles of all level-0 and level-1 sections. This saves you from having to type section titles in all uppercase. It also makes the document portable to other output formats since this style is only needed in the man page output to align with conventions.  If you’re use Ruby 2.4 or better, Asciidoctor will uppercase any letter in the title that is recognized by the Unicode specification as having an uppercase equivalent (which includes non-Latin letters). Prior to Ruby 2.4, Ruby could only uppercase Latin letters. Asciidoctor can also produce HTML and PDF versions similar to the man output for viewing in other contexts. To see the man page in HTML instead, run:  asciidoctor source.adoc

Here is an example man page composed in AsciiDoc for the eve command:

= eve(1)
Andrew Stanton
v1.0.0
:doctype: manpage
:manmanual: EVE
:mansource: EVE

== Name

eve - analyzes an image to determine if it's a picture of a life form

== Synopsis

*eve* [_OPTION_]... _FILE_...

== Options

*-o, --out-file*=_OUT_FILE_::
Write result to file _OUT_FILE_.

*-c, --capture*::
Capture specimen if it's a picture of a life form.

== Exit status

*0*::
Success.
Image is a picture of a life form.

*1*::
Failure.
Image is not a picture of a life form.

== Resources

*Project web site:* http://eve.example.org

== Copying

Free use of this software is granted under the terms of the MIT License.

The manpage doctype has the following required parts:

A man page document header is mandatory. The title line contains the man page name followed immediately by the manual section number in round brackets. The title name should not contain white space. The manual section number is a single digit optionally followed by a single character.

The NAME Section

The first man page section is mandatory, must be titled “NAME” and must contain a single paragraph (usually a single line) consisting of a list of one or more comma separated command name(s) separated from the command purpose by a dash character. The dash must have at least one white space character on either side.

The SYNOPSIS Section

The second man page section is mandatory and must be titled “SYNOPSIS”.

There are several built-in document attributes that affect only man pages. If used, they must be set in the document header.

Built-in document attributes specific to the manpage doctype
Attribute name Description Value (as parsed from example above)

mantitle

Alternative way to set the man page name.

ASCIIDOCTOR(1)

manvolnum

Manual section number.

1

manname

Alternative way to set the command name.

asciidoctor

manpurpose

Alternative way to set the command purpose.

converts AsciiDoc source files

Style the links in the manpage output. A valid link format sequence.

blue R <>

mansource

The source to which the man page pertains. When producing DocBook, it becomes a DocBook refmiscinfo attribute and appears in the footer.

Asciidoctor

manversion

The version of the man page. Defaults to revnumber if not specified. When producing DocBook, it becomes a DocBook refmiscinfo attribute and appears in the footer. Not used by Asciidoctor.

1.5.4

manmanual

Manual name. When producing DocBook, it becomes a DocBook refmiscinfo attribute and appears in the footer.

Asciidoctor Manual

Refer to the AsciiDoc source of the Asciidoctor man page to see a complete example. The man page for Asciidoctor is produced using the built-in man page converter in Asciidoctor. The man pages for git are also produced from AsciiDoc documents, so you can use those as another example to follow.

## 67. PDFs

Conversion from AsciiDoc to PDF is made possible by a number of tools.

Asciidoctor PDF

A native PDF converter for Asciidoctor (converts directly from AsciiDoc to PDF using Prawn).

Instructions for installing and using Asciidoctor PDF are documented in the project’s README. The tool provides built-in theming via a YAML configuration file, which is documented in the theming guide.

 Asciidoctor PDF is the preferred tool for converting to PDF and is fully supported by the Asciidoctor community.
a2x

A DocBook toolchain frontend provided by that AsciiDoc Python project.

To use this tool, you should first convert to DocBook using Asciidoctor, then convert the DocBook to PDF using a2x. a2x accepts a DocBook file as input and can convert it to a PDF using either Apache FOP or dblatex. Instructions for using a2x are documented in the project’s man page.

asciidoctor-fopub

A DocBook toolchain frontend similar to a2x, but which only requires Java to be installed on your machine.

Instructions for using asciidoctor-fopub are documented in the project’s README. To alter the look and feel of the PDF, it’s necessary to pass XSL parameters or modify the XSLT. More information about customization can be found in DocBook XSL: The Complete Guide.

### 68.1. Guard/Live Viewer

Guard

AsciiDoc is a plugin for Guard that converts watched AsciiDoc files to the specified output format whenever they change using Asciidoctor.

Instructions for using the Guard/Live viewer are documented in the project’s README.

## 69. CLI Inputs and Outputs

So far, you’ve seen how to pass a single input file to the CLI for it to convert. You can also convert multiple files at once, read content from STDIN, write content to STDOUT, or write content to a different output file or directory. This section explains the various input and output options of the CLI.

### 69.1. Process Multiple Source Files from the CLI

You can pass multiple source files or a filename pattern to the Asciidoctor CLI and it will convert each file given in turn.

Let’s assume there exist two AsciiDoc files in the current directory, a.adoc and b.adoc. You can pass both files to Asciidoctor using a single command, as follows:

$asciidoctor a.adoc b.adoc Asciidoctor will convert both files, transforming a.adoc to a.html and b.adoc to b.html. To save some typing, you can use the glob operator (*) to match all AsciiDoc files in the current directory using a single argument: $ asciidoctor *.adoc

Your shell will automatically expand the pattern and interpret the command exactly as you had typed it above:

$asciidoctor a.adoc b.adoc You can pass all AsciiDoc files inside direct subfolders using the glob operator (*) in place of the directory name: $ asciidoctor */*.adoc

To match all files in the current directory and direct subfolders, combine both glob patterns:

$asciidoctor *.adoc */*.adoc Since the globs in this command rely on shell expansion, the command is not portable across platforms. To make it portable, you can allow the Asciidoctor CLI to expand the globs. To do so, instruct the shell to not expand the glob by quoting the pattern, as shown here: $ asciidoctor '*.adoc' '*/*.adoc'

This time, the arguments *.adoc and */*.adoc are passed directly to Asciidoctor instead of being expanded. Asciidoctor handles the glob matching in a manner that is portable across platforms.

But it gets better. The glob handling in Asciidoctor (which matches the rules of file globbing in Ruby) is likely more powerful than what your shell offers. For example, you can match AsciiDoc files in the current folder and in folders of any depth using the double glob operator (**).

$asciidoctor '**/*.adoc' Most shells do not honor this double glob pattern. In conclusion, when specifying a glob pattern, we always recommend enclosing the argument in quotes.  If you process multiple nested AsciiDoc files at once and are also applying a custom stylesheet to them, you’ll need to manage the stylesheet’s location. ### 69.2. Specifying an Output File By default, the CLI writes the converted output to the same directory as the input file and with the same name as the input file, except with a file extension that matches the output format (e.g., replacing .adoc with .html). You can override this default and have the CLI write to a file and directory of your choice. There are several circumstances when you’ll want to specify a different output file: • You want to write the output file to a different name, perhaps to append a qualifier such as a version string. • You want to write the output file to a different directory. • You are piping content to the CLI, but want to write the output to a file (in this case, an output file is required).  By specifying an output file, you implicitly overwrite the output directory as well. The output file will be resolved relative to the current working directory, not the directory of the input file. To specify the output file, you’ll use the -o option. For example, let’s say we want to convert mydoc.adoc and write the output to a filename that includes the current date. You’d use: $ asciidoctor -o mydoc-$(date +%Y-%m-%d).html mydoc.adoc We could write it to another folder as well by prefixing the output file with a folder name: $ asciidoctor -o build/mydoc-$(date +%Y-%m-%d).html mydoc.adoc If you only want to specify the output directory, but let the filename be defaulted, use the -D option: $ asciidoctor -D build mydoc.adoc

The -D option can also be used when processing multiple input files:

$asciidoctor -D build *.adoc If you are piping content to the CLI, the default is to write the output to STDOUT. If you want to write the output to a file in this case, you have to specify one: $ cat mydoc.adoc | asciidoctor -o build/mydoc-$(date +%Y-%m-%d).html - You’ll learn more about piping content through the CLI in the next section. ### 69.3. Piping Content Through the CLI Using the - flag, you can pipe content to the asciidoctor command. This flag tells Asciidoctor read the source from standard input (STDIN). For example: $ echo 'content' | asciidoctor -
 Any variation of STDIN will work.

This command is effectively the same as:

$echo 'content' | asciidoctor -o - - When reading source from STDIN, Asciidoctor doesn’t have a reference to an input file. Therefore, it sends the converted text to standard output (STDOUT) by default. If, instead, you want to write the full document to an output file, you specify it using the -o flag. For example, the following command writes a standalone HTML document to output.html instead of STDOUT: $ echo "content" | asciidoctor -o output.html -

When you pipe content to the asciidoctor command, it no longer has a concept of where the document is located. Therefore, relative references such as includes may not work as expected. To resolve this problem, you should specify an absolute base directory using the -B option:

$echo "content" | asciidoctor -B /path/to/basedir -o output.html - Alternately, you can set an artificial document directory by passing an absolute path to the docdir attribute: $ echo "content" | asciidoctor -a docdir=/path/to/docdir -o output.html -

Try both approaches to determine which one suits your needs better.

When piping source from STDIN to STDOUT through the asciidoctor command, you often just want the converted body (i.e., embeddable HTML). To produce that variant, add the -s flag:

$echo 'content' | asciidoctor -s - Or perhaps you want to include the doctitle as well: $ echo -e '= Document Title\n\ncontent' | asciidoctor -s -a showtitle -

## 70. Running Asciidoctor Securely

Asciidoctor provides security levels that control the read and write access of attributes, the include directive, macros, and scripts while a document is processing. Each level includes the restrictions enabled in the prior security level.

 UNSAFE A safe mode level that disables any security features enforced by Asciidoctor. Ruby is still subject to its own restrictions. This is the default safe mode for the CLI. Its integer value is 0. SAFE This safe mode level prevents access to files which reside outside of the parent directory of the source file. The include directive is enabled, but paths to include files must be within the parent directory. This mode allows assets (such as the stylesheet) to be embedded in the document. Its integer value is 1. SERVER A safe mode level that disallows the document from setting attributes that would affect conversion of the document. This level trims docfile to its relative path and prevents the document from: setting source-highlighter, doctype, docinfo and backend seeing docdir It allows icons and linkcss. Its integer value is 10. SECURE A safe mode level that disallows the document from attempting to read files from the file system and including their contents into the document. Additionally, it: disables icons disables the include directive data can not be retrieved from URIs prevents access to stylesheets and JavaScripts sets the backend to html5 disables docinfo files disables data-uri disables docdir and docfile disables source highlighting Asciidoctor extensions may still embed content into the document depending whether they honor the safe mode setting. This is the default safe mode for the API. Its integer value is 20.

You can set Asciidoctor’s safe mode level using the CLI or API.

### 70.1. Set the Safe Mode in the CLI

When Asciidoctor is invoked via the CLI, the safe mode is set to UNSAFE by default. You can change the safe level by executing one of the following commands in the CLI.

-S, --safe-mode=SAFE_MODE

Sets the safe mode level of the document according to the assigned level (UNSAFE, SAFE, SERVER, SECURE).

--safe, asciidoctor-safe

Sets the safe mode level to SAFE. Provided for compatibility with the python AsciiDoc safe command.

### 70.2. Set the Safe Mode in the API

The default safe level in the API is SECURE.

In the API, you can set the safe mode using a string, symbol or integer value. The value must be set in the document constructor using the :safe option.

result = Asciidoctor.convert_file('master.adoc', :safe => 'server')

or

result = Asciidoctor.convert_file('master.adoc', :safe => :server)

or

result = Asciidoctor.convert_file('master.adoc', :safe => 10)

### 70.3. Set Attributes Based on the Safe Mode

Asciidoctor provides access to the current safe mode through built-in attributes. You can use these attributes to enable or disable content based on the current safe mode of the processor.

The safe mode can be referenced by one of the following attributes:

• The value of the safe-mode-name attribute (e.g., unsafe, safe, etc.)

• The value of the safe-mode-level attribute (e.g., 0, 10, etc.)

• The presense of the safe-mode-<name> attribute, where <name> is the safe mode name.

The attributes in the next example define replacement text for features that are disabled in high security environments:

ifdef::safe-mode-secure[]
endif::safe-mode-secure[]

This feature is particularly handy for displaying content on GitHub, where the safe mode is set to its most restrictive setting, secure.

Asciidoctor provides a default stylesheet and built-in converters so you can quickly process and convert your document, but it also lets you use custom stylesheets and converters. The Asciidoctor project includes alternative stylesheet themes from the stylesheet factory and specialized backends. You can also create your own themes and backends.

## 71. Applying a Theme

A custom stylesheet can be stored in the same directory as your document or in a separate directory. Like the default stylesheet, you can have the output document link to your custom stylesheet or embed it.

If the stylesheet is in the same directory as your document, you can apply it when converting your document to HTML from the CLI.

$asciidoctor -a stylesheet=mystyles.css mysample.adoc 1. Save your custom stylesheet in the same directory as mysample.adoc 2. Call the asciidoctor processor 3. Set -a (--attribute) and stylesheet 4. Assign the stylesheet file’s name to the stylesheet attribute 5. Enter your document file’s name. Alternatively, let’s set the stylesheet attribute in the header of mysample.adoc. = My First Experience with the Dangers of Documentation :stylesheet: mystyles.css In my world, we don't have to worry about mutant, script-injecting warlocks. No. We have something far worse. We're plagued by Wolpertingers. == Origins You may not be familiar with these https://en.wikipedia.org/wiki/Wolpertinger[ravenous beasts], but, trust me, they'll eat your shorts and suck the loops from your code. When your document and the stylesheet are stored in different directories, you need to tell Asciidoctor where to look for the stylesheet in relation to your document. Asciidoctor uses the relative or absolute path you assign to the stylesdir attribute to find the stylesheet. Let’s move mystyles.css into mydocuments/mystylesheets/. Our AsciiDoc document, mysample.adoc, is saved in the mydocuments/ directory. = My First Experience with the Dangers of Documentation :stylesdir: mystylesheets/ :stylesheet: mystyles.css In my world, we don't have to worry about mutant, script-injecting warlocks. No. We have something far worse. We're plagued by Wolpertingers. == Origins You may not be familiar with these https://en.wikipedia.org/wiki/Wolpertinger[ravenous beasts], but, trust me, they'll eat your shorts and suck the loops from your code. After processing mysample.adoc, its HTML output (mysample.html), which includes the embedded mystyles.css stylesheet, is created in the mydocuments/ directory. You can also set stylesdir in the CLI. $ asciidoctor -a stylesdir=mystylesheets/ -a stylesheet=mystyles.css mysample.adoc

If you don’t want to embed the mystyles.css stylesheet into your HTML output, make sure to set linkcss.

= My First Experience with the Dangers of Documentation
:stylesdir: mystylesheets/
:stylesheet: mystyles.css

In my world, we don't have to worry about mutant, script-injecting warlocks.
No.
We have something far worse.
We're plagued by Wolpertingers.

== Origins

You may not be familiar with these https://en.wikipedia.org/wiki/Wolpertinger[ravenous beasts], but, trust me, they'll eat your shorts and suck the loops from your code.

After your document is converted, notice that a copy of mystyles.css was not created in the mydocuments/ directory. Unlike when you link to the default Asciidoctor stylesheet, any custom stylesheets you link to are not copied to the directory where your output is saved.

Stylesheets and processing multiple nested documents

When you are running Asciidoctor once across a nested set of documents, it’s currently not possible to specify a single relative path for the stylesdir attribute that would work for all of the documents. This is because the relative depth of the stylesheet’s location differs for the documents in the subdirectories. One way to solve this problem is to maintain the path to stylesdir in each document.

Let’s say you have three AsciiDoc documents saved in the following directory structure:

/mydocuments
/mynesteddocuments
/mystylesheets

For a.adoc and b.adoc, set stylesdir to:

:stylesdir: mystylesheets

For c.adoc, set stylesdir to:

:stylesdir: ../mystylesheets

If you’re serving your documents from a webserver, you can solve this problem by providing an absolute path to the stylesheet.

## 72. Stylesheet Factory

The Asciidoctor stylesheet factory is where themes are developed for styling your documents. Specifically, these stylesheets can be used to quickly customize the look and feel of HTML 5 documents generated by Asciidoctor.

To view the Asciidoctor themes in action, visit the theme showcase.

 The Asciidoctor stylesheet factory is only compatible with Asciidoctor 0.1.2 and greater.

### 72.1. Setting up the Factory

The stylesheets in the Asciidoctor stylesheet factory are built using Compass, a CSS authoring framework that uses Sass to generate CSS files. The styles and components are generated by Foundation 4, an awesome and flexible CSS component framework that ensures your stylesheet is cross-browser and mobile friendly.

#### 72.1.1. Install the Gems

In order to build the stylesheets, you must download the Asciidoctor stylesheet factory repository and install the Compass and Foundation gems.

 It does not matter where you save the project on your system.
2. Make sure you have Ruby and RubyGems installed, and, ideally, Bundler.

3. Run Bundler to install the Compass and Foundation gems.

$bundle install  The previous bundle command is equivalent to the following two commands: $ gem install compass --version 0.12.2 $gem install zurb-foundation --version 4.3.2 You don’t need to execute these gem install commands if you use Bundler. Once you have the gems installed, you can build the stylesheets. #### 72.1.2. Build the Stylesheets To build the stylesheets: 1. Navigate to the Asciidoctor stylesheet factory directory on your system. 2. Run Compass’s compile command. $ compass compile

The stylesheets are compiled from the Sass source files in the sass/ folder and written to the stylesheets/ folder. You can reference the stylesheets in stylesheets/ from your HTML file.

### 72.2. Creating a Theme

Themes go in the sass/ folder. To create a new theme, let’s call it hipster, start by creating two new files:

sass/hipster.scss
• Imports the theme settings, which includes default variables and resets

• Imports the AsciiDoc components

• Defines any explicit customization

sass/settings/_hipster.scss
• Sets variables that customize Foundation 4 and the AsciiDoc CSS components

Here’s a minimal version of sass/hipster.scss:

@import "settings/hipster";
@import "components/asciidoc";
@import "components/awesome-icons";
 You don’t have to include the underscore prefix when importing files.
 The awesome-icons component is only applicable to HTML generated by Asciidoctor > 0.1.2 with the icons attribute set to font.

You can add any explicit customization below the import lines.

The variables you can set in sass/settings/_hipster.scss are a combination of the Foundation 4 built-in global settings and global settings and imports for the AsciiDoc components.

Once you’ve created your custom theme, it’s time to apply it to your document.

### 72.3. Applying a Stylesheet

Let’s practice applying a stylesheet to a simple AsciiDoc file.

1. Create an AsciiDoc file like the one below.

2. Save the file as mysample.adoc.

= Introduction to AsciiDoc
Doc Writer <[email protected]>

== First Section

* item 1
* item 2

[source,ruby]
puts "Hello, World!"

Next, you’ll use the Asciidoctor processor to generate HTML and apply a stylesheet to it from the stylesheets/ directory.

### 72.4. Generate an HTML Document

Now it’s time to pick the stylesheet you want to apply to your content when it is rendered. In your file browser, navigate to the stylesheets/ directory. Or, using a console, change to the stylesheets/ directory and list the available stylesheets using the ls command.

$ls Console output of ls command asciidoctor.css foundation-lime.css iconic.css riak.css colony.css foundation-potion.css maker.css rubygems.css foundation.css golo.css readthedocs.css Let’s apply the colony.css stylesheet to the sample document. 1. Navigate to the directory where you saved mysample.adoc. 2. Call the asciidoctor processor. 3. Specify the stylesheet you want applied with the stylesheet attribute. 4. Tell the processor where the specified stylesheet is located with the stylesdir attribute. $ asciidoctor -a stylesheet=colony.css -a stylesdir=../stylesheets mysample.adoc

Open a browser, navigate to mysample.html and checkout the result! If you inspect the mysample.html document, you should see that the stylesheet is embedded in the converted document.

Stylesheet images

The Golo, Maker, and Riak themes include image assets. To apply these themes to your document correctly, the applicable images must be copied into the same directory as the generated output.

For example, to apply the maker.css stylesheet to mysample.adoc:

1. Copy body-bh.png from the images/maker/ directory into the output directory.

2. Call the stylesheet and styledir attributes.

$asciidoctor -a stylesheet=maker.css -a stylesdir=../stylesheets mysample.adoc Navigate to mysample.html in your browser. The body-bh.png image should add a graph paper-like background to your generated output. ### 72.5. External Preview You may want to preview sample HTML files on another computer or device. To do that, you need to serve them through a web server. You can quickly serve HTML files in the root directory of the project using the following command: Using Python $ python -m SimpleHTTPServer 4242

or

Using Ruby >= 1.9.3
$ruby -run -e httpd . -p 4242 ## 73. Slide Decks In addition to generating normal documents from AsciiDoc (e.g., a book or article), you can also use AsciiDoc to create HTML-based slide decks. The converters for creating HTML-based slides add some additional structure rules to the document for defining slides. However, nothing in this structure restricts you from still being able to publish the content as a normal document too. The conversion from AsciiDoc to an HTML-based slide deck is handled by one of the following converters from the Asciidoctor ecosystem: There’s also a converter for making deck.js slide decks, but we discourage using it as deck.js itself is very outdated. ## 74. Custom Backends ### 74.1. Storing Multiple Templates Custom templates can be stored in multiple directories. That means you can build on an existing backend by copying only the templates you want to modify. Then, just pass both the directory holding the original templates and the directory containing your customized templates when you invoke Asciidoctor. In the CLI, multiple template directories are specified by using the -T option multiple times. $ asciidoctor -T /path/to/original/templates -T /path/to/modified/templates mysample.adoc

In the API, multiple template directories are specified by passing an array to the template_dirs option:

Asciidoctor.convert_file 'mysample.adoc', safe: :safe
template_dirs: %w(/path/to/original/templates /path/to/modified/templates)

## 75. Using Asciidoctor with Other Languages

The built-in labels, messages, and syntax keywords in Asciidoctor are English by default. However, Asciidoctor is not restricted to working with English-only content. Asciidoctor can process the full range of the UTF-8 character set. That means you can write your document in any language, save the file with UTF-8 encoding, and expect Asciidoctor to convert the text properly. Furthermore, you can customize the built-in labels (e.g., “Appendix”) to match the language in which you are writing.

There are some caveats to know about:

• Currently, the official HTML and PDF converters only fully support left-to-right (and top-to-bottom) reading. Support for right-to-left (RTL) is being worked on. See issue #1601 for details. In the interim, you can leverage the DocBook toolchain to get right-to-left support.

• Attributes that store dates and times (e.g., docdatetime) are always formatted like 2019-01-04 19:26:06 GMT+0000.

• Message (aka logging) strings are always in English.

• Asciidoctor does not support the language conf files used by AsciiDoc Python. However, Asciidoctor does provide a translation file that can be used for a similar purpose.

### 75.1. Translating built-in labels

When converting to DocBook, you can rely on the DocBook toolchain to translate (most) built-in labels. To activate this feature, simply set the lang attribute to a valid country code (which defaults to en for English). For example:

$asciidoctor -a lang=es -b docbook article.adoc The list of supported languages, as well as additional language considerations for DocBook, are described in DocBook XSL: The Complete Guide. The lang attribute does not enable automatic translation of built-in labels when converting directly to HTML or PDF. It’s merely a hint to configure the DocBook toolchain. If you’re not using the DocBook toolchain for publishing, you must translate each built-in label yourself. One way is to set the following attributes in the document header or by passing the attributes via the API or CLI: Attributes that control built-in labels Attribute name Used for Default appendix-caption Appendix titles. Appendix caution-caption CAUTION admonitions (when icons are not in use). Caution chapter-label Prefix added to chapter titles (i.e., level-1 section titles when doctype is book). (pdf converter only) Chapter example-caption Example titles. Example figure-caption Automatically prefixed to figure titles. Figure important-caption IMPORTANT admonitions (when icons are not in use). Important last-update-label Label for when the document was last updated. Last updated listing-caption The label for listing blocks. By default, listing blocks do not have captions. If you specify listing-caption, then you also turn on captions for listing blocks. not set manname-title Label for the program name section in the man page. NAME note-caption NOTE admonitions (when icons are not in use). Note preface-title Title text used for the anonymous preface (when the doctype is book). not set table-caption Automatically prefixed to table titles. Table tip-caption TIP admonitions (when icons are not in use). Tip toc-title Title of the table of contents. Table of Contents untitled-label The document title, for documents that have only body content. Untitled version-label The label preceding the revnumber in the document’s byline. Version warning-caption WARNING admonitions (when icons are not in use). Warning If you plan to support multiple languages, you’ll want to define the attributes for each language inside a conditional preprocessor directive. For example: ifeval::["{lang}" == "de"] :caution-caption: Achtung ... endif::[] Of course, you’re probably hoping this has already been done for you. Indeed, it has! You can find an AsciiDoc file in the Asciidoctor repository that provides translations of these attributes for most major languages. The translations are defined using AsciiDoc attribute entries inside conditional preprocessor blocks, just as suggested above. To use this file to translate the built-in labels according the the value of the lang attribute (just like the DocBook toolchain does), follow these steps: 1. Download the AsciiDoc file attributes.adoc from the Asciidoctor repository. 2. Put the file in the folder locale relative to your document. 3. Add the following line to the header of your AsciiDoc document: include::locale/attributes.adoc[] 4. Set the language using the lang attribute. This attribute must be set before the include directive gets processed. For example: -a lang=es The built-in labels will now be translated automatically based on the value of the lang attribute. There’s an ongoing discussion about how to make language support even simpler (issue #1129). Input is welcome. ### 75.2. Translation Asciidoctor (or DocBook) currently does not support translation of content out of the box. There’s a proposal to integrate gettext (discussion), but suggestions are welcome. # Publishing Your Content ## 76. Static Website Generators ### 76.1. Front Matter Added for Static Site Generators Many static site generators (i.e., Jekyll, Middleman, Awestruct) rely on "front matter" added to the top of the document to determine how to convert the content. Front matter typically starts on the first line of a file and is bounded by block delimiters (e.g., ---). Here’s an example of a document that contains front matter: --- (1) layout: default (2) --- (1) = Document Title content  1 Front matter delimiters 2 Front matter data The static site generator removes these lines before passing the document to the AsciiDoc processor to be converted. Outside of the tool, however, these extra lines can throw off the processor. If the skip-front-matter attribute is set via the CLI or API (e.g., -a skip-front-matter), Asciidoctor (as of 0.1.4) will recognize the front matter and consume it before parsing the document. Asciidoctor stores the content it removes in the front-matter attribute to make it available for integrations. Asciidoctor also removes front matter when reading include files.  Awestruct can read front matter directly from AsciiDoc attributes defined in the document header, thus eliminating the need for this feature. #### 76.1.1. Configuring Attributes for Awestruct Awestruct defines a set of default attributes that it passes to the API in its /default-site.yml file. One of the attributes in that configuration is imagesdir. The value there is set to /images. That means the value in your document is skipped due to the precedence rules. Fortunately, there is one additional place you can override the attribute. This gives you the opportunity to set your own default and to flip the precedence order so that the document wins out. If an attribute value that is passed to the API ends with an @ symbol, it makes that assignment have a lower precedence than an assignment in the document. You can define attributes you want to pass to the API in the _config/site.yml file. Here’s an example entry for Asciidoctor: asciidoctor: :safe: safe :attributes: imagesdir: /assets/[email protected] icons: font ...  The second-level keys (safe and attributes, in this case) must have colons on both sides of the key name. The rest of the keys only have a colon after the key. With this configuration added, you should observe that the imagesdir attribute in your document is now respected. # Using Asciidoctor’s API In addition to the command line interface, Asciidoctor provides a Ruby API. The API is intended for integration with other software projects and is suitable for server-side applications, such as Rails, Sinatra and GitHub. Asciidoctor also has a Java API that mirrors the Ruby API. The Java API calls through to the Ruby API using an embedded JRuby runtime. See the AsciidoctorJ project for more information. ## 77. Require the Library To use Asciidoctor in your application, you first need to require the gem: require 'asciidoctor' This statement makes all of the public APIs in Asciidoctor available to your script or application. You are now ready to start processing AsciiDoc documents. The main entry points in the Asciidoctor API are the static methods to load or convert AsciiDoc documents, which we’ll cover the next two chapters. ## 78. Load and Convert Files To parse a file into an Asciidoctor::Document object: doc = Asciidoctor.load_file 'mysample.adoc' You can get information about the document: puts doc.doctitle puts doc.attributes More than likely, you will want to convert the document. To convert a file containing AsciiDoc markup to HTML 5, use: Asciidoctor.convert_file 'mysample.adoc' The command will output to the file mysample.html in the same directory. You can convert the file to DocBook 5.0 by setting the :backend option to 'docbook': Asciidoctor.convert_file 'mysample.adoc', backend: 'docbook' The command will output to the file mysample.xml in the same directory. If you’re on Linux, you can view the file using Yelp. ## 79. Load and Convert Strings To parse an AsciiDoc-formatted string into a document object model, use: doc = Asciidoctor.load '*This* is Asciidoctor.' To convert the AsciiDoc-formatted string instead, use: puts Asciidoctor.convert '*This* is Asciidoctor.' When converting a string, Asciidoctor does not output a standalone document by default. Instead, it generates embeddable output. Let’s learn why that is and how to control it. ### 79.1. Embeddable output When you pass a string to Asciidoctor.convert to convert it to a backend format, such as HTML, this method only returns the converted content for those blocks. It does not include the shell around that content (i.e., the header and footer) that is needed to make a standalone document. Instead, it makes an embeddable document. This default was chosen to make Asciidoctor consistent with other lightweight markup processors like Markdown. Here’s what’s included in an embeddable document: • The document title, but only if the showtitle attribute is set (no attribution and revision information) • The table of contents if the toc attribute is enabled (and not macro or preamble) • The converted document body • The footnotes unless the nofootnotes attribute is set You can still generate a standalone document when converting a string. To go from an AsciiDoc string to a standalone output document, you need to explicitly set the :header_footer option to true. puts Asciidoctor.convert '*This* is Asciidoctor.', header_footer: true Now you’ll get back a full HTML 5 file. You can get the same behavior when converting a file by setting the :header_footer option to false. However, most of the time you’ll want to generate a standalone document when converting a file (which is the default). Another way to implicitly enable the shell is to output the result to a file. In this case, the default output behavior changes from embeddable to standalone. puts Asciidoctor.convert '*This* is Asciidoctor.', to_file: 'out.html' When converting a string, the TOC is only included by default when using the :header_footer option as shown above. However, you can force it to be included without the header and footer by setting the toc attribute with a value of macro and using the toc::[] macro in the string itself. ### 79.2. Convert inline markup only If you only want the inline markup to be returned, set the :doctype option to 'inline': puts Asciidoctor.convert '*This* is Asciidoctor.', :doctype => 'inline' In this mode, Asciidoctor will only process the first block (e.g., paragraph) in the document and ignore the rest. ### 79.3. Convert to DocBook You can produce DocBook 5.0 by setting the backend option to 'docbook'. Since embeddable DocBook isn’t that useful, we also enable the shell (i.e., header and footer) by setting the :header_footer option to true. puts Asciidoctor.convert '*This* is Asciidoctor.', :header_footer => true, :backend => 'docbook' Let’s say you don’t like some (or all) of the output that Asciidoctor produces. That’s no problem. You can change it. And yes, any of it! Let’s find out how to customize the output Asciidoctor spits out in the next chapter. ## 80. Generate an HTML TOC Asciidoctor’s HTML 5 converter has built-in support for generating a TOC. This TOC generator can also be used as a general purpose API. This logic is available via the outline method on the HTML5 converter. The outline method excepts a Document object and an optional Hash of options, and returns an HTML string. It can be resolved and invoked from anywhere using the following: html_toc = (Asciidoctor::Converter.for 'html5').outline document The method can also be executed from inside a converter template (e.g., Slim, Haml, or ERB). When using a composite converter, this call will be run through the converter chain. = converter.convert document, 'outline' The method is also available through the Document API: html_doc = document.converter.convert document, 'outline' The outline method accepts the following options: sectnumlevels the number of section levels to number (defaults to the value of the sectnumlevels attribute. toclevels the depth of the toc (defaults to the value of the toclevels attribute) ## 81. Provide Custom Templates Asciidoctor allows you to override the converter methods used to convert almost any individual AsciiDoc element. If you provide a directory of Tilt-compatible templates, named in such a way that Asciidoctor can figure out which template goes with which element, Asciidoctor will use the templates in this directory instead of its built-in templates for any elements for which it finds a matching template. It will fallback to its default templates for everything else. puts Asciidoctor.convert '*This* is Asciidoctor.', :header_footer => true, :template_dir => 'templates' The Document and Section templates should begin with document and section, respectively. The file extension is used by Tilt to determine which view framework it will use to use to interpret the template. For instance, if you want to write the template in ERB, you’d name these two templates document.html.erb and section.html.erb. The first file extension, .html, maps to the converter and the second, .erb maps to the template engine. To use Haml as the template engine, you’d name the templates document.html.haml and section.html.haml. Templates for block elements, like a paragraph or sidebar, are named after the block they handle. For instance, to override the default paragraph template with an ERB template, put a file named paragraph.html.erb in the template directory you pass to the Document constructor using the :template_dir option. For more usage examples, see the asciidoctor-backends, the O’Reilly htmlbook project and the (massive) test suite. # Extensions Extensions have proven to be central to the success of AsciiDoc because they open up the language to new use cases. However, the way extensions are implemented in AsciiDoc Python presents a number of problems: • They are challenging to write because they work at such a low-level (read as: nasty regular expressions). • They are fragile since they often rely on system commands to do anything significant. • They are hard to distribute due to the lack of integration with a formal distribution system. Asciidoctor addresses these issues by introducing a proper extension API that offers a superset of the extension points that AsciiDoc Python provides. As a result, extensions in Asciidoctor are easier to write, more powerful, and simpler to distribute. The goal for Asciidoctor has always been to allow extensions to be written using the full power of a programming language (whether it be Ruby, Java, Groovy or JavaScript), similar to what we’ve done with the backend (conversion) mechanism. That way, you don’t have to shave yaks to get the functionality you want, and you can distribute the extension using defacto-standard packaging mechanisms like RubyGems or JARs.  The extension API in Asciidoctor is stable with the exception of inline macros. Since inline content is not parsed until the convert phase, the inline macro processor must return converted text (e.g., HTML) rather than an AST node. Once Asciidoctor is changed to process inline content during the parse phase, the inline macro processor will need to return an inline node. When that switch occurs, there will either be some sort of adapter or required migration for inline macro processors, but that has yet to be determined. ## 82. Extension Points Here are the extension points that are available in Asciidoctor 0.1.4. Preprocessor Processes the raw source lines before they are passed to the parser. TreeProcessor Processes the Asciidoctor::Document (AST) once parsing is complete. Postprocessor Processes the output after the document has been converted, but before it’s written to disk. DocinfoProcessor Adds additional content to the header or footer regions of the generated document. Block processor Processes a block of content marked with a custom block style (i.e., [custom]). (similar to an AsciiDoc filter) Block macro processor Registers a custom block macro and processes it (e.g., gist::12345[]). Inline macro processor Registers a custom inline macro and processes it (e.g., Save). Include processor Processes the include::<filename>[] directive. These extensions are registered per document using a callback that feels sort of like a DSL: Asciidoctor::Extensions.register do |document| preprocessor FrontMatterPreprocessor tree_processor ShellSessionTreeProcessor postprocessor CopyrightFooterPostprocessor docinfo_processor TrackingCodeDocinfoProcessor if document.basebackend? 'html' block ShoutBlock block_macro GistBlockMacro if document.basebackend? 'html' inline_macro ManInlineMacro include_processor UriIncludeProcessor end  Extension classes must be defined outside of the register block. Once an extension class is registered, it is frozen, preventing further modification. If you define an extension class inside the register block, it will result in an error on subsequent invocations. You can register more than one processor of each type, though you can only have one processor per custom block or macro. Each registered class is instantiated when the Asciidoctor::Document is created.  There is currently no extension point for processing a built-in block, such as a normal paragraph. Look for that feature in a future Asciidoctor release. ## 83. Example Extensions Below are several examples of extensions and how they are registered. ### 83.1. Preprocessor Example Purpose Skim off front matter from the top of the document that gets used by site generators like Jekyll and Awestruct. sample-with-front-matter.adoc --- tags: [announcement, website] --- = Document Title content [subs="attributes,specialcharacters"] .Captured front matter .... --- {front-matter} --- .... FrontMatterPreprocessor require 'asciidoctor' require 'asciidoctor/extensions' class FrontMatterPreprocessor < Asciidoctor::Extensions::Preprocessor def process document, reader lines = reader.lines # get raw lines return reader if lines.empty? front_matter = [] if lines.first.chomp == '---' original_lines = lines.dup lines.shift while !lines.empty? && lines.first.chomp != '---' front_matter << lines.shift end if (first = lines.first).nil? || first.chomp != '---' lines = original_lines else lines.shift document.attributes['front-matter'] = front_matter.join.chomp # advance the reader by the number of lines taken (front_matter.length + 2).times { reader.advance } end end reader end end Usage Asciidoctor::Extensions.register do preprocessor FrontMatterPreprocessor end Asciidoctor.convert_file 'sample-with-front-matter.adoc', :safe => :safe ### 83.2. Tree Processor Example Purpose Detect literal blocks that contain shell commands, strip the prompt character and style the command using CSS in such a way that the prompt character cannot be selected (as seen on help.github.com). sample-with-shell-session.adoc $ echo "Hello, World!"
> Hello, World!

$gem install asciidoctor ShellSessionTreeProcessor class ShellSessionTreeProcessor < Asciidoctor::Extensions::TreeProcessor def process document return unless document.blocks? process_blocks document nil end def process_blocks node node.blocks.each_with_index do |block, i| if block.context == :literal && (((first_line = block.lines.first).start_with? '$ ') ||
(first_line.start_with? '> '))
node.blocks[i] = convert_to_terminal_listing block
else
process_blocks block if block.blocks?
end
end
end

def convert_to_terminal_listing block
attrs = block.attributes
attrs['role'] = 'terminal'
prompt_attr = (attrs.has_key? 'prompt') ?
%( data-prompt="#{block.sub_specialchars attrs['prompt']}") : nil
lines = block.lines.map do |line|
line = block.sub_specialchars line.chomp
if line.start_with? '$' %(<span class="command"#{prompt_attr}>#{line[2..-1]}</span>) elsif line.start_with? '&gt; ' %(<span class="output">#{line[5..-1]}</span>) else line end end create_listing_block block.document, lines * EOL, attrs, subs: nil end end Usage Asciidoctor::Extensions.register do treeprocessor ShellSessionTreeProcessor end Asciidoctor.convert_file 'sample-with-shell-session.adoc', :safe => :safe ### 83.3. Postprocessor Example Purpose Insert copyright text in the footer. CopyrightFooterPostprocessor class CopyrightFooterPostprocessor < Asciidoctor::Extensions::Postprocessor def process document, output content = (document.attr 'copyright') || 'Copyright Acme, Inc.' if document.basebackend? 'html' replacement = %(<div id="footer-text">\\1<br>\n#{content}\n</div>) output = output.sub(/<div id="footer-text">(.*?)<\/div>/m, replacement) elsif document.basebackend? 'docbook' replacement = %(<simpara>#{content}</simpara>\n\\1) output = output.sub(/(<\/(?:article|book)>)/, replacement) end output end end Usage Asciidoctor::Extensions.register do postprocessor CopyrightFooterPostprocessor end Asciidoctor.convert_file 'sample-with-copyright-footer.adoc', :safe => :safe ### 83.4. Docinfo Processor Example Purpose Appends the Google Analytics tracking code to the bottom of an HTML document. GoogleAnalyticsDocinfoProcessor class GoogleAnalyticsDocinfoProcessor < Asciidoctor::Extensions::DocinfoProcessor use_dsl at_location :footer def process document return unless (ga_account_id = document.attr 'google-analytics-account') %(<script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); ga('create','#{ga_account_id}','auto'); ga('send','pageview'); </script>) end end Usage Asciidoctor::Extensions.register do docinfo_processor GoogleAnalyticsDocinfoProcessor end Asciidoctor.convert_file 'sample.adoc', :safe => :safe, :attributes => 'UA-ABCXYZ123' ### 83.5. Block Processor Example Purpose Register a custom block style named shout that uppercases all the words and converts periods to exclamation points. sample-with-shout-block.adoc [shout] The time is now. Get a move on. ShoutBlock require 'asciidoctor' require 'asciidoctor/extensions' class ShoutBlock < Asciidoctor::Extensions::BlockProcessor PeriodRx = /\.(?= |$)/

use_dsl

named :shout
on_context :paragraph
name_positional_attributes 'vol'
parse_content_as :simple

volume = ((attrs.delete 'vol') || 1).to_i
create_paragraph parent, (reader.lines.map {|l| l.upcase.gsub PeriodRx, '!' * volume }), attrs
end
end
Usage
Asciidoctor::Extensions.register do
block ShoutBlock
end

Asciidoctor.convert_file 'sample-with-shout-block.adoc', :safe => :safe

### 83.6. Block Macro Processor Example

Purpose

Create a block macro named gist for embedding a gist.

.My Gist
gist::123456[]
GistBlockMacro
require 'asciidoctor'
require 'asciidoctor/extensions'

class GistBlockMacro < Asciidoctor::Extensions::BlockMacroProcessor
use_dsl

named :gist

def process parent, target, attrs
title_html = (attrs.has_key? 'title') ?
%(<div class="title">#{attrs['title']}</div>\n) : nil

html = %(<div class="openblock gist">
#{title_html}<div class="content">
<script src="https://gist.github.com/#{target}.js"></script>
</div>
</div>)

create_pass_block parent, html, attrs, subs: nil
end
end
Usage
Asciidoctor::Extensions.register do
block_macro GistBlockMacro if document.basebackend? 'html'
end

Asciidoctor.convert_file 'sample-with-gist.adoc', :safe => :safe

### 83.7. Inline Macro Processor Example

Purpose

Create an inline macro named man that links to a man page.

See man:gittutorial[7] to get started.
ManpageInlineMacro
require 'asciidoctor'
require 'asciidoctor/extensions'

class ManInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
use_dsl

named :man
name_positional_attributes 'volnum'

def process parent, target, attrs
text = manname = target
suffix = ''
target = %(#{manname}.html)
suffix = if (volnum = attrs['volnum'])
"(#{volnum})"
else
nil
end
%(#{(create_anchor parent, text, type: :link, target: target).convert}#{suffix})
end
end
Usage
Asciidoctor::Extensions.register do
inline_macro ManInlineMacro
end

Asciidoctor.convert_file 'sample-with-man-link.adoc', :safe => :safe

### 83.8. Include Processor Example

Purpose

Include a file from a URI.

 Asciidoctor supports including content from a URI out of the box if you set the allow-uri-read attribute (not available if the safe mode is secure).
:source-highlighter: coderay

.Gemfile
[source,ruby]
----
include::https://raw.githubusercontent.com/asciidoctor/asciidoctor/master/Gemfile[]
----
UriIncludeProcessor
require 'asciidoctor'
require 'asciidoctor/extensions'
require 'open-uri'

class UriIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor
def handles? target
(target.start_with? 'http://') or (target.start_with? 'https://')
end

def process doc, reader, target, attributes
reader.push_include content, target, target, 1, attributes
end
end
Usage
Asciidoctor::Extensions.register do
include_processor UriIncludeProcessor
end

Asciidoctor.convert_file 'sample-with-uri-include.adoc', :safe => :safe

You can see plenty more extension examples in the extensions lab.

# Build Integrations and Implementations

## 84. Java

AsciidoctorJ is the official library for running Asciidoctor on the JVM. Using AsciidoctorJ, you can convert AsciiDoc content or analyze the structure of a parsed AsciiDoc document from Java and other JVM languages. For details see Getting Started with Asciidoctor in Java using AsciidoctorJ.

The Asciidoctor Gradle Plugin is the official means of using Asciidoctor to convert all your AsciiDoc documentation using Gradle. For details see Getting Started with the Asciidoctor Gradle Plugin.

## 86. Maven

The Asciidoctor Maven Plugin is the official way to convert your AsciiDoc documentation using Asciidoctor from an Apache Maven build. For details see Installing and Using the Asciidoctor Maven Plugin.

## 87. Apache Ant

The asciidoctor-ant task is an all-in-one solution for running Asciidoctor from Ant. It is based on AsciidoctorJ and JRuby, both of which are encapsulated in a single jar file.

Usage is:

<project xmlns:asciidoctor="antlib:org.asciidoctor.ant">
...
<target name="doc">
resource="org/asciidoctor/ant/antlib.xml"
classpath="lib/asciidoctor-ant.jar"/>
<asciidoctor:convert sourceDirectory="src/asciidoc" outputDirectory="target"/>
</target>
...
</project>

For more details, see asciidoctor-ant on GitHub.

Using the Asciidoctor doclet, you can write your Javadoc comments using all the features of Asciidoctor including tables, lists, code examples with syntax highlighting, and pictures.

If you want to incorporate your Javadoc into another document instead, there is an experimental doclet that exports them to AsciiDoc files. See the exportdoclet project and the related discussion thread for details.

## 89. JavaScript

Asciidoctor.js is a JavaScript port of Asciidoctor, transpiled directly from the Ruby version. Asciidoctor.js brings the AsciiDoc syntax to the browser and the Node.js ecosystem. For details see Installing and Using Asciidoctor.js.

# Conversions and Migrations

In this part, you’ll learn how to migrate documents written in other documentation languages to AsciiDoc. We’ll start with the simplest migration, switching from AsciiDoc Python, the original implementation of AsciiDoc, to Asciidoctor, the modern implementation. We’ll then cover how to move to AsciiDoc from other documentation languages like DocBook, Markdown and HTML. In addition to differences in the syntax, many of the sections also suggest tools you can use to ease the migration.

## 90. 从AsciiDoc Python迁移

The purpose of this section is to help you migrate legacy AsciiDoc documents written for AsciiDoc Python to the modern AsciiDoc syntax supported by Asciidoctor and to learn about equivalent tools and extensions.

The differences are minor, so most documents will need very few changes, if any. Once you’ve made the necessary changes, this section also describes how to take advantage of the new features provided in Asciidoctor.

 This section specifically covers migration from AsciiDoc Python 8 to Asciidoctor 1.5.x. The content assumes you’ve already updated any content that is deprecated as of AsciiDoc Python 8.

### 90.1. Command Line Interface

Asciidoctor was designed from the outset to be a (must faster) drop-in replacement for AsciiDoc Python. For most documents, you can simply replace the call to AsciiDoc Python:

$asciidoc document.adoc with an equivalent call to Asciidoctor: $ asciidoctor -a compat-mode document.adoc

If you run into trouble, check out the differences below, namely Deleted and Deprecated Syntax and Attributes.

 Keep in mind you can also run Asciidoctor on the JVM using AsciidoctorJ or with JavaScript using Asciidoctor.js.

#### 90.1.1. Help Topics

In both AsciiDoc Python and Asciidoctor, the --help CLI option shows the command usage by default. They differ in how they handle the optional topic argument.

In AsciiDoc Python, the --help syntax topic shows a syntax cheatsheet and the --help manpage topic shows a plaintext version of the man page.

Asciidoctor only supports the manpage help topic. However, it outputs the formatted man page rather than the plaintext version. Therefore, to view it, you need to pipe the result to the man command as follows:

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

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

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

You can also view the man page for Asciidoctor online at asciidoctor(1).

To get help with the AsciiDoc syntax in Asciidoctor, refer to the AsciiDoc Syntax Quick Reference.

#### 90.1.2. Configuration Files

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

#### 90.1.3. Internationalization

AsciiDoc Python has built-in .conf files that are used to translate built-in labels. You load the .conf file for a given language by setting the lang attribute to a supported language code (e.g., -a lang=<language code>). In Asciidoctor, you must define the translations for these labels explicitly. See Using Asciidoctor with Other Languages for details.

#### 90.1.4. Themes

AsciiDoc Python provides a theming mechanism that encapsulates CSS, JavaScript and images. The --theme option activates one of these themes, which is resolved from your home directory. In Asciidoctor, you control the theme using CSS (i.e., a stylesheet) only, which you can specify using -a stylesheet=<stylesheet>.

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

#### 90.1.5. Default HTML Backend

AsciiDoc Python uses XHTML 1.1 as its default output (the xhtml11 backend), though it supports HTML5 output as well (the html5 backend). Asciidoctor defaults to creating HTML5 output (the html5 backend), which closely adheres to the backend by the same name in AsciiDoc Python. The web has moved forward since AsciiDoc Python was created, so the switch to HTML5 is recommended anyway.

#### 90.1.6. Doctest

AsciiDoc Python --doctest runs units tests. See Tests for 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.

### 90.2. Changed Syntax

These changes are not backward-compatible, but if you set the compat-mode attribute, Asciidoctor will accept the AsciiDoc Python syntax. For the long term, you should update to the Asciidoctor syntax. Consult the Migration Guide to get the full details and learn how to migrate smoothly.

AsciiDoc syntax affected by compat mode
Feature AsciiDoc Python (or Asciidoctor in compat mode) Asciidoctor (no compat mode)

italic text

'italic text' or _italic text_

_italic text_

monospaced text

+monospaced text+

monospaced text

monospaced text (literal)

{asciidoc-version}

+{asciidoc-version}+

double quotes''

double quotes''
not available in compat mode

"double quotes" or insert the Unicode quote characters using your editor

single quotes'

single quotes'
not available in compat mode

'single quotes' or insert the Unicode quote characters using your editor

Document title [1]

Title or = Title
=====

= Title

[1] Asciidoctor accepts the two-line heading style to set the document title. However, by using it, you implicitly set compat-mode. If you want to use the new Asciidoctor syntax, make sure to use the single-line style for the document title or unset the compat-mode attribute explicitly.

The following changes are not affected by the compat-mode attribute:

AsciiDoc syntax not affected by compat mode
Feature AsciiDoc Python Asciidoctor

Underlined titles

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

Underline length must match title length +/- 1 character (Underlined titles are deprecated anyway. See Sections.)

ifeval::[]

Evaluates any Python expression.

Evaluates simple logical expressions testing the value of attributes. See ifeval directive.

Block delimiters

Delimiter lines do not have to match in length.

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

AsciiDoc table cell

a| or asciidoc|

a| only

Table cell separator

A Python regular expression.

One or more literal characters or \t for tab.

### 90.3. Deleted and Deprecated Syntax and Attributes

These are attributes that either no longer exist, work differently, or have better alternatives.

Deleted and deprecated syntax and attributes
AsciiDoc Python Asciidoctor Notes

big, small, underline, overline, line-through, colors

deprecated

Character attributes to apply formatting directly. Usually better to apply a role, then apply the formatting based on that role by using a stylesheet.

halign, valign for table cells

Column and cell specifiers

See Cell Formatting.

infile

not implemented

Provides the name and directory of the current document. (Distinct from docfile, because infile may be an included document, and docfile is always the master document.) No Asciidoctor equivalent.

indir

asciidoc

asciidoctor

AsciiDoc Python sets asciidoc to show that it is the current processor. Asciidoctor sets asciidoctor instead.

toc2

toc

toc-placement

toc-position

options="pgwide"

not implemented

DocBook attribute to make tables full page width, whatever the current indent. No Asciidoctor equivalent.

options="unbreakable"

In Asciidoctor, this only works for tables, not paragraphs.