Chapter 36. Tips and Tricks

36.1. Know Your Editor

Writing AsciiDoc documents will be a whole lot more pleasant if you know your favorite text editor. Learn how to indent and reformat text blocks, paragraphs, lists and sentences. Tips for vim users follow.

36.2. Vim Commands for Formatting AsciiDoc

36.2.1. Text Wrap Paragraphs

Use the vim :gq command to reformat paragraphs. Setting the textwidth sets the right text wrap margin; for example:

:set textwidth=70

To reformat a paragraph:

  1. Position the cursor at the start of the paragraph.
  2. Type gq}.

Execute :help gq command to read about the vim gq command.

[Tip]
  • Assign the gq} command to the Q key with the nnoremap Q gq} command or put it in your ~/.vimrc file to so it’s always available (see the Example ~/.vimrc file).
  • Put set commands in your ~/.vimrc file so you don’t have to enter them manually.
  • The Vim website (https://www.vim.org/) has a wealth of resources, including scripts for automated spell checking and ASCII Art drawing.

36.2.2. Format Lists

The gq command can also be used to format bulleted, numbered and callout lists. First you need to set the comments, formatoptions and formatlistpat (see the Example ~/.vimrc file).

Now you can format simple lists that use dash, asterisk, period and plus bullets along with numbered ordered lists:

  1. Position the cursor at the start of the list.
  2. Type gq}.

36.2.3. Indent Paragraphs

Indent whole paragraphs by indenting the fist line with the desired indent and then executing the gq} command.

36.2.4. Example ~/.vimrc File

" Use bold bright fonts.
set background=dark

" Show tabs and trailing characters.
"set listchars=tab:»·,trail:·,eol:¬
set listchars=tab:»·,trail:·
set list

" Reformat paragraphs and list.
nnoremap <Leader>r gq}

" Delete trailing white space and Dos-returns and to expand tabs to spaces.
nnoremap <Leader>t :set et<CR>:retab!<CR>:%s/[\r \t]\+$//<CR>

autocmd BufRead,BufNewFile *.txt,*.asciidoc,README,TODO,CHANGELOG,NOTES,ABOUT
        \ setlocal autoindent expandtab tabstop=8 softtabstop=2 shiftwidth=2 filetype=asciidoc
        \ textwidth=70 wrap formatoptions=tcqn
        \ formatlistpat=^\\s*\\d\\+\\.\\s\\+\\\\|^\\s*<\\d\\+>\\s\\+\\\\|^\\s*[a-zA-Z.]\\.\\s\\+\\\\|^\\s*[ivxIVX]\\+\\.\\s\\+
        \ comments=s1:/*,ex:*/,://,b:#,:%,:XCOMM,fb:-,fb:*,fb:+,fb:.,fb:>

36.3. Troubleshooting

AsciiDoc diagnostic features are detailed in the Diagnostics appendix.

36.4. Gotchas

Incorrect character encoding
If you get an error message like 'UTF-8' codec can't decode ... then you source file contains invalid UTF-8 characters — set the AsciiDoc encoding attribute for the correct character set (typically ISO-8859-1 (Latin-1) for European languages).
Invalid output

AsciiDoc attempts to validate the input AsciiDoc source but makes no attempt to validate the output markup, it leaves that to external tools such as xmllint(1) (integrated into a2x(1)). Backend validation cannot be hardcoded into AsciiDoc because backends are dynamically configured. The following example generates valid HTML but invalid DocBook (the DocBook literal element cannot contain an emphasis element):

+monospaced text with an _emphasized_ word+
Misinterpreted text formatting

You can suppress markup expansion by placing a backslash character immediately in front of the element. The following example suppresses inline monospaced formatting:

\+1 for C++.
Overlapping text formatting

Overlapping text formatting will generate illegal overlapping markup tags which will result in downstream XML parsing errors. Here’s an example:

Some *strong markup _that overlaps* emphasized markup_.
Ambiguous underlines
A DelimitedBlock can immediately follow a paragraph without an intervening blank line, but be careful, a single line paragraph underline may be misinterpreted as a section title underline resulting in a “closing block delimiter expected” error.
Ambiguous ordered list items

Lines beginning with numbers at the end of sentences will be interpreted as ordered list items. The following example (incorrectly) begins a new list with item number 1999:

He was last sighted in
1999. Since then things have moved on.

The list item out of sequence warning makes it unlikely that this problem will go unnoticed.

Special characters in attribute values

Special character substitution precedes attribute substitution so if attribute values contain special characters you may, depending on the substitution context, need to escape the special characters yourself. For example:

$ asciidoc -a 'orgname=Bill &amp; Ben Inc.' mydoc.txt
Attribute lists

If any named attribute entries are present then all string attribute values must be quoted. For example:

["Desktop screenshot",width=32]

36.5. Combining separate documents

You have a number of stand-alone AsciiDoc documents that you want to process as a single document. Simply processing them with a series of include macros won’t work because the documents contain (level 0) document titles. The solution is to create a top level wrapper document and use the leveloffset attribute to push them all down one level. For example:

Combined Document Title
=======================

// Push titles down one level.
:leveloffset: 1

include::document1.txt[]

// Return to normal title levels.
:leveloffset: 0

A Top Level Section
-------------------
Lorum ipsum.

// Push titles down one level.
:leveloffset: 1

include::document2.txt[]

include::document3.txt[]

The document titles in the included documents will now be processed as level 1 section titles, level 1 sections as level 2 sections and so on.

  • Put a blank line between the include macro lines to ensure the title of the included document is not seen as part of the last paragraph of the previous document.
  • You won’t want non-title document header lines (for example, Author and Revision lines) in the included files — conditionally exclude them if they are necessary for stand-alone processing.

36.6. Processing document sections separately

You have divided your AsciiDoc document into separate files (one per top level section) which are combined and processed with the following top level document:

Combined Document Title
=======================
Joe Bloggs
v1.0, 12-Aug-03

include::section1.txt[]

include::section2.txt[]

include::section3.txt[]

You also want to process the section files as separate documents. This is easy because asciidoc(1) will quite happily process section1.txt, section2.txt and section3.txt separately — the resulting output documents contain the section but have no document title.

36.7. Processing document snippets

Use the -s (--no-header-footer) command-line option to suppress header and footer output, this is useful if the processed output is to be included in another file. For example:

$ asciidoc -sb docbook section1.txt

asciidoc(1) can be used as a filter, so you can pipe chunks of text through it. For example:

$ echo 'Hello *World!*' | asciidoc -s -
<div class="paragraph"><p>Hello <strong>World!</strong></p></div>

36.8. Badges in HTML page footers

See the [footer] section in the AsciiDoc distribution xhtml11.conf configuration file.

36.9. Pretty printing AsciiDoc output

If the indentation and layout of the asciidoc(1) output is not to your liking you can:

  1. Change the indentation and layout of configuration file markup template sections. The {empty} attribute is useful for outputting trailing blank lines in markup templates.
  2. Use HTML Tidy program to tidy asciidoc(1) output. Example:

    $ asciidoc -b docbook -o - mydoc.txt | tidy -indent -xml >mydoc.xml
  3. Use the xmllint(1) format option. Example:

    $ xmllint --format mydoc.xml

36.10. Supporting minor DocBook DTD variations

The conditional inclusion of DocBook SGML markup at the end of the distribution docbook45.conf file illustrates how to support minor DTD variations. The included sections override corresponding entries from preceding sections.

36.11. Creating stand-alone HTML documents

If you’ve ever tried to send someone an HTML document that includes stylesheets and images you’ll know that it’s not as straight-forward as exchanging a single file. AsciiDoc has options to create stand-alone documents containing embedded images, stylesheets and scripts. The following AsciiDoc command creates a single file containing embedded images, CSS stylesheets, and JavaScript (for table of contents and footnotes):

$ asciidoc -a data-uri -a icons -a toc -a max-width=55em article.txt

You can view the HTML file here: https://asciidoc.org/article-standalone.html

36.12. Shipping stand-alone AsciiDoc source

Reproducing presentation documents from someone else’s source has one major problem: unless your configuration files are the same as the creator’s you won’t get the same output.

The solution is to create a single backend specific configuration file using the asciidoc(1) -c (--dump-conf) command-line option. You then ship this file along with the AsciiDoc source document plus the asciidoc.py script. The only end user requirement is that they have Python installed (and that they consider you a trusted source). This example creates a composite HTML configuration file for mydoc.txt:

$ asciidoc -cb xhtml11 mydoc.txt > mydoc-xhtml11.conf

Ship mydoc.txt, mydoc-html.conf, and asciidoc.py. With these three files (and a Python interpreter) the recipient can regenerate the HMTL output:

$ ./asciidoc.py -eb xhtml11 mydoc.txt

The -e (--no-conf) option excludes the use of implicit configuration files, ensuring that only entries from the mydoc-html.conf configuration are used.

36.13. Inserting blank space

Adjust your style sheets to add the correct separation between block elements. Inserting blank paragraphs containing a single non-breaking space character {nbsp} works but is an ad hoc solution compared to using style sheets.

36.14. Closing open sections

You can close off section tags up to level N by calling the eval::[Section.setlevel(N)] system macro. This is useful if you want to include a section composed of raw markup. The following example includes a DocBook glossary division at the top section level (level 0):

ifdef::basebackend-docbook[]

eval::[Section.setlevel(0)]

+++++++++++++++++++++++++++++++
<glossary>
  <title>Glossary</title>
  <glossdiv>
  ...
  </glossdiv>
</glossary>
+++++++++++++++++++++++++++++++
endif::basebackend-docbook[]

36.15. Validating output files

Use xmllint(1) to check the AsciiDoc generated markup is both well formed and valid. Here are some examples:

$ xmllint --nonet --noout --valid docbook-file.xml
$ xmllint --nonet --noout --valid xhtml11-file.html
$ xmllint --nonet --noout --valid --html html4-file.html

The --valid option checks the file is valid against the document type’s DTD, if the DTD is not installed in your system’s catalog then it will be fetched from its Internet location. If you omit the --valid option the document will only be checked that it is well formed.

The online W3C Markup Validation Service is the defacto standard when it comes to validating HTML (it validates all HTML standards including HTML5).