Mark Needham

Thoughts on Software Development

Archive for the ‘asciidoctor’ tag

Asciidoctor: Creating a macro

without comments

I’ve been writing the TWIN4j blog for almost a year now and during that time I’ve written a few different asciidoc macros to avoid repetition.

The most recent one I wrote does the formatting around the Featured Community Member of the Week. I call it like this from the asciidoc, passing in the name of the person and a link to an image:

featured::https://s3.amazonaws.com/dev.assets.neo4j.com/wp-content/uploads/20180202004247/this-week-in-neo4j-3-february-2018.jpg[name="Suellen Stringer-Hye"]

The code for the macro has two parts. The first is some wiring code that registers the macro with Asciidoctor:

lib/featured-macro.rb

RUBY_ENGINE == 'opal' ? (require 'featured-macro/extension') : (require_relative 'featured-macro/extension')
 
Asciidoctor::Extensions.register do
  if (@document.basebackend? 'html') && (@document.safe < SafeMode::SECURE)
    block_macro FeaturedBlockMacro
  end
end

And this is the code for the macro itself:

lib/featured-macro/extension.rb

require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal'
 
include ::Asciidoctor
 
class FeaturedBlockMacro < Extensions::BlockMacroProcessor
  use_dsl
 
  named :featured
 
  def process parent, target, attrs
    name = attrs["name"]
 
    html = %(<div class="imageblock image-heading">
                <div class="content">
                    <img src="#{target}" alt="#{name} - This Week’s Featured Community Member" width="800" height="400">
                </div>
            </div>
            <p style="font-size: .8em; line-height: 1.5em;" align="center">
              <strong>#{name} - This Week's Featured Community Member</strong>
            </p>)
 
    create_pass_block parent, html, attrs, subs: nil
  end
end

When we convert the asciidoc into HTML we need to tell asciidoctor about the macro, which we can do like this:

asciidoctor template.adoc \
  -r ./lib/featured-macro.rb \
  -o -

And that’s it!

Written by Mark Needham

February 19th, 2018 at 8:51 pm

Posted in Software Development

Tagged with ,

Asciidoc to Asciidoc: Exploding includes

without comments

One of my favourite features in AsciiDoc is the ability to include other files, but when using lots of includes is that it becomes difficult to read the whole document unless you convert it to one of the supported backends.

$ asciidoctor --help
Usage: asciidoctor [OPTION]... FILE...
Translate the AsciiDoc source FILE or FILE(s) into the backend output format (e.g., HTML 5, DocBook 4.5, etc.)
By default, the output is written to a file with the basename of the source file and the appropriate extension.
Example: asciidoctor -b html5 source.asciidoc
 
    -b, --backend BACKEND            set output format backend: [html5, xhtml5, docbook5, docbook45, manpage] (default: html5)
                                     additional backends are supported via extensions (e.g., pdf, latex)

I don’t want to have to convert my code to one of these formats each time – I want to convert asciidoc to asciidoc!

For example, given the following files:

mydoc.adoc

= My Blog example
 
== Heading 1
 
Some awesome text
 
== Heading 2
 
include::blog_include.adoc[]

blog_include.adoc

Some included text

I want to generate another asciidoc file where the contents of the include file are exploded and displayed inline.

After a lot of searching I came across an excellent script written by Dan Allen and put it in a file called adoc.rb. We can then call it like this:

$ ruby adoc.rb mydoc.adoc
= My Blog example
 
== Heading 1
 
Some awesome text
 
== Heading 2
 
Some included text

Problem solved!

In my case I actually wanted to explode HTTP includes so I needed to pass the -a allow-uri-read flag to the script:

$ ruby adoc.rb mydoc.adoc -a allow-uri-read

And now I can generate asciidoc files until my heart’s content.

Written by Mark Needham

January 23rd, 2018 at 9:11 pm

Posted in Software Development

Tagged with ,