1 ;;; org-export.el --- Export engine for Org
3 ;; Copyright 2008 2010 Bastien Guerry
5 ;; Emacs Lisp Archive Entry
6 ;; Filename: org-export.el
8 ;; Author: Bastien <bzg AT altern DOT org>
9 ;; Maintainer: Bastien <bzg AT altern DOT org>
12 ;; URL: [Not distributed yet]
14 ;; This program is free software; you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation; either version 3, or (at your option)
19 ;; This program is distributed in the hope that it will be useful,
20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 ;; GNU General Public License for more details.
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with this program; if not, write to the Free Software
26 ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 ;; org-export.el implements a new experimental export engine for Org.
32 ;; Put this file into your load-path and the following into your ~/.emacs:
33 ;; (require 'org-export)
37 ;; Rewrite `org-export-export-preprocess-string'.
44 ;;; Preparation functions:
46 (defvar org-export-structure nil
)
47 (defvar org-export-content nil
)
48 (defvar org-export-properties nil
)
50 (defun org-export-set-backend (suffix)
51 "Set the backend functions names from SUFFIX."
52 (setq org-export-structure
53 `((header ,(intern (concat "org-" suffix
"-export-header")))
54 (first-lines ,(intern (concat "org-" suffix
"-export-first-lines")))
55 (section-beginning ,(intern (concat "org-" suffix
"-export-section-beginning")))
56 (heading ,(intern (concat "org-" suffix
"-export-heading")))
57 (section-end ,(intern (concat "org-" suffix
"-export-section-end")))
58 (footer ,(intern (concat "org-" suffix
"-export-footer")))))
59 (setq org-export-content
60 `((fonts ,(intern (concat "org-" suffix
"-export-fonts")))
61 (links ,(intern (concat "org-" suffix
"-export-links")))
62 (lists ,(intern (concat "org-" suffix
"-export-lists")))
63 (envs ,(intern (concat "org-" suffix
"-export-quote-verse-center")))
64 (tables ,(intern (concat "org-" suffix
"-export-tables"))))))
66 ;;; Parsing functions:
68 (defun org-export-parse (&optional level
)
69 "Recursively parse the current buffer.
70 If LEVEL is set, do the parsing at that level of sectioning.
71 Return a nested list containing the structure of the parsed
72 buffer and information about each section, including its
76 (goto-char (point-min))
77 (while (re-search-forward org-complex-heading-regexp nil t
)
78 (let ((heading (match-string 4))
79 (properties (org-entry-properties)))
81 (narrow-to-region (if (looking-at "\n") (1+ (point)) (point))
83 (setq eos
(org-end-of-subtree t t
))))
87 (list :level
(or level
1)
89 :properties properties
90 :content
(org-export-get-entry-content)
91 :subtree
(org-export-parse
92 (if level
(1+ level
) 2)))))))
93 (goto-char (1- eos
)))))
96 (defun org-export-get-entry-content ()
97 "Extract the content of an entry.
98 The content of a entry is the part before its first subtree or
99 the end of the entry."
101 (goto-char (point-min))
102 ;; FIXME The following shouldn't be necessary since we are cleaning
103 ;; up the buffer ith org-export-preprocess-string
104 (while (or (looking-at org-property-drawer-re
)
105 (looking-at org-clock-drawer-re
)
106 (looking-at org-keyword-time-regexp
))
107 (move-beginning-of-line 1))
110 (if (re-search-forward org-complex-heading-regexp nil t
)
111 (match-beginning 0) (point-max)))))
113 ;;; Rendering functions:
115 (defun org-export-render (&optional filter
)
116 "Render the current Org buffer and export it.
117 First parse the buffer and return it as a nested list. If FILTER
118 is set, use it to filter this list (see `org-export-filter') then
119 export the (filtered) list with `org-export-render-structure'."
120 (setq org-export-properties
121 (org-combine-plists (org-default-export-plist)
122 (org-infile-export-plist)))
124 (bstring (buffer-string))
128 (insert (apply 'org-export-export-preprocess-string
129 bstring org-export-properties
))
130 (goto-char (point-min))
131 (setq first-lines
(org-export-get-entry-content))
132 (org-export-parse))))
133 (switch-to-buffer (get-buffer-create "*Org export*"))
135 (funcall (cadr (assoc 'header org-export-structure
)))
136 (funcall (cadr (assoc 'first-lines org-export-structure
)) first-lines
)
137 (org-export-render-structure parsed-buffer filter
)
138 (funcall (cadr (assoc 'footer org-export-structure
)))))
140 (defun org-export-render-structure (parsed-buffer &optional filter
)
141 "Render PARSED-BUFFER.
142 An optional argument FILTER specifies a filter to pass to the
145 (funcall (cadr (assoc 'section-beginning org-export-structure
)) s
)
146 (funcall (cadr (assoc 'heading org-export-structure
)) s
)
147 (insert (org-export-render-content s
) "\n\n")
148 (org-export-render-structure (plist-get s
:subtree
) filter
)
149 (funcall (cadr (assoc 'section-end org-export-structure
)) s
))
150 (org-export-filter parsed-buffer filter
)))
152 (defun org-export-render-content (section)
154 SECTION is either a string or a property list containing
155 informations (including content) for a section."
157 (insert (if (listp section
) (plist-get section
:content
) section
))
159 (goto-char (point-min))
160 (funcall (cadr (assoc e org-export-content
))))
161 '(fonts tables lists envs links
))
164 (defun org-export-filter (parsed-buffer filter
)
165 "Filter out PARSED-BUFFER with FILTER.
166 PARSED-BUFFER is a nested list of sections and subsections, as
167 produced by `org-export-parse'. FILTER is an alist of rules to
168 apply to PARSED-BUFFER. For the syntax of a filter, please check
169 the docstring of `org-export-latex-filter'."
170 ;; FIXME where is org-export-latex-filter
179 (let ((cnd (car f
)) (re (cadr f
)) prop-cnd
)
180 (or (and (eq cnd
'heading
)
181 (string-match re
(plist-get s
:heading
)))
182 (and (eq cnd
'content
)
183 (string-match re
(plist-get s
:content
)))
185 (assoc cnd
(plist-get s
:properties
)))
186 (string-match re
(cadr prop-cnd
))))))
188 nil
;; return nil if the section is filtered out
189 (progn (plist-put s
:subtree
190 (org-export-filter (plist-get s
:subtree
) filter
))
191 s
))) ;; return the section if it isn't filtered out
194 ;; FIXME This function is a copy of `org-export-preprocess-string' which
195 ;; should be rewritten for this export engine to work okay.
196 (defun org-export-export-preprocess-string (string &rest parameters
)
197 "Cleanup STRING so that that the true exported has a more consistent source.
198 This function takes STRING, which should be a buffer-string of an org-file
199 to export. It then creates a temporary buffer where it does its job.
200 The result is then again returned as a string, and the exporter works
201 on this string to produce the exported version."
203 (let* ((htmlp (plist-get parameters
:for-html
))
204 (asciip (plist-get parameters
:for-ascii
))
205 (latexp (plist-get parameters
:for-LaTeX
))
206 (docbookp (plist-get parameters
:for-docbook
))
207 (backend (cond (htmlp 'html
)
210 (docbookp 'docbook
)))
211 (archived-trees (plist-get parameters
:archived-trees
))
212 (inhibit-read-only t
)
213 (drawers org-drawers
)
214 (outline-regexp "\\*+ ")
217 (setq org-export-target-aliases nil
218 org-export-preferred-target-alist nil
219 org-export-id-target-alist nil
220 org-export-code-refs nil
)
222 (with-current-buffer (get-buffer-create " org-mode-tmp")
225 (setq case-fold-search t
)
227 (let ((inhibit-read-only t
))
228 (remove-text-properties (point-min) (point-max)
231 ;; Remove license-to-kill stuff
232 ;; The caller marks some stuff for killing, stuff that has been
233 ;; used to create the page title, for example.
234 (org-export-kill-licensed-text)
236 (let ((org-inhibit-startup t
)) (org-mode))
237 (setq case-fold-search t
)
238 (org-install-letbind)
241 (run-hooks 'org-export-preprocess-hook
)
243 ;; Process the macros
244 (org-export-preprocess-apply-macros)
245 (run-hooks 'org-export-preprocess-after-macros-hook
)
247 (untabify (point-min) (point-max))
249 ;; Handle include files, and call a hook
250 (org-export-handle-include-files-recurse)
251 (run-hooks 'org-export-preprocess-after-include-files-hook
)
253 ;; Get rid of archived trees
254 (org-export-remove-archived-trees archived-trees
)
256 ;; Remove comment environment and comment subtrees
257 (org-export-remove-comment-blocks-and-subtrees)
259 ;; Get rid of excluded trees, and call a hook
260 (org-export-handle-export-tags (plist-get parameters
:select-tags
)
261 (plist-get parameters
:exclude-tags
))
262 (run-hooks 'org-export-preprocess-after-tree-selection-hook
)
265 (org-export-mark-list-ending backend
)
267 ;; Handle source code snippets
268 ;; (org-export-export-replace-src-segments-and-examples backend)
270 ;; Protect short examples marked by a leading colon
271 (org-export-protect-colon-examples)
273 ;; Normalize footnotes
274 (when (plist-get parameters
:footnotes
)
275 (org-footnote-normalize nil t
))
277 ;; Find all headings and compute the targets for them
278 (setq target-alist
(org-export-define-heading-targets target-alist
))
280 (run-hooks 'org-export-preprocess-after-headline-targets-hook
)
282 ;; Find HTML special classes for headlines
283 (org-export-remember-html-container-classes)
285 ;; Get rid of drawers
286 (org-export-remove-or-extract-drawers
287 drawers
(plist-get parameters
:drawers
) backend
)
289 ;; Get the correct stuff before the first headline
290 (when (plist-get parameters
:skip-before-1st-heading
)
291 (goto-char (point-min))
292 (when (re-search-forward "^\\(#.*\n\\)?\\*+[ \t]" nil t
)
293 (delete-region (point-min) (match-beginning 0))
294 (goto-char (point-min))
296 (when (plist-get parameters
:text
)
297 (goto-char (point-min))
298 (insert (plist-get parameters
:text
) "\n"))
300 ;; Remove todo-keywords before exporting, if the user has requested so
301 (org-export-remove-headline-metadata parameters
)
303 ;; Find targets in comments and move them out of comments,
304 ;; but mark them as targets that should be invisible
305 (setq target-alist
(org-export-handle-invisible-targets target-alist
))
307 ;; Select and protect backend specific stuff, throw away stuff
308 ;; that is specific for other backends
309 (run-hooks 'org-export-preprocess-before-selecting-backend-code-hook
)
310 (org-export-select-backend-specific-text backend
)
312 ;; Protect quoted subtrees
313 (org-export-protect-quoted-subtrees)
315 ;; Remove clock lines
316 (org-export-remove-clock-lines)
318 ;; Protect verbatim elements
319 (org-export-protect-verbatim)
321 ;; Blockquotes, verse, and center
322 (org-export-mark-blockquote-verse-center)
323 (run-hooks 'org-export-preprocess-after-blockquote-hook
)
325 ;; Remove timestamps, if the user has requested so
326 (unless (plist-get parameters
:timestamps
)
327 (org-export-remove-timestamps))
329 ;; Attach captions to the correct object
330 ;; (setq target-alist (org-export-attach-captions-and-attributes
331 ;; backend target-alist))
333 ;; Find matches for radio targets and turn them into internal links
334 (org-export-mark-radio-links)
335 (run-hooks 'org-export-preprocess-after-radio-targets-hook
)
337 ;; Find all links that contain a newline and put them into a single line
338 (org-export-concatenate-multiline-links)
340 ;; Normalize links: Convert angle and plain links into bracket links
341 ;; and expand link abbreviations
342 (run-hooks 'org-export-preprocess-before-normalizing-links-hook
)
343 (org-export-normalize-links)
345 ;; Find all internal links. If they have a fuzzy match (i.e. not
346 ;; a *dedicated* target match, let the link point to the
347 ;; corresponding section.
348 (org-export-target-internal-links target-alist
)
350 ;; Find multiline emphasis and put them into single line
351 (when (plist-get parameters
:emph-multiline
)
352 (org-export-concatenate-multiline-emphasis))
354 ;; Remove special table lines
355 (when org-export-table-remove-special-lines
356 (org-export-remove-special-table-lines))
359 (run-hooks 'org-export-preprocess-before-backend-specifics-hook
)
361 ;; LaTeX-specific preprocessing
363 (require 'org-latex nil
)
364 (org-export-latex-preprocess parameters
))
366 ;; ASCII-specific preprocessing
368 (org-export-ascii-preprocess parameters
))
370 ;; HTML-specific preprocessing
372 (org-export-html-preprocess parameters
))
374 ;; DocBook-specific preprocessing
376 (require 'org-docbook nil
)
377 (org-export-docbook-preprocess parameters
))
379 ;; Remove or replace comments
380 (org-export-handle-comments (plist-get parameters
:comments
))
382 ;; Remove #+TBLFM and #+TBLNAME lines
383 (org-export-handle-table-metalines)
385 ;; Run the final hook
386 (run-hooks 'org-export-preprocess-final-hook
)
388 (setq rtn
(buffer-string))
389 (kill-buffer " org-mode-tmp"))
392 (provide 'org-export
)
394 ;;; User Options, Variables
396 ;;; org-export.el ends here