org-export.el 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. ;;; org-export.el --- Export engine for Org
  2. ;;
  3. ;; Copyright 2008 2010 Bastien Guerry
  4. ;;
  5. ;; Emacs Lisp Archive Entry
  6. ;; Filename: org-export.el
  7. ;; Version: 0.3
  8. ;; Author: Bastien <bzg AT altern DOT org>
  9. ;; Maintainer: Bastien <bzg AT altern DOT org>
  10. ;; Keywords:
  11. ;; Description:
  12. ;; URL: [Not distributed yet]
  13. ;;
  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)
  17. ;; any later version.
  18. ;;
  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.
  23. ;;
  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.
  27. ;;
  28. ;;; Commentary:
  29. ;;
  30. ;; org-export.el implements a new experimental export engine for Org.
  31. ;;
  32. ;; Put this file into your load-path and the following into your ~/.emacs:
  33. ;; (require 'org-export)
  34. ;;
  35. ;;; Todo:
  36. ;;
  37. ;; Rewrite `org-export-export-preprocess-string'.
  38. ;;
  39. ;;; Code:
  40. (eval-when-compile
  41. (require 'cl))
  42. ;;; Preparation functions:
  43. (defvar org-export-structure nil)
  44. (defvar org-export-content nil)
  45. (defvar org-export-properties nil)
  46. (defun org-export-set-backend (suffix)
  47. "Set the backend functions names from SUFFIX."
  48. (setq org-export-structure
  49. `((header ,(intern (concat "org-" suffix "-export-header")))
  50. (first-lines ,(intern (concat "org-" suffix "-export-first-lines")))
  51. (section-beginning ,(intern (concat "org-" suffix "-export-section-beginning")))
  52. (heading ,(intern (concat "org-" suffix "-export-heading")))
  53. (section-end ,(intern (concat "org-" suffix "-export-section-end")))
  54. (footer ,(intern (concat "org-" suffix "-export-footer")))))
  55. (setq org-export-content
  56. `((fonts ,(intern (concat "org-" suffix "-export-fonts")))
  57. (links ,(intern (concat "org-" suffix "-export-links")))
  58. (lists ,(intern (concat "org-" suffix "-export-lists")))
  59. (envs ,(intern (concat "org-" suffix "-export-quote-verse-center")))
  60. (tables ,(intern (concat "org-" suffix "-export-tables"))))))
  61. ;;; Parsing functions:
  62. (defun org-export-parse (&optional level)
  63. "Recursively parse the current buffer.
  64. If LEVEL is set, do the parsing at that level of sectioning.
  65. Return a nested list containing the structure of the parsed
  66. buffer and information about each section, including its
  67. content."
  68. (let (output eos)
  69. (save-excursion
  70. (goto-char (point-min))
  71. (while (re-search-forward org-complex-heading-regexp nil t)
  72. (let ((heading (match-string 4))
  73. (properties (org-entry-properties)))
  74. (save-restriction
  75. (narrow-to-region (if (looking-at "\n") (1+ (point)) (point))
  76. (save-excursion
  77. (setq eos (org-end-of-subtree t t))))
  78. (setq output
  79. (append output
  80. (list
  81. (list :level (or level 1)
  82. :heading heading
  83. :properties properties
  84. :content (org-export-get-entry-content)
  85. :subtree (org-export-parse
  86. (if level (1+ level) 2)))))))
  87. (goto-char (1- eos)))))
  88. output))
  89. (defun org-export-get-entry-content ()
  90. "Extract the content of an entry.
  91. The content of a entry is the part before its first subtree or
  92. the end of the entry."
  93. (save-excursion
  94. (goto-char (point-min))
  95. ;; FIXME The following shouldn't be necessary since we are cleaning
  96. ;; up the buffer ith org-export-preprocess-string
  97. (while (or (looking-at org-property-drawer-re)
  98. (looking-at org-clock-drawer-re)
  99. (looking-at org-keyword-time-regexp))
  100. (move-beginning-of-line 1))
  101. (buffer-substring
  102. (point)
  103. (if (re-search-forward org-complex-heading-regexp nil t)
  104. (match-beginning 0) (point-max)))))
  105. ;;; Rendering functions:
  106. (defun org-export-render (&optional filter)
  107. "Render the current Org buffer and export it.
  108. First parse the buffer and return it as a nested list. If FILTER
  109. is set, use it to filter this list (see `org-export-filter') then
  110. export the (filtered) list with `org-export-render-structure'."
  111. (setq org-export-properties
  112. (org-combine-plists (org-default-export-plist)
  113. (org-infile-export-plist)))
  114. (let* (first-lines
  115. (bstring (buffer-string))
  116. (parsed-buffer
  117. (with-temp-buffer
  118. (org-mode)
  119. (insert (apply 'org-export-export-preprocess-string
  120. bstring org-export-properties))
  121. (goto-char (point-min))
  122. (setq first-lines (org-export-get-entry-content))
  123. (org-export-parse))))
  124. (switch-to-buffer (get-buffer-create "*Org export*"))
  125. (erase-buffer)
  126. (funcall (cadr (assoc 'header org-export-structure)))
  127. (funcall (cadr (assoc 'first-lines org-export-structure)) first-lines)
  128. (org-export-render-structure parsed-buffer filter)
  129. (funcall (cadr (assoc 'footer org-export-structure)))))
  130. (defun org-export-render-structure (parsed-buffer &optional filter)
  131. "Render PARSED-BUFFER.
  132. An optional argument FILTER specifies a filter to pass to the
  133. rendering engine."
  134. (mapc (lambda(s)
  135. (funcall (cadr (assoc 'section-beginning org-export-structure)) s)
  136. (funcall (cadr (assoc 'heading org-export-structure)) s)
  137. (insert (org-export-render-content s) "\n\n")
  138. (org-export-render-structure (plist-get s :subtree) filter)
  139. (funcall (cadr (assoc 'section-end org-export-structure)) s))
  140. (org-export-filter parsed-buffer filter)))
  141. (defun org-export-render-content (section)
  142. "Render SECTION.
  143. SECTION is either a string or a property list containing
  144. informations (including content) for a section."
  145. (with-temp-buffer
  146. (insert (if (listp section) (plist-get section :content) section))
  147. (mapc (lambda(e)
  148. (goto-char (point-min))
  149. (funcall (cadr (assoc e org-export-content))))
  150. '(fonts tables lists envs links))
  151. (buffer-string)))
  152. (defun org-export-filter (parsed-buffer filter)
  153. "Filter out PARSED-BUFFER with FILTER.
  154. PARSED-BUFFER is a nested list of sections and subsections, as
  155. produced by `org-export-parse'. FILTER is an alist of rules to
  156. apply to PARSED-BUFFER. For the syntax of a filter, please check
  157. the docstring of `org-export-latex-filter'."
  158. ;; FIXME where is org-export-latex-filter
  159. (delete
  160. nil
  161. (mapcar
  162. (lambda(s)
  163. (if (delete
  164. nil
  165. (mapcar
  166. (lambda(f)
  167. (let ((cnd (car f)) (re (cadr f)) prop-cnd)
  168. (or (and (eq cnd 'heading)
  169. (string-match re (plist-get s :heading)))
  170. (and (eq cnd 'content)
  171. (string-match re (plist-get s :content)))
  172. (and (setq prop-cnd
  173. (assoc cnd (plist-get s :properties)))
  174. (string-match re (cadr prop-cnd))))))
  175. filter))
  176. nil ;; return nil if the section is filtered out
  177. (progn (plist-put s :subtree
  178. (org-export-filter (plist-get s :subtree) filter))
  179. s))) ;; return the section if it isn't filtered out
  180. parsed-buffer)))
  181. ;; FIXME This function is a copy of `org-export-preprocess-string' which
  182. ;; should be rewritten for this export engine to work okay.
  183. (defun org-export-export-preprocess-string (string &rest parameters)
  184. "Cleanup STRING so that that the true exported has a more consistent source.
  185. This function takes STRING, which should be a buffer-string of an org-file
  186. to export. It then creates a temporary buffer where it does its job.
  187. The result is then again returned as a string, and the exporter works
  188. on this string to produce the exported version."
  189. (interactive)
  190. (let* ((htmlp (plist-get parameters :for-html))
  191. (asciip (plist-get parameters :for-ascii))
  192. (latexp (plist-get parameters :for-LaTeX))
  193. (docbookp (plist-get parameters :for-docbook))
  194. (backend (cond (htmlp 'html)
  195. (latexp 'latex)
  196. (asciip 'ascii)
  197. (docbookp 'docbook)))
  198. (archived-trees (plist-get parameters :archived-trees))
  199. (inhibit-read-only t)
  200. (drawers org-drawers)
  201. (outline-regexp "\\*+ ")
  202. target-alist rtn)
  203. (setq org-export-target-aliases nil
  204. org-export-preferred-target-alist nil
  205. org-export-id-target-alist nil
  206. org-export-code-refs nil)
  207. (with-current-buffer (get-buffer-create " org-mode-tmp")
  208. (erase-buffer)
  209. (insert string)
  210. (setq case-fold-search t)
  211. (let ((inhibit-read-only t))
  212. (remove-text-properties (point-min) (point-max)
  213. '(read-only t)))
  214. ;; Remove license-to-kill stuff
  215. ;; The caller marks some stuff for killing, stuff that has been
  216. ;; used to create the page title, for example.
  217. (org-export-kill-licensed-text)
  218. (let ((org-inhibit-startup t)) (org-mode))
  219. (setq case-fold-search t)
  220. (org-install-letbind)
  221. ;; Call the hook
  222. (run-hooks 'org-export-preprocess-hook)
  223. ;; Process the macros
  224. (org-export-preprocess-apply-macros)
  225. (run-hooks 'org-export-preprocess-after-macros-hook)
  226. (untabify (point-min) (point-max))
  227. ;; Handle include files, and call a hook
  228. (org-export-handle-include-files-recurse)
  229. (run-hooks 'org-export-preprocess-after-include-files-hook)
  230. ;; Get rid of archived trees
  231. (org-export-remove-archived-trees archived-trees)
  232. ;; Remove comment environment and comment subtrees
  233. (org-export-remove-comment-blocks-and-subtrees)
  234. ;; Get rid of excluded trees, and call a hook
  235. (org-export-handle-export-tags (plist-get parameters :select-tags)
  236. (plist-get parameters :exclude-tags))
  237. (run-hooks 'org-export-preprocess-after-tree-selection-hook)
  238. ;; Mark end of lists
  239. (org-export-mark-list-ending backend)
  240. ;; Handle source code snippets
  241. ;; (org-export-export-replace-src-segments-and-examples backend)
  242. ;; Protect short examples marked by a leading colon
  243. (org-export-protect-colon-examples)
  244. ;; Normalize footnotes
  245. (when (plist-get parameters :footnotes)
  246. (org-footnote-normalize nil t))
  247. ;; Find all headings and compute the targets for them
  248. (setq target-alist (org-export-define-heading-targets target-alist))
  249. (run-hooks 'org-export-preprocess-after-headline-targets-hook)
  250. ;; Find HTML special classes for headlines
  251. (org-export-remember-html-container-classes)
  252. ;; Get rid of drawers
  253. (org-export-remove-or-extract-drawers
  254. drawers (plist-get parameters :drawers) backend)
  255. ;; Get the correct stuff before the first headline
  256. (when (plist-get parameters :skip-before-1st-heading)
  257. (goto-char (point-min))
  258. (when (re-search-forward "^\\(#.*\n\\)?\\*+[ \t]" nil t)
  259. (delete-region (point-min) (match-beginning 0))
  260. (goto-char (point-min))
  261. (insert "\n")))
  262. (when (plist-get parameters :text)
  263. (goto-char (point-min))
  264. (insert (plist-get parameters :text) "\n"))
  265. ;; Remove todo-keywords before exporting, if the user has requested so
  266. (org-export-remove-headline-metadata parameters)
  267. ;; Find targets in comments and move them out of comments,
  268. ;; but mark them as targets that should be invisible
  269. (setq target-alist (org-export-handle-invisible-targets target-alist))
  270. ;; Select and protect backend specific stuff, throw away stuff
  271. ;; that is specific for other backends
  272. (run-hooks 'org-export-preprocess-before-selecting-backend-code-hook)
  273. (org-export-select-backend-specific-text backend)
  274. ;; Protect quoted subtrees
  275. (org-export-protect-quoted-subtrees)
  276. ;; Remove clock lines
  277. (org-export-remove-clock-lines)
  278. ;; Protect verbatim elements
  279. (org-export-protect-verbatim)
  280. ;; Blockquotes, verse, and center
  281. (org-export-mark-blockquote-verse-center)
  282. (run-hooks 'org-export-preprocess-after-blockquote-hook)
  283. ;; Remove timestamps, if the user has requested so
  284. (unless (plist-get parameters :timestamps)
  285. (org-export-remove-timestamps))
  286. ;; Attach captions to the correct object
  287. ;; (setq target-alist (org-export-attach-captions-and-attributes
  288. ;; backend target-alist))
  289. ;; Find matches for radio targets and turn them into internal links
  290. (org-export-mark-radio-links)
  291. (run-hooks 'org-export-preprocess-after-radio-targets-hook)
  292. ;; Find all links that contain a newline and put them into a single line
  293. (org-export-concatenate-multiline-links)
  294. ;; Normalize links: Convert angle and plain links into bracket links
  295. ;; and expand link abbreviations
  296. (run-hooks 'org-export-preprocess-before-normalizing-links-hook)
  297. (org-export-normalize-links)
  298. ;; Find all internal links. If they have a fuzzy match (i.e. not
  299. ;; a *dedicated* target match, let the link point to the
  300. ;; corresponding section.
  301. (org-export-target-internal-links target-alist)
  302. ;; Find multiline emphasis and put them into single line
  303. (when (plist-get parameters :emph-multiline)
  304. (org-export-concatenate-multiline-emphasis))
  305. ;; Remove special table lines
  306. (when org-export-table-remove-special-lines
  307. (org-export-remove-special-table-lines))
  308. ;; Another hook
  309. (run-hooks 'org-export-preprocess-before-backend-specifics-hook)
  310. ;; LaTeX-specific preprocessing
  311. (when latexp
  312. (require 'org-latex nil)
  313. (org-export-latex-preprocess parameters))
  314. ;; ASCII-specific preprocessing
  315. (when asciip
  316. (org-export-ascii-preprocess parameters))
  317. ;; HTML-specific preprocessing
  318. (when htmlp
  319. (org-export-html-preprocess parameters))
  320. ;; DocBook-specific preprocessing
  321. (when docbookp
  322. (require 'org-docbook nil)
  323. (org-export-docbook-preprocess parameters))
  324. ;; Remove or replace comments
  325. (org-export-handle-comments (plist-get parameters :comments))
  326. ;; Remove #+TBLFM and #+TBLNAME lines
  327. (org-export-handle-table-metalines)
  328. ;; Run the final hook
  329. (run-hooks 'org-export-preprocess-final-hook)
  330. (setq rtn (buffer-string))
  331. (kill-buffer " org-mode-tmp"))
  332. rtn))
  333. (provide 'org-export)
  334. ;;; User Options, Variables
  335. ;;; org-export.el ends here