Customize the Substitutions Applied to Blocks

Each block context is associated with a set default substitutions that best suit the content model. However, there are situations where you may need a different set of substitutions to be applied. For example, you may want the AsciiDoc processor to substitute attribute references in a listing block. Therefore, the AsciiDoc language provides a mechanism for altering the substitutions on a block.

The subs attribute

The substitutions that get applied to a block (and to certain inline elements) can be changed or modified using the subs element attribute. This attribute accepts a comma-separated list of substitution steps or groups.

The names of those substitution steps and groups are as follows:

none

Substitution group that disables all substitutions.

normal

Substitution group that performs all substitution types except callouts.

verbatim

Substitution group that replaces special characters and processes callouts.

specialchars

Substitution step that replaces <, >, and & with their corresponding entities. For source blocks, this substitution step enables syntax highlighting as well.

callouts

Substitution step that processes callouts in literal, listing, and source blocks.

quotes

Substitution step that applies inline text formatting.

attributes

Substitution step that replaces attribute references.

replacements

Substitution step that replaces hexadecimal Unicode code points and entity, HTML, and XML character references with the characters' decimal Unicode code point. The output of replacements may depend on whether the specialcharacters substitution was previously applied.

macros

Substitution step that processes inline and block macros.

post_replacements

Substitution step that processes the line break character (+).

If a + or - modifier is added to a step, the existing substitutions are modified accordingly (see incremental subs). Otherwise, the existing substitutions are replaced. The value also specifies the order in which the substitutions are applied.

The subs element attribute does not inherit to nested blocks. It can only be applied to a leaf block, which is any block that cannot have child blocks (e.g., a paragraph or a listing block).

Set the subs attribute on a block

You should always prefer to use incremental substitutions, and only revert to exact substitutions when you require the additional control.

Let’s look at an example where you want to process inline formatting markup in a source block. By default, source blocks (as well as other verbatim blocks) are only subject to the verbatim substitution group (specialchars and callouts). You can change this behavior by setting the subs attribute in the block’s attribute list.

[source,java,subs="verbatim,quotes"] (1)
----
System.out.println("Hello *<name>*") (2)
----
1 The subs attribute is set in the attribute list and assigned the verbatim and quotes values. It’s important to reinstate the verbatim substitution step to ensure special characters are encoded (which, for source blocks, also enables syntax highlighting).
2 The formatting markup in this line will be replaced when the quotes substitution step runs.

Here’s the result.

System.out.println("Hello <name>") (1) (2)
1 The verbatim value enables any special characters and callouts to be processed.
2 The quotes value enables the bold text formatting to be processed.

If enabling the quotes substitution step on the whole block causes problems, you can instead enable the macros substitution step, then use the pass macro to enable the quotes substitution step locally.

[source,java,subs="verbatim,macros"]
----
System.out.println("No bold *here*");
pass:c,q[System.out.println("Hello *<name>*");] (1)
----
1 The pass macro with the c,q target applies the specialchars and quotes substitution steps to the enclosed text.

You may be wondering why verbatim is specified in the previous examples since it’s applied to literal blocks by default. The reason is that when you specify substitutions without a modifier, it replaces all existing substitutions. Therefore, it’s necessary to start with verbatim in order to restore the default substitutions. You can avoid having to do this by using incremental substitutions instead, which is covered in the next section.

Add and remove substitution types from a default substitution group

When you set the subs attribute on a block, you automatically remove all of its default substitutions. For example, if you set subs on a literal block, and assign it a value of attributes, only attribute references are substituted. The verbatim substitution group will not be applied. To remedy this situation, AsciiDoc provides a syntax to append or remove substitutions instead of replacing them outright.

You can add or remove a substitution type from the default substitution group using the plus (+) and minus (-) modifiers. These are known as incremental substitutions.

<substitution>+

Prepends the substitution to the default list.

+<substitution>

Appends the substitution to the default list.

-<substitution>

Removes the substitution from the default list.

For example, you can add the attributes substitution to the beginning of a listing block’s default substitution group by placing the plus (+) modifier at the end of the attributes value.

Example 1. Add attributes substitution to default substitution group
[source,xml,subs="attributes+"]
----
<version>{version}</version>
----

Similarly, you can remove the callouts substitution from a block’s default substitution group by placing the minus (-) modifier in front of the callouts value.

Example 2. Remove callouts substitution from default substitution group
[source,xml,subs="-callouts"]
.An illegal XML tag
----
<1>
  content inside "1" tag
</1>
----

You can also specify whether the substitution type is added to the end of the substitution group. If a + comes before the name of the substitution, then it’s added to the end of the existing list, whereas if a + comes after the name, it’s added to the beginning of the list.

[source,xml,subs="attributes+,+replacements,-callouts"]
----
<version>{version}</version>
<copyright>(C) ACME</copyright>
<1>
  content inside "1" tag
</1>
----

In the above example, the attributes substitution step is added to the beginning of the default substitution group, the replacements step is added to the end of the group, and the callouts step is removed from the group.

If you are applying the same set of substitutions to numerous blocks, you should consider making them an attribute entry to ensure consistency.

:markup-in-source: verbatim,quotes

[source,java,subs="{markup-in-source}"]
----
System.out.println("Hello *bold* text").
----

Another way to ensure consistency and keep your documents clean and simple is to use the tree Processor extension.