Commit | Line | Data |
---|---|---|
c8d0cf5c CD |
1 | ;;; org-docbook.el --- DocBook exporter for org-mode |
2 | ;; | |
dfd98937 | 3 | ;; Copyright (C) 2007-2012 Free Software Foundation, Inc. |
c8d0cf5c CD |
4 | ;; |
5 | ;; Emacs Lisp Archive Entry | |
6 | ;; Filename: org-docbook.el | |
c8d0cf5c CD |
7 | ;; Author: Baoqiu Cui <cbaoqiu AT yahoo DOT com> |
8 | ;; Maintainer: Baoqiu Cui <cbaoqiu AT yahoo DOT com> | |
9 | ;; Keywords: org, wp, docbook | |
10 | ;; Description: Converts an org-mode buffer into DocBook | |
c8d0cf5c CD |
11 | ;; URL: |
12 | ||
750268f0 | 13 | ;; This file is part of GNU Emacs. |
c8d0cf5c CD |
14 | |
15 | ;; GNU Emacs is free software: you can redistribute it and/or modify | |
16 | ;; it under the terms of the GNU General Public License as published by | |
17 | ;; the Free Software Foundation, either version 3 of the License, or | |
18 | ;; (at your option) any later version. | |
19 | ||
20 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
21 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
22 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
23 | ;; GNU General Public License for more details. | |
24 | ||
25 | ;; You should have received a copy of the GNU General Public License | |
26 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | |
27 | ||
86fbb8ca | 28 | ;;; Commentary: |
c8d0cf5c CD |
29 | ;; |
30 | ;; This library implements a DocBook exporter for org-mode. The basic | |
31 | ;; idea and design is very similar to what `org-export-as-html' has. | |
32 | ;; Code prototype was also started with `org-export-as-html'. | |
33 | ;; | |
34 | ;; Put this file into your load-path and the following line into your | |
35 | ;; ~/.emacs: | |
36 | ;; | |
37 | ;; (require 'org-docbook) | |
38 | ;; | |
39 | ;; The interactive functions are similar to those of the HTML and LaTeX | |
40 | ;; exporters: | |
41 | ;; | |
42 | ;; M-x `org-export-as-docbook' | |
43 | ;; M-x `org-export-as-docbook-pdf' | |
44 | ;; M-x `org-export-as-docbook-pdf-and-open' | |
45 | ;; M-x `org-export-as-docbook-batch' | |
46 | ;; M-x `org-export-as-docbook-to-buffer' | |
47 | ;; M-x `org-export-region-as-docbook' | |
48 | ;; M-x `org-replace-region-by-docbook' | |
49 | ;; | |
50 | ;; Note that, in order to generate PDF files using the DocBook XML files | |
51 | ;; created by DocBook exporter, the following two variables have to be | |
52 | ;; set based on what DocBook tools you use for XSLT processor and XSL-FO | |
53 | ;; processor: | |
54 | ;; | |
55 | ;; org-export-docbook-xslt-proc-command | |
56 | ;; org-export-docbook-xsl-fo-proc-command | |
57 | ;; | |
58 | ;; Check the document of these two variables to see examples of how they | |
59 | ;; can be set. | |
60 | ;; | |
61 | ;; If the Org file to be exported contains special characters written in | |
62 | ;; TeX-like syntax, like \alpha and \beta, you need to include the right | |
63 | ;; entity file(s) in the DOCTYPE declaration for the DocBook XML file. | |
64 | ;; This is required to make the DocBook XML file valid. The DOCTYPE | |
65 | ;; declaration string can be set using the following variable: | |
66 | ;; | |
67 | ;; org-export-docbook-doctype | |
68 | ;; | |
69 | ;;; Code: | |
70 | ||
71 | (eval-when-compile | |
72 | (require 'cl)) | |
73 | ||
74 | (require 'footnote) | |
75 | (require 'org) | |
76 | (require 'org-exp) | |
77 | (require 'org-html) | |
86fbb8ca | 78 | (require 'format-spec) |
c8d0cf5c CD |
79 | |
80 | ;;; Variables: | |
81 | ||
82 | (defvar org-docbook-para-open nil) | |
83 | (defvar org-export-docbook-inline-images t) | |
84 | (defvar org-export-docbook-link-org-files-as-docbook nil) | |
85 | ||
86 | (declare-function org-id-find-id-file "org-id" (id)) | |
87 | ||
88 | ;;; User variables: | |
89 | ||
90 | (defgroup org-export-docbook nil | |
91 | "Options for exporting Org-mode files to DocBook." | |
92 | :tag "Org Export DocBook" | |
93 | :group 'org-export) | |
94 | ||
95 | (defcustom org-export-docbook-extension ".xml" | |
96 | "Extension of DocBook XML files." | |
97 | :group 'org-export-docbook | |
98 | :type 'string) | |
99 | ||
100 | (defcustom org-export-docbook-header "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" | |
101 | "Header of DocBook XML files." | |
102 | :group 'org-export-docbook | |
103 | :type 'string) | |
104 | ||
105 | (defcustom org-export-docbook-doctype nil | |
106 | "DOCTYPE declaration string for DocBook XML files. | |
107 | This can be used to include entities that are needed to handle | |
108 | special characters in Org files. | |
109 | ||
110 | For example, if the Org file to be exported contains XHTML | |
111 | entities, you can set this variable to: | |
112 | ||
113 | \"<!DOCTYPE article [ | |
114 | <!ENTITY % xhtml1-symbol PUBLIC | |
115 | \"-//W3C//ENTITIES Symbol for HTML//EN//XML\" | |
116 | \"http://www.w3.org/2003/entities/2007/xhtml1-symbol.ent\" | |
117 | > | |
118 | %xhtml1-symbol; | |
119 | ]> | |
120 | \" | |
121 | ||
8bfe682a | 122 | If you want to process DocBook documents without an Internet |
c8d0cf5c CD |
123 | connection, it is suggested that you download the required entity |
124 | file(s) and use system identifier(s) (external files) in the | |
125 | DOCTYPE declaration." | |
126 | :group 'org-export-docbook | |
127 | :type 'string) | |
128 | ||
129 | (defcustom org-export-docbook-article-header "<article xmlns=\"http://docbook.org/ns/docbook\" | |
130 | xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"5.0\" xml:lang=\"en\">" | |
131 | "Article header of DocBook XML files." | |
132 | :group 'org-export-docbook | |
133 | :type 'string) | |
134 | ||
135 | (defcustom org-export-docbook-section-id-prefix "sec-" | |
136 | "Prefix of section IDs used during exporting. | |
137 | This can be set before exporting to avoid same set of section IDs | |
138 | being used again and again, which can be a problem when multiple | |
139 | people work on the same document." | |
140 | :group 'org-export-docbook | |
141 | :type 'string) | |
142 | ||
143 | (defcustom org-export-docbook-footnote-id-prefix "fn-" | |
86fbb8ca CD |
144 | "The prefix of footnote IDs used during exporting. |
145 | Like `org-export-docbook-section-id-prefix', this variable can help | |
c8d0cf5c CD |
146 | avoid same set of footnote IDs being used multiple times." |
147 | :group 'org-export-docbook | |
148 | :type 'string) | |
149 | ||
3ab2c837 BG |
150 | (defcustom org-export-docbook-footnote-separator "<superscript>, </superscript>" |
151 | "Text used to separate footnotes." | |
152 | :group 'org-export-docbook | |
372d7b21 | 153 | :version "24.1" |
3ab2c837 BG |
154 | :type 'string) |
155 | ||
c8d0cf5c CD |
156 | (defcustom org-export-docbook-emphasis-alist |
157 | `(("*" "<emphasis role=\"bold\">" "</emphasis>") | |
158 | ("/" "<emphasis>" "</emphasis>") | |
159 | ("_" "<emphasis role=\"underline\">" "</emphasis>") | |
160 | ("=" "<code>" "</code>") | |
161 | ("~" "<literal>" "</literal>") | |
162 | ("+" "<emphasis role=\"strikethrough\">" "</emphasis>")) | |
86fbb8ca | 163 | "A list of DocBook expressions to convert emphasis fontifiers. |
c8d0cf5c CD |
164 | Each element of the list is a list of three elements. |
165 | The first element is the character used as a marker for fontification. | |
8223b1d2 | 166 | The second element is a format string to wrap fontified text with. |
c8d0cf5c CD |
167 | The third element decides whether to protect converted text from other |
168 | conversions." | |
169 | :group 'org-export-docbook | |
170 | :type 'alist) | |
171 | ||
172 | (defcustom org-export-docbook-default-image-attributes | |
173 | `(("align" . "\"center\"") | |
174 | ("valign". "\"middle\"")) | |
175 | "Alist of default DocBook image attributes. | |
176 | These attributes will be inserted into element <imagedata> by | |
177 | default, but users can override them using `#+ATTR_DocBook:'." | |
178 | :group 'org-export-docbook | |
179 | :type 'alist) | |
180 | ||
181 | (defcustom org-export-docbook-inline-image-extensions | |
182 | '("jpeg" "jpg" "png" "gif" "svg") | |
183 | "Extensions of image files that can be inlined into DocBook." | |
184 | :group 'org-export-docbook | |
185 | :type '(repeat (string :tag "Extension"))) | |
186 | ||
187 | (defcustom org-export-docbook-coding-system nil | |
188 | "Coding system for DocBook XML files." | |
189 | :group 'org-export-docbook | |
190 | :type 'coding-system) | |
191 | ||
86fbb8ca CD |
192 | (defcustom org-export-docbook-xslt-stylesheet nil |
193 | "File name of the XSLT stylesheet used by DocBook exporter. | |
194 | This XSLT stylesheet is used by | |
195 | `org-export-docbook-xslt-proc-command' to generate the Formatting | |
196 | Object (FO) files. You can use either `fo/docbook.xsl' that | |
197 | comes with DocBook, or any customization layer you may have." | |
198 | :group 'org-export-docbook | |
372d7b21 | 199 | :version "24.1" |
86fbb8ca CD |
200 | :type 'string) |
201 | ||
c8d0cf5c | 202 | (defcustom org-export-docbook-xslt-proc-command nil |
86fbb8ca CD |
203 | "Format of XSLT processor command used by DocBook exporter. |
204 | This command is used to process a DocBook XML file to generate | |
205 | the Formatting Object (FO) file. | |
c8d0cf5c CD |
206 | |
207 | The value of this variable should be a format control string that | |
86fbb8ca CD |
208 | includes three arguments: `%i', `%o', and `%s'. During exporting |
209 | time, `%i' is replaced by the input DocBook XML file name, `%o' | |
210 | is replaced by the output FO file name, and `%s' is replaced by | |
211 | `org-export-docbook-xslt-stylesheet' (or the #+XSLT option if it | |
212 | is specified in the Org file). | |
c8d0cf5c CD |
213 | |
214 | For example, if you use Saxon as the XSLT processor, you may want | |
215 | to set the variable to | |
216 | ||
86fbb8ca | 217 | \"java com.icl.saxon.StyleSheet -o %o %i %s\" |
c8d0cf5c CD |
218 | |
219 | If you use Xalan, you can set it to | |
220 | ||
86fbb8ca | 221 | \"java org.apache.xalan.xslt.Process -out %o -in %i -xsl %s\" |
c8d0cf5c CD |
222 | |
223 | For xsltproc, the following string should work: | |
224 | ||
86fbb8ca | 225 | \"xsltproc --output %o %s %i\" |
c8d0cf5c CD |
226 | |
227 | You can include additional stylesheet parameters in this command. | |
228 | Just make sure that they meet the syntax requirement of each | |
229 | processor." | |
230 | :group 'org-export-docbook | |
231 | :type 'string) | |
232 | ||
233 | (defcustom org-export-docbook-xsl-fo-proc-command nil | |
86fbb8ca CD |
234 | "Format of XSL-FO processor command used by DocBook exporter. |
235 | This command is used to process a Formatting Object (FO) file to | |
236 | generate the PDF file. | |
c8d0cf5c CD |
237 | |
238 | The value of this variable should be a format control string that | |
86fbb8ca CD |
239 | includes two arguments: `%i' and `%o'. During exporting time, |
240 | `%i' is replaced by the input FO file name, and `%o' is replaced | |
241 | by the output PDF file name. | |
c8d0cf5c CD |
242 | |
243 | For example, if you use FOP as the XSL-FO processor, you can set | |
244 | the variable to | |
245 | ||
86fbb8ca | 246 | \"fop %i %o\"" |
c8d0cf5c CD |
247 | :group 'org-export-docbook |
248 | :type 'string) | |
249 | ||
250 | (defcustom org-export-docbook-keywords-markup "<literal>%s</literal>" | |
251 | "A printf format string to be applied to keywords by DocBook exporter." | |
252 | :group 'org-export-docbook | |
253 | :type 'string) | |
254 | ||
255 | (defcustom org-export-docbook-timestamp-markup "<emphasis>%s</emphasis>" | |
256 | "A printf format string to be applied to time stamps by DocBook exporter." | |
257 | :group 'org-export-docbook | |
258 | :type 'string) | |
259 | ||
8d642074 CD |
260 | ;;; Hooks |
261 | ||
262 | (defvar org-export-docbook-final-hook nil | |
263 | "Hook run at the end of DocBook export, in the new buffer.") | |
264 | ||
c8d0cf5c CD |
265 | ;;; Autoload functions: |
266 | ||
267 | ;;;###autoload | |
268 | (defun org-export-as-docbook-batch () | |
269 | "Call `org-export-as-docbook' in batch style. | |
270 | This function can be used in batch processing. | |
271 | ||
272 | For example: | |
273 | ||
274 | $ emacs --batch | |
275 | --load=$HOME/lib/emacs/org.el | |
276 | --visit=MyOrgFile.org --funcall org-export-as-docbook-batch" | |
277 | (org-export-as-docbook 'hidden)) | |
278 | ||
279 | ;;;###autoload | |
280 | (defun org-export-as-docbook-to-buffer () | |
281 | "Call `org-export-as-docbook' with output to a temporary buffer. | |
282 | No file is created." | |
283 | (interactive) | |
284 | (org-export-as-docbook nil nil "*Org DocBook Export*") | |
285 | (when org-export-show-temporary-export-buffer | |
286 | (switch-to-buffer-other-window "*Org DocBook Export*"))) | |
287 | ||
288 | ;;;###autoload | |
289 | (defun org-replace-region-by-docbook (beg end) | |
290 | "Replace the region from BEG to END with its DocBook export. | |
291 | It assumes the region has `org-mode' syntax, and then convert it to | |
292 | DocBook. This can be used in any buffer. For example, you could | |
293 | write an itemized list in `org-mode' syntax in an DocBook buffer and | |
294 | then use this command to convert it." | |
295 | (interactive "r") | |
296 | (let (reg docbook buf) | |
297 | (save-window-excursion | |
8223b1d2 | 298 | (if (derived-mode-p 'org-mode) |
c8d0cf5c CD |
299 | (setq docbook (org-export-region-as-docbook |
300 | beg end t 'string)) | |
301 | (setq reg (buffer-substring beg end) | |
302 | buf (get-buffer-create "*Org tmp*")) | |
81ad75af | 303 | (with-current-buffer buf |
c8d0cf5c CD |
304 | (erase-buffer) |
305 | (insert reg) | |
306 | (org-mode) | |
307 | (setq docbook (org-export-region-as-docbook | |
308 | (point-min) (point-max) t 'string))) | |
309 | (kill-buffer buf))) | |
310 | (delete-region beg end) | |
311 | (insert docbook))) | |
312 | ||
313 | ;;;###autoload | |
314 | (defun org-export-region-as-docbook (beg end &optional body-only buffer) | |
315 | "Convert region from BEG to END in `org-mode' buffer to DocBook. | |
316 | If prefix arg BODY-ONLY is set, omit file header and footer and | |
317 | only produce the region of converted text, useful for | |
318 | cut-and-paste operations. If BUFFER is a buffer or a string, | |
319 | use/create that buffer as a target of the converted DocBook. If | |
320 | BUFFER is the symbol `string', return the produced DocBook as a | |
321 | string and leave not buffer behind. For example, a Lisp program | |
322 | could call this function in the following way: | |
323 | ||
324 | (setq docbook (org-export-region-as-docbook beg end t 'string)) | |
325 | ||
326 | When called interactively, the output buffer is selected, and shown | |
327 | in a window. A non-interactive call will only return the buffer." | |
328 | (interactive "r\nP") | |
3ab2c837 | 329 | (when (org-called-interactively-p 'any) |
c8d0cf5c CD |
330 | (setq buffer "*Org DocBook Export*")) |
331 | (let ((transient-mark-mode t) | |
332 | (zmacs-regions t) | |
333 | rtn) | |
334 | (goto-char end) | |
335 | (set-mark (point)) ;; To activate the region | |
336 | (goto-char beg) | |
337 | (setq rtn (org-export-as-docbook | |
338 | nil nil | |
339 | buffer body-only)) | |
340 | (if (fboundp 'deactivate-mark) (deactivate-mark)) | |
3ab2c837 | 341 | (if (and (org-called-interactively-p 'any) (bufferp rtn)) |
c8d0cf5c CD |
342 | (switch-to-buffer-other-window rtn) |
343 | rtn))) | |
344 | ||
345 | ;;;###autoload | |
346 | (defun org-export-as-docbook-pdf (&optional hidden ext-plist | |
347 | to-buffer body-only pub-dir) | |
348 | "Export as DocBook XML file, and generate PDF file." | |
349 | (interactive "P") | |
350 | (if (or (not org-export-docbook-xslt-proc-command) | |
86fbb8ca | 351 | (not (string-match "%[ios].+%[ios].+%[ios]" org-export-docbook-xslt-proc-command))) |
c8d0cf5c CD |
352 | (error "XSLT processor command is not set correctly")) |
353 | (if (or (not org-export-docbook-xsl-fo-proc-command) | |
86fbb8ca | 354 | (not (string-match "%[io].+%[io]" org-export-docbook-xsl-fo-proc-command))) |
c8d0cf5c CD |
355 | (error "XSL-FO processor command is not set correctly")) |
356 | (message "Exporting to PDF...") | |
357 | (let* ((wconfig (current-window-configuration)) | |
86fbb8ca CD |
358 | (opt-plist |
359 | (org-export-process-option-filters | |
360 | (org-combine-plists (org-default-export-plist) | |
361 | ext-plist | |
362 | (org-infile-export-plist)))) | |
c8d0cf5c CD |
363 | (docbook-buf (org-export-as-docbook hidden ext-plist |
364 | to-buffer body-only pub-dir)) | |
365 | (filename (buffer-file-name docbook-buf)) | |
366 | (base (file-name-sans-extension filename)) | |
367 | (fofile (concat base ".fo")) | |
368 | (pdffile (concat base ".pdf"))) | |
369 | (and (file-exists-p pdffile) (delete-file pdffile)) | |
370 | (message "Processing DocBook XML file...") | |
86fbb8ca CD |
371 | (shell-command (format-spec org-export-docbook-xslt-proc-command |
372 | (format-spec-make | |
373 | ?i (shell-quote-argument filename) | |
374 | ?o (shell-quote-argument fofile) | |
375 | ?s (shell-quote-argument | |
376 | (or (plist-get opt-plist :xslt) | |
377 | org-export-docbook-xslt-stylesheet))))) | |
378 | (shell-command (format-spec org-export-docbook-xsl-fo-proc-command | |
379 | (format-spec-make | |
380 | ?i (shell-quote-argument fofile) | |
381 | ?o (shell-quote-argument pdffile)))) | |
c8d0cf5c CD |
382 | (message "Processing DocBook file...done") |
383 | (if (not (file-exists-p pdffile)) | |
384 | (error "PDF file was not produced") | |
385 | (set-window-configuration wconfig) | |
386 | (message "Exporting to PDF...done") | |
387 | pdffile))) | |
388 | ||
389 | ;;;###autoload | |
390 | (defun org-export-as-docbook-pdf-and-open () | |
391 | "Export as DocBook XML file, generate PDF file, and open it." | |
392 | (interactive) | |
393 | (let ((pdffile (org-export-as-docbook-pdf))) | |
394 | (if pdffile | |
395 | (org-open-file pdffile) | |
396 | (error "PDF file was not produced")))) | |
397 | ||
e66ba1df BG |
398 | (defvar org-heading-keyword-regexp-format) ; defined in org.el |
399 | ||
c8d0cf5c CD |
400 | ;;;###autoload |
401 | (defun org-export-as-docbook (&optional hidden ext-plist | |
402 | to-buffer body-only pub-dir) | |
403 | "Export the current buffer as a DocBook file. | |
404 | If there is an active region, export only the region. When | |
405 | HIDDEN is obsolete and does nothing. EXT-PLIST is a | |
406 | property list with external parameters overriding org-mode's | |
407 | default settings, but still inferior to file-local settings. | |
408 | When TO-BUFFER is non-nil, create a buffer with that name and | |
409 | export to that buffer. If TO-BUFFER is the symbol `string', | |
410 | don't leave any buffer behind but just return the resulting HTML | |
411 | as a string. When BODY-ONLY is set, don't produce the file | |
412 | header and footer, simply return the content of the document (all | |
413 | top-level sections). When PUB-DIR is set, use this as the | |
414 | publishing directory." | |
415 | (interactive "P") | |
ed21c5c8 CD |
416 | (run-hooks 'org-export-first-hook) |
417 | ||
c8d0cf5c CD |
418 | ;; Make sure we have a file name when we need it. |
419 | (when (and (not (or to-buffer body-only)) | |
420 | (not buffer-file-name)) | |
421 | (if (buffer-base-buffer) | |
422 | (org-set-local 'buffer-file-name | |
423 | (with-current-buffer (buffer-base-buffer) | |
424 | buffer-file-name)) | |
f924a367 | 425 | (error "Need a file name to be able to export"))) |
c8d0cf5c CD |
426 | |
427 | (message "Exporting...") | |
428 | (setq-default org-todo-line-regexp org-todo-line-regexp) | |
429 | (setq-default org-deadline-line-regexp org-deadline-line-regexp) | |
430 | (setq-default org-done-keywords org-done-keywords) | |
431 | (setq-default org-maybe-keyword-time-regexp org-maybe-keyword-time-regexp) | |
432 | (let* ((opt-plist | |
433 | (org-export-process-option-filters | |
434 | (org-combine-plists (org-default-export-plist) | |
435 | ext-plist | |
436 | (org-infile-export-plist)))) | |
437 | (link-validate (plist-get opt-plist :link-validation-function)) | |
438 | valid | |
439 | (odd org-odd-levels-only) | |
440 | (region-p (org-region-active-p)) | |
441 | (rbeg (and region-p (region-beginning))) | |
442 | (rend (and region-p (region-end))) | |
443 | (subtree-p | |
8bfe682a | 444 | (if (plist-get opt-plist :ignore-subtree-p) |
c8d0cf5c CD |
445 | nil |
446 | (when region-p | |
447 | (save-excursion | |
448 | (goto-char rbeg) | |
449 | (and (org-at-heading-p) | |
450 | (>= (org-end-of-subtree t t) rend)))))) | |
451 | (level-offset (if subtree-p | |
452 | (save-excursion | |
453 | (goto-char rbeg) | |
454 | (+ (funcall outline-level) | |
455 | (if org-odd-levels-only 1 0))) | |
456 | 0)) | |
457 | (opt-plist (setq org-export-opt-plist | |
458 | (if subtree-p | |
459 | (org-export-add-subtree-options opt-plist rbeg) | |
460 | opt-plist))) | |
461 | ;; The following two are dynamically scoped into other | |
462 | ;; routines below. | |
463 | (org-current-export-dir | |
464 | (or pub-dir (org-export-directory :docbook opt-plist))) | |
465 | (org-current-export-file buffer-file-name) | |
466 | (level 0) (line "") (origline "") txt todo | |
467 | (filename (if to-buffer nil | |
468 | (expand-file-name | |
469 | (concat | |
470 | (file-name-sans-extension | |
471 | (or (and subtree-p | |
472 | (org-entry-get (region-beginning) | |
473 | "EXPORT_FILE_NAME" t)) | |
474 | (file-name-nondirectory buffer-file-name))) | |
475 | org-export-docbook-extension) | |
476 | (file-name-as-directory | |
477 | (or pub-dir (org-export-directory :docbook opt-plist)))))) | |
478 | (current-dir (if buffer-file-name | |
479 | (file-name-directory buffer-file-name) | |
480 | default-directory)) | |
e66ba1df | 481 | (auto-insert nil); Avoid any auto-insert stuff for the new file |
c8d0cf5c CD |
482 | (buffer (if to-buffer |
483 | (cond | |
e66ba1df BG |
484 | ((eq to-buffer 'string) |
485 | (get-buffer-create "*Org DocBook Export*")) | |
c8d0cf5c CD |
486 | (t (get-buffer-create to-buffer))) |
487 | (find-file-noselect filename))) | |
488 | ;; org-levels-open is a global variable | |
489 | (org-levels-open (make-vector org-level-max nil)) | |
490 | (date (plist-get opt-plist :date)) | |
491 | (author (or (plist-get opt-plist :author) | |
492 | user-full-name)) | |
493 | (email (plist-get opt-plist :email)) | |
494 | firstname othername surname | |
495 | (title (or (and subtree-p (org-export-get-title-from-subtree)) | |
496 | (plist-get opt-plist :title) | |
497 | (and (not | |
498 | (plist-get opt-plist :skip-before-1st-heading)) | |
499 | (org-export-grab-title-from-buffer)) | |
500 | (and buffer-file-name | |
501 | (file-name-sans-extension | |
502 | (file-name-nondirectory buffer-file-name))) | |
503 | "UNTITLED")) | |
504 | ;; We will use HTML table formatter to export tables to DocBook | |
505 | ;; format, so need to set html-table-tag here. | |
506 | (html-table-tag (plist-get opt-plist :html-table-tag)) | |
e66ba1df BG |
507 | (quote-re0 (concat "^ *" org-quote-string "\\( +\\|[ \t]*$\\)")) |
508 | (quote-re (format org-heading-keyword-regexp-format | |
509 | org-quote-string)) | |
c8d0cf5c CD |
510 | (inquote nil) |
511 | (infixed nil) | |
512 | (inverse nil) | |
c8d0cf5c CD |
513 | (llt org-plain-list-ordered-item-terminator) |
514 | (email (plist-get opt-plist :email)) | |
515 | (language (plist-get opt-plist :language)) | |
516 | (lang-words nil) | |
517 | cnt | |
518 | (start 0) | |
519 | (coding-system (and (boundp 'buffer-file-coding-system) | |
520 | buffer-file-coding-system)) | |
521 | (coding-system-for-write (or org-export-docbook-coding-system | |
522 | coding-system)) | |
523 | (save-buffer-coding-system (or org-export-docbook-coding-system | |
524 | coding-system)) | |
525 | (charset (and coding-system-for-write | |
526 | (fboundp 'coding-system-get) | |
527 | (coding-system-get coding-system-for-write | |
528 | 'mime-charset))) | |
529 | (region | |
530 | (buffer-substring | |
531 | (if region-p (region-beginning) (point-min)) | |
532 | (if region-p (region-end) (point-max)))) | |
3ab2c837 BG |
533 | (org-export-footnotes-seen nil) |
534 | (org-export-footnotes-data (org-footnote-all-labels 'with-defs)) | |
c8d0cf5c CD |
535 | (lines |
536 | (org-split-string | |
537 | (org-export-preprocess-string | |
538 | region | |
539 | :emph-multiline t | |
3ab2c837 | 540 | :for-backend 'docbook |
c8d0cf5c CD |
541 | :skip-before-1st-heading |
542 | (plist-get opt-plist :skip-before-1st-heading) | |
543 | :drawers (plist-get opt-plist :drawers) | |
544 | :todo-keywords (plist-get opt-plist :todo-keywords) | |
3ab2c837 | 545 | :tasks (plist-get opt-plist :tasks) |
c8d0cf5c CD |
546 | :tags (plist-get opt-plist :tags) |
547 | :priority (plist-get opt-plist :priority) | |
548 | :footnotes (plist-get opt-plist :footnotes) | |
549 | :timestamps (plist-get opt-plist :timestamps) | |
550 | :archived-trees | |
551 | (plist-get opt-plist :archived-trees) | |
552 | :select-tags (plist-get opt-plist :select-tags) | |
553 | :exclude-tags (plist-get opt-plist :exclude-tags) | |
554 | :add-text | |
555 | (plist-get opt-plist :text) | |
556 | :LaTeX-fragments | |
557 | (plist-get opt-plist :LaTeX-fragments)) | |
558 | "[\r\n]")) | |
559 | ;; Use literal output to show check boxes. | |
560 | (checkbox-start | |
561 | (nth 1 (assoc "=" org-export-docbook-emphasis-alist))) | |
562 | (checkbox-end | |
563 | (nth 2 (assoc "=" org-export-docbook-emphasis-alist))) | |
564 | table-open type | |
565 | table-buffer table-orig-buffer | |
afe98dfa | 566 | ind item-type starter |
c8d0cf5c | 567 | rpl path attr caption label desc descp desc1 desc2 link |
afe98dfa | 568 | fnc item-tag item-number |
c8d0cf5c CD |
569 | footref-seen footnote-list |
570 | id-file | |
571 | ) | |
572 | ||
573 | ;; Fine detailed info about author name. | |
574 | (if (string-match "\\([^ ]+\\) \\(.+ \\)?\\([^ ]+\\)" author) | |
575 | (progn | |
576 | (setq firstname (match-string 1 author) | |
577 | othername (or (match-string 2 author) "") | |
578 | surname (match-string 3 author)))) | |
579 | ||
580 | ;; Get all footnote text. | |
581 | (setq footnote-list | |
582 | (org-export-docbook-get-footnotes lines)) | |
583 | ||
584 | (let ((inhibit-read-only t)) | |
585 | (org-unmodified | |
586 | (remove-text-properties (point-min) (point-max) | |
587 | '(:org-license-to-kill t)))) | |
588 | ||
589 | (setq org-min-level (org-get-min-level lines level-offset)) | |
590 | (setq org-last-level org-min-level) | |
591 | (org-init-section-numbers) | |
592 | ||
593 | ;; Get and save the date. | |
594 | (cond | |
595 | ((and date (string-match "%" date)) | |
596 | (setq date (format-time-string date))) | |
597 | (date) | |
598 | (t (setq date (format-time-string "%Y-%m-%d %T %Z")))) | |
599 | ||
600 | ;; Get the language-dependent settings | |
601 | (setq lang-words (or (assoc language org-export-language-setup) | |
602 | (assoc "en" org-export-language-setup))) | |
603 | ||
604 | ;; Switch to the output buffer. Use fundamental-mode for now. We | |
605 | ;; could turn on nXML mode later and do some indentation. | |
606 | (set-buffer buffer) | |
607 | (let ((inhibit-read-only t)) (erase-buffer)) | |
608 | (fundamental-mode) | |
609 | (org-install-letbind) | |
610 | ||
611 | (and (fboundp 'set-buffer-file-coding-system) | |
612 | (set-buffer-file-coding-system coding-system-for-write)) | |
613 | ||
614 | ;; The main body... | |
615 | (let ((case-fold-search nil) | |
616 | (org-odd-levels-only odd)) | |
617 | ||
618 | ;; Create local variables for all options, to make sure all called | |
619 | ;; functions get the correct information | |
620 | (mapc (lambda (x) | |
621 | (set (make-local-variable (nth 2 x)) | |
622 | (plist-get opt-plist (car x)))) | |
623 | org-export-plist-vars) | |
624 | ||
625 | ;; Insert DocBook file header, title, and author info. | |
626 | (unless body-only | |
627 | (insert org-export-docbook-header) | |
628 | (if org-export-docbook-doctype | |
629 | (insert org-export-docbook-doctype)) | |
630 | (insert "<!-- Date: " date " -->\n") | |
631 | (insert (format "<!-- DocBook XML file generated by Org-mode %s Emacs %s -->\n" | |
8223b1d2 | 632 | (org-version) emacs-major-version)) |
c8d0cf5c CD |
633 | (insert org-export-docbook-article-header) |
634 | (insert (format | |
635 | "\n <title>%s</title> | |
636 | <info> | |
637 | <author> | |
638 | <personname> | |
639 | <firstname>%s</firstname> <othername>%s</othername> <surname>%s</surname> | |
640 | </personname> | |
641 | %s | |
642 | </author> | |
643 | </info>\n" | |
644 | (org-docbook-expand title) | |
645 | firstname othername surname | |
ed21c5c8 CD |
646 | (if (and org-export-email-info |
647 | email (string-match "\\S-" email)) | |
648 | (concat "<email>" email "</email>") "") | |
c8d0cf5c CD |
649 | ))) |
650 | ||
651 | (org-init-section-numbers) | |
652 | ||
653 | (org-export-docbook-open-para) | |
654 | ||
655 | ;; Loop over all the lines... | |
656 | (while (setq line (pop lines) origline line) | |
657 | (catch 'nextline | |
658 | ||
659 | ;; End of quote section? | |
3ab2c837 | 660 | (when (and inquote (string-match org-outline-regexp-bol line)) |
ed21c5c8 | 661 | (insert "]]></programlisting>\n") |
c8d0cf5c CD |
662 | (org-export-docbook-open-para) |
663 | (setq inquote nil)) | |
664 | ;; Inside a quote section? | |
665 | (when inquote | |
666 | (insert (org-docbook-protect line) "\n") | |
667 | (throw 'nextline nil)) | |
668 | ||
669 | ;; Fixed-width, verbatim lines (examples) | |
670 | (when (and org-export-with-fixed-width | |
671 | (string-match "^[ \t]*:\\(\\([ \t]\\|$\\)\\(.*\\)\\)" line)) | |
672 | (when (not infixed) | |
673 | (setq infixed t) | |
674 | (org-export-docbook-close-para-maybe) | |
675 | (insert "<programlisting><![CDATA[")) | |
676 | (insert (match-string 3 line) "\n") | |
677 | (when (or (not lines) | |
678 | (not (string-match "^[ \t]*\\(:.*\\)" | |
679 | (car lines)))) | |
680 | (setq infixed nil) | |
ed21c5c8 | 681 | (insert "]]></programlisting>\n") |
c8d0cf5c CD |
682 | (org-export-docbook-open-para)) |
683 | (throw 'nextline nil)) | |
684 | ||
c8d0cf5c CD |
685 | ;; Protected HTML |
686 | (when (get-text-property 0 'org-protected line) | |
687 | (let (par (ind (get-text-property 0 'original-indentation line))) | |
688 | (when (re-search-backward | |
689 | "\\(<para>\\)\\([ \t\r\n]*\\)\\=" (- (point) 100) t) | |
690 | (setq par (match-string 1)) | |
691 | (replace-match "\\2\n")) | |
692 | (insert line "\n") | |
693 | (while (and lines | |
694 | (or (= (length (car lines)) 0) | |
695 | (not ind) | |
696 | (equal ind (get-text-property 0 'original-indentation (car lines)))) | |
697 | (or (= (length (car lines)) 0) | |
698 | (get-text-property 0 'org-protected (car lines)))) | |
699 | (insert (pop lines) "\n")) | |
700 | (and par (insert "<para>\n"))) | |
701 | (throw 'nextline nil)) | |
702 | ||
703 | ;; Start of block quotes and verses | |
704 | (when (or (equal "ORG-BLOCKQUOTE-START" line) | |
705 | (and (equal "ORG-VERSE-START" line) | |
706 | (setq inverse t))) | |
707 | (org-export-docbook-close-para-maybe) | |
708 | (insert "<blockquote>") | |
709 | ;; Check whether attribution for this blockquote exists. | |
710 | (let (tmp1 | |
711 | attribution | |
712 | (end (if inverse "ORG-VERSE-END" "ORG-BLOCKQUOTE-END")) | |
713 | (quote-lines nil)) | |
714 | (while (and (setq tmp1 (pop lines)) | |
715 | (not (equal end tmp1))) | |
716 | (push tmp1 quote-lines)) | |
717 | (push tmp1 lines) ; Put back quote end mark | |
718 | ;; Check the last line in the quote to see if it contains | |
719 | ;; the attribution. | |
720 | (setq tmp1 (pop quote-lines)) | |
721 | (if (string-match "\\(^.*\\)\\(--[ \t]+\\)\\(.+\\)$" tmp1) | |
722 | (progn | |
723 | (setq attribution (match-string 3 tmp1)) | |
724 | (when (save-match-data | |
725 | (string-match "[^ \t]" (match-string 1 tmp1))) | |
726 | (push (match-string 1 tmp1) lines))) | |
727 | (push tmp1 lines)) | |
728 | (while (setq tmp1 (pop quote-lines)) | |
729 | (push tmp1 lines)) | |
730 | (when attribution | |
731 | (insert "<attribution>" attribution "</attribution>"))) | |
732 | ;; Insert <literallayout> for verse. | |
733 | (if inverse | |
734 | (insert "\n<literallayout>") | |
735 | (org-export-docbook-open-para)) | |
736 | (throw 'nextline nil)) | |
737 | ||
738 | ;; End of block quotes | |
739 | (when (equal "ORG-BLOCKQUOTE-END" line) | |
740 | (org-export-docbook-close-para-maybe) | |
741 | (insert "</blockquote>\n") | |
742 | (org-export-docbook-open-para) | |
743 | (throw 'nextline nil)) | |
744 | ||
745 | ;; End of verses | |
746 | (when (equal "ORG-VERSE-END" line) | |
747 | (insert "</literallayout>\n</blockquote>\n") | |
748 | (org-export-docbook-open-para) | |
749 | (setq inverse nil) | |
750 | (throw 'nextline nil)) | |
751 | ||
752 | ;; Text centering. Element <para role="centered"> does not | |
753 | ;; seem to work with FOP, so for now we use <informaltable> to | |
754 | ;; center the text, which can contain multiple paragraphs. | |
755 | (when (equal "ORG-CENTER-START" line) | |
756 | (org-export-docbook-close-para-maybe) | |
757 | (insert "<informaltable frame=\"none\" colsep=\"0\" rowsep=\"0\">\n" | |
758 | "<tgroup align=\"center\" cols=\"1\">\n" | |
759 | "<tbody><row><entry>\n") | |
760 | (org-export-docbook-open-para) | |
761 | (throw 'nextline nil)) | |
762 | ||
763 | (when (equal "ORG-CENTER-END" line) | |
764 | (org-export-docbook-close-para-maybe) | |
765 | (insert "</entry></row></tbody>\n" | |
766 | "</tgroup>\n</informaltable>\n") | |
767 | (org-export-docbook-open-para) | |
768 | (throw 'nextline nil)) | |
769 | ||
770 | ;; Make targets to anchors. Note that currently FOP does not | |
771 | ;; seem to support <anchor> tags when generating PDF output, | |
772 | ;; but this can be used in DocBook --> HTML conversion. | |
8bfe682a CD |
773 | (setq start 0) |
774 | (while (string-match | |
775 | "<<<?\\([^<>]*\\)>>>?\\((INVISIBLE)\\)?[ \t]*\n?" line start) | |
c8d0cf5c | 776 | (cond |
8bfe682a CD |
777 | ((get-text-property (match-beginning 1) 'org-protected line) |
778 | (setq start (match-end 1))) | |
c8d0cf5c CD |
779 | ((match-end 2) |
780 | (setq line (replace-match | |
781 | (format "@<anchor xml:id=\"%s\"/>" | |
782 | (org-solidify-link-text (match-string 1 line))) | |
783 | t t line))) | |
784 | (t | |
785 | (setq line (replace-match | |
786 | (format "@<anchor xml:id=\"%s\"/>" | |
787 | (org-solidify-link-text (match-string 1 line))) | |
788 | t t line))))) | |
789 | ||
790 | ;; Put time stamps and related keywords into special mark-up | |
791 | ;; elements. | |
792 | (setq line (org-export-docbook-handle-time-stamps line)) | |
793 | ||
794 | ;; Replace "&", "<" and ">" by "&", "<" and ">". | |
795 | ;; Handle @<..> HTML tags (replace "@>..<" by "<..>"). | |
796 | ;; Also handle sub_superscripts and check boxes. | |
797 | (or (string-match org-table-hline-regexp line) | |
798 | (setq line (org-docbook-expand line))) | |
799 | ||
800 | ;; Format the links | |
801 | (setq start 0) | |
802 | (while (string-match org-bracket-link-analytic-regexp++ line start) | |
803 | (setq start (match-beginning 0)) | |
804 | (setq path (save-match-data (org-link-unescape | |
805 | (match-string 3 line)))) | |
806 | (setq type (cond | |
807 | ((match-end 2) (match-string 2 line)) | |
808 | ((save-match-data | |
809 | (or (file-name-absolute-p path) | |
810 | (string-match "^\\.\\.?/" path))) | |
811 | "file") | |
812 | (t "internal"))) | |
813 | (setq path (org-extract-attributes (org-link-unescape path))) | |
814 | (setq attr (get-text-property 0 'org-attributes path) | |
815 | caption (get-text-property 0 'org-caption path) | |
816 | label (get-text-property 0 'org-label path)) | |
817 | (setq desc1 (if (match-end 5) (match-string 5 line)) | |
818 | desc2 (if (match-end 2) (concat type ":" path) path) | |
819 | descp (and desc1 (not (equal desc1 desc2))) | |
820 | desc (or desc1 desc2)) | |
821 | ;; Make an image out of the description if that is so wanted | |
822 | (when (and descp (org-file-image-p | |
823 | desc org-export-docbook-inline-image-extensions)) | |
824 | (save-match-data | |
825 | (if (string-match "^file:" desc) | |
826 | (setq desc (substring desc (match-end 0)))))) | |
827 | ;; FIXME: do we need to unescape here somewhere? | |
828 | (cond | |
829 | ((equal type "internal") | |
830 | (setq rpl (format "<link linkend=\"%s\">%s</link>" | |
831 | (org-solidify-link-text | |
832 | (save-match-data (org-link-unescape path)) nil) | |
833 | (org-export-docbook-format-desc desc)))) | |
834 | ((and (equal type "id") | |
835 | (setq id-file (org-id-find-id-file path))) | |
836 | ;; This is an id: link to another file (if it was the same file, | |
837 | ;; it would have become an internal link...) | |
838 | (save-match-data | |
839 | (setq id-file (file-relative-name | |
840 | id-file (file-name-directory org-current-export-file))) | |
841 | (setq id-file (concat (file-name-sans-extension id-file) | |
842 | org-export-docbook-extension)) | |
843 | (setq rpl (format "<link xlink:href=\"%s#%s\">%s</link>" | |
844 | id-file path (org-export-docbook-format-desc desc))))) | |
845 | ((member type '("http" "https")) | |
846 | ;; Standard URL, just check if we need to inline an image | |
847 | (if (and (or (eq t org-export-docbook-inline-images) | |
848 | (and org-export-docbook-inline-images (not descp))) | |
849 | (org-file-image-p | |
850 | path org-export-docbook-inline-image-extensions)) | |
851 | (setq rpl (org-export-docbook-format-image | |
852 | (concat type ":" path))) | |
853 | (setq link (concat type ":" path)) | |
854 | (setq rpl (format "<link xlink:href=\"%s\">%s</link>" | |
855 | (org-export-html-format-href link) | |
856 | (org-export-docbook-format-desc desc))) | |
857 | )) | |
858 | ((member type '("ftp" "mailto" "news")) | |
859 | ;; Standard URL | |
860 | (setq link (concat type ":" path)) | |
861 | (setq rpl (format "<link xlink:href=\"%s\">%s</link>" | |
862 | (org-export-html-format-href link) | |
863 | (org-export-docbook-format-desc desc)))) | |
864 | ((string= type "coderef") | |
865 | (setq rpl (format (org-export-get-coderef-format path (and descp desc)) | |
866 | (cdr (assoc path org-export-code-refs))))) | |
867 | ((functionp (setq fnc (nth 2 (assoc type org-link-protocols)))) | |
868 | ;; The link protocol has a function for format the link | |
869 | (setq rpl | |
870 | (save-match-data | |
871 | (funcall fnc (org-link-unescape path) desc1 'html)))) | |
872 | ||
873 | ((string= type "file") | |
874 | ;; FILE link | |
875 | (let* ((filename path) | |
876 | (abs-p (file-name-absolute-p filename)) | |
877 | thefile file-is-image-p search) | |
878 | (save-match-data | |
879 | (if (string-match "::\\(.*\\)" filename) | |
880 | (setq search (match-string 1 filename) | |
881 | filename (replace-match "" t nil filename))) | |
882 | (setq valid | |
883 | (if (functionp link-validate) | |
884 | (funcall link-validate filename current-dir) | |
885 | t)) | |
886 | (setq file-is-image-p | |
887 | (org-file-image-p | |
888 | filename org-export-docbook-inline-image-extensions)) | |
889 | (setq thefile (if abs-p (expand-file-name filename) filename)) | |
890 | ;; Carry over the properties (expand-file-name will | |
891 | ;; discard the properties of filename) | |
892 | (add-text-properties 0 (1- (length thefile)) | |
893 | (list 'org-caption caption | |
894 | 'org-attributes attr | |
895 | 'org-label label) | |
896 | thefile) | |
897 | (when (and org-export-docbook-link-org-files-as-docbook | |
898 | (string-match "\\.org$" thefile)) | |
899 | (setq thefile (concat (substring thefile 0 | |
900 | (match-beginning 0)) | |
901 | org-export-docbook-extension)) | |
902 | (if (and search | |
903 | ;; make sure this is can be used as target search | |
904 | (not (string-match "^[0-9]*$" search)) | |
905 | (not (string-match "^\\*" search)) | |
906 | (not (string-match "^/.*/$" search))) | |
907 | (setq thefile (concat thefile "#" | |
908 | (org-solidify-link-text | |
909 | (org-link-unescape search))))) | |
910 | (when (string-match "^file:" desc) | |
911 | (setq desc (replace-match "" t t desc)) | |
912 | (if (string-match "\\.org$" desc) | |
913 | (setq desc (replace-match "" t t desc)))))) | |
914 | (setq rpl (if (and file-is-image-p | |
915 | (or (eq t org-export-docbook-inline-images) | |
916 | (and org-export-docbook-inline-images | |
917 | (not descp)))) | |
918 | (progn | |
919 | (message "image %s %s" thefile org-docbook-para-open) | |
920 | (org-export-docbook-format-image thefile)) | |
921 | (format "<link xlink:href=\"%s\">%s</link>" | |
922 | thefile (org-export-docbook-format-desc desc)))) | |
923 | (if (not valid) (setq rpl desc)))) | |
924 | ||
925 | (t | |
926 | ;; Just publish the path, as default | |
927 | (setq rpl (concat "<" type ":" | |
928 | (save-match-data (org-link-unescape path)) | |
929 | ">")))) | |
930 | (setq line (replace-match rpl t t line) | |
931 | start (+ start (length rpl)))) | |
932 | ||
933 | ;; TODO items: can we do something better?! | |
934 | (if (and (string-match org-todo-line-regexp line) | |
935 | (match-beginning 2)) | |
936 | (setq line | |
937 | (concat (substring line 0 (match-beginning 2)) | |
938 | "[" (match-string 2 line) "]" | |
939 | (substring line (match-end 2))))) | |
940 | ||
941 | ;; Does this contain a reference to a footnote? | |
942 | (when org-export-with-footnotes | |
943 | (setq start 0) | |
944 | (while (string-match "\\([^* \t].*?\\)\\[\\([0-9]+\\)\\]" line start) | |
3ab2c837 BG |
945 | ;; Discard protected matches not clearly identified as |
946 | ;; footnote markers. | |
947 | (if (or (get-text-property (match-beginning 2) 'org-protected line) | |
948 | (not (get-text-property (match-beginning 2) 'org-footnote line))) | |
c8d0cf5c | 949 | (setq start (match-end 2)) |
ed21c5c8 CD |
950 | (let* ((num (match-string 2 line)) |
951 | (footnote-def (assoc num footnote-list))) | |
c8d0cf5c CD |
952 | (if (assoc num footref-seen) |
953 | (setq line (replace-match | |
954 | (format "%s<footnoteref linkend=\"%s%s\"/>" | |
955 | (match-string 1 line) | |
956 | org-export-docbook-footnote-id-prefix num) | |
957 | t t line)) | |
958 | (setq line (replace-match | |
3ab2c837 BG |
959 | (concat |
960 | (format "%s<footnote xml:id=\"%s%s\"><para>%s</para></footnote>" | |
961 | (match-string 1 line) | |
962 | org-export-docbook-footnote-id-prefix | |
963 | num | |
964 | (if footnote-def | |
965 | (save-match-data | |
966 | (org-docbook-expand (cdr footnote-def))) | |
967 | (format "FOOTNOTE DEFINITION NOT FOUND: %s" num))) | |
968 | ;; If another footnote is following the | |
969 | ;; current one, add a separator. | |
970 | (if (save-match-data | |
971 | (string-match "\\`\\[[0-9]+\\]" | |
972 | (substring line (match-end 0)))) | |
973 | org-export-docbook-footnote-separator | |
974 | "")) | |
c8d0cf5c CD |
975 | t t line)) |
976 | (push (cons num 1) footref-seen)))))) | |
977 | ||
978 | (cond | |
e66ba1df | 979 | ((string-match "^\\(\\*+\\)\\(?: +\\(.*?\\)\\)?[ \t]*$" line) |
c8d0cf5c CD |
980 | ;; This is a headline |
981 | (setq level (org-tr-level (- (match-end 1) (match-beginning 1) | |
982 | level-offset)) | |
983 | txt (match-string 2 line)) | |
984 | (if (string-match quote-re0 txt) | |
985 | (setq txt (replace-match "" t t txt))) | |
c8d0cf5c CD |
986 | (org-export-docbook-level-start level txt) |
987 | ;; QUOTES | |
988 | (when (string-match quote-re line) | |
989 | (org-export-docbook-close-para-maybe) | |
990 | (insert "<programlisting><![CDATA[") | |
991 | (setq inquote t))) | |
992 | ||
993 | ;; Tables: since version 4.3 of DocBook DTD, HTML tables are | |
994 | ;; supported. We can use existing HTML table exporter code | |
995 | ;; here. | |
996 | ((and org-export-with-tables | |
997 | (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line)) | |
998 | (if (not table-open) | |
999 | ;; New table starts | |
1000 | (setq table-open t | |
1001 | table-buffer nil | |
1002 | table-orig-buffer nil)) | |
1003 | ;; Accumulate lines | |
1004 | (setq table-buffer (cons line table-buffer) | |
1005 | table-orig-buffer (cons origline table-orig-buffer)) | |
1006 | (when (or (not lines) | |
1007 | (not (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" | |
1008 | (car lines)))) | |
1009 | (setq table-open nil | |
1010 | table-buffer (nreverse table-buffer) | |
1011 | table-orig-buffer (nreverse table-orig-buffer)) | |
1012 | (org-export-docbook-close-para-maybe) | |
1013 | (insert (org-export-docbook-finalize-table | |
afe98dfa CD |
1014 | (org-format-table-html table-buffer table-orig-buffer |
1015 | 'no-css))))) | |
1016 | ||
3ab2c837 | 1017 | ;; Normal lines |
c8d0cf5c | 1018 | (t |
3ab2c837 BG |
1019 | ;; This line either is list item or end a list. |
1020 | (when (when (get-text-property 0 'list-item line) | |
8223b1d2 BG |
1021 | (setq line (org-export-docbook-list-line |
1022 | line | |
1023 | (get-text-property 0 'list-item line) | |
1024 | (get-text-property 0 'list-struct line) | |
1025 | (get-text-property 0 'list-prevs line))))) | |
c8d0cf5c CD |
1026 | |
1027 | ;; Empty lines start a new paragraph. If hand-formatted lists | |
1028 | ;; are not fully interpreted, lines starting with "-", "+", "*" | |
1029 | ;; also start a new paragraph. | |
1030 | (if (and (string-match "^ [-+*]-\\|^[ \t]*$" line) | |
1031 | (not inverse)) | |
1032 | (org-export-docbook-open-para)) | |
1033 | ||
1034 | ;; Is this the start of a footnote? | |
1035 | (when org-export-with-footnotes | |
1036 | (when (and (boundp 'footnote-section-tag-regexp) | |
1037 | (string-match (concat "^" footnote-section-tag-regexp) | |
1038 | line)) | |
1039 | ;; ignore this line | |
1040 | (throw 'nextline nil)) | |
1041 | ;; These footnote lines have been read and saved before, | |
1042 | ;; ignore them at this time. | |
1043 | (when (string-match "^[ \t]*\\[\\([0-9]+\\)\\]" line) | |
1044 | (org-export-docbook-close-para-maybe) | |
1045 | (throw 'nextline nil))) | |
1046 | ||
1047 | ;; FIXME: It might be a good idea to add an option to | |
1048 | ;; support line break processing instruction <?linebreak?>. | |
1049 | ;; Org-mode supports line break "\\" in HTML exporter, and | |
1050 | ;; some DocBook users may also want to force line breaks | |
1051 | ;; even though DocBook only supports that in | |
1052 | ;; <literallayout>. | |
1053 | ||
1054 | (insert line "\n"))))) | |
1055 | ||
1056 | ;; Properly close all local lists and other lists | |
1057 | (when inquote | |
ed21c5c8 | 1058 | (insert "]]></programlisting>\n") |
c8d0cf5c | 1059 | (org-export-docbook-open-para)) |
afe98dfa | 1060 | |
c8d0cf5c CD |
1061 | ;; Close all open sections. |
1062 | (org-export-docbook-level-start 1 nil) | |
1063 | ||
1064 | (unless (plist-get opt-plist :buffer-will-be-killed) | |
1065 | (normal-mode) | |
14acf2f5 | 1066 | (if (eq major-mode (default-value 'major-mode)) |
c8d0cf5c CD |
1067 | (nxml-mode))) |
1068 | ||
8223b1d2 | 1069 | ;; Remove empty paragraphs. Replace them with a newline. |
c8d0cf5c CD |
1070 | (goto-char (point-min)) |
1071 | (while (re-search-forward | |
1072 | "[ \r\n\t]*\\(<para>\\)[ \r\n\t]*</para>[ \r\n\t]*" nil t) | |
1073 | (when (not (get-text-property (match-beginning 1) 'org-protected)) | |
1074 | (replace-match "\n") | |
1075 | (backward-char 1))) | |
1076 | ;; Fill empty sections with <para></para>. This is to make sure | |
1077 | ;; that the DocBook document generated is valid and well-formed. | |
1078 | (goto-char (point-min)) | |
1079 | (while (re-search-forward | |
1080 | "</title>\\([ \r\n\t]*\\)</section>" nil t) | |
1081 | (when (not (get-text-property (match-beginning 0) 'org-protected)) | |
1082 | (replace-match "\n<para></para>\n" nil nil nil 1))) | |
1083 | ;; Insert the last closing tag. | |
1084 | (goto-char (point-max)) | |
1085 | (unless body-only | |
1086 | (insert "</article>")) | |
8d642074 | 1087 | (run-hooks 'org-export-docbook-final-hook) |
c8d0cf5c CD |
1088 | (or to-buffer (save-buffer)) |
1089 | (goto-char (point-min)) | |
1090 | (or (org-export-push-to-kill-ring "DocBook") | |
1091 | (message "Exporting... done")) | |
1092 | (if (eq to-buffer 'string) | |
1093 | (prog1 (buffer-substring (point-min) (point-max)) | |
1094 | (kill-buffer (current-buffer))) | |
1095 | (current-buffer))))) | |
1096 | ||
1097 | (defun org-export-docbook-open-para () | |
1098 | "Insert <para>, but first close previous paragraph if any." | |
1099 | (org-export-docbook-close-para-maybe) | |
1100 | (insert "\n<para>") | |
1101 | (setq org-docbook-para-open t)) | |
1102 | ||
1103 | (defun org-export-docbook-close-para-maybe () | |
1104 | "Close DocBook paragraph if there is one open." | |
1105 | (when org-docbook-para-open | |
1106 | (insert "</para>\n") | |
1107 | (setq org-docbook-para-open nil))) | |
1108 | ||
1109 | (defun org-export-docbook-close-li (&optional type) | |
1110 | "Close list if necessary." | |
1111 | (org-export-docbook-close-para-maybe) | |
1112 | (if (equal type "d") | |
1113 | (insert "</listitem></varlistentry>\n") | |
1114 | (insert "</listitem>\n"))) | |
1115 | ||
c8d0cf5c CD |
1116 | (defun org-export-docbook-level-start (level title) |
1117 | "Insert a new level in DocBook export. | |
1118 | When TITLE is nil, just close all open levels." | |
1119 | (org-export-docbook-close-para-maybe) | |
1120 | (let* ((target (and title (org-get-text-property-any 0 'target title))) | |
1121 | (l org-level-max) | |
1122 | section-number) | |
1123 | (while (>= l level) | |
1124 | (if (aref org-levels-open (1- l)) | |
1125 | (progn | |
1126 | (insert "</section>\n") | |
1127 | (aset org-levels-open (1- l) nil))) | |
1128 | (setq l (1- l))) | |
1129 | (when title | |
1130 | ;; If title is nil, this means this function is called to close | |
1131 | ;; all levels, so the rest is done only if title is given. | |
1132 | ;; | |
1133 | ;; Format tags: put them into a superscript like format. | |
afe98dfa | 1134 | (when (string-match (org-re "\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$") title) |
c8d0cf5c CD |
1135 | (setq title |
1136 | (replace-match | |
1137 | (if org-export-with-tags | |
1138 | (save-match-data | |
1139 | (concat | |
1140 | "<superscript>" | |
1141 | (match-string 1 title) | |
1142 | "</superscript>")) | |
1143 | "") | |
1144 | t t title))) | |
1145 | (aset org-levels-open (1- level) t) | |
1146 | (setq section-number (org-section-number level)) | |
1147 | (insert (format "\n<section xml:id=\"%s%s\">\n<title>%s</title>" | |
1148 | org-export-docbook-section-id-prefix | |
86fbb8ca CD |
1149 | (replace-regexp-in-string "\\." "_" section-number) |
1150 | title)) | |
c8d0cf5c CD |
1151 | (org-export-docbook-open-para)))) |
1152 | ||
1153 | (defun org-docbook-expand (string) | |
1154 | "Prepare STRING for DocBook export. | |
1155 | Applies all active conversions. If there are links in the | |
1156 | string, don't modify these." | |
1157 | (let* ((re (concat org-bracket-link-regexp "\\|" | |
afe98dfa | 1158 | (org-re "[ \t]+\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$"))) |
c8d0cf5c CD |
1159 | m s l res) |
1160 | (while (setq m (string-match re string)) | |
1161 | (setq s (substring string 0 m) | |
1162 | l (match-string 0 string) | |
1163 | string (substring string (match-end 0))) | |
1164 | (push (org-docbook-do-expand s) res) | |
1165 | (push l res)) | |
1166 | (push (org-docbook-do-expand string) res) | |
1167 | (apply 'concat (nreverse res)))) | |
1168 | ||
1169 | (defun org-docbook-do-expand (s) | |
1170 | "Apply all active conversions to translate special ASCII to DocBook." | |
1171 | (setq s (org-html-protect s)) | |
1172 | (while (string-match "@<\\([^&]*\\)>" s) | |
1173 | (setq s (replace-match "<\\1>" t nil s))) | |
1174 | (if org-export-with-emphasize | |
1175 | (setq s (org-export-docbook-convert-emphasize s))) | |
1176 | (if org-export-with-special-strings | |
1177 | (setq s (org-export-docbook-convert-special-strings s))) | |
1178 | (if org-export-with-sub-superscripts | |
1179 | (setq s (org-export-docbook-convert-sub-super s))) | |
1180 | (if org-export-with-TeX-macros | |
ed21c5c8 | 1181 | (let ((start 0) wd rep) |
c8d0cf5c CD |
1182 | (while (setq start (string-match "\\\\\\([a-zA-Z]+\\)\\({}\\)?" |
1183 | s start)) | |
1184 | (if (get-text-property (match-beginning 0) 'org-protected s) | |
1185 | (setq start (match-end 0)) | |
1186 | (setq wd (match-string 1 s)) | |
ed21c5c8 CD |
1187 | (if (setq rep (org-entity-get-representation wd 'html)) |
1188 | (setq s (replace-match rep t t s)) | |
c8d0cf5c CD |
1189 | (setq start (+ start (length wd)))))))) |
1190 | s) | |
1191 | ||
1192 | (defun org-export-docbook-format-desc (desc) | |
1193 | "Make sure DESC is valid as a description in a link." | |
1194 | (save-match-data | |
1195 | (org-docbook-do-expand desc))) | |
1196 | ||
1197 | (defun org-export-docbook-convert-emphasize (string) | |
1198 | "Apply emphasis for DocBook exporting." | |
1199 | (let ((s 0) rpl) | |
1200 | (while (string-match org-emph-re string s) | |
1201 | (if (not (equal | |
1202 | (substring string (match-beginning 3) (1+ (match-beginning 3))) | |
1203 | (substring string (match-beginning 4) (1+ (match-beginning 4))))) | |
1204 | (setq s (match-beginning 0) | |
1205 | rpl | |
1206 | (concat | |
1207 | (match-string 1 string) | |
1208 | (nth 1 (assoc (match-string 3 string) | |
1209 | org-export-docbook-emphasis-alist)) | |
1210 | (match-string 4 string) | |
1211 | (nth 2 (assoc (match-string 3 string) | |
1212 | org-export-docbook-emphasis-alist)) | |
1213 | (match-string 5 string)) | |
1214 | string (replace-match rpl t t string) | |
1215 | s (+ s (- (length rpl) 2))) | |
1216 | (setq s (1+ s)))) | |
1217 | string)) | |
1218 | ||
1219 | (defun org-docbook-protect (string) | |
1220 | (org-html-protect string)) | |
1221 | ||
1222 | ;; For now, simply return string as it is. | |
1223 | (defun org-export-docbook-convert-special-strings (string) | |
1224 | "Convert special characters in STRING to DocBook." | |
1225 | string) | |
1226 | ||
1227 | (defun org-export-docbook-get-footnotes (lines) | |
1228 | "Given a list of LINES, return a list of alist footnotes." | |
1229 | (let ((list nil) line) | |
1230 | (while (setq line (pop lines)) | |
1231 | (if (string-match "^[ \t]*\\[\\([0-9]+\\)\\] \\(.+\\)" line) | |
1232 | (push (cons (match-string 1 line) (match-string 2 line)) | |
1233 | list))) | |
1234 | list)) | |
1235 | ||
1236 | (defun org-export-docbook-format-image (src) | |
1237 | "Create image element in DocBook." | |
1238 | (save-match-data | |
1239 | (let* ((caption (org-find-text-property-in-string 'org-caption src)) | |
1240 | (attr (or (org-find-text-property-in-string 'org-attributes src) | |
1241 | "")) | |
1242 | (label (org-find-text-property-in-string 'org-label src)) | |
1243 | (default-attr org-export-docbook-default-image-attributes) | |
1244 | tmp) | |
ed21c5c8 | 1245 | (setq caption (and caption (org-html-do-expand caption))) |
c8d0cf5c CD |
1246 | (while (setq tmp (pop default-attr)) |
1247 | (if (not (string-match (concat (car tmp) "=") attr)) | |
1248 | (setq attr (concat attr " " (car tmp) "=" (cdr tmp))))) | |
1249 | (format "<mediaobject%s> | |
1250 | <imageobject>\n<imagedata fileref=\"%s\" %s/>\n</imageobject> | |
1251 | %s</mediaobject>" | |
1252 | (if label (concat " xml:id=\"" label "\"") "") | |
1253 | src attr | |
1254 | (if caption | |
1255 | (concat "<caption>\n<para>" | |
1256 | caption | |
1257 | "</para>\n</caption>\n") | |
1258 | "") | |
1259 | )))) | |
1260 | ||
1261 | (defun org-export-docbook-preprocess (parameters) | |
1262 | "Extra preprocessing work for DocBook export." | |
1263 | ;; Merge lines starting with "\par" to one line. Such lines are | |
1264 | ;; regarded as the continuation of a long footnote. | |
1265 | (goto-char (point-min)) | |
1266 | (while (re-search-forward "\n\\(\\\\par\\>\\)" nil t) | |
1267 | (if (not (get-text-property (match-beginning 1) 'org-protected)) | |
1268 | (replace-match "")))) | |
1269 | ||
1270 | (defun org-export-docbook-finalize-table (table) | |
ed21c5c8 CD |
1271 | "Clean up TABLE and turn it into DocBook format. |
1272 | This function adds a label to the table if it is available, and | |
1273 | also changes TABLE to informaltable if caption does not exist. | |
c8d0cf5c CD |
1274 | TABLE is a string containing the HTML code generated by |
1275 | `org-format-table-html' for a table in Org-mode buffer." | |
ed21c5c8 CD |
1276 | (let (table-with-label) |
1277 | ;; Get the label if it exists, and move it into the <table> element. | |
1278 | (setq table-with-label | |
1279 | (if (string-match | |
1280 | "^<table \\(\\(.\\|\n\\)+\\)<a name=\"\\(.+\\)\" id=\".+\"></a>\n\\(\\(.\\|\n\\)+\\)</table>" | |
1281 | table) | |
1282 | (replace-match (concat "<table xml:id=\"" (match-string 3 table) "\" " | |
1283 | (match-string 1 table) | |
1284 | (match-string 4 table) | |
1285 | "</table>") | |
3ab2c837 | 1286 | nil t table) |
ed21c5c8 CD |
1287 | table)) |
1288 | ;; Change <table> into <informaltable> if caption does not exist. | |
1289 | (if (string-match | |
1290 | "^<table \\(\\(.\\|\n\\)+\\)<caption></caption>\n\\(\\(.\\|\n\\)+\\)</table>" | |
1291 | table-with-label) | |
1292 | (replace-match (concat "<informaltable " | |
1293 | (match-string 1 table-with-label) | |
1294 | (match-string 3 table-with-label) | |
1295 | "</informaltable>") | |
3ab2c837 | 1296 | nil t table-with-label) |
ed21c5c8 | 1297 | table-with-label))) |
c8d0cf5c CD |
1298 | |
1299 | ;; Note: This function is very similar to | |
1300 | ;; org-export-html-convert-sub-super. They can be merged in the future. | |
1301 | (defun org-export-docbook-convert-sub-super (string) | |
1302 | "Convert sub- and superscripts in STRING for DocBook." | |
1303 | (let (key c (s 0) (requireb (eq org-export-with-sub-superscripts '{}))) | |
1304 | (while (string-match org-match-substring-regexp string s) | |
1305 | (cond | |
1306 | ((and requireb (match-end 8)) (setq s (match-end 2))) | |
1307 | ((get-text-property (match-beginning 2) 'org-protected string) | |
1308 | (setq s (match-end 2))) | |
1309 | (t | |
1310 | (setq s (match-end 1) | |
1311 | key (if (string= (match-string 2 string) "_") | |
1312 | "subscript" | |
1313 | "superscript") | |
1314 | c (or (match-string 8 string) | |
1315 | (match-string 6 string) | |
1316 | (match-string 5 string)) | |
1317 | string (replace-match | |
1318 | (concat (match-string 1 string) | |
1319 | "<" key ">" c "</" key ">") | |
1320 | t t string))))) | |
1321 | (while (string-match "\\\\\\([_^]\\)" string) | |
1322 | (setq string (replace-match (match-string 1 string) t t string))) | |
1323 | string)) | |
1324 | ||
1325 | (defun org-export-docbook-protect-tags (string) | |
1326 | "Change ``<...>'' in string STRING into ``@<...>''. | |
1327 | This is normally needed when STRING contains DocBook elements | |
1328 | that need to be preserved in later phase of DocBook exporting." | |
1329 | (let ((start 0)) | |
1330 | (while (string-match "<\\([^>]*\\)>" string start) | |
1331 | (setq string (replace-match | |
1332 | "@<\\1>" t nil string) | |
1333 | start (match-end 0))) | |
1334 | string)) | |
1335 | ||
1336 | (defun org-export-docbook-handle-time-stamps (line) | |
1337 | "Format time stamps in string LINE." | |
1338 | (let (replaced | |
1339 | (kw-markup (org-export-docbook-protect-tags | |
1340 | org-export-docbook-keywords-markup)) | |
1341 | (ts-markup (org-export-docbook-protect-tags | |
1342 | org-export-docbook-timestamp-markup))) | |
1343 | (while (string-match org-maybe-keyword-time-regexp line) | |
1344 | (setq replaced | |
1345 | (concat replaced | |
1346 | (substring line 0 (match-beginning 0)) | |
1347 | (if (match-end 1) | |
1348 | (format kw-markup | |
1349 | (match-string 1 line))) | |
1350 | " " | |
1351 | (format ts-markup | |
1352 | (substring (org-translate-time | |
1353 | (match-string 3 line)) 1 -1))) | |
1354 | line (substring line (match-end 0)))) | |
1355 | (concat replaced line))) | |
1356 | ||
3ab2c837 | 1357 | (defun org-export-docbook-list-line (line pos struct prevs) |
8223b1d2 | 1358 | "Insert list syntax in export buffer. Return LINE, maybe modified. |
3ab2c837 BG |
1359 | |
1360 | POS is the item position or line position the line had before | |
8223b1d2 | 1361 | modifications to buffer. STRUCT is the list structure. PREVS is |
3ab2c837 BG |
1362 | the alist of previous items." |
1363 | (let* ((get-type | |
1364 | (function | |
1365 | ;; Translate type of list containing POS to "ordered", | |
1366 | ;; "variable" or "itemized". | |
1367 | (lambda (pos struct prevs) | |
1368 | (let ((type (org-list-get-list-type pos struct prevs))) | |
1369 | (cond | |
1370 | ((eq 'ordered type) "ordered") | |
1371 | ((eq 'descriptive type) "variable") | |
1372 | (t "itemized")))))) | |
1373 | (get-closings | |
1374 | (function | |
1375 | ;; Return list of all items and sublists ending at POS, in | |
1376 | ;; reverse order. | |
1377 | (lambda (pos) | |
1378 | (let (out) | |
1379 | (catch 'exit | |
1380 | (mapc (lambda (e) | |
1381 | (let ((end (nth 6 e)) | |
1382 | (item (car e))) | |
1383 | (cond | |
1384 | ((= end pos) (push item out)) | |
1385 | ((>= item pos) (throw 'exit nil))))) | |
1386 | struct)) | |
1387 | out))))) | |
1388 | ;; First close any previous item, or list, ending at POS. | |
1389 | (mapc (lambda (e) | |
1390 | (let* ((lastp (= (org-list-get-last-item e struct prevs) e)) | |
1391 | (first-item (org-list-get-list-begin e struct prevs)) | |
1392 | (type (funcall get-type first-item struct prevs))) | |
1393 | ;; Ending for every item | |
1394 | (org-export-docbook-close-para-maybe) | |
1395 | (insert (if (equal type "variable") | |
1396 | "</listitem></varlistentry>\n" | |
1397 | "</listitem>\n")) | |
1398 | ;; We're ending last item of the list: end list. | |
1399 | (when lastp | |
1400 | (insert (format "</%slist>\n" type)) | |
1401 | (org-export-docbook-open-para)))) | |
1402 | (funcall get-closings pos)) | |
1403 | (cond | |
1404 | ;; At an item: insert appropriate tags in export buffer. | |
1405 | ((assq pos struct) | |
1406 | (string-match (concat "[ \t]*\\(\\S-+[ \t]*\\)" | |
1407 | "\\(?:\\[@\\(?:start:\\)?\\([0-9]+\\|[a-zA-Z]\\)\\][ \t]*\\)?" | |
1408 | "\\(?:\\(\\[[ X-]\\]\\)[ \t]+\\)?" | |
1409 | "\\(?:\\(.*\\)[ \t]+::\\(?:[ \t]+\\|$\\)\\)?" | |
1410 | "\\(.*\\)") | |
1411 | line) | |
1412 | (let* ((checkbox (match-string 3 line)) | |
1413 | (desc-tag (or (match-string 4 line) "???")) | |
1414 | (body (match-string 5 line)) | |
1415 | (list-beg (org-list-get-list-begin pos struct prevs)) | |
1416 | (firstp (= list-beg pos)) | |
1417 | ;; Always refer to first item to determine list type, in | |
1418 | ;; case list is ill-formed. | |
1419 | (type (funcall get-type list-beg struct prevs)) | |
1420 | ;; Special variables for ordered lists. | |
1421 | (counter (let ((count-tmp (org-list-get-counter pos struct))) | |
1422 | (cond | |
1423 | ((not count-tmp) nil) | |
1424 | ((string-match "[A-Za-z]" count-tmp) | |
1425 | (- (string-to-char (upcase count-tmp)) 64)) | |
1426 | ((string-match "[0-9]+" count-tmp) | |
1427 | count-tmp))))) | |
1428 | ;; When FIRSTP, a new list or sub-list is starting. | |
1429 | (when firstp | |
1430 | (org-export-docbook-close-para-maybe) | |
1431 | (insert (format "<%slist>\n" type))) | |
1432 | (insert (cond | |
1433 | ((equal type "variable") | |
1434 | (format "<varlistentry><term>%s</term><listitem>" desc-tag)) | |
1435 | ((and (equal type "ordered") counter) | |
1436 | (format "<listitem override=\"%s\">" counter)) | |
1437 | (t "<listitem>"))) | |
1438 | ;; For DocBook, we need to open a para right after tag | |
1439 | ;; <listitem>. | |
1440 | (org-export-docbook-open-para) | |
1441 | ;; If line had a checkbox, some additional modification is required. | |
1442 | (when checkbox (setq body (concat checkbox " " body))) | |
1443 | ;; Return modified line | |
1444 | body)) | |
1445 | ;; At a list ender: normal text follows: need <para>. | |
1446 | ((equal "ORG-LIST-END-MARKER" line) | |
1447 | (org-export-docbook-open-para) | |
1448 | (throw 'nextline nil)) | |
1449 | ;; Not at an item: return line unchanged (side-effects only). | |
1450 | (t line)))) | |
1451 | ||
c8d0cf5c CD |
1452 | (provide 'org-docbook) |
1453 | ||
bdebdb64 BG |
1454 | ;; Local variables: |
1455 | ;; generated-autoload-file: "org-loaddefs.el" | |
1456 | ;; End: | |
1457 | ||
c8d0cf5c | 1458 | ;;; org-docbook.el ends here |