Hintergrundbild
Navigation

Aafigure Filter for pandoc

Version: 0.1.1
Article in PDF format

Table of Contents


ASCII Art with aafigure and pandoc

The aafigure tool converts ASCII art images to formats suitable for HTML, LaTeX and other formats. It is implemented as a pandoc filter using the Python pandocfilters module and based on the abc.py example code.

Attention: PDF images created by aafigure using the ReportLab package can cause weird errors when used with LaTeX. You might see lines like

** WARNING ** Multiple DecodeFilter not supported.
** WARNING ** Could not handle a content stream.
** WARNING ** pdf: image inclusion failed for "./box_and_fills.pdf".
(see the transcript file for additional information)
Output written on pandoc_aafigure_filter.pdf (5 pages).
Transcript written on pandoc_aafigure_filter.log.

but the transcript shows no errors. The relevant line here is Multiple DecodeFilter not supported. To circumvent this convert the PDF image to PostScript format using pdftops <pdf filename> and then back to PDF with pstopdf <ps filename>. Then the file should show up in without errors.

Installation

aafigure version 0.5 runs only with Python versions prior 3. Luckily the 2to3 conversion tool that is part of every Python 3.x installation can translate the code automatically. The result can then be installed with pip (or pip3 if you have both Python 2.x and 3.x installed):

2to3 -w aafigure-0.5
pip3 install ./aafigure-0.5

aafigure makes use of several other Python modules, namely ReportLab for PDF and Pillow for PNG and JPEG images. These modules need some libraries installed before:

sudo aptitude install libjpeg-dev libpng-dev libfreetype6-dev
pip3 install reportlab Pillow

Now we can use either the aafigure commandline tool or use the module directly as shown below.

Usage

The filter works on fenced code blocks that have the class .aafigure. A given identifier will be used as the image filename, otherwise a SHA-1 checksum will be generated.

This example code shows how to draw two boxes connected by an arrow, one striped:

  ~~~ {#box_and_fills .aafigure}
  
   +---+    DDDD
   |   +--->DDDD
   +---+    DDDD
  ~~~
  

The resulting image:

The Filter Code

Looking for Fenced Code Blocks

The aafigure2X function checks if a CodeBlock has a class named aafigure and takes an optional identifier as the filename for the resulting image file. If there is no identifier, a SHA-1 checksum of the code will be used instead.

According to the format the filter creates either a PNG file (for HTML) oder a PDF (for LaTeX).

<look for fenced code blocks>=

  def aafigure2X(key, value, format, meta):
      if key=='CodeBlock':
          [[ident, classes, keyvals], code] = value
          if "aafigure" in classes:
              if ident:
                  outfile = ident
              else:
                  outfile = sha1(code)
              if format=="html":
                  filetype = "png"
              elif format=="latex":
                  filetype = "pdf"
              else:
                  filetype = "png"
              src = outfile + '.' + filetype
  
              aafigure2img(code, filetype, outfile)
              
              return Para([Image([], [src, ""])])
  

Creating the Output File

The aafigure.render function needs a dictionary to work with options like the filetype, so we create a simple one with the filetype as the format value. According to the documentation the render function should create an output file by itself, but this creates an error. So we open the file by ourselves and pass the handle to the function.

<call aafigure to create an image file>=

  def aafigure2img(code, filetype, outfile):
      options = {
          "format": filetype,
      }
      with open(outfile + "." + filetype, "wb") as output:
          aafigure.render(code, output, options)
  

Main program

<aafigure-filter.py>=

  #!/usr/bin/env python3.4
  
  """
  Pandoc filter to process code blocks with class "aafigure" containing
  aafigure ASCII art into images.  Assumes that aafigure, ReportLab and Pillow
  modules a installed.
  
  """
  __author__ = "Meik Teßmer"
  __email__ = "mtessmer@wiwi.uni-bielefeld.de"
  __version__ = "0.1.1"
  
  
  import hashlib
  import sys
  
  from aafigure import aafigure
  from pandocfilters import toJSONFilter, Para, Image
  
  
  def sha1(x):
      return hashlib.sha1(x.encode()).hexdigest()
  
  
  <<look for fenced code blocks>>
  <<call aafigure to create an image file>>
  
  
  if __name__ == "__main__":
      toJSONFilter(aafigure2X)
  

<build-script>=

  #!/bin/sh
  if [ -z "${NOWEB_SOURCE}" ]; then
          NOWEB_SOURCE=pandoc_aafigure_filter.nw
  fi
  if [ -z "${NOWEB_CODE}" ]; then
          NOWEB_CODE=`pwd`/code
  fi
  
  # check if we need to create target dirs
  [ -d ${NOWEB_CODE} ] || mkdir -p ${NOWEB_CODE}
  
  FILES="aafigure-filter.py"
  
  for f in ${FILES}; do
          ./tangle -R"$f" "${NOWEB_SOURCE}" > "${NOWEB_CODE}/$f"
          chmod u+x "${NOWEB_CODE}/$f"
  done
  

Code Chunks

Aktuelles

ipmi-telegraf

2017-02-09

ipmi-telegraf: IPMI-Skript für Telegraf-exec-Plugin veröffentlicht.

blockdiag-Filter für pandoc

2016-10-28

Die Version 0.1.0 des pandoc-Filters für blockdiag-ASCII-Bilder wurde veröffentlicht.

Update nw2md2ctags auf v0.1.3

2015-04-21

Das Werkzeug nw2md2ctags wurde auf die Version 0.1.3 aktualisiert.

Filter für die Verwendung von ASCII-Art mit pandoc

2015-04-08

Der pandoc_aafigure_filter ermöglicht die Verwendung von ASCII-Art-Bildern in pandoc-Dokumenten und generiert automatisch die entsprechenden Bilder.