= Jekyll AsciiDoc Plugin (powered by Asciidoctor)
Dan Allen https://github.com/mojavelinux[@mojavelinux]; Paul Rayner https://github.com/paulrayner[@paulrayner]
v3.0.1, 2023-11-06
// Settings:
:idprefix:
:idseparator: -
ifndef::env-github[:icons: font]
ifdef::env-github,env-browser[]
:toc: macro
:toclevels: 1
endif::[]
ifdef::env-github[]
:branch: main
:status:
:outfilesuffix: .adoc
:!toc-title:
:caution-caption: :fire:
:important-caption: :exclamation:
:note-caption: :paperclip:
:tip-caption: :bulb:
:warning-caption: :warning:
endif::[]
// Aliases:
:path-config: pass:q[[.path]_config.yml]
:conum-guard: {sp}
ifndef::icons[:conum-guard: {sp}#{sp}]
// URIs:
:url-repo: https://github.com/asciidoctor/jekyll-asciidoc
:url-issues: {url-repo}/issues
:url-search-issues: {url-repo}/search?type=Issues
:url-chat: https://chat.asciidoctor.org
:url-gem: https://rubygems.org/gems/jekyll-asciidoc
:url-gem-asciidoctor: https://rubygems.org/gems/asciidoctor
:url-asciidoc: https://asciidoc.org
:url-asciidoctor: https://asciidoctor.org
:url-asciidoctor-backends: https://github.com/asciidoctor/asciidoctor-backends
:url-asciidoctor-docs: {url-asciidoctor}/docs
:url-asciidoctor-diagram: {url-asciidoctor-docs}/asciidoctor-diagram
:url-asciidoctor-manual: {url-asciidoctor-docs}/user-manual
:url-asciidoc-practices: {url-asciidoctor-docs}/asciidoc-recommended-practices
:url-jaq: https://github.com/asciidoctor/jekyll-asciidoc-quickstart
:url-jekyll: https://jekyllrb.com
:url-jekyll-docs: {url-jekyll}/docs
:url-jekyll-discuss: https://talk.jekyllrb.com
:url-front-matter: {url-jekyll-docs}/frontmatter
:url-liquid-templates: {url-jekyll-docs}/templates
:url-variables: {url-jekyll-docs}/variables
:url-graphviz: https://www.graphviz.org
:url-tilt: https://github.com/rtomayko/tilt
:url-yaml: https://en.wikipedia.org/wiki/YAML
:url-guide-publish-gem: https://guides.rubygems.org/publishing/#publishing-to-rubygemsorg
ifdef::status[]
image:https://img.shields.io/gem/v/jekyll-asciidoc.svg[Latest Release, link={url-gem}]
image:https://img.shields.io/badge/license-MIT-blue.svg[MIT License, link=#copyright-and-license]
image:{url-repo}/actions/workflows/ci.yml/badge.svg?branch={branch}[Build Status (GitHub Actions),link={url-repo}/actions/workflows/ci.yml?query=branch%3A{branch}]
image:https://img.shields.io/badge/zulip-join_chat-brightgreen.svg[Project Chat (Zulip),link={url-chat}]
endif::[]
A plugin for {url-jekyll}[Jekyll] (>= 3.0.0) that converts {url-asciidoc}[AsciiDoc] source files in your site to HTML pages using {url-asciidoctor}[Asciidoctor].
ifeval::['{branch}' == 'main']
NOTE: You're viewing the documentation for the upcoming release.
If you're looking for the documentation for an older release, please refer to one of the following branches: +
{url-repo}/tree/v3.0.x#readme[3.0.x]
⁃
{url-repo}/tree/v2.1.x#readme[2.1.x]
⁃
{url-repo}/tree/v2.0.x#readme[2.0.x]
⁃
{url-repo}/tree/v1.1.x#readme[1.1.x]
⁃
{url-repo}/tree/v1.0.x#readme[1.0.x]
endif::[]
toc::[]
== Overview
The plugin consists of three extensions:
Converter -- Jekyll::AsciiDoc::Converter
::
Converts AsciiDoc files to HTML pages.
This plugin currently uses Asciidoctor to convert AsciiDoc content.
Generator -- Jekyll::AsciiDoc::Integrator
::
Promotes eligible AsciiDoc attributes (e.g., doctitle, id, author, and attributes that begin with the page attribute prefix) to page variables.
These attributes are merged with the page variables defined in the front matter header.
Liquid Filters::
asciidocify
-- Uses the converter from this plugin to convert a string of AsciiDoc content to HTML.
tocify_asciidoc
-- Generates a table of contents in HTML from the parsed AsciiDoc document of the current page (since 2.1.0).
These extensions are registered automatically when the [.app]jekyll-asciidoc gem is required.
== Prerequisites
To use this plugin, you must be using Jekyll >= 3.0.0 and Ruby >= 2.7.0 (with development headers installed).
You should also be familiar with creating sites with Jekyll.
If you're not, you should first read the {url-jekyll-docs}[Jekyll documentation] to familiarize yourself with how it works.
Experience with AsciiDoc and Asciidoctor is also helpful, but not a requirement.
Like Jekyll, this plugin was designed for developers, so some assembly is required.
That means you'll be expected to edit configuration, modify HTML templates, and customize CSS to use it fully.
== Installation
This plugin is packaged as a gem named [.app]{url-gem}[jekyll-asciidoc] and published to RubyGems.org.
The plugin depends on the [.app]{url-gem-asciidoctor}[asciidoctor] gem, which gets installed automatically.
Your method of installation will depend on whether you use Bundler to manage the dependencies for your Jekyll project.
IMPORTANT: Jekyll relies on several native gems, so it's necessary to have the Ruby development headers (e.g., ruby.h) on your machine in order to install AsciiDoc Jekyll (due to the requirements of Jekyll).
The instructions for how to install the Ruby development headers are platform-specific and outside of the scope of this document.
TIP: If you're using RVM, you should add a [.path].ruby-version file to the project so your shell automatically switches to the correct version of Ruby each time you enter the project.
For more information, refer to the the page https://rvm.io/workflow/projects[RVM Project Workflow].
=== Installation Using Bundler
If you're using Bundler to manage the dependencies for your project (as recommended), simply add the [.app]jekyll-asciidoc gem to the :jekyll_plugins
group in your [.path]Gemfile:
[source,ruby]
group :jekyll_plugins do
gem 'jekyll-asciidoc'
end
Then, run the bundle
command from Bundler to install the gem:
$ bundle
Jekyll will automatically activate any plugins listed in the :jekyll_plugins
group.
If you want to keep the installed gems inside the project, use this command instead:
$ bundle config set --local path .bundle/gems
bundle
TIP: Subsequent calls to bundle
will retain the path
setting.
Keep in mind that the gems Bundler installs are linked to the current version of Ruby.
If you switch Ruby versions, you'll need to run bundle
again.
=== Manual Installation
If you're not using Bundler to manage the dependencies for your Jekyll project, you'll need to install the gem manually:
$ [sudo] gem install jekyll-asciidoc
NOTE: The sudo
prefix is only required if you are installing gems into your system.
To avoid this bad practice, we recommend using RVM (or another Ruby version manager), which sets up Ruby safely in your home directory.
Then add the [.app]jekyll-asciidoc gem to the list of gems for Jekyll to load in your site's _config.yml
file:
[source,yaml]
plugins:
If you're running Jekyll < 3.5.0, you'll need to use gems
in place of plugins
:
[source,yaml]
gems:
=== Plugin Ordering
Since the [.app]jekyll-asciidoc plugin promotes <<page-attributes,page attributes>> to the front matter, it must run first.
To make sure it does, rearrange the sequence of plugins in your Gemfile or _config.yml
file so the [.app]jekyll-asciidoc plugin is listed before other plugins.
By doing so, other plugins will be able to access any front matter that this plugin assigns.
Let's consider the case of using the [.app]jekyll-archives plugin alongside the [.app]jekyll-asciidoc plugin.
[source,ruby]
group :jekyll_plugins do
gem 'jekyll-asciidoc'
gem 'jekyll-archives' <1>
end
<1> The [.app]*jekyll-archives* plugin should be listed after the [.app]*jekyll-asciidoc* plugin since it needs to access front matter that is promoted from the header of the AsciiDoc document.
== Creating Pages
This plugin converts eligible AsciiDoc files located inside the source directory (by default, the project root) to HTML pages in the generated site.
There are a few conditions that must be met in order for an AsciiDoc file to be eligible:
. The file must have an AsciiDoc file extension (see <
>).
. The name of the file must not begin with a dot (`.`) or an underscore (`_`).footnote:excluded_files[Hidden files and folders are automatically excluded by Jekyll.]
. The file must not be located in a folder whose name begins with a dot (`.`) or an underscore (`_`) (unless the folder is a designated collection, such as _posts).footnote:excluded_files[]
. While you can use a Jekyll front matter header, it is not required.
Here's a sample AsciiDoc file that meets these criteria:
.sample.adoc
[source,asciidoc]
----
---
layout: info
permalink: /sample/
---
= Sample Page
:url-asciidoctor: https://asciidoctor.org
This is a sample page composed in AsciiDoc.
Jekyll converts it to HTML using {url-asciidoctor}[Asciidoctor].
[source,ruby]
puts "Hello, World!"
----
Alternatively, you can define the page variables directly in the AsciiDoc header, which we recommend:
.sample.adoc
[source,asciidoc]
----
= Sample Page
:page-layout: info
:page-permalink: /sample/
:url-asciidoctor: https://asciidoctor.org
This is a sample page composed in AsciiDoc.
Jekyll converts it to HTML using {url-asciidoctor}[Asciidoctor].
[source,ruby]
puts "Hello, World!"
----
=== Page Attributes
Any AsciiDoc attribute defined in the AsciiDoc document header whose name begins with ``page-``footnote:[The prefix used to label page attributes can be customized.] gets promoted to a {url-variables}[page variables].
The part of the name after the `page-` prefix is _lowercased_ and used as the variable name (e.g., page-layout becomes layout).
The value is processed as {url-yaml}[YAML] data (single-line form).
Since the attribute value is processed as YAML data, you can build nested data structure using the inline YAML syntax.
For example, here's how you can assign a value to the `page.header.image` page variable:
[source,asciidoc]
----
:page-header: { image: logo.png }
----
To define a page attribute that contains multiple words, use either a hyphen or underscore character to connect the words.
[source,asciidoc]
----
:page-short-name: slug
----
IMPORTANT: Page attributes must be defined in the document header.
That means either putting them directly below the document title (the line beginning with a single equals sign in the sample above) or above all other AsciiDoc content if the document title is not defined in AsciiDoc.
The AsciiDoc document header stops after the first blank line.
For more details about the document header, see the https://asciidoctor.org/docs/user-manual/#doc-header[Document Header] chapter in the Asciidoctor User Manual.
IMPORTANT: You may use include directives in the the document header.
However, you must ensure that the file included _does not_ contain blank lines.
CAUTION: If an attribute defined in the header of an AsciiDoc document is not visible to another plugin or Liquid template, you may have a plugin ordering problem.
See <> to learn how to fix it.
=== Specifying a Layout
The most commonly defined page variable is layout, which determines which template is used to wrap the generated content.
Jekyll will look for a template file inside the [.path]_{empty}_layouts_ folder whose root name matches the name of the layout.
For example, if the layout variable has the value `info`, Jekyll looks for a layout template at the path [.path]__layout/info.html_.
If the layout is empty, the auto-selected layout layout is used (documented in the list below).
If the layout is unset or `false`, the AsciiDoc processor will generate a standalone document.
In this case, the page will appear like an HTML file generated by the AsciiDoc processor directly (with the option `header_footer: true`).
If the layout is ~, no layout is applied.
To review, here are the different ways to specify a layout using the AsciiDoc attribute page-layout:
* `:page-layout: info` -- use the layout named `info` (e.g., [.path]__layout/info.html_)
* _not specified_, `:page-layout:` or `:page-layout: _auto` -- use the automatic layout (i.e., `page` for pages, `post` for posts, the singular form of the collection label for a document; if the auto-selected layout isn't available, the layout `default` is used)
* `:!page-layout:` or `:page-layout: false` -- don't use a layout; instead, generate a standalone HTML document
* `:page-layout: none` or `:page-layout: ~` -- don't use a layout or create a standalone HTML document (often produces an HTML fragment); use of the value `~` is discouraged; the value `none` is preferred
=== Disabling Publishing of a Page
To prevent a page from being published, set the page attribute named `page-published` to `false` (which, in turn, sets the page variable named `published` to `false`.
[source,asciidoc]
----
= Top Secret Info
:page-published: false
This page should not be published.
----
=== Implicit Page Variables
In addition to page attributes defined explicitly (e.g., layout, permalink, etc), the following implicit AsciiDoc attributes are also promoted to page variables:
* doctitle (aka the document title) (becomes `title`)
* id (becomes `docid`)
* author
* revdate (becomes `date`; value is converted to a DateTime object; not applied to pages)
Although not an implicit page variable, another very common page variable to set is `page-description`, which becomes `description` in the model.
==== Showing the Document Title
By default, when Asciidoctor converts your document, it does not include the document title in the body (aka `content`) part of the document that is passed to the layout.
Instead, it skims off the document title and assigns it to the model as `page.title`.
If you don't see the document title on the generated page at first, that's normal.
There are two ways to have the document title included in the page:
. Configure the layout to output the document title explicitly
. Configure Asciidoctor to include the document title in the body
The first option is the most typical.
Somewhere in your layout, you should include the following statement:
----
{{ page.title }}
----
This approach gives you the most control over how the document title appears and what HTML is used to enclose it.
If, instead, you want the document title to be included in the body, add the following configuration to your site's `_config.yml` file:
[source,yaml]
----
asciidoctor:
attributes:
showtitle: '@'
----
It's also possible to enable or override this setting per page.
[source,asciidoc]
----
= Page Title
:showtitle:
----
Using either of these approaches, the document title will be shown on the generated page.
==== Giving Your Post the Time of Day
By default, all posts are assigned a date that is computed from the file name (e.g., the date for 2016-03-20-welcome.adoc is 2016-03-20).
If you want to give your post a specific time as well, you can set the `revdate` attribute in the AsciiDoc header.
We recommend using the format `YYYY-MM-DD HH:MM:SS Z` as shown in this example:
[source,asciidoc]
----
= Post Title
Author Name
:revdate: 2016-03-20 10:30:00 -0600
Lorem ipsum.
----
If you don't provide a time zone in the date, the date is assumed to be in the same time zone as the site (which is your local time zone by default).
Alternatively, you can specify the date in the implicit revision line.
In this case, you must substitute the colons in the time part with "h", "m", and "s", respectively, since the colon demarcates the revision remark.
[source,asciidoc]
----
= Post Title
Author Name
2016-03-20 10h30m00s -0600
Lorem ipsum.
----
Note that the revision line must be preceded by the implicit author line.
==== Classifying Your Post
In Jekyll, you classify a post by assigning it to categories and/or tags.
While you can define them in the front matter, as normal, it's also possible to omit the front matter and assign them in the AsciiDoc header instead.
The AsciiDoc attributes to use to assign categories and tags to your post are `page-categories` and `page-tags`, respectively.
The attribute value must be expressed using the inline Array syntax for YAML, which is a comma-separated list of items surrounded by square brackets.
If you only have one item, you can omit the brackets.
In this case, you can also drop the plural from the attribute name.
[source,asciidoc]
----
= Introducing the Jekyll AsciiDoc Plugin
Author Name
:page-category: Tech
:page-tags: [ruby, jekyll, asciidoctor, ssg]
The Jekyll AsciiDoc plugin makes Jekyll awesome.
Why?
Because you can write posts like this one in AsciiDoc!
----
Recall that the value of page attributes is parsed as an inline YAML value.
==== Publishing a Draft Post
You can defer adding a date to a post until it's ready to publish by making it a draft.
To make a draft post, just place it in the [.path]_{empty}_drafts_ folder instead of the [.path]_{empty}_posts_ folder.
But don't include the date in the filename or AsciiDoc header.
To include the drafts when building the site, pass the `--drafts` flag to the `jekyll` command:
$ jekyll build --drafts
The date of each draft post will be based on the file's last modification time.
When you're ready to publish the post, move the file from the [.path]_{empty}_drafts_ folder to the [.path]_{empty}_posts_ folder and add a date prefix to the filename in the form `YYYY-mm-dd-` (e.g., `2021-06-26-`).
You can further refine this date, such as to specify the time and time zone, by defining the `revdate` attribute in the AsciiDoc header.
=== Enabling Liquid Preprocessing
Unlike other content files, the {url-liquid-templates}[Liquid template preprocessor] is not applied to AsciiDoc files by default (since version 2.0.0 of this plugin).
If you want the Liquid template preprocessor to be applied to an AsciiDoc file (prior to the content being passed to the AsciiDoc processor), you must enable it by setting the `liquid` page variable (shown here defined using a page attribute).
[source,asciidoc]
----
:page-liquid:
----
IMPORTANT: AsciiDoc files may include a {url-front-matter}[front matter header] for defining page variables.
If present, the front matter header must be the very first character of the file.
The front matter header won't be seen--and could distort conversion--if the front matter is preceded by whitespace or a Byte Order Mark (BOM).
NOTE: Since version 2.0.0 of this plugin, you may exclude the front matter header, as shown in the second example above.
Prior to version 2.0.0, you had to include at least an empty front matter header (except for posts).
In these cases, you define all the page variables (e.g., layout) using AsciiDoc page attributes instead of in the front matter.
You can also use a combination of both.
When intermixed, the page attributes defined in the AsciiDoc header take precedence.
Liquid processing does not extend to files included using the AsciiDoc include directive (see {url-issues}/166[#166]).
If you're using the Liquid include tag to include HTML into the AsciiDoc document, you need to enclose it in a passthrough block.
----
++++
{% include file.html %}
++++
----
This is necessary since AsciiDoc will escape HTML by default.
To pass it through raw requires enclosing it in a passthrough block.
=== Preventing Liquid Processing on AsciiDoc Includes
The Liquid preprocessor does not process content included using the AsciiDoc include directive.
However, if those files are otherwise publishable, they are processed independently by Jekyll with the Liquid preprocessor and will appear in your site.
If this is not the behavior you want, you can exclude them from being processed independently using one of the following techniques:
* Place them in an automatically excluded location, such as a directory starting with `_` (e.g. [.path]___includes__).
* Name them in such a way that they are automatically excluded, such as starting the name with `_` ([.path]___excluded-include.yml__).
* Adding them to the https://jekyllrb.com/docs/configuration/options/[excludes] key in the Jekyll configuration.
=== Extracting Excerpts
This plugin will extract an excerpt for any post or document in a collection if the `excerpt` page variable isn't set using the same logic as for Markdown files.
By default, it will use the content between the header and the first blank line.
If the `excerpt` page variable is set, that value will be used instead.
The excerpt will automatically be converted from AsciiDoc to embedded HTML whereever the `excerpt` property is referenced in a Liquid template.
----
{% post.excerpt %}
----
IMPORTANT: Since version 3.0.0 of this plugin, you no longer have to run the excerpt through the `asciidocify` filter since the conversion is already done for you.
In fact, if you do, the HTML in the converted excerpt will be escaped, which is not what you want.
If you want to use a different excerpt separator for AsciiDoc files, set the `excerpt_separator` under the `asciidoc` key in the site configuration.
For example, you can configure the plugin to use the line comment `//more` as the excerpt separator as follows:
[source,yaml]
----
asciidoc:
excerpt_separator: "\n//more\n"
----
If you're only working with AsciiDoc files in your site, you can go ahead and set this for all files by using the top-level property:
[source,yaml]
----
excerpt_separator: "\n//more\n"
----
If the excerpt separator isn't found, the content of the whole document is used instead.
By default, the excerpt is converted to HTML using the article doctype.
If you want to use a different doctype, such as inline, you can set it in the site configuration as follows:
[source,yaml]
----
asciidoc:
excerpt_doctype: inline
----
You can also set the excerpt doctype per page using the page attribute named `page-excerpt_doctype`.
== Building and Previewing Your Site
You can build your site into the [.path]__site_ directory using:
$ jekyll build
If you're using Bundler, prefix each command with `bundle exec`:
[subs=+quotes]
$ *bundle exec* jekyll build
You can preview your site at \http://localhost:4000 using:
$ jekyll serve
The `serve` command monitors the file system and rebuilds the site whenever a change is detected by default (i.e., watch mode).
To disable watch mode, use the `--no-watch` flag:
$ jekyll serve --no-watch
You can also use the `--watch` flag with the `build` command:
$ jekyll build --watch
If you only want Jekyll to build files which have changed, and not the whole site, add the `--incremental` flag:
$ jekyll serve --incremental
or
$ jekyll build --watch --incremental
To see a report of all the files that are processed, add the `--verbose` flag:
$ jekyll build --verbose
IMPORTANT: If you add the `--safe` flag, third-party plugins such as this one are disabled by default.
To reenable the plugin, you must add the name of the gem to the whitelist.
See <> for details.
== Configuration
This section describes the configuration options for this plugin, which are _optional_.
You should at least assign an empty Hash as a default (e.g., `{}`) to the `asciidoc` and `asciidoctor` keys in `_config.yml`, respectively, if you don't plan on making any further customizations.
[source,yaml]
----
asciidoc: {}
asciidoctor: {}
----
Using these placeholder values prevents initialization from being performed more than once when using watch mode (see https://github.com/jekyll/jekyll/issues/4858[issue jekyll#4858]).
=== AsciiDoc
NOTE: Prior to version 2.0.0 of this plugin, the configuration keys in this section were defined as flat, top-level names (e.g., `asciidoc_ext`).
These names are now deprecated, but still supported.
By default, this plugin uses Asciidoctor to convert AsciiDoc files.
Because Asciidoctor is currently the only option, the default setting is equivalent to the following configuration in `_config.yml`:
[source,yaml]
----
asciidoc:
processor: asciidoctor
----
IMPORTANT: The `asciidoc` block should only appear _once_ inside `_config.yml`.
If you define any other options that are documented in this section, you should append them to the `asciidoc` block.
To tell Jekyll which file extensions to match as AsciiDoc files, append the `ext` option to the `asciidoc` block of your `_config.yml`:
[source,yaml]
----
asciidoc:
ext: asciidoc,adoc,ad
----
The extensions shown in the previous listing are the default values, so you don't need to specify this option if those defaults are sufficient.
AsciiDoc attributes defined in the document header whose names begin with `page-` are promoted to page variables.
The part of the name after the `page-` prefix is used as the key (e.g., page-layout becomes layout).
If you want to change this attribute prefix, append the `page_attribute_prefix` option to the `asciidoc` block of your `_config.yml`:
[source,yaml]
----
asciidoc:
page_attribute_prefix: jekyll
----
A hyphen is automatically added to the value of this configuration setting if the value is non-empty (e.g, jekyll-).
Since version 2.0.0 of this plugin, all non-hidden AsciiDoc files are processed by default, even those without a front matter header.
If you only want files containing a front matter header to be processed (as was the behavior prior to version 2.0.0), add the `require_front_matter_header` option to the `asciidoc` block of your `_config.yml`:
[source,yaml]
----
asciidoc:
require_front_matter_header: true
----
=== Asciidoctor
In addition to the built-in attributes in AsciiDoc, the following additional AsciiDoc attributes are automatically defined by this plugin and available to all AsciiDoc-based pages:
....
site-root=(absolute path of root directory)
site-source=(absolute path of source directory)
site-destination=(absolute path of output directory)
site-baseurl=(value of the baseurl config option)
site-url=(value of the url config option)
env=site
env-site
site-gen=jekyll
site-gen-jekyll
builder=jekyll
builder-jekyll
jekyll-version=(value of the Jekyll::VERSION constant)
idprefix
idseparator=-
linkattrs=@
....
The following additional attributes are defined per page:
....
outpath=(path of page relative to baseurl)
....
You can pass custom attributes to AsciiDoc, or override default attributes provided by the plugin, using the `attributes` option of the `asciidoctor` block in your `_config.yml`.
The value of this option can either be a Hash of key-value pairs:
[source,yaml]
----
asciidoctor:
attributes:
idprefix: _
source-highlighter: pygments
pygments-css: style
----
or an Array containing key-value pairs:
[source,yaml]
----
asciidoctor:
attributes:
- idprefix=_
- source-highlighter=pygments
- pygments-css=style
----
When using the Hash syntax, you may find that you need to enclose the value in single quotes for it to be accepted as valid YAML.
NOTE: The examples elsewhere in this README use the Hash syntax, though you can use the Array syntax if you prefer.
YAML does not allow the syntax forms to be mixed, so pick one and stick with it.
When using the Array syntax, you can set a valueless attribute by using the name along, such as `sectanchors`:
[source,yaml]
----
asciidoctor:
attributes:
- sectanchors
----
When using the Hash syntax, you must use an empty string value to indicate that you want to set the attribute:
[source,yaml]
----
asciidoctor:
attributes:
sectanchors: ''
----
By default, an attribute value defined in `_config.yml` overrides the same attribute set in the front matter or header of a document.
For example, if you set `page-layout` in `_config.yml`, you won't be able to set it per page.
[source,yaml]
----
asciidoctor:
attributes:
page-layout: false
----
If you want to allow individual pages to be able to override the attribute, append the charcter `@` to the value in `_config.yml`:
[source,yaml]
----
asciidoctor:
attributes:
page-layout: false@
----
You may use attribute references in the attribute value to reference any attribute that's already defined, including implicit attributes.
For example, to set the `iconsdir` attribute based on the `imagesdir` attribute, use the following:
[source,yaml]
----
asciidoctor:
attributes:
imagesdir: /images
iconsdir: '{imagesdir}/icons'
----
CAUTION: If the value begins with an attribute reference, and you're defining the attributes using the Hash syntax, you must enclose the value in quotes.
There are other cases when the value must be enclosed in quotes, so it's generally recommended to use them.
Since version 2.1.0 of this plugin, you can remove a previously defined attribute by prefixing the name with a minus sign (without any space between):
[source,yaml]
----
asciidoctor:
attributes:
-idprefix:
----
In addition to `attributes`, you may define any other option key (e.g., `safe`) recognized by the {url-asciidoctor-manual}#ruby-api-options[Asciidoctor API].
One of those options is `base_dir`, which is covered in the next section.
==== Specifying the Base Directory
In Asciidoctor, the base directory (i.e., `base_dir` option) is used as the root when resolving relative include paths in top-level documents.
By default, this plugin does not specify a base directory when invoking the Asciidoctor API.
Asciidoctor will therefore use the current working directory (i.e., the project root) as the base directory.
If your source directory is not the project root, and you want Asciidoctor to use the source directory as the base directory, set the value of the `base_dir` option to `:source`.
[source,yaml]
----
asciidoctor:
base_dir: :source
...
----
If, instead, you want the base directory to track the directory of the document being processed, and you're using Jekyll 3 or better, you can set the value of the `base_dir` option to `:docdir`.
This behavior matches how Asciidoctor works when running it outside of Jekyll.
Since the base directory is also the jail, we also recommend setting the `safe` option to enable unsafe mode so you can still resolve paths outside of this directory.
[source,yaml]
----
asciidoctor:
base_dir: :docdir
safe: unsafe
...
----
You can also set the `base_dir` option to any relative or absolute path.
In that case, the same value will be used for all documents.
==== Using AsciiDoc attributes in a Liquid template
Let's say you want to reuse your AsciiDoc attributes in a Liquid template.
This section describes how to do it.
Liquid can only access simple data structures, not complex ones like the one used to store site-wide AsciiDoc attributes. (Site-wide AsciiDoc attributes are stored deep within the Jekyll configuration data as a Hash with symbol keys).
This puts them out of the reach of Liquid templates by default.
This plugin must store site-wide AsciiDoc attributes in this way due to how Jekyll is implemented and the lifecycle it exposes for plugins.
That part can't be changed.
The plugin is limited by Jekyll's design.
However, YAML provides a mechanism that we can leverage to expose these attributes to our Liquid templates.
First, you define your AsciiDoc attributes at the top level of your configuration file where Liquid is able to access them.
If you also assign a YAML reference to this key, you can then pass that Hash to the attributes key in the asciidoctor block, thus allowing the configuration to be shared.
[source,yaml]
----
asciidoc_attributes: &asciidoc_attributes
imagesdir: /images
asciidoctor:
attributes: *asciidoc_attributes
...
----
You can now reference one of the site-wide AsciiDoc attributes in the Liquid template as follows:
----
{{ site.asciidoc_attributes.imagesdir }}
----
Keep in mind that the value of the attribute will be unmodified from the value defined in the configuration file.
==== Enabling Hard Line Breaks Globally
Many Jekyll users are used to writing in GitHub-flavored Markdown (GFM), which preserves hard line breaks in paragraph content.
Asciidoctor supports this feature for AsciiDoc files.
(In fact, previous versions of this plugin enabled this behavior by default).
If you want to enable this behavior for AsciiDoc files, add the `hardbreaks` attribute to the Asciidoctor attributes configuration in your site's `_config.yml` file:
[source,yaml]
----
asciidoctor:
attributes:
hardbreaks: ''
----
If you still want to allow individual files to be able to override the attribute, append the charcter `@` to the value in the site configuration:
[source,yaml]
----
asciidoctor:
attributes:
hardbreaks: '@'
----
If you already have AsciiDoc attributes defined in the `_config.yml`, the new attribute should be added as a sibling entry in the YAML collection.
WARNING: Keep in mind, if you enable hard line breaks, you won't be able to use the {url-asciidoc-practices}#one-sentence-per-line[one sentence-per-line writing technique].
== Running in Safe Mode
If you want to use this plugin when running Jekyll in safe mode, you must add the [.app]*jekyll-asciidoc* gem to the whitelist in your site's `_config.yml` file:
[source,yaml]
----
whitelist:
- jekyll-asciidoc
----
Safe mode is enabled either through the `--safe` flag:
$ jekyll build --safe
or the `safe` configuration option in your site's `_config.yml` file:
[source,yaml]
----
safe: true
----
== Working with AsciiDoc Content in Templates
Jekyll uses the Liquid templating language to process templates.
This plugin defines two additional Liquid filters, `asciidocify` and `tocify_asciidoc`, for working with AsciiDoc content in those templates.
=== Converting a String from AsciiDoc
You can use the `asciidocify` filter to convert an arbitrary AsciiDoc string anywhere in your template.
This filter allows you to compose site-wide data in AsciiDoc, such your site's description or synopsis, then convert it to HTML for use in the page template(s).
Let's assume you've defined a page variable named `synopsis` that you want treat as AsciiDoc.
You can convert it in your template as follows:
----
{{ page.synopsis | asciidocify }}
----
By default, the AsciiDoc content is parsed as an embedded AsciiDoc document.
If the content represents a single paragraph, and you only want to perform inline substitutions on that content, add the `inline` doctype as the filter's first argument:
----
{{ page.synopsis | asciidocify: 'inline' }}
----
=== Generating a Table of Contents
Since version 2.1.0 of this plugin, you can use the `tocify_asciidoc` filter to generate a table of contents from the content of any page that is generated from AsciiDoc.
This filter gives you the ability to place this table of contents anywhere inside the page layout, but outside the main content.
You apply the `tocify_asciidoc` filter to `page.document`, the page variable that resolves to the parsed AsciiDoc document, as shown here:
----
{{ page.document | tocify_asciidoc }}
----
The number of section levels (i.e., depth) shown in the table of contents defaults to the value defined by the `toclevels` attribute in the AsciiDoc document.
To tune the number of levels, pass a numeric value as the filter's first argument.
----
{{ page.document | tocify_asciidoc: 3 }}
----
When you use the `tocify_asciidoc` filter, you'll also want to disable the `toc` attribute in your document.
You can do this using a conditional preprocessor directive.
[source,asciidoc]
----
= Guide
ifndef::env-site[:toc: left]
== Section A
content
== Section B
content
----
By default, the `tocify_asciidoc` filter will insert a table of contents on any page that has even one section below the page title.
It's possible to conditionally disable this by using a Liquid `if` statement in your template with a custom attribute, similar to:
----
{% if page.show-toc != false %}
{{ page.document | tocify_asciidoc }}
{% endif %}
----
Then in the front matter of pages where you do not want a table of contents to appear, use the attribute `:page-show-toc: false`.
Note that since this example uses a custom attribute, its name can be anything you'd like, it only needs to start with with `page-`.
If you change the attribute name from this example, be sure to update the it in the `if` statement as appropriate.
== Customizing the Generated HTML
You can use templates to customize the HTML output that Asciidoctor generates for your site.
Template files can be composed in any templating language that is supported by {url-tilt}[Tilt].
Each template file corresponds to a node in the AsciiDoc document tree (aka AST).
Below are the steps you need to take to configure Asciidoctor to use custom templates with your site.
=== Step {counter:step}: Add Required Gems
You'll first need to add the thread_safe gem as well as the gem for the templating language you plan to use.
We'll assume that you are using Slim.
[source,ruby]
----
gem 'slim', '~> 3.0.7'
gem 'thread_safe', '~> 0.3.5'
----
=== Step {counter:step}: Install New Gems
Now run the `bundle` command to install the new gems.
$ bundle
=== Step {counter:step}: Create a Templates Folder
Next, create a new folder in your site named [.path]__templates_ to store your templates.
$ mkdir _templates
=== Step {counter:step}: Configure Asciidoctor to Load Templates
In your site's `_config.yml` file, configure Asciidoctor to load the templates by telling it the location where the templates are stored.
[source,yaml]
----
asciidoctor:
template_dir: _templates
attributes: ...
----
=== Step {counter:step}: Compose a Template
The final step is to compose a template.
We'll be customizing the unordered list node.
Name the file [.path]_ulist.html.slim_.
.ulist.html.slim
[source,slim]
----
- if title?
figure.list.unordered id=id
figcaption=title
ul class=[style, role]
- items.each do |_item|
li
span.primary=_item.text
- if _item.blocks?
=_item.content
- else
ul id=id class=[style, role]
- items.each do |_item|
li
span.primary=_item.text
- if _item.blocks?
=_item.content
----
The next time you build your site, Asciidoctor will use your custom template to generate the HTML for unordered lists.
TIP: You can find additional examples of custom templates in the {url-asciidoctor-backends}[asciidoctor-backends] repository.
== Enabling Asciidoctor Extensions
You enable Asciidoctor extensions in much the same way as this plugin.
You just need to get Jekyll to load the source.
If the extension you want to use is published as a gem, and you're using Bundler to manage the dependencies for your project (as recommended), then you simply add the gem to the `jekyll_plugins` group in your [.path]_Gemfile_:
[source,ruby]
----
group :jekyll_plugins do
gem 'asciidoctor-extension-xyz'
end
----
Then, run the `bundle` command from Bundler to install the gem:
$ bundle
If you're not using Bundler to manage the dependencies for your Jekyll project, you'll need to install the gem manually.
Once that's done, add the gem to the list gems for Jekyll to load in your site's `_config.yml` file:
[source,ruby]
----
plugins:
- asciidoctor-extension-xyz
----
If you're running Jekyll < 3.5.0, you'll need to use `gems` in place of `plugins`:
[source,ruby]
----
gems:
- asciidoctor-extension-xyz
----
If the extension you want to use is not published as a gem, or is something you're developing, then you'll load it like an ad-hoc Jekyll plugin.
Add the file [.path]_asciidoctor-extensions.rb_ to the [.path]__plugins_ folder of your project root (creating the folder if it does not already exist) and populate the file with the following content:
._plugins/asciidoctor-extensions.rb
[source,ruby]
----
require 'asciidoctor/extensions'
Asciidoctor::Extensions.register do
treeprocessor do
process do |doc|
doc
end
end
end
----
Asciidoctor will automatically enable the extensions in this file when it is loaded by Jekyll.
For a concrete example of using an Asciidoctor extension, refer to the next section.
== Enabling Asciidoctor Diagram
{url-asciidoctor-diagram}[Asciidoctor Diagram] is a set of extensions for Asciidoctor that allow you to embed diagrams generated by PlantUML, Graphviz, ditaa, Shaape, and other plain-text diagram tools inside your AsciiDoc documents.
In order to use Asciidoctor Diagram in a Jekyll project successfully, *you must use a version of this plugin >= 2.0.0*.
Other combinations are known to have issues.
IMPORTANT: For Graphviz and PlantUML diagram generation, {url-graphviz}[Graphviz] must be installed (i.e., the `dot` utility must be available on your `$PATH`.
TIP: To follow a start-to-finish tutorial that covers how to integrate Asciidoctor Diagram, see https://gist.github.com/mojavelinux/968623c493190dd61c059c2d85f9bdc3[this gist].
=== Installation
Using Bundler::
+
--
Add the `asciidoctor-diagram` gem to your [.path]_Gemfile_:
[source,ruby,subs=attributes+]
----
group :jekyll_plugins do
gem 'asciidoctor-diagram', '~> 1.5.4' #{conum-guard}<1>
gem 'jekyll-asciidoc'
...
end
----
<1> Customize the version of Asciidoctor Diagram as needed.
Then, run Bundler's install command to install the new gem:
$ bundle
--
Without Bundler::
+
--
Install gems manually
$ [sudo] gem install asciidoctor-diagram
Then, add the `asciidoctor-diagram` gem to the list of plugins for Jekyll to load in your site's `_config.yml` file:
[source,yaml]
----
plugins:
- asciidoctor-diagram
- jekyll-asciidoc
----
If you're running Jekyll < 3.5.0, you'll need to use `gems` in place of `plugins`:
[source,yaml]
----
gems:
- asciidoctor-diagram
- jekyll-asciidoc
----
--
The preceding configurations are equivalent to passing `-r asciidoctor-diagram` to the `asciidoctor` command.
=== Generated Image Location
Asciidoctor Diagram needs some context in order to write the images to the proper location.
At a minimum, you must set the following configuration in `_config.yml`:
[source,yaml]
----
asciidoctor:
base_dir: :docdir
safe: unsafe
----
With this configuration, Asciidoctor Diagram will generate images relative to the generated HTML page (i.e., in the same directory) within the destination folder.
WARNING: Jekyll will *delete* the images Asciidoctor Diagram generates unless you follow the instructions in <>.
You can use the following example to test your setup:
._posts/2016-01-01-diagram-sample.adoc
[source,asciidoc]
----
= Diagram Sample
[graphviz,dot-example,svg]
....
digraph g {
a -> b
b -> c
c -> d
d -> a
}
....
----
If you prefer to serve all images from the same folder, assign a value to the `imagesdir` attribute that is relative to the site root:
[source,yaml]
----
asciidoctor:
base_dir: :docdir
safe: unsafe
attributes:
imagesdir: /images
----
With this configuration, Asciidoctor Diagram will generate images into the [.path]_images_ directory within the destination folder.
WARNING: Jekyll will *delete* the images Asciidoctor Diagram generates unless you follow the instructions in <>.
==== Preserving Generated Images
Since Asciidoctor Diagram writes to the output folder, you have to instruct Jekyll not to remove these generated files in the middle of the build process.
One way to do this is to apply a "`monkeypatch`" to Jekyll.
Add the file [.path]_jekyll-ext.rb_ to the [.path]__plugins_ folder of your project root (creating the folder if it does not already exist) and populate the file with the following content:
._plugins/jekyll-ext.rb
[source,ruby]
----
class Jekyll::Cleaner
def cleanup!; end
end
----
An alternative to the monkeypath approach is to identify folders that contain generated images in the `keep_files` option in `_config.yml`:
[source,yaml]
----
keep_files:
- images
asciidoctor:
base_dir: :docdir
safe: unsafe
attributes:
imagesdir: /images
----
== Enabling STEM Support
Thanks to Asciidoctor, Jekyll AsciiDoc provides built-in support for processing STEM (Science, Technology, Engineering & Math) equations in your AsciiDoc documents.
To enable this support, you just need to do a bit of configuration.
=== Activating the STEM processing
The first thing you need to do is activate the STEM processing integration in the processor itself.
To do that, set the `stem` attribute on the document.
One way is to set the `stem` attribute in the document header:
[source,asciidoc]
----
= Page Title
:stem:
----
Alternatively, you can enable it the `stem` attribute globally for all AsciiDoc documents in your site by adding the following to your site's `_config.yml` file:
[source,yaml]
----
asciidoctor:
attributes:
stem: ''
----
To learn more about the built-in STEM integration, see the https://asciidoctor.org/docs/user-manual/#activating-stem-support[STEM] chapter in the Asciidoctor User Manual.
=== Adding the STEM assets to the page
Technically, Asciidoctor only prepares the STEM equations for interpretation by https://mathjax.org[MathJax].
That means you have to load MathJax on any page that contains STEM equations (or all pages, if that's easier).
To do so requires some customization of the page layout.
First, create the file [.path]__includes/mathjax.html_ and populate it with the following contents:
[source,html]
----
----
Then, include this file before the closing `