Asciidoctor: Enable control over substitutions for certain block types globally

Created on 16 Feb 2017  路  6Comments  路  Source: asciidoctor/asciidoctor

Summary:
Sometimes, in some specific types of documentation one would like to change the substitutions applied to specific block types by default.
Asciidoctor substitutions and block types: http://asciidoctor.org/docs/user-manual/#built-in-blocks-summary

Use case:
For example, when documenting examples that use attributes to customize the content, one requires adding subs="attributes+" to all Example and Source block types.

= Environment info
:user: some_user
:machine: machine.name.domain

== Remote access

Use the following command to access your environment:

[subs="attributes+"]
----
 ssh {user}@{machine}
----

This increases the effort to develop and maintain the documents.
Also, though this is a personal note, it breaks the mental focus of the writer, forcing him to constantly remind himself to apply the substitutions.

Current alternatives available
As suggested in subs-quot-attributes-quot-by-default-for-code-blocks, by @mojavelinux, this can be implemented using an extension. A _"TreeProcessor can visit all the source blocks and set the substitutions just as though subs=attributes+ was set on every block explicitly"_.
PROS:

  • Does not require Asciidoctor core changes and is available right now.
    CONS:
  • Requires knowledge of the Asciidoctor extension API, and the later integration of the component in the build pipeline.
  • Won't show on editor's preview (e.g. Atom.io or IntelliJ). Can be mitigated if support for extensions is provided in the preview.

Proposal
An attribute that defines the substitutions applied could be defined for every block type (e.g. following the convention blockTypeName-subs). These attributes would allow to define the substitutions being applied globally by default, ideally following the same syntax as in the blocks. That is, allowing to define the substitutions in an absolute or incremental way.
Example:

= Environment info
:example-subs: attributes+
:user: some_user
:machine: machine.name.domain

== Remote access

Use the following command to access your environment:

 ssh {user}@{machine}

Alternatively, the attributes could be invoked from the shell.

Most helpful comment

I tried the TreeProcessor:

After you modify the subs attribute, you have to commit the subs.

block.attributes['subs'] = ''
block.commit_subs

The alternative is to modify the subs property directly:

block.subs.clear

(Since subs is not a writable property, you'd need to use .replace to replace it with another list...which is what .commit_subs does).

All 6 comments

On a personal note, I'd like to add that I agree with the default substitutions applied and I see why this should be enforced on every block. Changing it globally, can create confusion to anyone reading the document if they are not aware of the configuration. Basically, this changes the meaning of the content in the block. For instance {user} is no longer a literal text, as it should be, but a variable replaced.
I retract in the previous comment on the other issue comparing this with :icons: font option. In the :icons: case, you are changing the presentation but not the meaning of the block.

For me, this is a case of adding a "convenient and nice-to-have" feature that can ease the maintenance of documents.

Running into this when trying to develop a custom confluence backend, it is mostly the same as HTML but there are those edge cases.
My code is littered with [subs={code_subs}] everywhere, where code_subs=normal for html and code_subs=none for confluence.

You can modify subs using a TreeProcessor. That's what I recommend doing. Since the need for subs is a converter concern, it's not something that should be in the document.

I tried the TreeProcessor:

    def process(document)
      document.find_by(context: :listing) do |block|
        blocks.attributes["subs"] = "none"
      end
    end

But it didn't seem to update the output, I am starting to try a Preprocessor instead, unless I am wrong with the Treeprocessor.

I am starting to try a Preprocessor instead

Please do not use the Preprocessor. It has tremendous side effects once you start reading lines from the reader. It should only be used to set global document attributes.

I tried the TreeProcessor:

After you modify the subs attribute, you have to commit the subs.

block.attributes['subs'] = ''
block.commit_subs

The alternative is to modify the subs property directly:

block.subs.clear

(Since subs is not a writable property, you'd need to use .replace to replace it with another list...which is what .commit_subs does).

Was this page helpful?
0 / 5 - 0 ratings