This is the official manual for the latest Org-mode release.

Table of Contents

Previous: Export in foreign buffers, Up: Exporting


12.15 Advanced configuration

Hooks

Two hooks are run during the first steps of the export process. The first one, org-export-before-processing-hook is called before expanding macros, Babel code and include keywords in the buffer. The second one, org-export-before-parsing-hook, as its name suggests, happens just before parsing the buffer. Their main use is for heavy duties, that is duties involving structural modifications of the document. For example, one may want to remove every headline in the buffer during export. The following code can achieve this:

     (defun my-headline-removal (backend)
       "Remove all headlines in the current buffer.
     BACKEND is the export back-end being used, as a symbol."
       (org-map-entries
        (lambda () (delete-region (point) (progn (forward-line) (point))))))
     
     (add-hook 'org-export-before-parsing-hook 'my-headline-removal)

Note that functions used in these hooks require a mandatory argument, a symbol representing the back-end used.

Filters

Filters are lists of functions applied on a specific part of the output from a given back-end. More explicitly, each time a back-end transforms an Org object or element into another language, all functions within a given filter type are called in turn on the string produced. The string returned by the last function will be the one used in the final output.

There are filters sets for each type of element or object, for plain text, for the parse tree, for the export options and for the final output. They are all named after the same scheme: org-export-filter-TYPE-functions, where TYPE is the type targeted by the filter. Valid types are:

bold babel-call center-block
clock code comment
comment-block diary-sexp drawer
dynamic-block entity example-block
export-block export-snippet final-output
fixed-width footnote-definition footnote-reference
headline horizontal-rule inline-babel-call
inline-src-block inlinetask italic
item keyword latex-environment
latex-fragment line-break link
node-property options paragraph
parse-tree plain-list plain-text
planning property-drawer quote-block
quote-section radio-target section
special-block src-block statistics-cookie
strike-through subscript superscript
table table-cell table-row
target timestamp underline
verbatim verse-block

For example, the following snippet allows me to use non-breaking spaces in the Org buffer and get them translated into LaTeX without using the \nbsp macro (where _ stands for the non-breaking space):

     (defun my-latex-filter-nobreaks (text backend info)
       "Ensure \" \" are properly handled in LaTeX export."
       (when (org-export-derived-backend-p backend 'latex)
             (replace-regexp-in-string " " "~" text)))
     
     (add-to-list 'org-export-filter-plain-text-functions
                  'my-latex-filter-nobreaks)

Three arguments must be provided to a filter: the code being changed, the back-end used, and some information about the export process. You can safely ignore the third argument for most purposes. Note the use of org-export-derived-backend-p, which ensures that the filter will only be applied when using latex back-end or any other back-end derived from it (e.g., beamer).

Extending an existing back-end

This is obviously the most powerful customization, since the changes happen at the parser level. Indeed, some export back-ends are built as extensions of other ones (e.g. Markdown back-end an extension of HTML back-end).

Extending a back-end means that if an element type is not transcoded by the new back-end, it will be handled by the original one. Hence you can extend specific parts of a back-end without too much work.

As an example, imagine we want the ascii back-end to display the language used in a source block, when it is available, but only when some attribute is non-nil, like the following:

     #+ATTR_ASCII: :language t

Because that back-end is lacking in that area, we are going to create a new back-end, my-ascii that will do the job.

     (defun my-ascii-src-block (src-block contents info)
       "Transcode a SRC-BLOCK element from Org to ASCII.
     CONTENTS is nil.  INFO is a plist used as a communication
     channel."
       (if (not (org-export-read-attribute :attr_ascii src-block :language))
         (org-export-with-backend 'ascii src-block contents info)
       (concat
        (format ",--[ %s ]--\n%s`----"
                (org-element-property :language src-block)
                (replace-regexp-in-string
                 "^" "| "
                 (org-element-normalize-string
                  (org-export-format-code-default src-block info)))))))
     
     (org-export-define-derived-backend 'my-ascii 'ascii
       :translate-alist '((src-block . my-ascii-src-block)))

The my-ascii-src-block function looks at the attribute above the element. If it isn't true, it gives hand to the ascii back-end. Otherwise, it creates a box around the code, leaving room for the language. A new back-end is then created. It only changes its behavior when translating src-block type element. Now, all it takes to use the new back-end is calling the following from an Org buffer:

     (org-export-to-buffer 'my-ascii "*Org MY-ASCII Export*")

It is obviously possible to write an interactive function for this, install it in the export dispatcher menu, and so on.