Using AsciiDoc attributes it’s possible to have conditional content, which will appear under some conditions but be absent in others.
We’ll use the following AsciiDoc conditionals:
These conditionals are applied by the AsciiDoc preprocessor.
🚀 TL;DR
Show me the code. Look at the 13-asciidoc-conditional-content
branch. This site is deployed here.
Iterating & Preprocessing Versions
The frontmatter of the AsciiDoc documents looks something like this:
= What is Gatsby?
Some Fictional Dude <some-fictional-dude@gmail.com>
v2.0, 29 October 2023: Rewritten for version 2
:description: An explanation of Gatsby.
:page-version: 0.1, 0.2, 0.3, 1.0, 1.1, 1.2
:page-order: 10
:page-permalink: d2b6d682
The page-version
attribute specifies the versions of the documentation in which a particular page is present. For example, the page with title “What is Gatsby?” will appear in versions 0.1, 0.2, 0.3, 1.0, 1.1 and 1.2 of the documentation.
In previous versions of the site we implicitly converted the AsciiDoc source into HTML. However, now that we want to use the preprocessor directives we need to be more intentional.
We’re going to use the conditional directives to create customised content which depends on the documentation version. In order to do this we will need to process each page separately for each version of the documentation. In gatsby-node.js
we’ll iterate over each of the nodes in allAsciidoc.nodes
, and for each node extract the relevant versions from the page-version
attribute.
The extractVersions()
function, implemented in src/utils/versions.js
, returns an array of versions for a specific node. For each version the preprocessAsciidoc()
function, implemented in src/utils/asciidoc.js
, then
- accepts the raw AsciiDoc content (set up in the previous post) and a version number;
- dynamically inserts a
version
attribute into the frontmatter, and assigns to it the specific version number; and - converts the raw AsciiDoc content into HTML, evaluating the preprocessor directives.
Some examples of how those directive might be used:
ifdef::version[]
The `version` attribute is defined.
endif::[]
ifndef::title[]
The `title` attribute is **not** defined.
endif::[]
ifeval::[{version} == 0.1]
This is the first version of the documentation.
endif::[]
Rendered Conditional Content
The rendered HTML is then inserted into the page template defined in src/templates/article.js
.
Below is an image showing the “What is Gatsby?” page for version 0.1 (the first version) of the documentation. In the first paragraph on the page the version
attribute is used to dynamically insert the version number. There is an ifdef
conditional which causes this paragraph to only be rendered if the version
attribute is defined. The second paragraph states that this is the first version of the documentation . An ifeval
conditional is used to ensure that this paragraph is only rendered if the value of version
is 0.1. Finally, an ifndef
directive is used to only render the third paragraph if the title
attribute is not defined.
The next image shows the “What is Gatsby?” page for version 1.2 (the latest version) of the documentation. Most of the content is the same except for the second paragraph. The content of this paragraph has changed because the ifdef
conditional which was true previously no longer applies. A second ifdef
conditional now checks if the value version
is 1.2.
Conclusion
Inserting conditional content into a site via the ifdef
, ifndef
and ifeval
preprocessor directives can provide a lot of flexibility. They make it possible to only maintain a single file for a page and create different versions of the rendered content depending on whether or not various attributes are defined and what values they contain.
There is a little work required to get the site set up to leverage the preprocessor directives, but it is time and energy well spent.
🚀 TL;DR
Show me the code. Look at the 13-asciidoc-conditional-content
branch. This site is deployed here.