diff options
author | Luke Shumaker <LukeShu@sbcglobal.net> | 2011-04-13 23:20:15 -0400 |
---|---|---|
committer | Luke Shumaker <LukeShu@sbcglobal.net> | 2011-04-13 23:20:15 -0400 |
commit | f7464fdd2e33e5dc6c159a4adc8f53902e6d4511 (patch) | |
tree | b1d65db982af54cc2088de3228174c4ea710c2f4 /.emacs.d/org-7.4/lisp/org-docbook.el |
Initial commit of Luke Shumaker's "dot-files".
Diffstat (limited to '.emacs.d/org-7.4/lisp/org-docbook.el')
-rw-r--r-- | .emacs.d/org-7.4/lisp/org-docbook.el | 1444 |
1 files changed, 1444 insertions, 0 deletions
diff --git a/.emacs.d/org-7.4/lisp/org-docbook.el b/.emacs.d/org-7.4/lisp/org-docbook.el new file mode 100644 index 0000000..91ebb97 --- /dev/null +++ b/.emacs.d/org-7.4/lisp/org-docbook.el @@ -0,0 +1,1444 @@ +;;; org-docbook.el --- DocBook exporter for org-mode +;; +;; Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +;; +;; Emacs Lisp Archive Entry +;; Filename: org-docbook.el +;; Version: 7.4 +;; Author: Baoqiu Cui <cbaoqiu AT yahoo DOT com> +;; Maintainer: Baoqiu Cui <cbaoqiu AT yahoo DOT com> +;; Keywords: org, wp, docbook +;; Description: Converts an org-mode buffer into DocBook +;; URL: + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. + +;;; Commentary: +;; +;; This library implements a DocBook exporter for org-mode. The basic +;; idea and design is very similar to what `org-export-as-html' has. +;; Code prototype was also started with `org-export-as-html'. +;; +;; Put this file into your load-path and the following line into your +;; ~/.emacs: +;; +;; (require 'org-docbook) +;; +;; The interactive functions are similar to those of the HTML and LaTeX +;; exporters: +;; +;; M-x `org-export-as-docbook' +;; M-x `org-export-as-docbook-pdf' +;; M-x `org-export-as-docbook-pdf-and-open' +;; M-x `org-export-as-docbook-batch' +;; M-x `org-export-as-docbook-to-buffer' +;; M-x `org-export-region-as-docbook' +;; M-x `org-replace-region-by-docbook' +;; +;; Note that, in order to generate PDF files using the DocBook XML files +;; created by DocBook exporter, the following two variables have to be +;; set based on what DocBook tools you use for XSLT processor and XSL-FO +;; processor: +;; +;; org-export-docbook-xslt-proc-command +;; org-export-docbook-xsl-fo-proc-command +;; +;; Check the document of these two variables to see examples of how they +;; can be set. +;; +;; If the Org file to be exported contains special characters written in +;; TeX-like syntax, like \alpha and \beta, you need to include the right +;; entity file(s) in the DOCTYPE declaration for the DocBook XML file. +;; This is required to make the DocBook XML file valid. The DOCTYPE +;; declaration string can be set using the following variable: +;; +;; org-export-docbook-doctype +;; +;;; Code: + +(eval-when-compile + (require 'cl)) + +(require 'footnote) +(require 'org) +(require 'org-exp) +(require 'org-html) +(require 'format-spec) + +;;; Variables: + +(defvar org-docbook-para-open nil) +(defvar org-export-docbook-inline-images t) +(defvar org-export-docbook-link-org-files-as-docbook nil) + +(declare-function org-id-find-id-file "org-id" (id)) + +;;; User variables: + +(defgroup org-export-docbook nil + "Options for exporting Org-mode files to DocBook." + :tag "Org Export DocBook" + :group 'org-export) + +(defcustom org-export-docbook-extension ".xml" + "Extension of DocBook XML files." + :group 'org-export-docbook + :type 'string) + +(defcustom org-export-docbook-header "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "Header of DocBook XML files." + :group 'org-export-docbook + :type 'string) + +(defcustom org-export-docbook-doctype nil + "DOCTYPE declaration string for DocBook XML files. +This can be used to include entities that are needed to handle +special characters in Org files. + +For example, if the Org file to be exported contains XHTML +entities, you can set this variable to: + +\"<!DOCTYPE article [ +<!ENTITY % xhtml1-symbol PUBLIC +\"-//W3C//ENTITIES Symbol for HTML//EN//XML\" +\"http://www.w3.org/2003/entities/2007/xhtml1-symbol.ent\" +> +%xhtml1-symbol; +]> +\" + +If you want to process DocBook documents without an Internet +connection, it is suggested that you download the required entity +file(s) and use system identifier(s) (external files) in the +DOCTYPE declaration." + :group 'org-export-docbook + :type 'string) + +(defcustom org-export-docbook-article-header "<article xmlns=\"http://docbook.org/ns/docbook\" + xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"5.0\" xml:lang=\"en\">" + "Article header of DocBook XML files." + :group 'org-export-docbook + :type 'string) + +(defcustom org-export-docbook-section-id-prefix "sec-" + "Prefix of section IDs used during exporting. +This can be set before exporting to avoid same set of section IDs +being used again and again, which can be a problem when multiple +people work on the same document." + :group 'org-export-docbook + :type 'string) + +(defcustom org-export-docbook-footnote-id-prefix "fn-" + "The prefix of footnote IDs used during exporting. +Like `org-export-docbook-section-id-prefix', this variable can help +avoid same set of footnote IDs being used multiple times." + :group 'org-export-docbook + :type 'string) + +(defcustom org-export-docbook-emphasis-alist + `(("*" "<emphasis role=\"bold\">" "</emphasis>") + ("/" "<emphasis>" "</emphasis>") + ("_" "<emphasis role=\"underline\">" "</emphasis>") + ("=" "<code>" "</code>") + ("~" "<literal>" "</literal>") + ("+" "<emphasis role=\"strikethrough\">" "</emphasis>")) + "A list of DocBook expressions to convert emphasis fontifiers. +Each element of the list is a list of three elements. +The first element is the character used as a marker for fontification. +The second element is a formatting string to wrap fontified text with. +The third element decides whether to protect converted text from other +conversions." + :group 'org-export-docbook + :type 'alist) + +(defcustom org-export-docbook-default-image-attributes + `(("align" . "\"center\"") + ("valign". "\"middle\"")) + "Alist of default DocBook image attributes. +These attributes will be inserted into element <imagedata> by +default, but users can override them using `#+ATTR_DocBook:'." + :group 'org-export-docbook + :type 'alist) + +(defcustom org-export-docbook-inline-image-extensions + '("jpeg" "jpg" "png" "gif" "svg") + "Extensions of image files that can be inlined into DocBook." + :group 'org-export-docbook + :type '(repeat (string :tag "Extension"))) + +(defcustom org-export-docbook-coding-system nil + "Coding system for DocBook XML files." + :group 'org-export-docbook + :type 'coding-system) + +(defcustom org-export-docbook-xslt-stylesheet nil + "File name of the XSLT stylesheet used by DocBook exporter. +This XSLT stylesheet is used by +`org-export-docbook-xslt-proc-command' to generate the Formatting +Object (FO) files. You can use either `fo/docbook.xsl' that +comes with DocBook, or any customization layer you may have." + :group 'org-export-docbook + :type 'string) + +(defcustom org-export-docbook-xslt-proc-command nil + "Format of XSLT processor command used by DocBook exporter. +This command is used to process a DocBook XML file to generate +the Formatting Object (FO) file. + +The value of this variable should be a format control string that +includes three arguments: `%i', `%o', and `%s'. During exporting +time, `%i' is replaced by the input DocBook XML file name, `%o' +is replaced by the output FO file name, and `%s' is replaced by +`org-export-docbook-xslt-stylesheet' (or the #+XSLT option if it +is specified in the Org file). + +For example, if you use Saxon as the XSLT processor, you may want +to set the variable to + + \"java com.icl.saxon.StyleSheet -o %o %i %s\" + +If you use Xalan, you can set it to + + \"java org.apache.xalan.xslt.Process -out %o -in %i -xsl %s\" + +For xsltproc, the following string should work: + + \"xsltproc --output %o %s %i\" + +You can include additional stylesheet parameters in this command. +Just make sure that they meet the syntax requirement of each +processor." + :group 'org-export-docbook + :type 'string) + +(defcustom org-export-docbook-xsl-fo-proc-command nil + "Format of XSL-FO processor command used by DocBook exporter. +This command is used to process a Formatting Object (FO) file to +generate the PDF file. + +The value of this variable should be a format control string that +includes two arguments: `%i' and `%o'. During exporting time, +`%i' is replaced by the input FO file name, and `%o' is replaced +by the output PDF file name. + +For example, if you use FOP as the XSL-FO processor, you can set +the variable to + + \"fop %i %o\"" + :group 'org-export-docbook + :type 'string) + +(defcustom org-export-docbook-keywords-markup "<literal>%s</literal>" + "A printf format string to be applied to keywords by DocBook exporter." + :group 'org-export-docbook + :type 'string) + +(defcustom org-export-docbook-timestamp-markup "<emphasis>%s</emphasis>" + "A printf format string to be applied to time stamps by DocBook exporter." + :group 'org-export-docbook + :type 'string) + +;;; Hooks + +(defvar org-export-docbook-final-hook nil + "Hook run at the end of DocBook export, in the new buffer.") + +;;; Autoload functions: + +;;;###autoload +(defun org-export-as-docbook-batch () + "Call `org-export-as-docbook' in batch style. +This function can be used in batch processing. + +For example: + +$ emacs --batch + --load=$HOME/lib/emacs/org.el + --visit=MyOrgFile.org --funcall org-export-as-docbook-batch" + (org-export-as-docbook 'hidden)) + +;;;###autoload +(defun org-export-as-docbook-to-buffer () + "Call `org-export-as-docbook' with output to a temporary buffer. +No file is created." + (interactive) + (org-export-as-docbook nil nil "*Org DocBook Export*") + (when org-export-show-temporary-export-buffer + (switch-to-buffer-other-window "*Org DocBook Export*"))) + +;;;###autoload +(defun org-replace-region-by-docbook (beg end) + "Replace the region from BEG to END with its DocBook export. +It assumes the region has `org-mode' syntax, and then convert it to +DocBook. This can be used in any buffer. For example, you could +write an itemized list in `org-mode' syntax in an DocBook buffer and +then use this command to convert it." + (interactive "r") + (let (reg docbook buf) + (save-window-excursion + (if (org-mode-p) + (setq docbook (org-export-region-as-docbook + beg end t 'string)) + (setq reg (buffer-substring beg end) + buf (get-buffer-create "*Org tmp*")) + (with-current-buffer buf + (erase-buffer) + (insert reg) + (org-mode) + (setq docbook (org-export-region-as-docbook + (point-min) (point-max) t 'string))) + (kill-buffer buf))) + (delete-region beg end) + (insert docbook))) + +;;;###autoload +(defun org-export-region-as-docbook (beg end &optional body-only buffer) + "Convert region from BEG to END in `org-mode' buffer to DocBook. +If prefix arg BODY-ONLY is set, omit file header and footer and +only produce the region of converted text, useful for +cut-and-paste operations. If BUFFER is a buffer or a string, +use/create that buffer as a target of the converted DocBook. If +BUFFER is the symbol `string', return the produced DocBook as a +string and leave not buffer behind. For example, a Lisp program +could call this function in the following way: + + (setq docbook (org-export-region-as-docbook beg end t 'string)) + +When called interactively, the output buffer is selected, and shown +in a window. A non-interactive call will only return the buffer." + (interactive "r\nP") + (when (interactive-p) + (setq buffer "*Org DocBook Export*")) + (let ((transient-mark-mode t) + (zmacs-regions t) + rtn) + (goto-char end) + (set-mark (point)) ;; To activate the region + (goto-char beg) + (setq rtn (org-export-as-docbook + nil nil + buffer body-only)) + (if (fboundp 'deactivate-mark) (deactivate-mark)) + (if (and (interactive-p) (bufferp rtn)) + (switch-to-buffer-other-window rtn) + rtn))) + +;;;###autoload +(defun org-export-as-docbook-pdf (&optional hidden ext-plist + to-buffer body-only pub-dir) + "Export as DocBook XML file, and generate PDF file." + (interactive "P") + (if (or (not org-export-docbook-xslt-proc-command) + (not (string-match "%[ios].+%[ios].+%[ios]" org-export-docbook-xslt-proc-command))) + (error "XSLT processor command is not set correctly")) + (if (or (not org-export-docbook-xsl-fo-proc-command) + (not (string-match "%[io].+%[io]" org-export-docbook-xsl-fo-proc-command))) + (error "XSL-FO processor command is not set correctly")) + (message "Exporting to PDF...") + (let* ((wconfig (current-window-configuration)) + (opt-plist + (org-export-process-option-filters + (org-combine-plists (org-default-export-plist) + ext-plist + (org-infile-export-plist)))) + (docbook-buf (org-export-as-docbook hidden ext-plist + to-buffer body-only pub-dir)) + (filename (buffer-file-name docbook-buf)) + (base (file-name-sans-extension filename)) + (fofile (concat base ".fo")) + (pdffile (concat base ".pdf"))) + (and (file-exists-p pdffile) (delete-file pdffile)) + (message "Processing DocBook XML file...") + (shell-command (format-spec org-export-docbook-xslt-proc-command + (format-spec-make + ?i (shell-quote-argument filename) + ?o (shell-quote-argument fofile) + ?s (shell-quote-argument + (or (plist-get opt-plist :xslt) + org-export-docbook-xslt-stylesheet))))) + (shell-command (format-spec org-export-docbook-xsl-fo-proc-command + (format-spec-make + ?i (shell-quote-argument fofile) + ?o (shell-quote-argument pdffile)))) + (message "Processing DocBook file...done") + (if (not (file-exists-p pdffile)) + (error "PDF file was not produced") + (set-window-configuration wconfig) + (message "Exporting to PDF...done") + pdffile))) + +;;;###autoload +(defun org-export-as-docbook-pdf-and-open () + "Export as DocBook XML file, generate PDF file, and open it." + (interactive) + (let ((pdffile (org-export-as-docbook-pdf))) + (if pdffile + (org-open-file pdffile) + (error "PDF file was not produced")))) + +;;;###autoload +(defun org-export-as-docbook (&optional hidden ext-plist + to-buffer body-only pub-dir) + "Export the current buffer as a DocBook file. +If there is an active region, export only the region. When +HIDDEN is obsolete and does nothing. EXT-PLIST is a +property list with external parameters overriding org-mode's +default settings, but still inferior to file-local settings. +When TO-BUFFER is non-nil, create a buffer with that name and +export to that buffer. If TO-BUFFER is the symbol `string', +don't leave any buffer behind but just return the resulting HTML +as a string. When BODY-ONLY is set, don't produce the file +header and footer, simply return the content of the document (all +top-level sections). When PUB-DIR is set, use this as the +publishing directory." + (interactive "P") + (run-hooks 'org-export-first-hook) + + ;; Make sure we have a file name when we need it. + (when (and (not (or to-buffer body-only)) + (not buffer-file-name)) + (if (buffer-base-buffer) + (org-set-local 'buffer-file-name + (with-current-buffer (buffer-base-buffer) + buffer-file-name)) + (error "Need a file name to be able to export"))) + + (message "Exporting...") + (setq-default org-todo-line-regexp org-todo-line-regexp) + (setq-default org-deadline-line-regexp org-deadline-line-regexp) + (setq-default org-done-keywords org-done-keywords) + (setq-default org-maybe-keyword-time-regexp org-maybe-keyword-time-regexp) + (let* ((opt-plist + (org-export-process-option-filters + (org-combine-plists (org-default-export-plist) + ext-plist + (org-infile-export-plist)))) + (link-validate (plist-get opt-plist :link-validation-function)) + valid + (odd org-odd-levels-only) + (region-p (org-region-active-p)) + (rbeg (and region-p (region-beginning))) + (rend (and region-p (region-end))) + (subtree-p + (if (plist-get opt-plist :ignore-subtree-p) + nil + (when region-p + (save-excursion + (goto-char rbeg) + (and (org-at-heading-p) + (>= (org-end-of-subtree t t) rend)))))) + (level-offset (if subtree-p + (save-excursion + (goto-char rbeg) + (+ (funcall outline-level) + (if org-odd-levels-only 1 0))) + 0)) + (opt-plist (setq org-export-opt-plist + (if subtree-p + (org-export-add-subtree-options opt-plist rbeg) + opt-plist))) + ;; The following two are dynamically scoped into other + ;; routines below. + (org-current-export-dir + (or pub-dir (org-export-directory :docbook opt-plist))) + (org-current-export-file buffer-file-name) + (level 0) (line "") (origline "") txt todo + (filename (if to-buffer nil + (expand-file-name + (concat + (file-name-sans-extension + (or (and subtree-p + (org-entry-get (region-beginning) + "EXPORT_FILE_NAME" t)) + (file-name-nondirectory buffer-file-name))) + org-export-docbook-extension) + (file-name-as-directory + (or pub-dir (org-export-directory :docbook opt-plist)))))) + (current-dir (if buffer-file-name + (file-name-directory buffer-file-name) + default-directory)) + (buffer (if to-buffer + (cond + ((eq to-buffer 'string) (get-buffer-create "*Org DocBook Export*")) + (t (get-buffer-create to-buffer))) + (find-file-noselect filename))) + ;; org-levels-open is a global variable + (org-levels-open (make-vector org-level-max nil)) + (date (plist-get opt-plist :date)) + (author (or (plist-get opt-plist :author) + user-full-name)) + (email (plist-get opt-plist :email)) + firstname othername surname + (title (or (and subtree-p (org-export-get-title-from-subtree)) + (plist-get opt-plist :title) + (and (not + (plist-get opt-plist :skip-before-1st-heading)) + (org-export-grab-title-from-buffer)) + (and buffer-file-name + (file-name-sans-extension + (file-name-nondirectory buffer-file-name))) + "UNTITLED")) + ;; We will use HTML table formatter to export tables to DocBook + ;; format, so need to set html-table-tag here. + (html-table-tag (plist-get opt-plist :html-table-tag)) + (quote-re0 (concat "^[ \t]*" org-quote-string "\\>")) + (quote-re (concat "^\\(\\*+\\)\\([ \t]+" org-quote-string "\\>\\)")) + (inquote nil) + (infixed nil) + (inverse nil) + (in-local-list nil) + (local-list-type nil) + (local-list-indent nil) + (llt org-plain-list-ordered-item-terminator) + (email (plist-get opt-plist :email)) + (language (plist-get opt-plist :language)) + (lang-words nil) + cnt + (start 0) + (coding-system (and (boundp 'buffer-file-coding-system) + buffer-file-coding-system)) + (coding-system-for-write (or org-export-docbook-coding-system + coding-system)) + (save-buffer-coding-system (or org-export-docbook-coding-system + coding-system)) + (charset (and coding-system-for-write + (fboundp 'coding-system-get) + (coding-system-get coding-system-for-write + 'mime-charset))) + (region + (buffer-substring + (if region-p (region-beginning) (point-min)) + (if region-p (region-end) (point-max)))) + (lines + (org-split-string + (org-export-preprocess-string + region + :emph-multiline t + :for-docbook t + :skip-before-1st-heading + (plist-get opt-plist :skip-before-1st-heading) + :drawers (plist-get opt-plist :drawers) + :todo-keywords (plist-get opt-plist :todo-keywords) + :tags (plist-get opt-plist :tags) + :priority (plist-get opt-plist :priority) + :footnotes (plist-get opt-plist :footnotes) + :timestamps (plist-get opt-plist :timestamps) + :archived-trees + (plist-get opt-plist :archived-trees) + :select-tags (plist-get opt-plist :select-tags) + :exclude-tags (plist-get opt-plist :exclude-tags) + :add-text + (plist-get opt-plist :text) + :LaTeX-fragments + (plist-get opt-plist :LaTeX-fragments)) + "[\r\n]")) + ;; Use literal output to show check boxes. + (checkbox-start + (nth 1 (assoc "=" org-export-docbook-emphasis-alist))) + (checkbox-end + (nth 2 (assoc "=" org-export-docbook-emphasis-alist))) + table-open type + table-buffer table-orig-buffer + ind item-type starter + rpl path attr caption label desc descp desc1 desc2 link + fnc item-tag item-number + footref-seen footnote-list + id-file + ) + + ;; Fine detailed info about author name. + (if (string-match "\\([^ ]+\\) \\(.+ \\)?\\([^ ]+\\)" author) + (progn + (setq firstname (match-string 1 author) + othername (or (match-string 2 author) "") + surname (match-string 3 author)))) + + ;; Get all footnote text. + (setq footnote-list + (org-export-docbook-get-footnotes lines)) + + (let ((inhibit-read-only t)) + (org-unmodified + (remove-text-properties (point-min) (point-max) + '(:org-license-to-kill t)))) + + (setq org-min-level (org-get-min-level lines level-offset)) + (setq org-last-level org-min-level) + (org-init-section-numbers) + + ;; Get and save the date. + (cond + ((and date (string-match "%" date)) + (setq date (format-time-string date))) + (date) + (t (setq date (format-time-string "%Y-%m-%d %T %Z")))) + + ;; Get the language-dependent settings + (setq lang-words (or (assoc language org-export-language-setup) + (assoc "en" org-export-language-setup))) + + ;; Switch to the output buffer. Use fundamental-mode for now. We + ;; could turn on nXML mode later and do some indentation. + (set-buffer buffer) + (let ((inhibit-read-only t)) (erase-buffer)) + (fundamental-mode) + (org-install-letbind) + + (and (fboundp 'set-buffer-file-coding-system) + (set-buffer-file-coding-system coding-system-for-write)) + + ;; The main body... + (let ((case-fold-search nil) + (org-odd-levels-only odd)) + + ;; Create local variables for all options, to make sure all called + ;; functions get the correct information + (mapc (lambda (x) + (set (make-local-variable (nth 2 x)) + (plist-get opt-plist (car x)))) + org-export-plist-vars) + + ;; Insert DocBook file header, title, and author info. + (unless body-only + (insert org-export-docbook-header) + (if org-export-docbook-doctype + (insert org-export-docbook-doctype)) + (insert "<!-- Date: " date " -->\n") + (insert (format "<!-- DocBook XML file generated by Org-mode %s Emacs %s -->\n" + org-version emacs-major-version)) + (insert org-export-docbook-article-header) + (insert (format + "\n <title>%s</title> + <info> + <author> + <personname> + <firstname>%s</firstname> <othername>%s</othername> <surname>%s</surname> + </personname> + %s + </author> + </info>\n" + (org-docbook-expand title) + firstname othername surname + (if (and org-export-email-info + email (string-match "\\S-" email)) + (concat "<email>" email "</email>") "") + ))) + + (org-init-section-numbers) + + (org-export-docbook-open-para) + + ;; Loop over all the lines... + (while (setq line (pop lines) origline line) + (catch 'nextline + + ;; End of quote section? + (when (and inquote (string-match "^\\*+ " line)) + (insert "]]></programlisting>\n") + (org-export-docbook-open-para) + (setq inquote nil)) + ;; Inside a quote section? + (when inquote + (insert (org-docbook-protect line) "\n") + (throw 'nextline nil)) + + ;; Fixed-width, verbatim lines (examples) + (when (and org-export-with-fixed-width + (string-match "^[ \t]*:\\(\\([ \t]\\|$\\)\\(.*\\)\\)" line)) + (when (not infixed) + (setq infixed t) + (org-export-docbook-close-para-maybe) + (insert "<programlisting><![CDATA[")) + (insert (match-string 3 line) "\n") + (when (or (not lines) + (not (string-match "^[ \t]*\\(:.*\\)" + (car lines)))) + (setq infixed nil) + (insert "]]></programlisting>\n") + (org-export-docbook-open-para)) + (throw 'nextline nil)) + + ;; List ender: close every open list. + (when (equal "ORG-LIST-END" line) + (while local-list-type + (let ((listtype (car local-list-type))) + (org-export-docbook-close-li listtype) + (insert (cond + ((equal listtype "o") "</orderedlist>\n") + ((equal listtype "u") "</itemizedlist>\n") + ((equal listtype "d") "</variablelist>\n")))) + (pop local-list-type)) + ;; We did close a list, normal text follows: need <para> + (org-export-docbook-open-para) + (setq local-list-indent nil + in-local-list nil) + (throw 'nextline nil)) + + ;; Protected HTML + (when (get-text-property 0 'org-protected line) + (let (par (ind (get-text-property 0 'original-indentation line))) + (when (re-search-backward + "\\(<para>\\)\\([ \t\r\n]*\\)\\=" (- (point) 100) t) + (setq par (match-string 1)) + (replace-match "\\2\n")) + (insert line "\n") + (while (and lines + (or (= (length (car lines)) 0) + (not ind) + (equal ind (get-text-property 0 'original-indentation (car lines)))) + (or (= (length (car lines)) 0) + (get-text-property 0 'org-protected (car lines)))) + (insert (pop lines) "\n")) + (and par (insert "<para>\n"))) + (throw 'nextline nil)) + + ;; Start of block quotes and verses + (when (or (equal "ORG-BLOCKQUOTE-START" line) + (and (equal "ORG-VERSE-START" line) + (setq inverse t))) + (org-export-docbook-close-para-maybe) + (insert "<blockquote>") + ;; Check whether attribution for this blockquote exists. + (let (tmp1 + attribution + (end (if inverse "ORG-VERSE-END" "ORG-BLOCKQUOTE-END")) + (quote-lines nil)) + (while (and (setq tmp1 (pop lines)) + (not (equal end tmp1))) + (push tmp1 quote-lines)) + (push tmp1 lines) ; Put back quote end mark + ;; Check the last line in the quote to see if it contains + ;; the attribution. + (setq tmp1 (pop quote-lines)) + (if (string-match "\\(^.*\\)\\(--[ \t]+\\)\\(.+\\)$" tmp1) + (progn + (setq attribution (match-string 3 tmp1)) + (when (save-match-data + (string-match "[^ \t]" (match-string 1 tmp1))) + (push (match-string 1 tmp1) lines))) + (push tmp1 lines)) + (while (setq tmp1 (pop quote-lines)) + (push tmp1 lines)) + (when attribution + (insert "<attribution>" attribution "</attribution>"))) + ;; Insert <literallayout> for verse. + (if inverse + (insert "\n<literallayout>") + (org-export-docbook-open-para)) + (throw 'nextline nil)) + + ;; End of block quotes + (when (equal "ORG-BLOCKQUOTE-END" line) + (org-export-docbook-close-para-maybe) + (insert "</blockquote>\n") + (org-export-docbook-open-para) + (throw 'nextline nil)) + + ;; End of verses + (when (equal "ORG-VERSE-END" line) + (insert "</literallayout>\n</blockquote>\n") + (org-export-docbook-open-para) + (setq inverse nil) + (throw 'nextline nil)) + + ;; Text centering. Element <para role="centered"> does not + ;; seem to work with FOP, so for now we use <informaltable> to + ;; center the text, which can contain multiple paragraphs. + (when (equal "ORG-CENTER-START" line) + (org-export-docbook-close-para-maybe) + (insert "<informaltable frame=\"none\" colsep=\"0\" rowsep=\"0\">\n" + "<tgroup align=\"center\" cols=\"1\">\n" + "<tbody><row><entry>\n") + (org-export-docbook-open-para) + (throw 'nextline nil)) + + (when (equal "ORG-CENTER-END" line) + (org-export-docbook-close-para-maybe) + (insert "</entry></row></tbody>\n" + "</tgroup>\n</informaltable>\n") + (org-export-docbook-open-para) + (throw 'nextline nil)) + + ;; Make targets to anchors. Note that currently FOP does not + ;; seem to support <anchor> tags when generating PDF output, + ;; but this can be used in DocBook --> HTML conversion. + (setq start 0) + (while (string-match + "<<<?\\([^<>]*\\)>>>?\\((INVISIBLE)\\)?[ \t]*\n?" line start) + (cond + ((get-text-property (match-beginning 1) 'org-protected line) + (setq start (match-end 1))) + ((match-end 2) + (setq line (replace-match + (format "@<anchor xml:id=\"%s\"/>" + (org-solidify-link-text (match-string 1 line))) + t t line))) + (t + (setq line (replace-match + (format "@<anchor xml:id=\"%s\"/>" + (org-solidify-link-text (match-string 1 line))) + t t line))))) + + ;; Put time stamps and related keywords into special mark-up + ;; elements. + (setq line (org-export-docbook-handle-time-stamps line)) + + ;; Replace "&", "<" and ">" by "&", "<" and ">". + ;; Handle @<..> HTML tags (replace "@>..<" by "<..>"). + ;; Also handle sub_superscripts and check boxes. + (or (string-match org-table-hline-regexp line) + (setq line (org-docbook-expand line))) + + ;; Format the links + (setq start 0) + (while (string-match org-bracket-link-analytic-regexp++ line start) + (setq start (match-beginning 0)) + (setq path (save-match-data (org-link-unescape + (match-string 3 line)))) + (setq type (cond + ((match-end 2) (match-string 2 line)) + ((save-match-data + (or (file-name-absolute-p path) + (string-match "^\\.\\.?/" path))) + "file") + (t "internal"))) + (setq path (org-extract-attributes (org-link-unescape path))) + (setq attr (get-text-property 0 'org-attributes path) + caption (get-text-property 0 'org-caption path) + label (get-text-property 0 'org-label path)) + (setq desc1 (if (match-end 5) (match-string 5 line)) + desc2 (if (match-end 2) (concat type ":" path) path) + descp (and desc1 (not (equal desc1 desc2))) + desc (or desc1 desc2)) + ;; Make an image out of the description if that is so wanted + (when (and descp (org-file-image-p + desc org-export-docbook-inline-image-extensions)) + (save-match-data + (if (string-match "^file:" desc) + (setq desc (substring desc (match-end 0)))))) + ;; FIXME: do we need to unescape here somewhere? + (cond + ((equal type "internal") + (setq rpl (format "<link linkend=\"%s\">%s</link>" + (org-solidify-link-text + (save-match-data (org-link-unescape path)) nil) + (org-export-docbook-format-desc desc)))) + ((and (equal type "id") + (setq id-file (org-id-find-id-file path))) + ;; This is an id: link to another file (if it was the same file, + ;; it would have become an internal link...) + (save-match-data + (setq id-file (file-relative-name + id-file (file-name-directory org-current-export-file))) + (setq id-file (concat (file-name-sans-extension id-file) + org-export-docbook-extension)) + (setq rpl (format "<link xlink:href=\"%s#%s\">%s</link>" + id-file path (org-export-docbook-format-desc desc))))) + ((member type '("http" "https")) + ;; Standard URL, just check if we need to inline an image + (if (and (or (eq t org-export-docbook-inline-images) + (and org-export-docbook-inline-images (not descp))) + (org-file-image-p + path org-export-docbook-inline-image-extensions)) + (setq rpl (org-export-docbook-format-image + (concat type ":" path))) + (setq link (concat type ":" path)) + (setq rpl (format "<link xlink:href=\"%s\">%s</link>" + (org-export-html-format-href link) + (org-export-docbook-format-desc desc))) + )) + ((member type '("ftp" "mailto" "news")) + ;; Standard URL + (setq link (concat type ":" path)) + (setq rpl (format "<link xlink:href=\"%s\">%s</link>" + (org-export-html-format-href link) + (org-export-docbook-format-desc desc)))) + ((string= type "coderef") + (setq rpl (format (org-export-get-coderef-format path (and descp desc)) + (cdr (assoc path org-export-code-refs))))) + ((functionp (setq fnc (nth 2 (assoc type org-link-protocols)))) + ;; The link protocol has a function for format the link + (setq rpl + (save-match-data + (funcall fnc (org-link-unescape path) desc1 'html)))) + + ((string= type "file") + ;; FILE link + (let* ((filename path) + (abs-p (file-name-absolute-p filename)) + thefile file-is-image-p search) + (save-match-data + (if (string-match "::\\(.*\\)" filename) + (setq search (match-string 1 filename) + filename (replace-match "" t nil filename))) + (setq valid + (if (functionp link-validate) + (funcall link-validate filename current-dir) + t)) + (setq file-is-image-p + (org-file-image-p + filename org-export-docbook-inline-image-extensions)) + (setq thefile (if abs-p (expand-file-name filename) filename)) + ;; Carry over the properties (expand-file-name will + ;; discard the properties of filename) + (add-text-properties 0 (1- (length thefile)) + (list 'org-caption caption + 'org-attributes attr + 'org-label label) + thefile) + (when (and org-export-docbook-link-org-files-as-docbook + (string-match "\\.org$" thefile)) + (setq thefile (concat (substring thefile 0 + (match-beginning 0)) + org-export-docbook-extension)) + (if (and search + ;; make sure this is can be used as target search + (not (string-match "^[0-9]*$" search)) + (not (string-match "^\\*" search)) + (not (string-match "^/.*/$" search))) + (setq thefile (concat thefile "#" + (org-solidify-link-text + (org-link-unescape search))))) + (when (string-match "^file:" desc) + (setq desc (replace-match "" t t desc)) + (if (string-match "\\.org$" desc) + (setq desc (replace-match "" t t desc)))))) + (setq rpl (if (and file-is-image-p + (or (eq t org-export-docbook-inline-images) + (and org-export-docbook-inline-images + (not descp)))) + (progn + (message "image %s %s" thefile org-docbook-para-open) + (org-export-docbook-format-image thefile)) + (format "<link xlink:href=\"%s\">%s</link>" + thefile (org-export-docbook-format-desc desc)))) + (if (not valid) (setq rpl desc)))) + + (t + ;; Just publish the path, as default + (setq rpl (concat "<" type ":" + (save-match-data (org-link-unescape path)) + ">")))) + (setq line (replace-match rpl t t line) + start (+ start (length rpl)))) + + ;; TODO items: can we do something better?! + (if (and (string-match org-todo-line-regexp line) + (match-beginning 2)) + (setq line + (concat (substring line 0 (match-beginning 2)) + "[" (match-string 2 line) "]" + (substring line (match-end 2))))) + + ;; Does this contain a reference to a footnote? + (when org-export-with-footnotes + (setq start 0) + (while (string-match "\\([^* \t].*?\\)\\[\\([0-9]+\\)\\]" line start) + (if (get-text-property (match-beginning 2) 'org-protected line) + (setq start (match-end 2)) + (let* ((num (match-string 2 line)) + (footnote-def (assoc num footnote-list))) + (if (assoc num footref-seen) + (setq line (replace-match + (format "%s<footnoteref linkend=\"%s%s\"/>" + (match-string 1 line) + org-export-docbook-footnote-id-prefix num) + t t line)) + (setq line (replace-match + (format "%s<footnote xml:id=\"%s%s\"><para>%s</para></footnote>" + (match-string 1 line) + org-export-docbook-footnote-id-prefix + num + (if footnote-def + (save-match-data + (org-docbook-expand (cdr footnote-def))) + (format "FOOTNOTE DEFINITION NOT FOUND: %s" num))) + t t line)) + (push (cons num 1) footref-seen)))))) + + (cond + ((string-match "^\\(\\*+\\)[ \t]+\\(.*\\)" line) + ;; This is a headline + (setq level (org-tr-level (- (match-end 1) (match-beginning 1) + level-offset)) + txt (match-string 2 line)) + (if (string-match quote-re0 txt) + (setq txt (replace-match "" t t txt))) + (org-export-docbook-level-start level txt) + ;; QUOTES + (when (string-match quote-re line) + (org-export-docbook-close-para-maybe) + (insert "<programlisting><![CDATA[") + (setq inquote t))) + + ;; Tables: since version 4.3 of DocBook DTD, HTML tables are + ;; supported. We can use existing HTML table exporter code + ;; here. + ((and org-export-with-tables + (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line)) + (if (not table-open) + ;; New table starts + (setq table-open t + table-buffer nil + table-orig-buffer nil)) + ;; Accumulate lines + (setq table-buffer (cons line table-buffer) + table-orig-buffer (cons origline table-orig-buffer)) + (when (or (not lines) + (not (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" + (car lines)))) + (setq table-open nil + table-buffer (nreverse table-buffer) + table-orig-buffer (nreverse table-orig-buffer)) + (org-export-docbook-close-para-maybe) + (insert (org-export-docbook-finalize-table + (org-format-table-html table-buffer table-orig-buffer + 'no-css))))) + + (t + ;; Normal lines + (when (string-match + (cond + ((eq llt t) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+[.)]\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)") + ((= llt ?.) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+\\.\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)") + ((= llt ?\)) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+)\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)") + (t (error "Invalid value of `org-plain-list-ordered-item-terminator'"))) + line) + (setq ind (or (get-text-property 0 'original-indentation line) + (org-get-string-indentation line)) + item-type (if (match-beginning 4) "o" "u") + starter (if (match-beginning 2) + (substring (match-string 2 line) 0 -1)) + line (substring line (match-beginning 5)) + item-tag nil + item-number nil) + (if (string-match "\\[@\\(?:start:\\)?\\([0-9]+\\)\\][ \t]?" line) + (setq item-number (match-string 1 line) + line (replace-match "" t t line))) + (if (and starter (string-match "\\(.*?\\) ::[ \t]*" line)) + (setq item-type "d" + item-tag (match-string 1 line) + line (substring line (match-end 0)))) + (cond + ((and starter + (or (not in-local-list) + (> ind (car local-list-indent)))) + ;; Start new (level of) list + (org-export-docbook-close-para-maybe) + (insert (cond + ((equal item-type "u") "<itemizedlist>\n<listitem>\n") + ((and (equal item-type "o") item-number) + ;; Check for a specific start number. If it + ;; is specified, we use the ``override'' + ;; attribute of element <listitem> to pass the + ;; info to DocBook. We could also use the + ;; ``startingnumber'' attribute of element + ;; <orderedlist>, but the former works on both + ;; DocBook 5.0 and prior versions. + (format "<orderedlist>\n<listitem override=\"%s\">\n" item-number)) + ((equal item-type "o") "<orderedlist>\n<listitem>\n") + ((equal item-type "d") + (format "<variablelist>\n<varlistentry><term>%s</term><listitem>\n" item-tag)))) + ;; For DocBook, we need to open a para right after tag + ;; <listitem>. + (org-export-docbook-open-para) + (push item-type local-list-type) + (push ind local-list-indent) + (setq in-local-list t)) + ;; Continue current list + (starter + ;; terminate any previous sublist but first ensure + ;; list is not ill-formed + (let ((min-ind (apply 'min local-list-indent))) + (when (< ind min-ind) (setq ind min-ind))) + (while (< ind (car local-list-indent)) + (let ((listtype (car local-list-type))) + (org-export-docbook-close-li listtype) + (insert (cond + ((equal listtype "o") "</orderedlist>\n") + ((equal listtype "u") "</itemizedlist>\n") + ((equal listtype "d") "</variablelist>\n")))) + (pop local-list-type) (pop local-list-indent) + (setq in-local-list local-list-indent)) + ;; insert new item + (let ((listtype (car local-list-type))) + (org-export-docbook-close-li listtype) + (insert (cond + ((and (equal listtype "o") item-number) + (format "<listitem override=\"%s\">" item-number)) + ((equal listtype "o") "<listitem>") + ((equal listtype "u") "<listitem>") + ((equal listtype "d") (format + "<varlistentry><term>%s</term><listitem>" + (or item-tag + "???")))))) + ;; For DocBook, we need to open a para right after tag + ;; <listitem>. + (org-export-docbook-open-para))) + ;; Checkboxes. + (if (string-match "^[ \t]*\\(\\[[X -]\\]\\)" line) + (setq line + (replace-match (concat checkbox-start + (match-string 1 line) + checkbox-end) + t t line)))) + + ;; Empty lines start a new paragraph. If hand-formatted lists + ;; are not fully interpreted, lines starting with "-", "+", "*" + ;; also start a new paragraph. + (if (and (string-match "^ [-+*]-\\|^[ \t]*$" line) + (not inverse)) + (org-export-docbook-open-para)) + + ;; Is this the start of a footnote? + (when org-export-with-footnotes + (when (and (boundp 'footnote-section-tag-regexp) + (string-match (concat "^" footnote-section-tag-regexp) + line)) + ;; ignore this line + (throw 'nextline nil)) + ;; These footnote lines have been read and saved before, + ;; ignore them at this time. + (when (string-match "^[ \t]*\\[\\([0-9]+\\)\\]" line) + (org-export-docbook-close-para-maybe) + (throw 'nextline nil))) + + ;; FIXME: It might be a good idea to add an option to + ;; support line break processing instruction <?linebreak?>. + ;; Org-mode supports line break "\\" in HTML exporter, and + ;; some DocBook users may also want to force line breaks + ;; even though DocBook only supports that in + ;; <literallayout>. + + (insert line "\n"))))) + + ;; Properly close all local lists and other lists + (when inquote + (insert "]]></programlisting>\n") + (org-export-docbook-open-para)) + + ;; Close all open sections. + (org-export-docbook-level-start 1 nil) + + (unless (plist-get opt-plist :buffer-will-be-killed) + (normal-mode) + (if (eq major-mode (default-value 'major-mode)) + (nxml-mode))) + + ;; Remove empty paragraphs and lists. Replace them with a + ;; newline. + (goto-char (point-min)) + (while (re-search-forward + "[ \r\n\t]*\\(<para>\\)[ \r\n\t]*</para>[ \r\n\t]*" nil t) + (when (not (get-text-property (match-beginning 1) 'org-protected)) + (replace-match "\n") + ;; Avoid empty <listitem></listitem> caused by inline tasks. + ;; We should add an empty para to make everything valid. + (when (and (looking-at "</listitem>") + (save-excursion + (backward-char (length "<listitem>\n")) + (looking-at "<listitem>"))) + (insert "<para></para>")) + (backward-char 1))) + ;; Fill empty sections with <para></para>. This is to make sure + ;; that the DocBook document generated is valid and well-formed. + (goto-char (point-min)) + (while (re-search-forward + "</title>\\([ \r\n\t]*\\)</section>" nil t) + (when (not (get-text-property (match-beginning 0) 'org-protected)) + (replace-match "\n<para></para>\n" nil nil nil 1))) + ;; Insert the last closing tag. + (goto-char (point-max)) + (unless body-only + (insert "</article>")) + (run-hooks 'org-export-docbook-final-hook) + (or to-buffer (save-buffer)) + (goto-char (point-min)) + (or (org-export-push-to-kill-ring "DocBook") + (message "Exporting... done")) + (if (eq to-buffer 'string) + (prog1 (buffer-substring (point-min) (point-max)) + (kill-buffer (current-buffer))) + (current-buffer))))) + +(defun org-export-docbook-open-para () + "Insert <para>, but first close previous paragraph if any." + (org-export-docbook-close-para-maybe) + (insert "\n<para>") + (setq org-docbook-para-open t)) + +(defun org-export-docbook-close-para-maybe () + "Close DocBook paragraph if there is one open." + (when org-docbook-para-open + (insert "</para>\n") + (setq org-docbook-para-open nil))) + +(defun org-export-docbook-close-li (&optional type) + "Close list if necessary." + (org-export-docbook-close-para-maybe) + (if (equal type "d") + (insert "</listitem></varlistentry>\n") + (insert "</listitem>\n"))) + +(defvar in-local-list) +(defvar local-list-indent) +(defvar local-list-type) + +(defun org-export-docbook-level-start (level title) + "Insert a new level in DocBook export. +When TITLE is nil, just close all open levels." + (org-export-docbook-close-para-maybe) + (let* ((target (and title (org-get-text-property-any 0 'target title))) + (l org-level-max) + section-number) + (while (>= l level) + (if (aref org-levels-open (1- l)) + (progn + (insert "</section>\n") + (aset org-levels-open (1- l) nil))) + (setq l (1- l))) + (when title + ;; If title is nil, this means this function is called to close + ;; all levels, so the rest is done only if title is given. + ;; + ;; Format tags: put them into a superscript like format. + (when (string-match (org-re "\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$") title) + (setq title + (replace-match + (if org-export-with-tags + (save-match-data + (concat + "<superscript>" + (match-string 1 title) + "</superscript>")) + "") + t t title))) + (aset org-levels-open (1- level) t) + (setq section-number (org-section-number level)) + (insert (format "\n<section xml:id=\"%s%s\">\n<title>%s</title>" + org-export-docbook-section-id-prefix + (replace-regexp-in-string "\\." "_" section-number) + title)) + (org-export-docbook-open-para)))) + +(defun org-docbook-expand (string) + "Prepare STRING for DocBook export. +Applies all active conversions. If there are links in the +string, don't modify these." + (let* ((re (concat org-bracket-link-regexp "\\|" + (org-re "[ \t]+\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$"))) + m s l res) + (while (setq m (string-match re string)) + (setq s (substring string 0 m) + l (match-string 0 string) + string (substring string (match-end 0))) + (push (org-docbook-do-expand s) res) + (push l res)) + (push (org-docbook-do-expand string) res) + (apply 'concat (nreverse res)))) + +(defun org-docbook-do-expand (s) + "Apply all active conversions to translate special ASCII to DocBook." + (setq s (org-html-protect s)) + (while (string-match "@<\\([^&]*\\)>" s) + (setq s (replace-match "<\\1>" t nil s))) + (if org-export-with-emphasize + (setq s (org-export-docbook-convert-emphasize s))) + (if org-export-with-special-strings + (setq s (org-export-docbook-convert-special-strings s))) + (if org-export-with-sub-superscripts + (setq s (org-export-docbook-convert-sub-super s))) + (if org-export-with-TeX-macros + (let ((start 0) wd rep) + (while (setq start (string-match "\\\\\\([a-zA-Z]+\\)\\({}\\)?" + s start)) + (if (get-text-property (match-beginning 0) 'org-protected s) + (setq start (match-end 0)) + (setq wd (match-string 1 s)) + (if (setq rep (org-entity-get-representation wd 'html)) + (setq s (replace-match rep t t s)) + (setq start (+ start (length wd)))))))) + s) + +(defun org-export-docbook-format-desc (desc) + "Make sure DESC is valid as a description in a link." + (save-match-data + (org-docbook-do-expand desc))) + +(defun org-export-docbook-convert-emphasize (string) + "Apply emphasis for DocBook exporting." + (let ((s 0) rpl) + (while (string-match org-emph-re string s) + (if (not (equal + (substring string (match-beginning 3) (1+ (match-beginning 3))) + (substring string (match-beginning 4) (1+ (match-beginning 4))))) + (setq s (match-beginning 0) + rpl + (concat + (match-string 1 string) + (nth 1 (assoc (match-string 3 string) + org-export-docbook-emphasis-alist)) + (match-string 4 string) + (nth 2 (assoc (match-string 3 string) + org-export-docbook-emphasis-alist)) + (match-string 5 string)) + string (replace-match rpl t t string) + s (+ s (- (length rpl) 2))) + (setq s (1+ s)))) + string)) + +(defun org-docbook-protect (string) + (org-html-protect string)) + +;; For now, simply return string as it is. +(defun org-export-docbook-convert-special-strings (string) + "Convert special characters in STRING to DocBook." + string) + +(defun org-export-docbook-get-footnotes (lines) + "Given a list of LINES, return a list of alist footnotes." + (let ((list nil) line) + (while (setq line (pop lines)) + (if (string-match "^[ \t]*\\[\\([0-9]+\\)\\] \\(.+\\)" line) + (push (cons (match-string 1 line) (match-string 2 line)) + list))) + list)) + +(defun org-export-docbook-format-image (src) + "Create image element in DocBook." + (save-match-data + (let* ((caption (org-find-text-property-in-string 'org-caption src)) + (attr (or (org-find-text-property-in-string 'org-attributes src) + "")) + (label (org-find-text-property-in-string 'org-label src)) + (default-attr org-export-docbook-default-image-attributes) + tmp) + (setq caption (and caption (org-html-do-expand caption))) + (while (setq tmp (pop default-attr)) + (if (not (string-match (concat (car tmp) "=") attr)) + (setq attr (concat attr " " (car tmp) "=" (cdr tmp))))) + (format "<mediaobject%s> +<imageobject>\n<imagedata fileref=\"%s\" %s/>\n</imageobject> +%s</mediaobject>" + (if label (concat " xml:id=\"" label "\"") "") + src attr + (if caption + (concat "<caption>\n<para>" + caption + "</para>\n</caption>\n") + "") + )))) + +(defun org-export-docbook-preprocess (parameters) + "Extra preprocessing work for DocBook export." + ;; Merge lines starting with "\par" to one line. Such lines are + ;; regarded as the continuation of a long footnote. + (goto-char (point-min)) + (while (re-search-forward "\n\\(\\\\par\\>\\)" nil t) + (if (not (get-text-property (match-beginning 1) 'org-protected)) + (replace-match "")))) + +(defun org-export-docbook-finalize-table (table) + "Clean up TABLE and turn it into DocBook format. +This function adds a label to the table if it is available, and +also changes TABLE to informaltable if caption does not exist. +TABLE is a string containing the HTML code generated by +`org-format-table-html' for a table in Org-mode buffer." + (let (table-with-label) + ;; Get the label if it exists, and move it into the <table> element. + (setq table-with-label + (if (string-match + "^<table \\(\\(.\\|\n\\)+\\)<a name=\"\\(.+\\)\" id=\".+\"></a>\n\\(\\(.\\|\n\\)+\\)</table>" + table) + (replace-match (concat "<table xml:id=\"" (match-string 3 table) "\" " + (match-string 1 table) + (match-string 4 table) + "</table>") + nil nil table) + table)) + ;; Change <table> into <informaltable> if caption does not exist. + (if (string-match + "^<table \\(\\(.\\|\n\\)+\\)<caption></caption>\n\\(\\(.\\|\n\\)+\\)</table>" + table-with-label) + (replace-match (concat "<informaltable " + (match-string 1 table-with-label) + (match-string 3 table-with-label) + "</informaltable>") + nil nil table-with-label) + table-with-label))) + +;; Note: This function is very similar to +;; org-export-html-convert-sub-super. They can be merged in the future. +(defun org-export-docbook-convert-sub-super (string) + "Convert sub- and superscripts in STRING for DocBook." + (let (key c (s 0) (requireb (eq org-export-with-sub-superscripts '{}))) + (while (string-match org-match-substring-regexp string s) + (cond + ((and requireb (match-end 8)) (setq s (match-end 2))) + ((get-text-property (match-beginning 2) 'org-protected string) + (setq s (match-end 2))) + (t + (setq s (match-end 1) + key (if (string= (match-string 2 string) "_") + "subscript" + "superscript") + c (or (match-string 8 string) + (match-string 6 string) + (match-string 5 string)) + string (replace-match + (concat (match-string 1 string) + "<" key ">" c "</" key ">") + t t string))))) + (while (string-match "\\\\\\([_^]\\)" string) + (setq string (replace-match (match-string 1 string) t t string))) + string)) + +(defun org-export-docbook-protect-tags (string) + "Change ``<...>'' in string STRING into ``@<...>''. +This is normally needed when STRING contains DocBook elements +that need to be preserved in later phase of DocBook exporting." + (let ((start 0)) + (while (string-match "<\\([^>]*\\)>" string start) + (setq string (replace-match + "@<\\1>" t nil string) + start (match-end 0))) + string)) + +(defun org-export-docbook-handle-time-stamps (line) + "Format time stamps in string LINE." + (let (replaced + (kw-markup (org-export-docbook-protect-tags + org-export-docbook-keywords-markup)) + (ts-markup (org-export-docbook-protect-tags + org-export-docbook-timestamp-markup))) + (while (string-match org-maybe-keyword-time-regexp line) + (setq replaced + (concat replaced + (substring line 0 (match-beginning 0)) + (if (match-end 1) + (format kw-markup + (match-string 1 line))) + " " + (format ts-markup + (substring (org-translate-time + (match-string 3 line)) 1 -1))) + line (substring line (match-end 0)))) + (concat replaced line))) + +(provide 'org-docbook) + +;; arch-tag: a24a127c-d365-4c2a-9e9b-f7dcb0ebfdc3 +;;; org-docbook.el ends here |