PageRenderTime 70ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/prelude/elpa/org-pandoc-20130729.2050/ox-pandoc.el

https://bitbucket.org/hoangtu/emacs
Emacs Lisp | 227 lines | 160 code | 32 blank | 35 comment | 2 complexity | dd4e0ed1a2bfc716dc380b7dcd5ce627 MD5 | raw file
  1. ;;; ox-pandoc.el --- Org exporter using Pandoc
  2. ;; Copyright 2013 Rob Tillotson
  3. ;; Author: Rob Tillotson <rob@pyrite.org>
  4. ;; Created: 2013-07-29
  5. ;; Version: 1.0
  6. ;; Package-Requires: ((org "8.0"))
  7. ;; This file is not part of GNU Emacs.
  8. ;;; License:
  9. ;; Permission is hereby granted, free of charge, to any person obtaining a copy of
  10. ;; this software and associated documentation files (the "Software"), to deal in
  11. ;; the Software without restriction, including without limitation the rights to
  12. ;; use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  13. ;; the Software, and to permit persons to whom the Software is furnished to do so,
  14. ;; subject to the following conditions:
  15. ;; The above copyright notice and this permission notice shall be included in all
  16. ;; copies or substantial portions of the Software.
  17. ;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. ;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  19. ;; FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  20. ;; COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  21. ;; IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22. ;; CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. ;;; Commentary:
  24. ;; This is a pandoc exporter for Org, built upon Markdown as an
  25. ;; intermediate format, and targeted at production of e-books in ePub format.
  26. ;;; Code:
  27. (eval-when-compile (require 'cl))
  28. (require 'ox-md)
  29. ;;; User Modifiable Variables:
  30. (defgroup org-export-pandoc nil
  31. "Options specific to Pandoc export back-end."
  32. :tag "Org Pandoc"
  33. :group 'org-export
  34. :version "24.4"
  35. :package-version '(Org . "8.0"))
  36. (defcustom org-pandoc-process-after-export t
  37. "Run pandoc to process the file after exporting it?"
  38. :group 'org-export-pandoc
  39. :type '(choice
  40. (const :tag "Yes" t)
  41. (const :tag "No" nil)))
  42. (defcustom org-pandoc-command "pandoc"
  43. "Command to run pandoc."
  44. :group 'org-export-pandoc
  45. :type 'string)
  46. (defcustom org-pandoc-extra-options ""
  47. "Extra pandoc options to use every time.
  48. For example, if you encounter stack overflows, put the options
  49. to expand the stack here."
  50. :group 'org-export-pandoc
  51. :type 'string)
  52. (defcustom org-pandoc-output-format 'epub
  53. "Default output format for pandoc conversion."
  54. :group 'org-export-pandoc
  55. :type 'symbol)
  56. (defcustom org-pandoc-output-standalone t
  57. "Should output be a single standalone file or not?"
  58. :group 'org-export-pandoc
  59. :type 'boolean)
  60. (defcustom org-pandoc-epub-rights nil
  61. "Copyright/license statement to include in EPUB metadata."
  62. :group 'org-export-pandoc
  63. :type 'string)
  64. (defcustom org-pandoc-epub-stylesheet nil
  65. "Stylesheet to apply to EPUB files."
  66. :group 'org-export-pandoc
  67. :type 'string)
  68. (defvar org-pandoc---epub-metadata nil)
  69. (defvar org-pandoc---epub-cover-filename nil)
  70. (defvar org-pandoc---epub-stylesheet-filename nil)
  71. (defvar org-pandoc---command-options nil)
  72. (org-export-define-derived-backend 'pandoc 'md
  73. :menu-entry
  74. '(?p "Export with Pandoc"
  75. ((?P "Markdown to buffer"
  76. (lambda (a s v b) (org-pandoc-export-as-pandoc a s v)))
  77. (?p "To file"
  78. (lambda (a s v b) (org-pandoc-export-to-pandoc a s v)))))
  79. :translate-alist '((template . org-pandoc-template))
  80. :options-alist '((:epub-rights "EPUB_RIGHTS" nil org-pandoc-epub-rights t)
  81. (:epub-cover "EPUB_COVER" nil nil t)
  82. (:epub-stylesheet "EPUB_STYLESHEET" nil org-pandoc-epub-stylesheet t)
  83. (:pandoc-options "PANDOC_OPTIONS" nil org-pandoc-extra-options 'space)
  84. ))
  85. ;; Some simple XML escaping code. I'm surprised this isn't
  86. ;; already in emacs somewhere...
  87. (defvar org-pandoc-xml-escapes
  88. '(("&" . "&amp;")
  89. ("'" . "&apos;")
  90. ("\"" . "&quot;")
  91. ("<" . "&lt;")
  92. (">" . "&gt;")))
  93. (defun org-pandoc-escape-xml (string)
  94. (mapc #'(lambda (item)
  95. (setq string
  96. (replace-regexp-in-string (car item) (cdr item) string)))
  97. org-pandoc-xml-escapes)
  98. string)
  99. (defun org-pandoc-make-copyright-string (author email)
  100. (format "Copyright %s %s%s" (format-time-string "%Y") author
  101. (if email
  102. (format " <%s>" email)
  103. "")))
  104. (defun org-pandoc-template (contents info)
  105. (let ((title (plist-get info :title))
  106. (author (plist-get info :author))
  107. (email (plist-get info :email))
  108. (description (plist-get info :description))
  109. (keywords (plist-get info :keywords))
  110. (date (org-export-get-date info "%Y-%m-%d"))
  111. (rights (plist-get info :epub-rights)))
  112. ;; Since the info alist isn't available after the export, build the metadata
  113. ;; now and put it in a buffer local variable.
  114. (if (or (eq org-pandoc-output-format 'epub)
  115. (eq org-pandoc-output-format 'epub3))
  116. (let ((xml (concat
  117. (when description
  118. (format "<dc:description>%s</dc:description>\n" (org-pandoc-escape-xml description)))
  119. (format "<dc:rights>%s</dc:rights>\n"
  120. (org-pandoc-escape-xml (or rights
  121. (org-pandoc-make-copyright-string (org-export-data author info) (org-export-data email info)))))
  122. (when keywords
  123. (format "<dc:subject>%s</dc:subject>\n" (org-pandoc-escape-xml keywords))))))
  124. (setq org-pandoc---epub-stylesheet-filename (plist-get info :epub-stylesheet))
  125. (setq org-pandoc---epub-metadata xml)
  126. (setq org-pandoc---epub-cover-filename (plist-get info :epub-cover)))
  127. (progn
  128. (setq org-pandoc---epub-stylesheet-filename nil)
  129. (setq org-pandoc---epub-metadata nil)
  130. (setq org-pandoc---epub-cover-filename nil)))
  131. (setq org-pandoc---command-options (plist-get info :pandoc-options))
  132. (concat (format "%% %s\n" (org-export-data title info))
  133. (when (and (plist-get info :with-author)
  134. author)
  135. (format "%% %s\n" (org-export-data author info)))
  136. (when (plist-get info :with-date)
  137. (format "%% %s\n" (org-export-data date info)))
  138. "\n"
  139. contents)))
  140. (defun org-pandoc-export-as-pandoc (&optional async subtreep visible-only)
  141. (interactive)
  142. (if async
  143. (org-export-async-start
  144. (lambda (output)
  145. (with-current-buffer (get-buffer-create "*Org Pandoc Export*")
  146. (erase-buffer)
  147. (insert output)
  148. (goto-char (point-min))
  149. (markdown-mode)
  150. (org-export-add-to-stack (current-buffer) 'pandoc)))
  151. `(org-export-as 'pandoc ,subtreep ,visible-only))
  152. (let ((outbuf (org-export-to-buffer 'pandoc "*Org Pandoc Export*" subtreep visible-only)))
  153. (with-current-buffer outbuf (markdown-mode))
  154. (when org-export-show-temporary-export-buffer
  155. (switch-to-buffer-other-window outbuf)))))
  156. (defun org-pandoc-run-pandoc (filename outfilename output-format &optional options)
  157. (let* ((args (list "-t" (symbol-name output-format)
  158. "-o" outfilename
  159. options
  160. filename))
  161. (command (concat org-pandoc-command " " (mapconcat 'identity args " "))))
  162. (message "Running pandoc as: %s" command)
  163. (message "Ran pandoc: %s" (shell-command-to-string command))))
  164. (defun org-pandoc-export-to-file (&optional outfile subtreep visible-only)
  165. (let ((metadata-file (make-temp-file "org-pandoc" nil ".xml"))
  166. (pandoc-output (concat (file-name-base outfile) "." (symbol-name org-pandoc-output-format))))
  167. (org-export-to-file 'pandoc outfile subtreep visible-only)
  168. ;; I really hate passing info back with global variables, but I don't know how
  169. ;; else to do it. Can't use a buffer local variable because the current buffer
  170. ;; is different in this function than when the export is actually running and
  171. ;; we have access to the info plist.
  172. (let ((options (concat (when org-pandoc-output-standalone " -s")
  173. (when org-pandoc---epub-cover-filename
  174. (format " --epub-cover-image=%s" org-pandoc---epub-cover-filename))
  175. (when org-pandoc---epub-stylesheet-filename
  176. (format " --epub-stylesheet=%s" org-pandoc---epub-stylesheet-filename))
  177. (when org-pandoc---command-options
  178. (concat " " org-pandoc---command-options)))))
  179. (when org-pandoc---epub-metadata
  180. (with-temp-file metadata-file
  181. (insert org-pandoc---epub-metadata))
  182. (setq options (concat options " --epub-metadata=" metadata-file)))
  183. (org-pandoc-run-pandoc outfile pandoc-output org-pandoc-output-format options))
  184. (delete-file metadata-file)
  185. ))
  186. (defun org-pandoc-export-to-pandoc (&optional async subtreep visible-only)
  187. (interactive)
  188. (let ((outfile (org-export-output-file-name ".md" subtreep)))
  189. (if async
  190. (org-export-async-start
  191. (lambda (f) (org-export-add-to-stack f 'pandoc))
  192. `(expand-file-name
  193. (org-pandoc-export-to-file ,outfile ,subtreep ,visible-only)))
  194. (org-pandoc-export-to-file outfile subtreep visible-only))))
  195. (provide 'ox-pandoc)