Next: Export in foreign buffers, Previous: Other built-in back-ends, Up: Exporting
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.
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
.
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
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.