Callouts

Callout numbers (aka callouts) provide a means to add annotations to lines in a verbatim block.

Callout syntax

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:

Example 1. Callout syntax
[source,ruby]
----
require 'sinatra' <1>

get '/hi' do <2> <3>
  "Hello World!"
end
----
<1> Library import
<2> URL mapping
<3> Response block

The result of Example 1 is rendered below.

require 'sinatra' (1)

get '/hi' do (2) (3)
  "Hello World!"
end
1 Library import
2 URL mapping
3 Response block

Since callout numbers can interfere with the syntax of the code they are annotating, an AsciiDoc processor provides several features to hide the callout numbers from both the source and the converted document. The sections that follow detail these features.

Automatic numbering

Just like ordered lists, it’s possible to allow the processor to automatically number the callouts. To leverage this capability, you replace the numbers in each callout with a dot (e.g., <.>). Each time the processor comes across a callout in either the verbatim block or the callout list, it selects the next number in the sequence (scoped to that block), starting from 1.

Let’s return to the previous example to see how it looks if we use automatic numbering.

Example 2. Callout syntax with automatic numbering
[,ruby]
----
require 'sinatra' <.>

get '/hi' do <.> <.>
  "Hello World!"
end
----
<.> Library import
<.> URL mapping
<.> Response block

The result is exactly the same as before.

Mixed numbering

The <.> callouts are automatically numbered based on their sequence among other <.>, not any callouts that have an explicit number. In other words, the automatic numbering is not aware of any explicit numbering. Therefore, you should generally avoid mixing them.

However, if you want to repeat a number in the verbatim block, then you can use an explicit number to create additional occurrences of that callout number.

Let’s consider an example:

Example 3. Callout syntax with mixed numbering
[,ruby]
----
require 'asciidoctor' <.>

puts Asciidoctor::VERSION <1>

Asciidoctor.convert_file 'README.adoc' <.>
----
<.> The require statement exports the class from the gem to the global scope.
<.> We can then call methods provided by that class.

The result of Example 3 is rendered below.

require 'asciidoctor' (1)

puts Asciidoctor::VERSION (1)

Asciidoctor.convert_file 'README.adoc' (2)
1 The require statement exports the class from the gem to the global scope.
2 We can then call methods provided by that class.

The risk of this approach is that you have to keep track of which numbers are being assigned automatically.

Copy and paste friendly callouts

If you add callout numbers to example code in a verbatim (e.g., source) block, and a reader selects that source code in the generated HTML, we don’t want the callout numbers to get caught up in the copied text. If the reader pastes that example code into a code editor and tries to run it, the extra characters that define the callout numbers will likely lead to compile or runtime errors. To mitigate this problem, and AsciiDoc processor uses a CSS rule to prevent the callouts from being selected. That way, the callout numbers won’t get copied.

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. When font-based icons are enabled (e.g., icons=font), the AsciiDoc processor will recognize the line comments characters in front of a callout number—​optionally offset by a space—​and remove them when converting the document. When font-based icons aren’t enabled, the line comment characters are not removed so that the callout numbers remain hidden by the line comment.

Here are the line comments that are supported:

Example 4. Prevent callout copy and paste
----
line of code // <1>
line of code # <2>
line of code ;; <3>
line of code <!--4-->
----
<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.
<4> A callout behind a line comment for XML or SGML languages like HTML.

The result of Example 4 is rendered below.

line of code (1)
line of code (2)
line of code (3)
line of code (4)
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.
4 A callout behind a line comment for XML or SGML languages like HTML.

Custom line comment prefix

An AsciiDoc processor recognizes the most ubiquitous line comment prefixes as a convenience. If the source language you’re embedding does not support one of these line comment prefixes, you can customize the prefix using the line-comment attribute on the block.

Let’s say we want to tuck a callout behind a line comment in Erlang code. In this case, we would set the line-comment character to %, as shown in this example:

Example 5. Custom line comment prefix
[source,erlang,line-comment=%]
----
-module(hello_world).
-compile(export_all).

hello() ->
    io:format("hello world~n"). % <1>
----
<1> A callout behind a custom line comment prefix.

The result of Example 5 is rendered below.

-module(hello_world).
-compile(export_all).

hello() ->
    io:format("hello world~n"). (1)
1 A callout behind a custom line comment prefix.

Even though it’s not specified in the attribute, one space is still permitted immediately following the line comment prefix.

Disable line comment processing

If the source language you’re embedding does not support trailing line comments, or the line comment prefix is being misinterpreted, you can disable this feature using the line-comment attribute.

Let’s say we want to put a callout at the end of a block delimiter for an open block in AsciiDoc. In this case, the processor will think the double hyphen is a line comment, when in fact it’s the block delimiter. We can disable line comment processing by setting the line-comment character to an empty value, as shown in this example:

Example 6. No line comment prefix
[source,asciidoc,line-comment=]
----
-- <1>
A paragraph in an open block.
--
----
<1> An open block delimiter.

The result of Example 6 is rendered below.

-- (1)
A paragraph in an open block.
--
1 An open block delimiter.

Since the language doesn’t support trailing line comments, there’s no way to hide the callout number in the raw source.

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 XML comment and callout number.

Here’s how it appears in a listing:

Example 7. XML callout syntax
[source,xml]
----
<section>
  <title>Section Title</title> <!--1-->
</section>
----
<1> The section title is required.

The result of Example 7 is rendered below.

<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.

Callout icons

The font icons setting also enables callout icons drawn using CSS.

= Document Title
:icons: font (1)

NOTE: Asciidoctor 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.