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

Table of Contents

Next: , Previous: Other built-in back-ends, Up: Exporting


12.17 Advanced configuration

Hooks

The export process executes two hooks before the actual exporting begins. The first hook, org-export-before-processing-hook, runs before any expansions of macros, Babel code, and include keywords in the buffer. The second hook, org-export-before-parsing-hook, runs before the buffer is parsed. Both hooks are specified as functions, see example below. Their main use is for heavy duty structural modifications of the Org content. For example, removing every headline in the buffer during export:

     (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 the hook function must have a mandatory argument that is a symbol for the back-end.

Filters

The Org export process relies on filters to process specific parts of conversion process. Filters are just lists of functions to be applied to certain parts for a given back-end. The output from the first function in the filter is passed on to the next function in the filter. The final output is the output from the final function in the filter.

The Org export process has many filter sets applicable to different types of objects, plain text, parse trees, export options, and final output formats. The filters are named after the element type or object type: org-export-filter-TYPE-functions, where TYPE is the type targeted by the filter. Valid types are:

body bold babel-call
center-block clock code
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 radio-target
section special-block src-block
statistics-cookie strike-through subscript
superscript table table-cell
table-row target timestamp
underline verbatim verse-block

Here is an example filter that replaces non-breaking spaces ~ in the Org buffer with _ for the LaTeX back-end.

     (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)

A filter requires three arguments: the code to be transformed, the name of the back-end, and some optional information about the export process. The third argument can be safely ignored. Note the use of org-export-derived-backend-p predicate that tests for latex back-end or any other back-end, such as beamer, derived from latex.

Defining filters for individual files

The Org export can filter not just for back-ends, but also for specific files through the #+BIND keyword. Here is an example with two filters; one removes brackets from time stamps, and the other removes strike-through text. The filter functions are defined in a ‘src’ code block in the same Org file, which is a handy location for debugging.

     #+BIND: org-export-filter-timestamp-functions (tmp-f-timestamp)
     #+BIND: org-export-filter-strike-through-functions (tmp-f-strike-through)
     #+begin_src emacs-lisp :exports results :results none
       (defun tmp-f-timestamp (s backend info)
         (replace-regexp-in-string "&[lg]t;\\|[][]" "" s))
       (defun tmp-f-strike-through (s backend info) "")
     #+end_src

Extending an existing back-end

Some parts of the conversion process can be extended for certain elements so as to introduce a new or revised translation. That is how the HTML export back-end was extended to handle Markdown format. The extensions work seamlessly so any aspect of filtering not done by the extended back-end is handled by the original back-end. Of all the export customization in Org, extending is very powerful as it operates at the parser level.

For this example, make the ascii back-end display the language used in a source code block. Also make it display only when some attribute is non-nil, like the following:

     #+ATTR_ASCII: :language t

Then extend ascii back-end with a custom my-ascii back-end.

     (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 current element. If not true, hands over to ascii back-end. If true, which it is in this example, it creates a box around the code and leaves room for the inserting a string for language. The last form creates the new back-end that springs to action only when translating src-block type elements.

To use the newly defined back-end, call the following from an Org buffer:

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

Further steps to consider would be an interactive function, self-installing an item in the export dispatcher menu, and other user-friendly improvements.