Updated "include" behaviour in Metanorma AsciiDoc

Author’s picture Nick Nicholas on 08 Dec 2020

Recent changes in "include" directive processing

Many Metanorma users assemble their documents out of smaller components, using the include:[] macro in the AsciiDoc format, as documented in the Asciidoctor User Manual.

If you have created file sections-en/00-foreword.adoc to contain the foreword, and sections-en/00-introduction.adoc to contain the introduction, then you can include them in a master document by typing:

include::sections-en/00-foreword.adoc[]

include::sections-en/00-introduction.adoc[]

The contents of the file replace the include macro that invokes it.

The AsciiDoc parser used in Metanorma, Asciidoctor, is very sensitive to blank lines: if a blank line is not used to separate blocks of various kinds from each other, bad things will happen.

For that reason, it has been conventional to add a blank line at the end of files that are included, so that in the fully “include”-resolved file there are blank lines between the includes.

Until recently, include macros with no blank lines between them have worked fine, as long as there are blank lines at the top or bottom of the included files: which has the effect of separating the includes in the fully resolved file.

So this:

include::sections-en/00-foreword.adoc[]
include::sections-en/00-introduction.adoc[]

used to work, as long as there were at least one blank trailing line in the `include`d files.

Issue with new parsing behavior (used with Asciidoctor 2.0.11+)

That expectation, however, has changed — all blank lines wrapping the included files are now stripped since Asciidoctor 2.0.11, released on 2020-11-03.

As the Asciidoctor User Manual puts it,

The best way to think of the include directive is to imagine that it is being replaced by the lines from the include file (i.e., the imported lines). Only then does the parser read and interpret those lines. That’s also why it’s important to surround the include directive by blank lines if it imports in a discrete structure. You only want to place include files directly adjacent to one another if the imported content should be directly adjacent.

The same example snippet above will now cause the latter include snippet to be considered content of the first, since wrapping blank lines are now culled from the fully resolved file, and there are no more blank lines separating the first included text from the second.

A practical example would be if the first include ended with a list item, and if the the second include starts a new section, that new section will be subsumed into the list item and can no longer start the expected section.

As a result, unpleasant consequences now emerge when include macros are’t separated by blank lines. (See discussion in asciidoctor#3878, asciidoctor#3875.)

Moving forward

If you don’t have blank lines between include macros in your document, and your included files are blocks of text (including clauses, which is the typical case), we encourage you to insert blank lines between them now.

i.e. Start doing this!

include::sections-en/00-foreword.adoc[]

include::sections-en/00-introduction.adoc[]