How to create your own OpenOffice backend w/ @asciidoctor /cc @kubern @ysb33r

By Greg Turnquist

Greg is a member of the Spring team, an author of several books on Spring Boot, conference speaker, and the lead for Spring Data JPA.

February 24, 2015

asciidoctor My work on creating an asciidoctor backend for Packt Publishing (i.e. OpenOffice) seems to have caught several people’s attention. Today I spotted an exchange of tweets asking about OpenOffice in general. I figured a more detailed approach to doing that would better fit in a blog posting.

Starting with the basics

For starters, this whole thing is based on creating an FODT document, not an ODT one. The “F” stands for Flat and it is basically an XML document. Your mission, should you choose to accept it, is to create an XML document with all the right parts. That’s the reason my backend is written in SLIM.

SLIM is basically XML with every bit of unnecessary stuff removed. No closing tags. No angled brackets. Nested elements are denoted by indentation, hence giving it a more YAML-like feel. Checkout the following fragment for generating different section levels.

Working backwards

My recommendation is to start from a document you know and love. I started with Packt’s template they sent me. I performed a “Save As” and picked “Flat ODT” to get it into XML format. I then wrote a sample asciidoctor document with all the things I wanted. I suggest you start small and not get into complex layouts (yet). Remember: Minimum Viable Production (MVP) is the key to short, iterative success. From there, I started running my backend against this thing and comparing it with the outcome.

Got xmllint? If not, you should. Your output will be compressed XML. xmllint is the key to viewing your FODT output. Got giant monitor? .It can help dealing with stuff scrolling off the screen as you inspect your handiwork.

A key thing to understand. Asciidoctor splits up each “element” of asciidoc into a separate fragments and looks for the corresponding stuff in your backend. Got a “section”? Look for slim/packt/section.fodt.slim.

  • slim is the template engine
  • packt is the name of the backend (hence all your fragments will be there)
  • section.fodt.slim is convention-over-configuration for generating an FODT-styled chunk of XML everytime asciidoctor hits a “section”.

The top level thing for you document is, duh, document.fodt.slim. And this is also where you’ll find the root FODT XML <office:document>.  Way at the bottom is a common pattern, “=content”. This says, continue processing further asciidoc tokens and insert results at this level.

Iteration is the key to success

To run your backend against your asciidoc input:

asciidoctor -T /path/to/your/backend-root/slim -b packt your.adoc

My backend doesn’t cover every possible element of asciidoc because I didn’t need them. With asciidoctor, you can start with just document.fodt.slim & helpers.rb and when it hits an unknown token, it will tell in simple terms. Go and code <foo>.fodt.slim, and run again. Eventually, you can piece out your entire document. And in the process, you’ll become quite fluent with both FODT and asciidoctor.

Don’t give up!

You will undoubtedly hit some bumps. I sure did. One was getting my code fragments to apply a different style to the last line of any block of code. I probably invested two weeks of effort in this entire backend while writing Learning Spring Boot, but the payoff was enormous. If you are trying to convert a giant slew of documents, try to avoid after the fact edits. And if possible, get the core stuff working, like sections, paragraphs, bold/italics, bullets and admonitions. That stuff really motivated me to push forward.

Oh yeah…

Last time I checked, asciidoctor has special processing rules for double underscrores (__). Several of my style names from Packt had them, and it caused havoc. Once I tracked it down, I simply did a global replace, reducing them to single underscores. DON’T USE DOUBLE UNDERSCORES FOR ANYTHING!

Good luck!

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *