1 ;;; org-e-odt.el --- OpenDocument Text exporter for Org-mode
3 ;; Copyright (C) 2010-2012 Free Software Foundation, Inc.
5 ;; Author: Jambunathan K <kjambunathan at gmail dot com>
6 ;; Keywords: outlines, hypermedia, calendar, wp
7 ;; Homepage: http://orgmode.org
9 ;; This file is part of GNU Emacs.
11 ;; GNU Emacs is free software: you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation, either version 3 of the License, or
14 ;; (at your option) any later version.
16 ;; GNU Emacs is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
31 (defgroup org-export-e-odt nil
32 "Options specific for ODT export of Org-mode files."
37 ;; (defun org-e-odt-unload-function ()
38 ;; (org-lparse-unregister-backend 'odt)
39 ;; (remove-hook 'org-export-preprocess-after-blockquote-hook
40 ;; 'org-export-e-odt-preprocess-latex-fragments)
43 (defun org-e-odt-get-style-name-for-entity (category &optional entity
)
44 (let ((entity (or entity
'default
)))
46 (cdr (assoc entity
(cdr (assoc category
47 org-export-e-odt-org-styles-alist
))))
48 (cdr (assoc entity
(cdr (assoc category
49 org-export-e-odt-default-org-styles-alist
))))
50 (error "Cannot determine style name for entity %s of type %s"
55 (defun org-export-as-e-odt-and-open (arg)
56 "Export the outline as ODT and immediately open it with a browser.
57 If there is an active region, export only the region.
58 The prefix ARG specifies how many levels of the outline should become
59 headlines. The default is 3. Lower levels will become bulleted lists."
62 (or org-export-e-odt-preferred-output-format
"odt") "odt" arg
))
65 (defun org-export-as-e-odt-batch ()
66 "Call the function `org-lparse-batch'.
67 This function can be used in batch processing as:
69 --load=$HOME/lib/emacs/org.el
70 --eval \"(setq org-export-headline-levels 2)\"
71 --visit=MyFile --funcall org-export-as-e-odt-batch"
72 (org-lparse-batch "odt"))
74 ;;; org-export-as-e-odt
76 (defun org-export-as-e-odt (arg &optional hidden ext-plist
77 to-buffer body-only pub-dir
)
78 "Export the outline as a OpenDocumentText file.
79 If there is an active region, export only the region. The prefix
80 ARG specifies how many levels of the outline should become
81 headlines. The default is 3. Lower levels will become bulleted
82 lists. HIDDEN is obsolete and does nothing.
83 EXT-PLIST is a property list with external parameters overriding
84 org-mode's default settings, but still inferior to file-local
85 settings. When TO-BUFFER is non-nil, create a buffer with that
86 name and export to that buffer. If TO-BUFFER is the symbol
87 `string', don't leave any buffer behind but just return the
88 resulting XML as a string. When BODY-ONLY is set, don't produce
89 the file header and footer, simply return the content of
90 <body>...</body>, without even the body tags themselves. When
91 PUB-DIR is set, use this as the publishing directory."
93 (org-lparse (or org-export-e-odt-preferred-output-format
"odt")
94 "odt" arg hidden ext-plist to-buffer body-only pub-dir
))
98 ;; Following variable is let bound when `org-do-lparse' is in
99 ;; progress. See org-html.el.
101 (defun org-e-odt-format-preamble (info)
102 (let* ((title (plist-get info
:title
))
103 (author (plist-get info
:author
))
104 (date (plist-get info
:date
))
105 (iso-date (org-e-odt-format-date date
))
106 (date (org-e-odt-format-date date
"%d %b %Y"))
107 (email (plist-get info
:email
))
108 ;; switch on or off above vars based on user settings
109 (author (and (plist-get info
:with-author
) (or author email
)))
110 (email (and (plist-get info
:with-email
) email
))
111 ;; (date (and (plist-get info :time-stamp-file) date))
117 (org-e-odt-format-stylized-paragraph
118 'title
(format "\n<text:title>%s</text:title>" title
))
120 "\n<text:p text:style-name=\"OrgTitle\"/>"))
122 ((and author
(not email
))
125 (org-e-odt-format-stylized-paragraph
127 (format "<text:initial-creator>%s</text:initial-creator>" author
))
129 "\n<text:p text:style-name=\"OrgSubtitle\"/>"))
133 (org-e-odt-format-stylized-paragraph
135 (org-e-odt-format-link
136 (format "<text:initial-creator>%s</text:initial-creator>" author
)
137 (concat "mailto:" email
)))
139 "\n<text:p text:style-name=\"OrgSubtitle\"/>")))
143 (org-e-odt-format-stylized-paragraph
146 '("<text:date style:data-style-name=\"%s\" text:date-value=\"%s\">"
148 date
"N75" iso-date
))
150 "<text:p text:style-name=\"OrgSubtitle\"/>")))))
152 (defun org-e-odt-begin-section (style &optional name
)
153 (let ((default-name (car (org-e-odt-add-automatic-style "Section"))))
154 (format "<text:section text:style-name=\"%s\" text:name=\"%s\">"
155 style
(or name default-name
))))
157 (defun org-e-odt-end-section ()
160 (defun org-e-odt-begin-paragraph (&optional style
)
161 (format "<text:p%s>" (org-e-odt-get-extra-attrs-for-paragraph-style style
)))
163 (defun org-e-odt-end-paragraph ()
166 (defun org-e-odt-get-extra-attrs-for-paragraph-style (style)
170 ((stringp style
) style
)
171 ((symbolp style
) (org-e-odt-get-style-name-for-entity
174 (error "Don't know how to handle paragraph style %s" style
))
175 (format " text:style-name=\"%s\"" style-name
)))
177 (defun org-e-odt-format-stylized-paragraph (style text
)
178 (format "\n<text:p%s>%s</text:p>"
179 (org-e-odt-get-extra-attrs-for-paragraph-style style
)
182 (defun org-e-odt-format-author (&optional author
)
183 (when (setq author
(or author
(plist-get org-lparse-opt-plist
:author
)))
184 (format "<dc:creator>%s</dc:creator>" author
)))
186 (defun org-e-odt-format-date (&optional org-ts fmt
)
189 (and (stringp org-ts
)
190 (string-match org-ts-regexp0 org-ts
)
192 (org-fix-decoded-time
193 (org-parse-time-string (match-string 0 org-ts
) t
)))))
196 (fmt (format-time-string fmt time
))
197 (t (setq date
(format-time-string "%Y-%m-%dT%H:%M:%S%z" time
))
198 (format "%s:%s" (substring date
0 -
2) (substring date -
2)))))))
200 (defun org-e-odt-begin-annotation (&optional author date
)
201 (org-lparse-insert-tag "<office:annotation>")
202 (when (setq author
(org-e-odt-format-author author
))
204 (insert (org-e-odt-format-tags
205 '("<dc:date>" .
"</dc:date>")
206 (org-e-odt-format-date
207 (or date
(plist-get org-lparse-opt-plist
:date
)))))
208 (org-lparse-begin-paragraph))
210 (defun org-e-odt-end-annotation ()
211 (org-lparse-insert-tag "</office:annotation>"))
213 (defun org-e-odt-begin-environment (style env-options-plist
)
216 (org-lparse-stash-save-paragraph-state)
217 (org-e-odt-begin-annotation (plist-get env-options-plist
'author
)
218 (plist-get env-options-plist
'date
)))
219 ((blockquote verse center quote
)
220 (org-lparse-begin-paragraph style
)
223 (org-lparse-end-paragraph)
225 (t (error "Unknown environment %s" style
))))
227 (defun org-e-odt-end-environment (style env-options-plist
)
230 (org-lparse-end-paragraph)
231 (org-e-odt-end-annotation)
232 (org-lparse-stash-pop-paragraph-state))
233 ((blockquote verse center quote
)
234 (org-lparse-end-paragraph)
237 (org-lparse-begin-paragraph)
239 (t (error "Unknown environment %s" style
))))
241 (defun org-e-odt-begin-plain-list (ltype)
242 ;; (setq ltype (or (org-lparse-html-list-type-to-canonical-list-type ltype)
244 (let* ((style-name (org-e-odt-get-style-name-for-entity 'list ltype
))
246 ;; (if (or org-lparse-list-table-p
247 ;; (and (= 1 (length org-lparse-list-stack))
248 ;; (null org-e-odt-list-stack-stashed)))
249 ;; " text:continue-numbering=\"false\""
250 ;; " text:continue-numbering=\"true\"")
252 " text:continue-numbering=\"true\""
255 (format " text:style-name=\"%s\"" style-name
)))))
257 ((ordered unordered descriptive
)
259 ;; (org-e-odt-end-paragraph)
260 (format "<text:list%s>" extra
)))
261 (t (error "Unknown list type: %s" ltype
)))))
263 (defun org-e-odt-end-plain-list (ltype)
264 ;; (setq ltype (or (org-lparse-html-list-type-to-canonical-list-type ltype)
266 (if ltype
"</text:list>"
267 (error "Unknown list type: %s" ltype
)))
269 (defun org-e-odt-begin-list-item (ltype &optional arg headline
)
270 (setq ltype
(or (org-lparse-html-list-type-to-canonical-list-type ltype
)
274 (assert (not headline
) t
)
275 (let* ((counter arg
) (extra ""))
276 (concat "<text:list-item>" ;; (org-e-odt-begin-paragraph)
278 ;; (if (= (length org-lparse-list-stack)
279 ;; (length org-e-odt-list-stack-stashed))
280 ;; "<text:list-header>" "<text:list-item>")
283 (let* ((id arg
) (extra ""))
286 ;; (org-e-odt-begin-paragraph)
287 (if headline
(org-e-odt-format-target headline id
)
288 (org-e-odt-format-bookmark "" id
)))
289 ;; (if (= (length org-lparse-list-stack)
290 ;; (length org-e-odt-list-stack-stashed))
291 ;; "<text:list-header>" "<text:list-item>")
294 (assert (not headline
) t
)
295 (let ((term (or arg
"(no term)")))
297 (org-e-odt-format-tags
298 '("<text:list-item>" .
"</text:list-item>")
299 (org-e-odt-format-stylized-paragraph 'definition-term term
))
300 (org-e-odt-begin-list-item 'unordered
)
301 (org-e-odt-begin-plain-list 'descriptive
)
302 (org-e-odt-begin-list-item 'unordered
))))
303 (t (error "Unknown list type"))))
305 (defun org-e-odt-end-list-item (ltype)
306 ;; (setq ltype (or (org-lparse-html-list-type-to-canonical-list-type ltype)
310 ;; (org-lparse-insert-tag
311 ;; (if (= (length org-lparse-list-stack)
312 ;; (length org-e-odt-list-stack-stashed))
313 ;; (prog1 "</text:list-header>"
314 ;; (setq org-e-odt-list-stack-stashed nil))
315 ;; "</text:list-item>")
321 (org-e-odt-end-list-item 'unordered
)
322 (org-e-odt-end-plain-list 'descriptive
)
323 (org-e-odt-end-list-item 'unordered
)
325 (t (error "Unknown list type"))))
327 (defun org-e-odt-discontinue-list ()
328 (let ((stashed-stack org-lparse-list-stack
))
329 (loop for list-type in stashed-stack
330 do
(org-lparse-end-list-item-1 list-type
)
331 (org-lparse-end-list list-type
))
332 (setq org-e-odt-list-stack-stashed stashed-stack
)))
334 (defun org-e-odt-continue-list ()
335 (setq org-e-odt-list-stack-stashed
(nreverse org-e-odt-list-stack-stashed
))
336 (loop for list-type in org-e-odt-list-stack-stashed
337 do
(org-lparse-begin-list list-type
)
338 (org-lparse-begin-list-item list-type
)))
340 ;; Following variables are let bound when table emission is in
341 ;; progress. See org-lparse.el.
342 (defun org-e-odt-write-automatic-styles ()
343 "Write automatic styles to \"content.xml\"."
345 (find-file-noselect (expand-file-name "content.xml") t
)
346 ;; position the cursor
347 (goto-char (point-min))
348 (re-search-forward " </office:automatic-styles>" nil t
)
349 (goto-char (match-beginning 0))
350 ;; write automatic table styles
351 (loop for
(style-name props
) in
352 (plist-get org-e-odt-automatic-styles
'Table
) do
353 (when (setq props
(or (plist-get props
:rel-width
) 96))
354 (insert (format org-e-odt-table-style-format style-name props
))))))
356 (defun org-e-odt-add-automatic-style (object-type &optional object-props
)
357 "Create an automatic style of type OBJECT-TYPE with param OBJECT-PROPS.
358 OBJECT-PROPS is (typically) a plist created by passing
359 \"#+ATTR_ODT: \" option of the object in question to
360 `org-lparse-get-block-params'.
362 Use `org-e-odt-object-counters' to generate an automatic
363 OBJECT-NAME and STYLE-NAME. If OBJECT-PROPS is non-nil, add a
364 new entry in `org-e-odt-automatic-styles'. Return (OBJECT-NAME
366 (assert (stringp object-type
))
367 (let* ((object (intern object-type
))
369 (seqno (1+ (or (plist-get org-e-odt-object-counters seqvar
) 0)))
370 (object-name (format "%s%d" object-type seqno
)) style-name
)
371 (setq org-e-odt-object-counters
372 (plist-put org-e-odt-object-counters seqvar seqno
))
374 (setq style-name
(format "Org%s" object-name
))
375 (setq org-e-odt-automatic-styles
376 (plist-put org-e-odt-automatic-styles object
377 (append (list (list style-name object-props
))
378 (plist-get org-e-odt-automatic-styles object
)))))
379 (cons object-name style-name
)))
381 (defun org-e-odt-format-table-columns ()
382 (let* ((num-cols (length (plist-get table-info
:alignment
)))
383 (col-nos (loop for i from
1 below num-cols collect i
))
385 (col-widths (plist-get table-info
:width
))
386 (style (or (nth 1 org-e-odt-table-style-spec
) "OrgTable")))
389 (let* ((width (or (and org-lparse-table-is-styled
(aref col-widths c
))
391 (org-e-odt-make-string
393 (org-e-odt-format-tags
394 "<table:table-column table:style-name=\"%sColumn\"/>" "" style
))))
398 (defun org-e-odt-begin-table (caption label attributes
)
399 ;; (setq org-e-odt-table-indentedp (not (null org-lparse-list-stack)))
400 (setq org-e-odt-table-indentedp nil
) ; FIXME
401 (when org-e-odt-table-indentedp
402 ;; Within the Org file, the table is appearing within a list item.
403 ;; OpenDocument doesn't allow table to appear within list items.
404 ;; Temporarily terminate the list, emit the table and then
405 ;; re-continue the list.
406 (org-e-odt-discontinue-list)
407 ;; Put the Table in an indented section.
408 (let ((level (length org-e-odt-list-stack-stashed
)))
409 (org-e-odt-begin-section (format "OrgIndentedSection-Level-%d" level
))))
410 (setq attributes
(org-lparse-get-block-params attributes
))
411 (setq org-e-odt-table-style
(plist-get attributes
:style
))
412 (setq org-e-odt-table-style-spec
413 (assoc org-e-odt-table-style org-export-e-odt-table-styles
))
415 (org-e-odt-format-stylized-paragraph
416 'table
(org-e-odt-format-entity-caption label caption
"__Table__"))
417 (let ((name-and-style (org-e-odt-add-automatic-style "Table" attributes
)))
419 "\n<table:table table:name=\"%s\" table:style-name=\"%s\">\n"
420 (car name-and-style
) (or (nth 1 org-e-odt-table-style-spec
)
421 (cdr name-and-style
) "OrgTable")))
422 (org-e-odt-format-table-columns) "\n")
424 ;; (org-e-html-pp table-info)
426 ;; (setq org-lparse-table-begin-marker (point))
429 (defun org-e-odt-end-table ()
430 ;; fill style attributes for table cells
431 (when org-lparse-table-is-styled
432 (while (re-search-forward "@@\\(table-cell:p\\|table-cell:style-name\\)@@\\([0-9]+\\)@@\\([0-9]+\\)@@" nil t
)
433 (let* (;; (spec (match-string 1))
434 ;; (r (string-to-number (match-string 2)))
435 ;; (c (string-to-number (match-string 3)))
436 (cell-styles (org-e-odt-get-table-cell-styles
437 r c org-e-odt-table-style-spec
))
438 (table-cell-style (car cell-styles
))
439 (table-cell-paragraph-style (cdr cell-styles
)))
441 ((equal spec
"table-cell:p")
442 (replace-match table-cell-paragraph-style t t
))
443 ((equal spec
"table-cell:style-name")
444 (replace-match table-cell-style t t
))))))
445 (goto-char (point-max))
449 ;; (when org-e-odt-table-indentedp
450 ;; (org-e-odt-end-section)
451 ;; (org-e-odt-continue-list))
454 (defun org-e-odt-begin-table-rowgroup (&optional is-header-row
)
456 (concat (when org-e-odt-table-rowgrp-open
457 (org-e-odt-end-table-rowgroup))
458 (if is-header-row
"<table:table-header-rows>"
459 "<table:table-rows>"))
460 (setq org-e-odt-table-rowgrp-open t
)
461 (setq org-e-odt-table-cur-rowgrp-is-hdr is-header-row
)))
463 (defun org-e-odt-end-table-rowgroup ()
464 (when org-e-odt-table-rowgrp-open
465 (setq org-e-odt-table-rowgrp-open nil
)
466 (if org-e-odt-table-cur-rowgrp-is-hdr
467 "</table:table-header-rows>" "</table:table-rows>")))
469 (defun org-e-odt-format-table-row (row)
470 (org-e-odt-format-tags
471 '("<table:table-row>" .
"</table:table-row>") row
))
473 (defun org-e-odt-get-column-alignment (c)
474 (let ((colalign-vector (plist-get table-info
:alignment
)))
476 (assoc-default (aref colalign-vector c
)
481 (defun org-e-odt-get-table-cell-styles (r c
&optional style-spec
)
482 "Retrieve styles applicable to a table cell.
483 R and C are (zero-based) row and column numbers of the table
484 cell. STYLE-SPEC is an entry in `org-export-e-odt-table-styles'
485 applicable to the current table. It is `nil' if the table is not
486 associated with any style attributes.
488 Return a cons of (TABLE-CELL-STYLE-NAME . PARAGRAPH-STYLE-NAME).
490 When STYLE-SPEC is nil, style the table cell the conventional way
491 - choose cell borders based on row and column groupings and
492 choose paragraph alignment based on `org-col-cookies' text
494 `org-e-odt-get-paragraph-style-cookie-for-table-cell'.
496 When STYLE-SPEC is non-nil, ignore the above cookie and return
497 styles congruent with the ODF-1.2 specification."
501 ;; LibreOffice - particularly the Writer - honors neither table
502 ;; templates nor custom table-cell styles. Inorder to retain
503 ;; inter-operability with LibreOffice, only automatic styles are
504 ;; used for styling of table-cells. The current implementation is
505 ;; congruent with ODF-1.2 specification and hence is
506 ;; future-compatible.
508 ;; Additional Note: LibreOffice's AutoFormat facility for tables -
509 ;; which recognizes as many as 16 different cell types - is much
510 ;; richer. Unfortunately it is NOT amenable to easy configuration
513 (let* ((template-name (nth 1 style-spec
))
514 (cell-style-selectors (nth 2 style-spec
))
517 ((and (cdr (assoc 'use-first-column-styles cell-style-selectors
))
518 (= c
0)) "FirstColumn")
519 ((and (cdr (assoc 'use-last-column-styles cell-style-selectors
))
520 (= c
(1- org-lparse-table-ncols
))) "LastColumn")
521 ((and (cdr (assoc 'use-first-row-styles cell-style-selectors
))
523 ((and (cdr (assoc 'use-last-row-styles cell-style-selectors
))
524 (= r org-e-odt-table-rownum
))
526 ((and (cdr (assoc 'use-banding-rows-styles cell-style-selectors
))
527 (= (% r
2) 1)) "EvenRow")
528 ((and (cdr (assoc 'use-banding-rows-styles cell-style-selectors
))
529 (= (% r
2) 0)) "OddRow")
530 ((and (cdr (assoc 'use-banding-columns-styles cell-style-selectors
))
531 (= (% c
2) 1)) "EvenColumn")
532 ((and (cdr (assoc 'use-banding-columns-styles cell-style-selectors
))
533 (= (% c
2) 0)) "OddColumn")
536 (concat template-name cell-type
"TableCell")
537 (concat template-name cell-type
"TableParagraph"))))
544 ((eq (cdr (assoc r nil
;; org-lparse-table-rowgrp-info FIXME
547 (when (= r org-e-odt-table-rownum
) "B")
550 ((or (memq (nth c org-table-colgroup-info
) '(:start
:startend
))
551 (memq (nth (1- c
) org-table-colgroup-info
) '(:end
:startend
))) "L")
553 (capitalize (org-e-odt-get-column-alignment c
))))))
555 (defun org-e-odt-get-paragraph-style-cookie-for-table-cell (r c
)
557 (and (not org-e-odt-table-style-spec
)
559 (org-e-odt-table-cur-rowgrp-is-hdr "OrgTableHeading")
561 ;; (org-lparse-get 'TABLE-FIRST-COLUMN-AS-LABELS)
564 (t "OrgTableContents")))
565 (and org-lparse-table-is-styled
566 (cdr (org-e-odt-get-table-cell-styles
567 r c org-e-odt-table-style-spec
)))))
569 (defun org-e-odt-get-style-name-cookie-for-table-cell (r c
)
570 (when org-lparse-table-is-styled
571 (let* ((cell-styles (org-e-odt-get-table-cell-styles
572 r c org-e-odt-table-style-spec
))
573 (table-cell-style (car cell-styles
)))
576 (defun org-e-odt-format-table-cell (data r c horiz-span
)
578 (let* ((paragraph-style-cookie
579 (org-e-odt-get-paragraph-style-cookie-for-table-cell r c
))
581 (org-e-odt-get-style-name-cookie-for-table-cell r c
))
582 (extra (and style-name-cookie
583 (format " table:style-name=\"%s\"" style-name-cookie
)))
585 (and (> horiz-span
0)
586 (format " table:number-columns-spanned=\"%d\""
588 (org-e-odt-format-tags
589 '("<table:table-cell%s>" .
"</table:table-cell>")
590 (if org-lparse-list-table-p data
591 (org-e-odt-format-stylized-paragraph paragraph-style-cookie data
)) extra
))
593 (dotimes (i horiz-span
)
594 (setq s
(concat s
"\n<table:covered-table-cell/>"))) s
)
597 (defun org-e-odt-begin-footnote-definition (n)
598 (org-lparse-begin-paragraph 'footnote
))
600 (defun org-e-odt-end-footnote-definition (n)
601 (org-lparse-end-paragraph))
603 (defun org-e-odt-begin-toc (lang-specific-heading max-level
)
606 <text:table-of-content text:style-name=\"Sect2\" text:protected=\"true\" text:name=\"Table of Contents1\">
607 <text:table-of-content-source text:outline-level=\"%d\">
608 <text:index-title-template text:style-name=\"Contents_20_Heading\">%s</text:index-title-template>
609 " max-level lang-specific-heading
)
611 (let ((entry-templates ""))
612 (loop for level from
1 upto
10
613 do
(setq entry-templates
614 (concat entry-templates
617 <text:table-of-content-entry-template text:outline-level=\"%d\" text:style-name=\"Contents_20_%d\">
618 <text:index-entry-link-start text:style-name=\"Internet_20_link\"/>
619 <text:index-entry-chapter/>
620 <text:index-entry-text/>
621 <text:index-entry-link-end/>
622 </text:table-of-content-entry-template>
627 </text:table-of-content-source>
630 <text:index-title text:style-name=\"Sect1\" text:name=\"Table of Contents1_Head\">
631 <text:p text:style-name=\"Contents_20_Heading\">%s</text:p>
633 " lang-specific-heading
)))
635 (defun org-e-odt-end-toc ()
638 </text:table-of-content>
641 (defun org-e-odt-format-toc-entry (snumber todo headline tags href
)
644 (setq headline
(concat
645 (and org-export-with-section-numbers
646 (concat snumber
". "))
650 (org-e-odt-format-spaces 3)
651 (org-e-odt-format-fontify tags
"tag")))))
653 (setq headline
(org-e-odt-format-fontify headline
"todo")))
655 (let ((org-e-odt-suppress-xref t
))
656 (org-e-odt-format-link headline
(concat "#" href
))))
658 (defun org-e-odt-format-toc-item (toc-entry level org-last-level
)
659 (let ((style (format "Contents_20_%d"
660 (+ level
(or ;; (org-lparse-get 'TOPLEVEL-HLEVEL)
663 (concat "\n" (org-e-odt-format-stylized-paragraph style toc-entry
) "\n")))
665 ;; Following variable is let bound during 'ORG-LINK callback. See
668 (defun org-e-odt-format-link (desc href
&optional attr
)
670 ((and (= (string-to-char href
) ?
#) (not org-e-odt-suppress-xref
))
671 (setq href
(concat org-export-e-odt-bookmark-prefix
(substring href
1)))
672 (let ((xref-format "text"))
674 (setq desc
(format "%d" desc
) xref-format
"number"))
675 (org-e-odt-format-tags
676 '("<text:bookmark-ref text:reference-format=\"%s\" text:ref-name=\"%s\">" .
677 "</text:bookmark-ref>")
678 desc xref-format href
)))
679 (org-lparse-link-description-is-image
680 (org-e-odt-format-tags
681 '("<draw:a xlink:type=\"simple\" xlink:href=\"%s\" %s>" .
"</draw:a>")
682 desc href
(or attr
"")))
684 (org-e-odt-format-tags
685 '("<text:a xlink:type=\"simple\" xlink:href=\"%s\" %s>" .
"</text:a>")
686 desc href
(or attr
"")))))
688 (defun org-e-odt-format-spaces (n)
692 " " (org-e-odt-format-tags "<text:s text:c=\"%d\"/>" "" (1- n
))))
695 (defun org-e-odt-format-tabs (&optional n
)
696 (let ((tab "<text:tab/>")
700 (defun org-e-odt-format-line-break ()
701 (org-e-odt-format-tags "<text:line-break/>" ""))
703 (defun org-e-odt-format-horizontal-line ()
704 (org-e-odt-format-stylized-paragraph 'horizontal-line
""))
706 (defun org-e-odt-encode-plain-text (line &optional no-whitespace-filling
)
707 (setq line
(org-e-html-encode-plain-text line
))
708 (if no-whitespace-filling line
709 (org-e-odt-fill-tabs-and-spaces line
)))
711 (defun org-e-odt-format-line (line)
712 (case org-lparse-dyn-current-environment
714 (org-e-odt-format-stylized-paragraph
715 'fixedwidth
(org-e-odt-encode-plain-text line
)) "\n"))
716 (t (concat line
"\n"))))
718 (defun org-e-odt-format-comment (fmt &rest args
)
719 (let ((comment (apply 'format fmt args
)))
720 (format "\n<!-- %s -->\n" comment
)))
722 (defun org-e-odt-format-org-entity (wd)
723 (org-entity-get-representation wd
'utf8
))
725 (defun org-e-odt-fill-tabs-and-spaces (line)
726 (replace-regexp-in-string
727 "\\([\t]\\|\\([ ]+\\)\\)" (lambda (s)
729 ((string= s
"\t") (org-e-odt-format-tabs))
730 (t (org-e-odt-format-spaces (length s
))))) line
))
733 (defun org-e-odt-format-source-line-with-line-number-and-label
734 (line rpllbl num fontifier par-style
)
736 (let ((keep-label (not (numberp rpllbl
)))
737 (ref (org-find-text-property-in-string 'org-coderef line
)))
738 (setq line
(concat line
(and keep-label ref
(format "(%s)" ref
))))
739 (setq line
(funcall fontifier line
))
741 (setq line
(org-e-odt-format-target line
(concat "coderef-" ref
))))
742 (setq line
(org-e-odt-format-stylized-paragraph par-style line
))
744 (org-e-odt-format-tags '("<text:list-item>" .
"</text:list-item>") line
))))
746 (defun org-e-odt-format-source-code-or-example-plain
747 (lines lang caption textareap cols rows num cont rpllbl fmt
)
748 "Format source or example blocks much like fixedwidth blocks.
749 Use this when `org-export-e-odt-fontify-srcblocks' option is turned
751 (let* ((lines (org-split-string lines
"[\r\n]"))
752 (line-count (length lines
))
757 (org-e-odt-format-source-line-with-line-number-and-label
758 line rpllbl num
'org-e-odt-encode-plain-text
759 (if (= i line-count
) "OrgFixedWidthBlockLastLine"
760 "OrgFixedWidthBlock")))
763 (defun org-e-odt-hfy-face-to-css (fn)
764 "Create custom style for face FN.
765 When FN is the default face, use it's foreground and background
766 properties to create \"OrgSrcBlock\" paragraph style. Otherwise
767 use it's color attribute to create a character style whose name
768 is obtained from FN. Currently all attributes of FN other than
771 The style name for a face FN is derived using the following
772 operations on the face name in that order - de-dash, CamelCase
773 and prefix with \"OrgSrc\". For example,
774 `font-lock-function-name-face' is associated with
775 \"OrgSrcFontLockFunctionNameFace\"."
776 (let* ((css-list (hfy-face-to-style fn
))
777 (style-name ((lambda (fn)
780 'capitalize
(split-string
781 (hfy-face-or-def-to-name fn
) "-")
783 (color-val (cdr (assoc "color" css-list
)))
784 (background-color-val (cdr (assoc "background" css-list
)))
785 (style (and org-export-e-odt-create-custom-styles-for-srcblocks
788 (format org-src-block-paragraph-format
789 background-color-val color-val
))
793 <style:style style:name=\"%s\" style:family=\"text\">
794 <style:text-properties fo:color=\"%s\"/>
795 </style:style>" style-name color-val
))))))
796 (cons style-name style
)))
798 (defun org-e-odt-insert-custom-styles-for-srcblocks (styles)
799 "Save STYLES used for colorizing of source blocks.
800 Update styles.xml with styles that were collected as part of
801 `org-e-odt-hfy-face-to-css' callbacks."
804 (find-file-noselect (expand-file-name "styles.xml") t
)
805 (goto-char (point-min))
806 (when (re-search-forward "</office:styles>" nil t
)
807 (goto-char (match-beginning 0))
808 (insert "\n<!-- Org Htmlfontify Styles -->\n" styles
"\n")))))
810 (defun org-e-odt-format-source-code-or-example-colored
811 (lines lang caption textareap cols rows num cont rpllbl fmt
)
812 "Format source or example blocks using `htmlfontify-string'.
813 Use this routine when `org-export-e-odt-fontify-srcblocks' option
815 (let* ((lang-m (and lang
(or (cdr (assoc lang org-src-lang-modes
)) lang
)))
816 (mode (and lang-m
(intern (concat (if (symbolp lang-m
)
819 (org-inhibit-startup t
)
820 (org-startup-folded nil
)
821 (lines (with-temp-buffer
823 (if (functionp mode
) (funcall mode
) (fundamental-mode))
824 (font-lock-fontify-buffer)
826 (hfy-html-quote-regex "\\([<\"&> ]\\)")
827 (hfy-html-quote-map '(("\"" """)
832 (" " "<text:tab/>")))
833 (hfy-face-to-css 'org-e-odt-hfy-face-to-css
)
834 (hfy-optimisations-1 (copy-seq hfy-optimisations
))
835 (hfy-optimisations (add-to-list 'hfy-optimisations-1
837 (hfy-begin-span-handler
838 (lambda (style text-block text-id text-begins-block-p
)
839 (insert (format "<text:span text:style-name=\"%s\">" style
))))
840 (hfy-end-span-handler (lambda nil
(insert "</text:span>"))))
841 (when (fboundp 'htmlfontify-string
)
842 (let* ((lines (org-split-string lines
"[\r\n]"))
843 (line-count (length lines
))
848 (org-e-odt-format-source-line-with-line-number-and-label
849 line rpllbl num
'htmlfontify-string
850 (if (= i line-count
) "OrgSrcBlockLastLine" "OrgSrcBlock")))
853 (defun org-e-odt-format-source-code-or-example (lines lang
858 "Format source or example blocks for export.
859 Use `org-e-odt-format-source-code-or-example-plain' or
860 `org-e-odt-format-source-code-or-example-colored' depending on the
861 value of `org-export-e-odt-fontify-srcblocks."
862 (setq ;; lines (org-export-number-lines
863 ;; lines 0 0 num cont rpllbl fmt 'preprocess) FIXME
865 (or (and org-export-e-odt-fontify-srcblocks
866 (or (featurep 'htmlfontify
)
867 ;; htmlfontify.el was introduced in Emacs 23.2
868 ;; So load it with some caution
869 (require 'htmlfontify nil t
))
870 (fboundp 'htmlfontify-string
)
871 'org-e-odt-format-source-code-or-example-colored
)
872 'org-e-odt-format-source-code-or-example-plain
)
873 lines lang caption textareap cols rows num cont rpllbl fmt
))
875 (let ((extra (format " text:continue-numbering=\"%s\""
876 (if cont
"true" "false"))))
877 (org-e-odt-format-tags
878 '("<text:list text:style-name=\"OrgSrcBlockNumberedLine\"%s>"
879 .
"</text:list>") lines extra
))))
881 (defun org-e-odt-remap-stylenames (style-name)
883 (cdr (assoc style-name
'(("timestamp-wrapper" .
"OrgTimestampWrapper")
884 ("timestamp" .
"OrgTimestamp")
885 ("timestamp-kwd" .
"OrgTimestampKeyword")
889 ("target" .
"OrgTarget"))))
892 (defun org-e-odt-format-fontify (text style
&optional id
)
896 (org-e-odt-remap-stylenames style
))
898 (org-e-odt-get-style-name-for-entity 'character style
))
900 (assert (< 1 (length style
)))
901 (let ((parent-style (pop style
)))
902 (mapconcat (lambda (s)
903 ;; (assert (stringp s) t)
904 (org-e-odt-remap-stylenames s
)) style
"")
905 (org-e-odt-remap-stylenames parent-style
)))
906 (t (error "Don't how to handle style %s" style
)))))
907 (org-e-odt-format-tags
908 '("<text:span text:style-name=\"%s\">" .
"</text:span>")
911 (defun org-e-odt-relocate-relative-path (path dir
)
912 (if (file-name-absolute-p path
) path
913 (file-relative-name (expand-file-name path dir
)
914 (expand-file-name "eyecandy" dir
))))
916 (defun org-e-odt-format-inline-image (thefile
917 &optional caption label attrs
; FIXME - CLA
919 (let* ((thelink (if (file-name-absolute-p thefile
) thefile
921 (org-e-odt-relocate-relative-path
922 thefile org-current-export-file
))))
924 (org-e-odt-format-tags
925 "<draw:image xlink:href=\"%s\" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\"/>" ""
926 (if org-export-e-odt-embed-images
927 (org-e-odt-copy-image-file thefile
) thelink
))))
928 (org-export-e-odt-format-image thefile href
)))
930 (defun org-export-e-odt-format-formula (src href
)
932 (let* ((caption (org-find-text-property-in-string 'org-caption src
))
933 (caption (and caption
(org-xml-format-desc caption
)))
934 (label (org-find-text-property-in-string 'org-label src
))
935 (latex-frag (org-find-text-property-in-string 'org-latex-src src
))
936 (embed-as (or (and latex-frag
937 (org-find-text-property-in-string
938 'org-latex-src-embed-type src
))
939 (if (or caption label
) 'paragraph
'character
)))
942 (setq href
(org-propertize href
:title
"LaTeX Fragment"
943 :description latex-frag
)))
945 ((eq embed-as
'character
)
946 (org-e-odt-format-entity "InlineFormula" href width height
))
948 (org-lparse-end-paragraph)
949 (org-lparse-insert-list-table
950 `((,(org-e-odt-format-entity
951 (if caption
"CaptionedDisplayFormula" "DisplayFormula")
952 href width height
:caption caption
:label nil
)
954 (org-e-odt-format-entity-caption label nil
"__MathFormula__"))))
955 nil nil nil
":style \"OrgEquation\"" nil
'((1 "c" 8) (2 "c" 1)))
956 (throw 'nextline nil
))))))
958 (defun org-e-odt-copy-formula-file (path)
959 "Returns the internal name of the file"
960 (let* ((src-file (expand-file-name
961 path
(file-name-directory org-current-export-file
)))
962 (target-dir (format "Formula-%04d/"
963 (incf org-e-odt-embedded-formulas-count
)))
964 (target-file (concat target-dir
"content.xml")))
965 (when (not org-lparse-to-buffer
)
966 (message "Embedding %s as %s ..."
967 (substring-no-properties path
) target-file
)
969 (make-directory target-dir
)
970 (org-e-odt-create-manifest-file-entry
971 "application/vnd.oasis.opendocument.formula" target-dir
"1.2")
973 (case (org-e-odt-is-formula-link-p src-file
)
975 (copy-file src-file target-file
'overwrite
))
977 (org-e-odt-zip-extract-one src-file
"content.xml" target-dir
))
979 (error "%s is not a formula file" src-file
)))
981 (org-e-odt-create-manifest-file-entry "text/xml" target-file
))
984 (defun org-e-odt-format-inline-formula (thefile)
985 (let* ((thelink (if (file-name-absolute-p thefile
) thefile
987 (org-e-odt-relocate-relative-path
988 thefile org-current-export-file
))))
990 (org-e-odt-format-tags
991 "<draw:object xlink:href=\"%s\" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\"/>" ""
992 (file-name-directory (org-e-odt-copy-formula-file thefile
)))))
993 (org-export-e-odt-format-formula thefile href
)))
995 (defun org-e-odt-is-formula-link-p (file)
996 (let ((case-fold-search nil
))
998 ((string-match "\\.\\(mathml\\|mml\\)\\'" file
)
1000 ((string-match "\\.odf\\'" file
)
1003 (defun org-e-odt-format-org-link (opt-plist type-1 path fragment desc attr
1005 "Make a OpenDocument link.
1006 OPT-PLIST is an options list.
1007 TYPE-1 is the device-type of the link (THIS://foo.html).
1008 PATH is the path of the link (http://THIS#location).
1009 FRAGMENT is the fragment part of the link, if any (foo.html#THIS).
1010 DESC is the link description, if any.
1011 ATTR is a string of other attributes of the a element."
1012 (declare (special org-lparse-par-open
))
1014 (let* ((may-inline-p
1015 (and (member type-1
'("http" "https" "file"))
1016 (org-lparse-should-inline-p path descp
)
1018 (type (if (equal type-1
"id") "file" type-1
))
1022 ;; check for inlined images
1023 ((and (member type
'("file"))
1026 filename org-export-e-odt-inline-image-extensions
)
1027 (or (eq t org-export-e-odt-inline-images
)
1028 (and org-export-e-odt-inline-images
(not descp
))))
1029 (org-e-odt-format-inline-image thefile
))
1030 ;; check for embedded formulas
1031 ((and (member type
'("file"))
1033 (org-e-odt-is-formula-link-p filename
)
1035 (org-e-odt-format-inline-formula thefile
))
1036 ((string= type
"coderef")
1037 (let* ((ref fragment
)
1038 (lineno-or-ref (cdr (assoc ref org-export-code-refs
)))
1039 (desc (and descp desc
))
1040 (org-e-odt-suppress-xref nil
)
1041 (href (org-xml-format-href (concat "#coderef-" ref
))))
1043 ((and (numberp lineno-or-ref
) (not desc
))
1044 (org-e-odt-format-link lineno-or-ref href
))
1045 ((and (numberp lineno-or-ref
) desc
1046 (string-match (regexp-quote (concat "(" ref
")")) desc
))
1047 (format (replace-match "%s" t t desc
)
1048 (org-e-odt-format-link lineno-or-ref href
)))
1051 (if (and desc
(string-match
1052 (regexp-quote (concat "(" ref
")"))
1054 (replace-match "%s" t t desc
)
1057 (org-e-odt-format-link (org-xml-format-desc desc
) href
)))))
1059 (when (string= type
"file")
1062 ((file-name-absolute-p path
)
1063 (concat "file://" (expand-file-name path
)))
1064 (t (org-e-odt-relocate-relative-path
1065 thefile org-current-export-file
)))))
1067 (when (and (member type
'("" "http" "https" "file")) fragment
)
1068 (setq thefile
(concat thefile
"#" fragment
)))
1070 (setq thefile
(org-xml-format-href thefile
))
1072 (when (not (member type
'("" "file")))
1073 (setq thefile
(concat type
":" thefile
)))
1075 (let ((org-e-odt-suppress-xref nil
))
1076 (org-e-odt-format-link
1077 (org-xml-format-desc desc
) thefile attr
)))))))
1079 (defun org-e-odt-format-heading (text level
&optional id
)
1080 (let* ((text (if id
(org-e-odt-format-target text id
) text
)))
1081 (org-e-odt-format-tags
1082 '("<text:h text:style-name=\"Heading_20_%s\" text:outline-level=\"%s\">" .
1083 "</text:h>") text level level
)))
1085 (defun org-e-odt-format-headline (title extra-targets tags
1086 &optional snumber level
)
1088 (org-e-odt-format-extra-targets extra-targets
)
1090 ;; No need to generate section numbers. They are auto-generated by
1093 ;; (concat (org-lparse-format 'SECTION-NUMBER snumber level) " ")
1095 (and tags
(concat (org-e-odt-format-spaces 3)
1096 (org-e-odt-format-org-tags tags
)))))
1098 (defun org-e-odt-format-anchor (text name
&optional class
)
1099 (org-e-odt-format-target text name
))
1101 (defun org-e-odt-format-bookmark (text id
)
1103 (org-e-odt-format-tags "<text:bookmark text:name=\"%s\"/>" text id
)
1106 (defun org-e-odt-format-target (text id
)
1107 (let ((name (concat org-export-e-odt-bookmark-prefix id
)))
1109 (and id
(org-e-odt-format-tags
1110 "<text:bookmark-start text:name=\"%s\"/>" "" name
))
1111 (org-e-odt-format-bookmark text id
)
1112 (and id
(org-e-odt-format-tags
1113 "<text:bookmark-end text:name=\"%s\"/>" "" name
)))))
1115 (defun org-e-odt-format-footnote (n def
)
1116 (setq n
(format "%d" n
))
1117 (let ((id (concat "fn" n
))
1118 (note-class "footnote")
1119 (par-style "Footnote"))
1120 (org-e-odt-format-tags
1121 '("<text:note text:id=\"%s\" text:note-class=\"%s\">" .
1124 (org-e-odt-format-tags
1125 '("<text:note-citation>" .
"</text:note-citation>")
1127 (org-e-odt-format-tags
1128 '("<text:note-body>" .
"</text:note-body>")
1132 (defun org-e-odt-format-footnote-reference (n def refcnt
)
1134 (org-e-odt-format-footnote n def
)
1135 (org-e-odt-format-footnote-ref n
)))
1137 (defun org-e-odt-format-footnote-ref (n)
1138 (setq n
(format "%d" n
))
1139 (let ((note-class "footnote")
1141 (ref-name (concat "fn" n
)))
1142 (org-e-odt-format-tags
1143 '("<text:span text:style-name=\"%s\">" .
"</text:span>")
1144 (org-e-odt-format-tags
1145 '("<text:note-ref text:note-class=\"%s\" text:reference-format=\"%s\" text:ref-name=\"%s\">" .
"</text:note-ref>")
1146 n note-class ref-format ref-name
)
1149 (defun org-e-odt-get-image-name (file-name)
1153 (concat (sha1 file-name
) "." (file-name-extension file-name
)) "Pictures")))
1155 (defun org-export-e-odt-format-image (src href
)
1156 "Create image tag with source and attributes."
1158 (let* ((caption (org-find-text-property-in-string 'org-caption src
))
1159 (caption (and caption
(org-xml-format-desc caption
)))
1160 (attr (org-find-text-property-in-string 'org-attributes src
))
1161 (label (org-find-text-property-in-string 'org-label src
))
1162 (latex-frag (org-find-text-property-in-string
1163 'org-latex-src src
))
1164 (category (and latex-frag
"__DvipngImage__"))
1165 (attr-plist (org-lparse-get-block-params attr
))
1167 (car (assoc-string (plist-get attr-plist
:anchor
)
1168 '(("as-char") ("paragraph") ("page")) t
)))
1170 (and user-frame-anchor
(plist-get attr-plist
:style
)))
1172 (and user-frame-anchor
(plist-get attr-plist
:attributes
)))
1174 (list user-frame-style user-frame-attrs user-frame-anchor
))
1178 (case (org-find-text-property-in-string
1179 'org-latex-src-embed-type src
)
1180 (paragraph 'paragraph
)
1184 (size (org-e-odt-image-size-from-file
1185 src
(plist-get attr-plist
:width
)
1186 (plist-get attr-plist
:height
)
1187 (plist-get attr-plist
:scale
) nil embed-as
))
1188 (width (car size
)) (height (cdr size
)))
1190 (setq href
(org-propertize href
:title
"LaTeX Fragment"
1191 :description latex-frag
)))
1192 (let ((frame-style-handle (concat (and (or caption label
) "Captioned")
1194 (org-e-odt-format-entity
1195 frame-style-handle href width height
1196 :caption caption
:label label
:category category
1197 :user-frame-params user-frame-params
)))))
1199 (defun org-e-odt-format-object-description (title description
)
1200 (concat (and title
(org-e-odt-format-tags
1201 '("<svg:title>" .
"</svg:title>")
1202 (org-e-odt-encode-plain-text title t
)))
1203 (and description
(org-e-odt-format-tags
1204 '("<svg:desc>" .
"</svg:desc>")
1205 (org-e-odt-encode-plain-text description t
)))))
1207 (defun org-e-odt-format-frame (text width height style
&optional
1211 (if width
(format " svg:width=\"%0.2fcm\"" width
) "")
1212 (if height
(format " svg:height=\"%0.2fcm\"" height
) "")
1214 (format " text:anchor-type=\"%s\"" (or anchor-type
"paragraph")))))
1215 (org-e-odt-format-tags
1216 '("<draw:frame draw:style-name=\"%s\"%s>" .
"</draw:frame>")
1217 (concat text
(org-e-odt-format-object-description
1218 (get-text-property 0 :title text
)
1219 (get-text-property 0 :description text
)))
1220 style frame-attrs
)))
1222 (defun org-e-odt-format-textbox (text width height style
&optional
1224 (org-e-odt-format-frame
1225 (org-e-odt-format-tags
1226 '("<draw:text-box %s>" .
"</draw:text-box>")
1227 text
(concat (format " fo:min-height=\"%0.2fcm\"" (or height
.2))
1229 (format " fo:min-width=\"%0.2fcm\"" (or width
.2)))))
1230 width nil style extra anchor-type
))
1232 (defun org-e-odt-format-inlinetask (heading content
1233 &optional todo priority tags
)
1234 (org-e-odt-format-stylized-paragraph
1235 nil
(org-e-odt-format-textbox
1236 (concat (org-e-odt-format-stylized-paragraph
1237 "OrgInlineTaskHeading"
1239 'HEADLINE
(concat (org-lparse-format-todo todo
) " " heading
)
1241 content
) nil nil
"OrgInlineTaskFrame" " style:rel-width=\"100%\"")))
1244 (defun org-e-odt-merge-frame-params(default-frame-params user-frame-params
)
1245 (if (not user-frame-params
) default-frame-params
1246 (assert (= (length default-frame-params
) 3))
1247 (assert (= (length user-frame-params
) 3))
1248 (loop for user-frame-param in user-frame-params
1249 for default-frame-param in default-frame-params
1250 collect
(or user-frame-param default-frame-param
))))
1252 (defun* org-e-odt-format-entity
(entity href width height
1253 &key caption label category
1255 (let* ((entity-style (assoc-string entity org-e-odt-entity-frame-styles t
))
1256 default-frame-params frame-params
)
1258 ((not (or caption label
))
1259 (setq default-frame-params
(nth 2 entity-style
))
1260 (setq frame-params
(org-e-odt-merge-frame-params
1261 default-frame-params user-frame-params
))
1262 (apply 'org-e-odt-format-frame href width height frame-params
))
1264 (setq default-frame-params
(nth 3 entity-style
))
1265 (setq frame-params
(org-e-odt-merge-frame-params
1266 default-frame-params user-frame-params
))
1267 (apply 'org-e-odt-format-textbox
1268 (org-e-odt-format-stylized-paragraph
1271 (apply 'org-e-odt-format-frame href width height
1272 (nth 2 entity-style
))
1273 (org-e-odt-format-entity-caption
1274 label caption
(or category
(nth 1 entity-style
)))))
1275 width height frame-params
)))))
1278 (defun org-e-odt-copy-image-file (path)
1279 "Returns the internal name of the file"
1280 (let* ((image-type (file-name-extension path
))
1281 (media-type (format "image/%s" image-type
))
1282 (src-file (expand-file-name
1283 path
(file-name-directory org-current-export-file
)))
1284 (target-dir "Images/")
1286 (format "%s%04d.%s" target-dir
1287 (incf org-e-odt-embedded-images-count
) image-type
)))
1288 (when (not org-lparse-to-buffer
)
1289 (message "Embedding %s as %s ..."
1290 (substring-no-properties path
) target-file
)
1292 (when (= 1 org-e-odt-embedded-images-count
)
1293 (make-directory target-dir
)
1294 (org-e-odt-create-manifest-file-entry "" target-dir
))
1296 (copy-file src-file target-file
'overwrite
)
1297 (org-e-odt-create-manifest-file-entry media-type target-file
))
1300 (defun org-e-odt-do-image-size (probe-method file
&optional dpi anchor-type
)
1301 (setq dpi
(or dpi org-export-e-odt-pixels-per-inch
))
1302 (setq anchor-type
(or anchor-type
"paragraph"))
1303 (flet ((size-in-cms (size-in-pixels)
1304 (flet ((pixels-to-cms (pixels)
1305 (let* ((cms-per-inch 2.54)
1306 (inches (/ pixels dpi
)))
1307 (* cms-per-inch inches
))))
1309 (cons (pixels-to-cms (car size-in-pixels
))
1310 (pixels-to-cms (cdr size-in-pixels
)))))))
1313 (size-in-cms (ignore-errors ; Emacs could be in batch mode
1315 (image-size (create-image file
) 'pixels
))))
1318 (let ((dim (shell-command-to-string
1319 (format "identify -format \"%%w:%%h\" \"%s\"" file
))))
1320 (when (string-match "\\([0-9]+\\):\\([0-9]+\\)" dim
)
1321 (cons (string-to-number (match-string 1 dim
))
1322 (string-to-number (match-string 2 dim
)))))))
1324 (cdr (assoc-string anchor-type
1325 org-export-e-odt-default-image-sizes-alist
))))))
1327 (defun org-e-odt-image-size-from-file (file &optional user-width
1328 user-height scale dpi embed-as
)
1329 (unless (file-name-absolute-p file
)
1330 (setq file
(expand-file-name
1331 file
(file-name-directory org-current-export-file
))))
1332 (let* (size width height
)
1333 (unless (and user-height user-width
)
1334 (loop for probe-method in org-export-e-odt-image-size-probe-method
1336 do
(setq size
(org-e-odt-do-image-size
1337 probe-method file dpi embed-as
)))
1338 (or size
(error "Cannot determine Image size. Aborting ..."))
1339 (setq width
(car size
) height
(cdr size
)))
1342 (setq width
(* width scale
) height
(* height scale
)))
1343 ((and user-height user-width
)
1344 (setq width user-width height user-height
))
1346 (setq width
(* user-height
(/ width height
)) height user-height
))
1348 (setq height
(* user-width
(/ height width
)) width user-width
))
1350 ;; ensure that an embedded image fits comfortably within a page
1351 (let ((max-width (car org-export-e-odt-max-image-size
))
1352 (max-height (cdr org-export-e-odt-max-image-size
)))
1353 (when (or (> width max-width
) (> height max-height
))
1354 (let* ((scale1 (/ max-width width
))
1355 (scale2 (/ max-height height
))
1356 (scale (min scale1 scale2
)))
1357 (setq width
(* scale width
) height
(* scale height
)))))
1358 (cons width height
)))
1360 (defun org-e-odt-get-label-category-and-style (label default-category
)
1361 "See `org-export-e-odt-get-category-from-label'."
1362 (let ((default-category-map
1363 (assoc default-category org-e-odt-category-map-alist
))
1364 user-category user-category-map category
)
1366 ((not org-export-e-odt-get-category-from-label
)
1367 default-category-map
)
1368 ((not (setq user-category
1370 (and (string-match "\\`\\(.*\\):.+" label
)
1371 (match-string 1 label
)))))
1372 default-category-map
)
1374 (setq user-category-map
1375 (or (assoc user-category org-e-odt-category-map-alist
)
1376 (list nil user-category
"category-and-value"))
1377 category
(nth 1 user-category-map
))
1378 (if (member category org-export-e-odt-user-categories
)
1380 default-category-map
)))))
1382 (defun org-e-odt-add-label-definition (label default-category
)
1383 "Create an entry in `org-e-odt-entity-labels-alist' and return it."
1384 (setq label
(substring-no-properties label
))
1385 (let* ((label-props (org-e-odt-get-label-category-and-style
1386 label default-category
))
1387 (category (nth 1 label-props
))
1389 (label-style (nth 2 label-props
))
1390 (sequence-var (intern (mapconcat
1392 (org-split-string counter
) "-")))
1393 (seqno (1+ (or (plist-get org-e-odt-entity-counts-plist sequence-var
)
1395 (label-props (list label category seqno label-style
)))
1396 (setq org-e-odt-entity-counts-plist
1397 (plist-put org-e-odt-entity-counts-plist sequence-var seqno
))
1398 (push label-props org-e-odt-entity-labels-alist
)
1401 (defun org-e-odt-format-label-definition (caption label category seqno label-style
)
1404 (cadr (assoc-string label-style org-e-odt-label-styles t
))
1406 (?n .
,(org-e-odt-format-tags
1407 '("<text:sequence text:ref-name=\"%s\" text:name=\"%s\" text:formula=\"ooow:%s+1\" style:num-format=\"1\">" .
"</text:sequence>")
1408 (format "%d" seqno
) label category category
))
1409 (?c .
,(or (and caption
(concat ": " caption
)) "")))))
1411 (defun org-e-odt-format-label-reference (label category seqno label-style
)
1414 (let* ((fmt (cddr (assoc-string label-style org-e-odt-label-styles t
)))
1417 (org-e-odt-format-tags
1418 '("<text:sequence-ref text:reference-format=\"%s\" text:ref-name=\"%s\">"
1419 .
"</text:sequence-ref>")
1420 (format-spec fmt2
`((?e .
,category
)
1421 (?n .
,(format "%d" seqno
)))) fmt1 label
))))
1423 (defun org-e-odt-fixup-label-references ()
1424 (goto-char (point-min))
1425 (while (re-search-forward
1426 "<text:sequence-ref text:ref-name=\"\\([^\"]+\\)\">[ \t\n]*</text:sequence-ref>"
1428 (let* ((label (match-string 1))
1429 (label-def (assoc label org-e-odt-entity-labels-alist
))
1431 (apply 'org-e-odt-format-label-reference label-def
))))
1432 (if rpl
(replace-match rpl t t
)
1434 (format "Unable to resolve reference to label \"%s\"" label
))))))
1436 (defun org-e-odt-format-entity-caption (label caption category
)
1438 (apply 'org-e-odt-format-label-definition
1439 caption
(org-e-odt-add-label-definition label category
)))
1442 (defun org-e-odt-format-tags-1 (tag text prefix suffix
&rest args
)
1445 (concat prefix
(apply 'format
(car tag
) args
) text suffix
1446 (format (cdr tag
))))
1447 ((stringp tag
) ; singleton tag
1448 (concat prefix
(apply 'format tag args
) text
))))
1450 (defun org-e-odt-format-tags (tag text
&rest args
)
1451 (apply 'org-e-odt-format-tags-1 tag text
"\n" "\n" args
))
1453 (defun org-e-odt-init-outfile ()
1454 (unless (executable-find "zip")
1455 ;; Not at all OSes ship with zip by default
1456 (error "Executable \"zip\" needed for creating OpenDocument files"))
1458 (let* ((outdir (make-temp-file
1459 (format org-export-e-odt-tmpdir-prefix org-lparse-backend
) t
))
1460 (content-file (expand-file-name "content.xml" outdir
)))
1463 (setq org-e-odt-manifest-file-entries nil
1464 org-e-odt-embedded-images-count
0
1465 org-e-odt-embedded-formulas-count
0
1466 org-e-odt-section-count
0
1467 org-e-odt-entity-labels-alist nil
1468 org-e-odt-list-stack-stashed nil
1469 org-e-odt-automatic-styles nil
1470 org-e-odt-object-counters nil
1471 org-e-odt-entity-counts-plist nil
)
1474 (with-current-buffer
1475 (find-file-noselect content-file t
)
1480 (defun org-e-odt-save-as-outfile (target opt-plist
)
1481 ;; write automatic styles
1482 (org-e-odt-write-automatic-styles)
1484 ;; write styles file
1485 ;; (when (equal org-lparse-backend 'odt) FIXME
1488 (org-e-odt-update-styles-file opt-plist
)
1490 ;; create mimetype file
1491 (let ((mimetype (org-e-odt-write-mimetype-file ;; org-lparse-backend FIXME
1493 (org-e-odt-create-manifest-file-entry mimetype
"/" "1.2"))
1495 ;; create a manifest entry for content.xml
1496 (org-e-odt-create-manifest-file-entry "text/xml" "content.xml")
1498 ;; write out the manifest entries before zipping
1499 (org-e-odt-write-manifest-file)
1501 (let ((xml-files '("mimetype" "META-INF/manifest.xml" "content.xml"
1503 (zipdir default-directory
))
1504 (when (equal org-lparse-backend
'odt
)
1505 (push "styles.xml" xml-files
))
1506 (message "Switching to directory %s" (expand-file-name zipdir
))
1508 ;; save all xml files
1509 (mapc (lambda (file)
1510 (with-current-buffer
1511 (find-file-noselect (expand-file-name file
) t
)
1512 ;; prettify output if needed
1513 (when org-export-e-odt-prettify-xml
1514 (indent-region (point-min) (point-max)))
1518 (let* ((target-name (file-name-nondirectory target
))
1519 (target-dir (file-name-directory target
))
1520 (cmds `(("zip" "-mX0" ,target-name
"mimetype")
1521 ("zip" "-rmTq" ,target-name
"."))))
1522 (when (file-exists-p target
)
1523 ;; FIXME: If the file is locked this throws a cryptic error
1524 (delete-file target
))
1526 (let ((coding-system-for-write 'no-conversion
) exitcode err-string
)
1527 (message "Creating odt file...")
1530 (message "Running %s" (mapconcat 'identity cmd
" "))
1532 (with-output-to-string
1534 (apply 'call-process
(car cmd
)
1535 nil standard-output nil
(cdr cmd
)))))
1536 (or (zerop exitcode
)
1537 (ignore (message "%s" err-string
))
1538 (error "Unable to create odt file (%S)" exitcode
)))
1541 ;; move the file from outdir to target-dir
1542 (rename-file target-name target-dir
)
1544 ;; kill all xml buffers
1545 (mapc (lambda (file)
1547 (find-file-noselect (expand-file-name file zipdir
) t
)))
1550 (delete-directory zipdir
)))
1551 (message "Created %s" target
)
1552 (set-buffer (find-file-noselect target t
)))
1555 (defun org-e-odt-create-manifest-file-entry (&rest args
)
1556 (push args org-e-odt-manifest-file-entries
))
1558 (defun org-e-odt-write-manifest-file ()
1559 (make-directory "META-INF")
1560 (let ((manifest-file (expand-file-name "META-INF/manifest.xml")))
1561 (with-current-buffer
1562 (find-file-noselect manifest-file t
)
1564 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
1565 <manifest:manifest xmlns:manifest=\"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0\" manifest:version=\"1.2\">\n")
1567 (lambda (file-entry)
1568 (let* ((version (nth 2 file-entry
))
1570 (format " manifest:version=\"%s\"" version
)
1573 (format org-e-odt-manifest-file-entry-tag
1574 (nth 0 file-entry
) (nth 1 file-entry
) extra
))))
1575 org-e-odt-manifest-file-entries
)
1576 (insert "\n</manifest:manifest>"))))
1578 (defun org-e-odt-update-meta-file (info) ; FIXME opt-plist
1579 (let ((date (org-e-odt-format-date (plist-get info
:date
)))
1580 (author (or (plist-get info
:author
) ""))
1581 (email (plist-get info
:email
))
1582 (keywords (plist-get info
:keywords
))
1583 (description (plist-get info
:description
))
1584 (title (plist-get info
:title
)))
1587 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
1588 <office:document-meta
1589 xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"
1590 xmlns:xlink=\"http://www.w3.org/1999/xlink\"
1591 xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
1592 xmlns:meta=\"urn:oasis:names:tc:opendocument:xmlns:meta:1.0\"
1593 xmlns:ooo=\"http://openoffice.org/2004/office\"
1594 office:version=\"1.2\">
1596 (org-e-odt-format-author author
) "\n"
1597 (format "<meta:initial-creator>%s</meta:initial-creator>\n" author
)
1598 (format "<dc:date>%s</dc:date>\n" date
)
1599 (format "<meta:creation-date>%s</meta:creation-date>\n" date
)
1600 (format "<meta:generator>%s</meta:generator>\n"
1601 (when org-export-creator-info
1602 (format "Org-%s/Emacs-%s"
1603 org-version emacs-version
)))
1604 (format "<meta:keyword>%s</meta:keyword>\n" keywords
)
1605 (format "<dc:subject>%s</dc:subject>\n" description
)
1606 (format "<dc:title>%s</dc:title>\n" title
)
1608 " </office:meta>\n" "</office:document-meta>")
1609 nil
(expand-file-name "meta.xml")))
1611 ;; create a manifest entry for meta.xml
1612 (org-e-odt-create-manifest-file-entry "text/xml" "meta.xml"))
1614 (defun org-e-odt-update-styles-file (opt-plist)
1615 ;; write styles file
1616 (let ((styles-file (plist-get opt-plist
:odt-styles-file
)))
1617 (org-e-odt-copy-styles-file (and styles-file
1618 (read (org-trim styles-file
)))))
1620 ;; Update styles.xml - take care of outline numbering
1621 (with-current-buffer
1622 (find-file-noselect (expand-file-name "styles.xml") t
)
1623 ;; Don't make automatic backup of styles.xml file. This setting
1624 ;; prevents the backed-up styles.xml file from being zipped in to
1625 ;; odt file. This is more of a hackish fix. Better alternative
1626 ;; would be to fix the zip command so that the output odt file
1627 ;; includes only the needed files and excludes any auto-generated
1628 ;; extra files like backups and auto-saves etc etc. Note that
1629 ;; currently the zip command zips up the entire temp directory so
1630 ;; that any auto-generated files created under the hood ends up in
1631 ;; the resulting odt file.
1632 (set (make-local-variable 'backup-inhibited
) t
)
1634 ;; Import local setting of `org-export-with-section-numbers'
1635 (org-lparse-bind-local-variables opt-plist
)
1636 (org-e-odt-configure-outline-numbering
1637 (if org-export-with-section-numbers org-export-headline-levels
0)))
1639 ;; Write custom styles for source blocks
1640 ;; (org-e-odt-insert-custom-styles-for-srcblocks FIXME
1643 ;; (format " %s\n" (cddr style)))
1644 ;; hfy-user-sheet-assoc ""))
1647 (defun org-e-odt-write-mimetype-file (format)
1648 ;; create mimetype file
1651 (odt "application/vnd.oasis.opendocument.text")
1652 (odf "application/vnd.oasis.opendocument.formula")
1653 (t (error "Unknown OpenDocument backend %S" org-lparse-backend
)))))
1654 (write-region mimetype nil
(expand-file-name "mimetype"))
1657 (defun org-e-odt-finalize-outfile ()
1658 (org-e-odt-delete-empty-paragraphs))
1660 (defun org-e-odt-delete-empty-paragraphs ()
1661 (goto-char (point-min))
1662 (let ((open "<text:p[^>]*>")
1663 (close "</text:p>"))
1664 (while (re-search-forward (format "%s[ \r\n\t]*%s" open close
) nil t
)
1665 (replace-match ""))))
1667 (declare-function org-create-math-formula
"org"
1668 (latex-frag &optional mathml-file
))
1671 (defun org-export-e-odt-convert (&optional in-file out-fmt prefix-arg
)
1672 "Convert IN-FILE to format OUT-FMT using a command line converter.
1673 IN-FILE is the file to be converted. If unspecified, it defaults
1674 to variable `buffer-file-name'. OUT-FMT is the desired output
1675 format. Use `org-export-e-odt-convert-process' as the converter.
1676 If PREFIX-ARG is non-nil then the newly converted file is opened
1677 using `org-open-file'."
1679 (append (org-lparse-convert-read-params) current-prefix-arg
))
1680 (org-lparse-do-convert in-file out-fmt prefix-arg
))
1682 (defun org-e-odt-get (what &optional opt-plist
)
1685 (EXPORT-DIR (org-export-directory :html opt-plist
))
1686 (FILE-NAME-EXTENSION "odt")
1687 (EXPORT-BUFFER-NAME "*Org ODT Export*")
1688 (ENTITY-CONTROL org-e-odt-entity-control-callbacks-alist
)
1689 (ENTITY-FORMAT org-e-odt-entity-format-callbacks-alist
)
1690 (INIT-METHOD 'org-e-odt-init-outfile
)
1691 (FINAL-METHOD 'org-e-odt-finalize-outfile
)
1692 (SAVE-METHOD 'org-e-odt-save-as-outfile
)
1694 (and org-export-e-odt-convert-process
1695 (cadr (assoc-string org-export-e-odt-convert-process
1696 org-export-e-odt-convert-processes t
))))
1697 (CONVERT-CAPABILITIES
1698 (and org-export-e-odt-convert-process
1699 (cadr (assoc-string org-export-e-odt-convert-process
1700 org-export-e-odt-convert-processes t
))
1701 org-export-e-odt-convert-capabilities
))
1703 (SPECIAL-STRING-REGEXPS org-export-e-odt-special-string-regexps
)
1704 (INLINE-IMAGES 'maybe
)
1705 (INLINE-IMAGE-EXTENSIONS '("png" "jpeg" "jpg" "gif" "svg"))
1706 (PLAIN-TEXT-MAP '(("&" .
"&") ("<" .
"<") (">" .
">")))
1707 (TABLE-FIRST-COLUMN-AS-LABELS nil
)
1708 (FOOTNOTE-SEPARATOR )
1709 (CODING-SYSTEM-FOR-WRITE 'utf-8
)
1710 (CODING-SYSTEM-FOR-SAVE 'utf-8
)
1711 (t (error "Unknown property: %s" what
))))
1713 (defun org-export-e-odt-do-preprocess-latex-fragments ()
1714 "Convert LaTeX fragments to images."
1715 (let* ((latex-frag-opt (plist-get org-lparse-opt-plist
:LaTeX-fragments
))
1716 (latex-frag-opt ; massage the options
1717 (or (and (member latex-frag-opt
'(mathjax t
))
1718 (not (and (fboundp 'org-format-latex-mathml-available-p
)
1719 (org-format-latex-mathml-available-p)))
1720 (prog1 org-lparse-latex-fragment-fallback
1723 "LaTeX to MathML converter not available. "
1724 (format "Using %S instead."
1725 org-lparse-latex-fragment-fallback
)))))
1727 cache-dir display-msg
)
1729 ((eq latex-frag-opt
'dvipng
)
1730 (setq cache-dir
"ltxpng/")
1731 (setq display-msg
"Creating LaTeX image %s"))
1732 ((member latex-frag-opt
'(mathjax t
))
1733 (setq latex-frag-opt
'mathml
)
1734 (setq cache-dir
"ltxmathml/")
1735 (setq display-msg
"Creating MathML formula %s")))
1736 (when (and org-current-export-file
)
1738 (concat cache-dir
(file-name-sans-extension
1739 (file-name-nondirectory org-current-export-file
)))
1740 org-current-export-dir nil display-msg
1741 nil nil latex-frag-opt
))))
1743 (defadvice org-format-latex-as-mathml
1744 (after org-e-odt-protect-latex-fragment activate
)
1745 "Encode LaTeX fragment as XML.
1746 Do this when translation to MathML fails."
1747 (when (or (not (> (length ad-return-value
) 0))
1748 (get-text-property 0 'org-protected ad-return-value
))
1749 (setq ad-return-value
1750 (org-propertize (org-e-odt-encode-plain-text (ad-get-arg 0))
1751 'org-protected t
))))
1753 (defun org-export-e-odt-preprocess-latex-fragments ()
1754 (when (equal org-export-current-backend
'odt
)
1755 (org-export-e-odt-do-preprocess-latex-fragments)))
1757 (defun org-export-e-odt-preprocess-label-references ()
1758 (goto-char (point-min))
1759 (let (label label-components category value pretty-label
)
1760 (while (re-search-forward "\\\\ref{\\([^{}\n]+\\)}" nil t
)
1761 (org-if-unprotected-at (match-beginning 1)
1763 (let ((org-lparse-encode-pending t
)
1764 (label (match-string 1)))
1765 ;; markup generated below is mostly an eye-candy. At
1766 ;; pre-processing stage, there is no information on which
1767 ;; entity a label reference points to. The actual markup
1768 ;; is generated as part of `org-e-odt-fixup-label-references'
1769 ;; which gets called at the fag end of export. By this
1770 ;; time we would have seen and collected all the label
1771 ;; definitions in `org-e-odt-entity-labels-alist'.
1772 (org-e-odt-format-tags
1773 '("<text:sequence-ref text:ref-name=\"%s\">" .
1774 "</text:sequence-ref>")
1775 "" (org-add-props label
'(org-protected t
)))) t t
)))))
1777 ;; process latex fragments as part of
1778 ;; `org-export-preprocess-after-blockquote-hook'. Note that this hook
1779 ;; is the one that is closest and well before the call to
1780 ;; `org-export-attach-captions-and-attributes' in
1781 ;; `org-export-preprocess-string'. The above arrangement permits
1782 ;; captions, labels and attributes to be attached to png images
1783 ;; generated out of latex equations.
1784 (add-hook 'org-export-preprocess-after-blockquote-hook
1785 'org-export-e-odt-preprocess-latex-fragments
)
1787 (defun org-export-e-odt-preprocess (parameters)
1788 (org-export-e-odt-preprocess-label-references))
1791 (defun org-e-odt-zip-extract-one (archive member
&optional target
)
1793 (let* ((target (or target default-directory
))
1794 (archive (expand-file-name archive
))
1795 (archive-zip-extract
1796 (list "unzip" "-qq" "-o" "-d" target
))
1797 exit-code command-output
)
1798 (setq command-output
1800 (setq exit-code
(archive-zip-extract archive member
))
1802 (unless (zerop exit-code
)
1803 (message command-output
)
1804 (error "Extraction failed"))))
1806 (defun org-e-odt-zip-extract (archive members
&optional target
)
1807 (when (atom members
) (setq members
(list members
)))
1808 (mapc (lambda (member)
1809 (org-e-odt-zip-extract-one archive member target
))
1812 (defun org-e-odt-copy-styles-file (&optional styles-file
)
1813 ;; Non-availability of styles.xml is not a critical error. For now
1814 ;; throw an error purely for aesthetic reasons.
1815 (setq styles-file
(or styles-file
1816 org-export-e-odt-styles-file
1817 (expand-file-name "OrgOdtStyles.xml"
1818 org-e-odt-styles-dir
)
1819 (error "org-e-odt: Missing styles file?")))
1821 ((listp styles-file
)
1822 (let ((archive (nth 0 styles-file
))
1823 (members (nth 1 styles-file
)))
1824 (org-e-odt-zip-extract archive members
)
1827 (when (org-file-image-p member
)
1828 (let* ((image-type (file-name-extension member
))
1829 (media-type (format "image/%s" image-type
)))
1830 (org-e-odt-create-manifest-file-entry media-type member
))))
1832 ((and (stringp styles-file
) (file-exists-p styles-file
))
1833 (let ((styles-file-type (file-name-extension styles-file
)))
1835 ((string= styles-file-type
"xml")
1836 (copy-file styles-file
"styles.xml" t
))
1837 ((member styles-file-type
'("odt" "ott"))
1838 (org-e-odt-zip-extract styles-file
"styles.xml")))))
1840 (error (format "Invalid specification of styles.xml file: %S"
1841 org-export-e-odt-styles-file
))))
1843 ;; create a manifest entry for styles.xml
1844 (org-e-odt-create-manifest-file-entry "text/xml" "styles.xml"))
1846 (defun org-e-odt-configure-outline-numbering (level)
1847 "Outline numbering is retained only upto LEVEL.
1848 To disable outline numbering pass a LEVEL of 0."
1849 (goto-char (point-min))
1851 "<text:outline-level-style\\([^>]*\\)text:level=\"\\([^\"]*\\)\"\\([^>]*\\)>")
1853 "<text:outline-level-style\\1text:level=\"\\2\" style:num-format=\"\">"))
1854 (while (re-search-forward regex nil t
)
1855 (when (> (string-to-number (match-string 2)) level
)
1856 (replace-match replacement t nil
))))
1860 (defun org-export-as-odf (latex-frag &optional odf-file
)
1861 "Export LATEX-FRAG as OpenDocument formula file ODF-FILE.
1862 Use `org-create-math-formula' to convert LATEX-FRAG first to
1863 MathML. When invoked as an interactive command, use
1864 `org-latex-regexps' to infer LATEX-FRAG from currently active
1865 region. If no LaTeX fragments are found, prompt for it. Push
1866 MathML source to kill ring, if `org-export-copy-to-kill-ring' is
1870 (setq frag
(and (setq frag
(and (region-active-p)
1871 (buffer-substring (region-beginning)
1873 (loop for e in org-latex-regexps
1874 thereis
(when (string-match (nth 1 e
) frag
)
1875 (match-string (nth 2 e
) frag
)))))
1876 (read-string "LaTeX Fragment: " frag nil frag
))
1877 ,(let ((odf-filename (expand-file-name
1879 (file-name-sans-extension
1880 (or (file-name-nondirectory buffer-file-name
)))
1882 (file-name-directory buffer-file-name
))))
1883 (read-file-name "ODF filename: " nil odf-filename nil
1884 (file-name-nondirectory odf-filename
)))))
1885 (let* ((org-lparse-backend 'odf
)
1886 org-lparse-opt-plist
1887 (filename (or odf-file
1890 (file-name-sans-extension
1891 (or (file-name-nondirectory buffer-file-name
)))
1893 (file-name-directory buffer-file-name
))))
1894 (buffer (find-file-noselect (org-e-odt-init-outfile filename
)))
1895 (coding-system-for-write 'utf-8
)
1896 (save-buffer-coding-system 'utf-8
))
1898 (set-buffer-file-coding-system coding-system-for-write
)
1899 (let ((mathml (org-create-math-formula latex-frag
)))
1900 (unless mathml
(error "No Math formula created"))
1902 (or (org-export-push-to-kill-ring
1903 (upcase (symbol-name org-lparse-backend
)))
1904 (message "Exporting... done")))
1905 (org-e-odt-save-as-outfile filename nil
; FIXME
1909 (defun org-export-as-odf-and-open ()
1910 "Export LaTeX fragment as OpenDocument formula and immediately open it.
1911 Use `org-export-as-odf' to read LaTeX fragment and OpenDocument
1914 (org-lparse-and-open
1915 nil nil nil
(call-interactively 'org-export-as-odf
)))
1920 ;;; Driver Starts here
1923 (require 'format-spec
)
1924 (eval-when-compile (require 'cl
) (require 'table
))
1930 (defvar org-e-odt-after-blockquotes-hook nil
1931 "Hook run during HTML export, after blockquote, verse, center are done.")
1933 (defvar org-e-odt-final-hook nil
1934 "Hook run at the end of HTML export, in the new buffer.")
1936 ;; FIXME: it already exists in org-e-odt.el
1937 ;;; Function Declarations
1939 (declare-function org-element-property
"org-element" (property element
))
1940 (declare-function org-element-normalize-string
"org-element" (s))
1941 (declare-function org-element-parse-secondary-string
1942 "org-element" (string restriction
&optional buffer
))
1943 (defvar org-element-string-restrictions
)
1945 (declare-function org-export-clean-table
"org-export" (table specialp
))
1946 (declare-function org-export-data
"org-export" (data backend info
))
1947 (declare-function org-export-directory
"org-export" (type plist
))
1948 (declare-function org-export-expand-macro
"org-export" (macro info
))
1949 (declare-function org-export-first-sibling-p
"org-export" (headline info
))
1950 (declare-function org-export-footnote-first-reference-p
"org-export"
1951 (footnote-reference info
))
1952 (declare-function org-export-get-coderef-format
"org-export" (path desc
))
1953 (declare-function org-export-get-footnote-definition
"org-export"
1954 (footnote-reference info
))
1955 (declare-function org-export-get-footnote-number
"org-export" (footnote info
))
1956 (declare-function org-export-get-previous-element
"org-export" (blob info
))
1957 (declare-function org-export-get-relative-level
"org-export" (headline info
))
1958 (declare-function org-export-handle-code
1959 "org-export" (element info
&optional num-fmt ref-fmt delayed
))
1960 (declare-function org-export-included-file
"org-export" (keyword backend info
))
1961 (declare-function org-export-inline-image-p
"org-export"
1962 (link &optional extensions
))
1963 (declare-function org-export-last-sibling-p
"org-export" (headline info
))
1964 (declare-function org-export-low-level-p
"org-export" (headline info
))
1965 (declare-function org-export-output-file-name
1966 "org-export" (extension &optional subtreep pub-dir
))
1967 (declare-function org-export-resolve-coderef
"org-export" (ref info
))
1968 (declare-function org-export-resolve-fuzzy-link
"org-export" (link info
))
1969 (declare-function org-export-secondary-string
"org-export"
1970 (secondary backend info
))
1971 (declare-function org-export-solidify-link-text
"org-export" (s))
1972 (declare-function org-export-table-format-info
"org-export" (table))
1974 org-export-to-buffer
"org-export"
1975 (backend buffer
&optional subtreep visible-only body-only ext-plist
))
1977 org-export-to-file
"org-export"
1978 (backend file
&optional subtreep visible-only body-only ext-plist
))
1980 (declare-function org-id-find-id-file
"org-id" (id))
1981 (declare-function htmlize-region
"ext:htmlize" (beg end
))
1982 (declare-function org-pop-to-buffer-same-window
1983 "org-compat" (&optional buffer-or-name norecord label
))
1989 (declare-function hfy-face-to-style
"htmlfontify" (fn))
1990 (declare-function hfy-face-or-def-to-name
"htmlfontify" (fn))
1991 (declare-function archive-zip-extract
"arc-mode.el" (archive name
))
1993 ;;; Internal Variables
1995 ;;;; ODT Internal Variables
1997 (defconst org-e-odt-lib-dir
1998 (file-name-directory load-file-name
)
1999 "Location of ODT exporter.
2000 Use this to infer values of `org-e-odt-styles-dir' and
2001 `org-export-e-odt-schema-dir'.")
2003 (defvar org-e-odt-data-dir
2004 (expand-file-name "../etc/" org-e-odt-lib-dir
)
2005 "Data directory for ODT exporter.
2006 Use this to infer values of `org-e-odt-styles-dir' and
2007 `org-export-e-odt-schema-dir'.")
2012 (defconst org-export-e-odt-special-string-regexps
2013 '(("\\\\-" .
"­\\1") ; shy
2014 ("---\\([^-]\\)" .
"—\\1") ; mdash
2015 ("--\\([^-]\\)" .
"–\\1") ; ndash
2016 ("\\.\\.\\." .
"…")) ; hellip
2017 "Regular expressions for special string conversion.")
2019 (defconst org-e-odt-schema-dir-list
2021 (and org-e-odt-data-dir
2022 (expand-file-name "./schema/" org-e-odt-data-dir
)) ; bail out
2024 (and (boundp 'org-e-odt-data-dir
) org-e-odt-data-dir
; see make install
2025 (expand-file-name "./schema/" org-e-odt-data-dir
)))
2026 (expand-file-name "../contrib/odt/etc/schema/" org-e-odt-lib-dir
) ; git
2028 "List of directories to search for OpenDocument schema files.
2029 Use this list to set the default value of
2030 `org-export-e-odt-schema-dir'. The entries in this list are
2031 populated heuristically based on the values of `org-e-odt-lib-dir'
2032 and `org-e-odt-data-dir'.")
2035 (defconst org-e-odt-styles-dir-list
2037 (and org-e-odt-data-dir
2038 (expand-file-name "./styles/" org-e-odt-data-dir
)) ; bail out
2040 (and (boundp 'org-e-odt-data-dir
) org-e-odt-data-dir
; see make install
2041 (expand-file-name "./styles/" org-e-odt-data-dir
)))
2042 (expand-file-name "../etc/styles/" org-e-odt-lib-dir
) ; git
2043 (expand-file-name "./etc/styles/" org-e-odt-lib-dir
) ; elpa
2044 (expand-file-name "./org/" data-directory
) ; system
2046 "List of directories to search for OpenDocument styles files.
2047 See `org-e-odt-styles-dir'. The entries in this list are populated
2048 heuristically based on the values of `org-e-odt-lib-dir' and
2049 `org-e-odt-data-dir'.")
2051 (defconst org-e-odt-styles-dir
2054 (message "Debug (org-e-odt): Searching for OpenDocument styles files...")
2055 (mapc (lambda (styles-dir)
2057 (message "Debug (org-e-odt): Trying %s..." styles-dir
)
2058 (when (and (file-readable-p
2060 "OrgOdtContentTemplate.xml" styles-dir
))
2063 "OrgOdtStyles.xml" styles-dir
)))
2064 (message "Debug (org-e-odt): Using styles under %s"
2066 (throw 'styles-dir styles-dir
))))
2067 org-e-odt-styles-dir-list
)
2070 (error "Error (org-e-odt): Cannot find factory styles files. Aborting."))
2072 "Directory that holds auxiliary XML files used by the ODT exporter.
2074 This directory contains the following XML files -
2075 \"OrgOdtStyles.xml\" and \"OrgOdtContentTemplate.xml\". These
2076 XML files are used as the default values of
2077 `org-export-e-odt-styles-file' and
2078 `org-export-e-odt-content-template-file'.
2080 The default value of this variable varies depending on the
2081 version of org in use and is initialized from
2082 `org-e-odt-styles-dir-list'. Note that the user could be using org
2083 from one of: org's own private git repository, GNU ELPA tar or
2086 (defconst org-export-e-odt-tmpdir-prefix
"%s-")
2087 (defconst org-export-e-odt-bookmark-prefix
"OrgXref.")
2089 (defconst org-e-odt-manifest-file-entry-tag
2091 <manifest:file-entry manifest:media-type=\"%s\" manifest:full-path=\"%s\"%s/>")
2095 (defvar org-lparse-dyn-first-heading-pos
) ; let bound during org-do-lparse
2097 (defvar org-e-odt-suppress-xref nil
)
2098 (defvar org-e-odt-file-extensions
2099 '(("odt" .
"OpenDocument Text")
2100 ("ott" .
"OpenDocument Text Template")
2101 ("odm" .
"OpenDocument Master Document")
2102 ("ods" .
"OpenDocument Spreadsheet")
2103 ("ots" .
"OpenDocument Spreadsheet Template")
2104 ("odg" .
"OpenDocument Drawing (Graphics)")
2105 ("otg" .
"OpenDocument Drawing Template")
2106 ("odp" .
"OpenDocument Presentation")
2107 ("otp" .
"OpenDocument Presentation Template")
2108 ("odi" .
"OpenDocument Image")
2109 ("odf" .
"OpenDocument Formula")
2110 ("odc" .
"OpenDocument Chart")))
2112 (defvar org-export-e-odt-embed-images t
2113 "Should the images be copied in to the odt file or just linked?")
2115 (defvar org-export-e-odt-inline-images
'maybe
)
2116 (defvar org-export-e-odt-default-org-styles-alist
2117 '((paragraph .
((default .
"Text_20_body")
2118 (fixedwidth .
"OrgFixedWidthBlock")
2119 (verse .
"OrgVerse")
2120 (quote .
"Quotations")
2121 (blockquote .
"Quotations")
2122 (center .
"OrgCenter")
2124 (right .
"OrgRight")
2125 (title .
"OrgTitle")
2126 (subtitle .
"OrgSubtitle")
2127 (footnote .
"Footnote")
2128 (src .
"OrgSrcBlock")
2129 (illustration .
"Illustration")
2131 (definition-term .
"Text_20_body_20_bold")
2132 (horizontal-line .
"Horizontal_20_Line")))
2133 (character .
((bold .
"Bold")
2134 (emphasis .
"Emphasis")
2136 (verbatim .
"OrgCode")
2137 (strike .
"Strikethrough")
2138 (underline .
"Underline")
2139 (subscript .
"OrgSubscript")
2140 (superscript .
"OrgSuperscript")))
2141 (list .
((ordered .
"OrgNumberedList")
2142 (unordered .
"OrgBulletedList")
2143 (descriptive .
"OrgDescriptionList"))))
2144 "Default styles for various entities.")
2146 (defvar org-export-e-odt-org-styles-alist org-export-e-odt-default-org-styles-alist
)
2148 (defvar org-e-odt-entity-control-callbacks-alist
2150 .
(org-e-odt-begin-export org-e-odt-end-export
))
2152 .
(org-e-odt-begin-document-content org-e-odt-end-document-content
))
2154 .
(org-e-odt-begin-document-body org-e-odt-end-document-body
))
2156 .
(org-e-odt-begin-toc org-e-odt-end-toc
))
2158 .
(org-e-odt-begin-environment org-e-odt-end-environment
))
2159 (FOOTNOTE-DEFINITION
2160 .
(org-e-odt-begin-footnote-definition org-e-odt-end-footnote-definition
))
2162 .
(org-e-odt-begin-table org-e-odt-end-table
))
2164 .
(org-e-odt-begin-table-rowgroup org-e-odt-end-table-rowgroup
))
2166 .
(org-e-odt-begin-list org-e-odt-end-list
))
2168 .
(org-e-odt-begin-list-item org-e-odt-end-list-item
))
2170 .
(org-e-odt-begin-outline org-e-odt-end-outline
))
2172 .
(org-e-odt-begin-outline-text org-e-odt-end-outline-text
))
2174 .
(org-e-odt-begin-paragraph org-e-odt-end-paragraph
)))
2177 (defvar org-e-odt-entity-format-callbacks-alist
2178 `((EXTRA-TARGETS . org-lparse-format-extra-targets
)
2179 (ORG-TAGS . org-lparse-format-org-tags
)
2180 (SECTION-NUMBER . org-lparse-format-section-number
)
2181 (HEADLINE . org-e-odt-format-headline
)
2182 (TOC-ENTRY . org-e-odt-format-toc-entry
)
2183 (TOC-ITEM . org-e-odt-format-toc-item
)
2184 (TAGS . org-e-odt-format-tags
)
2185 (SPACES . org-e-odt-format-spaces
)
2186 (TABS . org-e-odt-format-tabs
)
2187 (LINE-BREAK . org-e-odt-format-line-break
)
2188 (FONTIFY . org-e-odt-format-fontify
)
2189 (TODO . org-lparse-format-todo
)
2190 (LINK . org-e-odt-format-link
)
2191 (INLINE-IMAGE . org-e-odt-format-inline-image
)
2192 (ORG-LINK . org-e-odt-format-org-link
)
2193 (HEADING . org-e-odt-format-heading
)
2194 (ANCHOR . org-e-odt-format-anchor
)
2195 (TABLE . org-lparse-format-table
)
2196 (TABLE-ROW . org-e-odt-format-table-row
)
2197 (TABLE-CELL . org-e-odt-format-table-cell
)
2198 (FOOTNOTES-SECTION . ignore
)
2199 (FOOTNOTE-REFERENCE . org-e-odt-format-footnote-reference
)
2200 (HORIZONTAL-LINE . org-e-odt-format-horizontal-line
)
2201 (COMMENT . org-e-odt-format-comment
)
2202 (LINE . org-e-odt-format-line
)
2203 (ORG-ENTITY . org-e-odt-format-org-entity
))
2207 ;;;_. control callbacks
2208 ;;;_ , document body
2210 (defvar org-lparse-toc
)
2211 (defvar org-lparse-body-only
) ; let bound during org-do-lparse
2212 (defvar org-lparse-to-buffer
) ; let bound during org-do-lparse
2213 (defvar org-lparse-opt-plist
) ; bound during org-do-lparse
2214 (defvar org-lparse-list-stack
) ; dynamically bound in org-do-lparse
2215 (defvar org-e-odt-list-stack-stashed
)
2216 (defvar org-lparse-table-begin-marker
)
2217 (defvar org-lparse-table-ncols
)
2218 (defvar org-e-odt-table-rowgrp-open
)
2219 (defvar org-e-odt-table-rownum
)
2220 (defvar org-e-odt-table-cur-rowgrp-is-hdr
)
2221 (defvar org-lparse-table-is-styled
)
2222 (defvar org-lparse-table-rowgrp-info
)
2223 (defvar org-lparse-table-colalign-vector
)
2225 (defvar org-e-odt-table-style nil
2226 "Table style specified by \"#+ATTR_ODT: <style-name>\" line.
2227 This is set during `org-e-odt-begin-table'.")
2229 (defvar org-e-odt-table-style-spec nil
2230 "Entry for `org-e-odt-table-style' in `org-export-e-odt-table-styles'.")
2233 (defvar org-e-odt-table-style-format
2235 <style:style style:name=\"%s\" style:family=\"table\">
2236 <style:table-properties style:rel-width=\"%d%%\" fo:margin-top=\"0cm\" fo:margin-bottom=\"0.20cm\" table:align=\"center\"/>
2239 "Template for auto-generated Table styles.")
2241 (defvar org-e-odt-automatic-styles
'()
2242 "Registry of automatic styles for various OBJECT-TYPEs.
2243 The variable has the following form:
2245 \(\(OBJECT-NAME-A.1 OBJECT-PROPS-A.1\)
2246 \(OBJECT-NAME-A.2 OBJECT-PROPS-A.2\) ...\)\)
2248 \(\(OBJECT-NAME-B.1 OBJECT-PROPS-B.1\)
2249 \(OBJECT-NAME-B.2 OBJECT-PROPS-B.2\) ...\)\)
2252 OBJECT-TYPEs could be \"Section\", \"Table\", \"Figure\" etc.
2253 OBJECT-PROPS is (typically) a plist created by passing
2254 \"#+ATTR_ODT: \" option to `org-lparse-get-block-params'.
2256 Use `org-e-odt-add-automatic-style' to add update this variable.'")
2258 (defvar org-e-odt-object-counters nil
2259 "Running counters for various OBJECT-TYPEs.
2260 Use this to generate automatic names and style-names. See
2261 `org-e-odt-add-automatic-style'.")
2263 (defvar org-e-odt-table-indentedp nil
)
2264 (defvar org-lparse-table-colalign-info
)
2265 (defvar org-lparse-link-description-is-image nil
)
2268 (defvar org-src-block-paragraph-format
2269 "<style:style style:name=\"OrgSrcBlock\" style:family=\"paragraph\" style:parent-style-name=\"Preformatted_20_Text\">
2270 <style:paragraph-properties fo:background-color=\"%s\" fo:padding=\"0.049cm\" fo:border=\"0.51pt solid #000000\" style:shadow=\"none\">
2271 <style:background-image/>
2272 </style:paragraph-properties>
2273 <style:text-properties fo:color=\"%s\"/>
2275 "Custom paragraph style for colorized source and example blocks.
2276 This style is much the same as that of \"OrgFixedWidthBlock\"
2277 except that the foreground and background colors are set
2278 according to the default face identified by the `htmlfontify'.")
2280 (defvar hfy-optimisations
)
2281 (defvar org-e-odt-embedded-formulas-count
0)
2282 (defvar org-e-odt-entity-frame-styles
2283 '(("As-CharImage" "__Figure__" ("OrgInlineImage" nil
"as-char"))
2284 ("ParagraphImage" "__Figure__" ("OrgDisplayImage" nil
"paragraph"))
2285 ("PageImage" "__Figure__" ("OrgPageImage" nil
"page"))
2286 ("CaptionedAs-CharImage" "__Figure__"
2287 ("OrgCaptionedImage"
2288 " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph")
2289 ("OrgInlineImage" nil
"as-char"))
2290 ("CaptionedParagraphImage" "__Figure__"
2291 ("OrgCaptionedImage"
2292 " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph")
2293 ("OrgImageCaptionFrame" nil
"paragraph"))
2294 ("CaptionedPageImage" "__Figure__"
2295 ("OrgCaptionedImage"
2296 " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph")
2297 ("OrgPageImageCaptionFrame" nil
"page"))
2298 ("InlineFormula" "__MathFormula__" ("OrgInlineFormula" nil
"as-char"))
2299 ("DisplayFormula" "__MathFormula__" ("OrgDisplayFormula" nil
"as-char"))
2300 ("CaptionedDisplayFormula" "__MathFormula__"
2301 ("OrgCaptionedFormula" nil
"paragraph")
2302 ("OrgFormulaCaptionFrame" nil
"as-char"))))
2304 (defvar org-e-odt-embedded-images-count
0)
2306 (defvar org-export-e-odt-image-size-probe-method
2307 (append (and (executable-find "identify") '(imagemagick)) ; See Bug#10675
2309 "Ordered list of methods for determining image sizes.")
2311 (defvar org-export-e-odt-default-image-sizes-alist
2312 '(("as-char" .
(5 .
0.4))
2313 ("paragraph" .
(5 .
5)))
2314 "Hardcoded image dimensions one for each of the anchor
2317 ;; A4 page size is 21.0 by 29.7 cms
2318 ;; The default page settings has 2cm margin on each of the sides. So
2319 ;; the effective text area is 17.0 by 25.7 cm
2320 (defvar org-export-e-odt-max-image-size
'(17.0 .
20.0)
2321 "Limiting dimensions for an embedded image.")
2323 (defvar org-e-odt-entity-labels-alist nil
2324 "Associate Labels with the Labeled entities.
2325 Each element of the alist is of the form (LABEL-NAME
2326 CATEGORY-NAME SEQNO LABEL-STYLE-NAME). LABEL-NAME is same as
2327 that specified by \"#+LABEL: ...\" line. CATEGORY-NAME is the
2328 type of the entity that LABEL-NAME is attached to. CATEGORY-NAME
2329 can be one of \"Table\", \"Figure\" or \"Equation\". SEQNO is
2330 the unique number assigned to the referenced entity on a
2331 per-CATEGORY basis. It is generated sequentially and is 1-based.
2332 LABEL-STYLE-NAME is a key `org-e-odt-label-styles'.
2334 See `org-e-odt-add-label-definition' and
2335 `org-e-odt-fixup-label-references'.")
2337 (defvar org-e-odt-entity-counts-plist nil
2338 "Plist of running counters of SEQNOs for each of the CATEGORY-NAMEs.
2339 See `org-e-odt-entity-labels-alist' for known CATEGORY-NAMEs.")
2341 (defvar org-e-odt-label-styles
2342 '(("text" "(%n)" "text" "(%n)")
2343 ("category-and-value" "%e %n%c" "category-and-value" "%e %n")
2344 ("value" "%e %n%c" "value" "%n"))
2345 "Specify how labels are applied and referenced.
2346 This is an alist where each element is of the
2347 form (LABEL-STYLE-NAME LABEL-ATTACH-FMT LABEL-REF-MODE
2350 LABEL-ATTACH-FMT controls how labels and captions are attached to
2351 an entity. It may contain following specifiers - %e, %n and %c.
2352 %e is replaced with the CATEGORY-NAME. %n is replaced with
2353 \"<text:sequence ...> SEQNO </text:sequence>\". %c is replaced
2354 with CAPTION. See `org-e-odt-format-label-definition'.
2356 LABEL-REF-MODE and LABEL-REF-FMT controls how label references
2357 are generated. The following XML is generated for a label
2358 reference - \"<text:sequence-ref
2359 text:reference-format=\"LABEL-REF-MODE\" ...> LABEL-REF-FMT
2360 </text:sequence-ref>\". LABEL-REF-FMT may contain following
2361 specifiers - %e and %n. %e is replaced with the CATEGORY-NAME.
2362 %n is replaced with SEQNO. See
2363 `org-e-odt-format-label-reference'.")
2365 (defvar org-e-odt-category-map-alist
2366 '(("__Table__" "Table" "value")
2367 ("__Figure__" "Figure" "value")
2368 ("__MathFormula__" "Equation" "text")
2369 ("__DvipngImage__" "Equation" "value")
2370 ;; ("__Table__" "Table" "category-and-value")
2371 ;; ("__Figure__" "Figure" "category-and-value")
2372 ;; ("__DvipngImage__" "Equation" "category-and-value")
2374 "Map a CATEGORY-HANDLE to CATEGORY-NAME and LABEL-STYLE.
2375 This is an alist where each element is of the form
2376 \\(CATEGORY-HANDLE CATEGORY-NAME LABEL-STYLE\\). CATEGORY_HANDLE
2377 could either be one of the internal handles (as seen above) or be
2378 derived from the \"#+LABEL:<label-name>\" specification. See
2379 `org-export-e-odt-get-category-from-label'. CATEGORY-NAME and
2380 LABEL-STYLE are used for generating ODT labels. See
2381 `org-e-odt-label-styles'.")
2383 (defvar org-export-e-odt-user-categories
2384 '("Illustration" "Table" "Text" "Drawing" "Equation" "Figure"))
2386 (defvar org-export-e-odt-get-category-from-label nil
2387 "Should category of label be inferred from label itself.
2388 When this option is non-nil, a label is parsed in to two
2389 component parts delimited by a \":\" (colon) as shown here -
2390 #+LABEL:[CATEGORY-HANDLE:]EXTRA. The CATEGORY-HANDLE is mapped
2391 to a CATEGORY-NAME and LABEL-STYLE using
2392 `org-e-odt-category-map-alist'. (If no such map is provided and
2393 CATEGORY-NAME is set to CATEGORY-HANDLE and LABEL-STYLE is set to
2394 \"category-and-value\"). If CATEGORY-NAME so obtained is listed
2395 under `org-export-e-odt-user-categories' then the user specified
2396 styles are used. Otherwise styles as determined by the internal
2397 CATEGORY-HANDLE is used. See
2398 `org-e-odt-get-label-category-and-style' for details.")
2400 (defvar org-e-odt-manifest-file-entries nil
)
2401 (defvar hfy-user-sheet-assoc
) ; bound during org-do-lparse
2402 (defvar org-lparse-latex-fragment-fallback
) ; set by org-do-lparse
2405 ;;;; HTML Internal Variables
2407 (defvar org-e-odt-option-alist
2409 ;; (:agenda-style nil nil org-agenda-export-html-style)
2410 ;; (:convert-org-links nil nil org-e-odt-link-org-files-as-html)
2411 ;; ;; FIXME Use (org-xml-encode-org-text-skip-links s) ??
2412 ;; ;; (:expand-quoted-html nil "@" org-e-odt-expand)
2413 ;; (:inline-images nil nil org-e-odt-inline-images)
2414 ;; ;; (:link-home nil nil org-e-odt-link-home) FIXME
2415 ;; ;; (:link-up nil nil org-e-odt-link-up) FIXME
2416 ;; (:style nil nil org-e-odt-style)
2417 ;; (:style-extra nil nil org-e-odt-style-extra)
2418 ;; (:style-include-default nil nil org-e-odt-style-include-default)
2419 ;; (:style-include-scripts nil nil org-e-odt-style-include-scripts)
2420 ;; ;; (:timestamp nil nil org-e-odt-with-timestamp)
2421 ;; (:html-extension nil nil org-e-odt-extension)
2422 ;; (:html-postamble nil nil org-e-odt-postamble)
2423 ;; (:html-preamble nil nil org-e-odt-preamble)
2424 ;; (:html-table-tag nil nil org-e-odt-table-tag)
2425 ;; (:xml-declaration nil nil org-e-odt-xml-declaration)
2426 (:LaTeX-fragments nil
"LaTeX" org-export-with-LaTeX-fragments
))
2427 "Alist between export properties and ways to set them.
2429 The car of the alist is the property name, and the cdr is a list
2430 like \(KEYWORD OPTION DEFAULT BEHAVIOUR\) where:
2432 KEYWORD is a string representing a buffer keyword, or nil.
2433 OPTION is a string that could be found in an #+OPTIONS: line.
2434 DEFAULT is the default value for the property.
2435 BEHAVIOUR determine how Org should handle multiple keywords for
2436 the same property. It is a symbol among:
2437 nil Keep old value and discard the new one.
2438 t Replace old value with the new one.
2439 `space' Concatenate the values, separating them with a space.
2440 `newline' Concatenate the values, separating them with
2442 `split' Split values at white spaces, and cons them to the
2445 KEYWORD and OPTION have precedence over DEFAULT.
2447 All these properties should be back-end agnostic. For back-end
2448 specific properties, define a similar variable named
2449 `org-BACKEND-option-alist', replacing BACKEND with the name of
2450 the appropriate back-end. You can also redefine properties
2451 there, as they have precedence over these.")
2453 (defvar html-table-tag nil
) ; dynamically scoped into this.
2455 ;; FIXME: it already exists in org-e-odt.el
2456 (defconst org-e-odt-cvt-link-fn
2458 "Function to convert link URLs to exportable URLs.
2459 Takes two arguments, TYPE and PATH.
2460 Returns exportable url as (TYPE PATH), or nil to signal that it
2461 didn't handle this case.
2462 Intended to be locally bound around a call to `org-export-as-html'." )
2467 (defvar org-e-odt-format-table-no-css
)
2468 (defvar htmlize-buffer-places
) ; from htmlize.el
2469 (defvar body-only
) ; dynamically scoped into this.
2471 (defvar org-e-odt-table-rowgrp-open
)
2472 (defvar org-e-odt-table-rownum
)
2473 (defvar org-e-odt-table-cur-rowgrp-is-hdr
)
2474 (defvar org-lparse-table-is-styled
)
2477 (defvar org-e-odt-headline-formatter
2478 (lambda (level snumber todo todo-type priority
2479 title tags target extra-targets extra-class
)
2480 (concat snumber
" " title
)))
2484 ;;; User Configuration Variables
2486 (defgroup org-export-e-odt nil
2487 "Options for exporting Org mode files to HTML."
2488 :tag
"Org Export HTML"
2491 (defcustom org-e-odt-protect-char-alist
2495 "Alist of characters to be converted by `org-e-html-protect'."
2496 :group
'org-export-e-html
2497 :type
'(repeat (cons (string :tag
"Character")
2498 (string :tag
"ODT equivalent"))))
2499 (defcustom org-export-e-odt-schema-dir
2502 (message "Debug (org-e-odt): Searching for OpenDocument schema files...")
2504 (lambda (schema-dir)
2506 (message "Debug (org-e-odt): Trying %s..." schema-dir
)
2507 (when (and (file-readable-p
2508 (expand-file-name "od-manifest-schema-v1.2-cs01.rnc"
2511 (expand-file-name "od-schema-v1.2-cs01.rnc"
2514 (expand-file-name "schemas.xml" schema-dir
)))
2515 (message "Debug (org-e-odt): Using schema files under %s"
2517 (throw 'schema-dir schema-dir
))))
2518 org-e-odt-schema-dir-list
)
2519 (message "Debug (org-e-odt): No OpenDocument schema files installed")
2522 "Directory that contains OpenDocument schema files.
2524 This directory contains:
2525 1. rnc files for OpenDocument schema
2526 2. a \"schemas.xml\" file that specifies locating rules needed
2527 for auto validation of OpenDocument XML files.
2529 Use the customize interface to set this variable. This ensures
2530 that `rng-schema-locating-files' is updated and auto-validation
2531 of OpenDocument XML takes place based on the value
2532 `rng-nxml-auto-validate-flag'.
2534 The default value of this variable varies depending on the
2535 version of org in use and is initialized from
2536 `org-e-odt-schema-dir-list'. The OASIS schema files are available
2537 only in the org's private git repository. It is *not* bundled
2538 with GNU ELPA tar or standard Emacs distribution."
2540 (const :tag
"Not set" nil
)
2541 (directory :tag
"Schema directory"))
2542 :group
'org-export-e-odt
2546 "Set `org-export-e-odt-schema-dir'.
2547 Also add it to `rng-schema-locating-files'."
2548 (let ((schema-dir value
))
2552 (expand-file-name "od-manifest-schema-v1.2-cs01.rnc" schema-dir
))
2554 (expand-file-name "od-schema-v1.2-cs01.rnc" schema-dir
))
2556 (expand-file-name "schemas.xml" schema-dir
)))
2559 (message "Error (org-e-odt): %s has no OpenDocument schema files"
2562 (when org-export-e-odt-schema-dir
2563 (eval-after-load 'rng-loc
2564 '(add-to-list 'rng-schema-locating-files
2565 (expand-file-name "schemas.xml"
2566 org-export-e-odt-schema-dir
))))))
2568 (defcustom org-export-e-odt-content-template-file nil
2569 "Template file for \"content.xml\".
2570 The exporter embeds the exported content just before
2571 \"</office:text>\" element.
2573 If unspecified, the file named \"OrgOdtContentTemplate.xml\"
2574 under `org-e-odt-styles-dir' is used."
2576 :group
'org-export-e-odt
2579 (defcustom org-export-e-odt-styles-file nil
2580 "Default styles file for use with ODT export.
2581 Valid values are one of:
2583 2. path to a styles.xml file
2584 3. path to a *.odt or a *.ott file
2585 4. list of the form (ODT-OR-OTT-FILE (FILE-MEMBER-1 FILE-MEMBER-2
2588 In case of option 1, an in-built styles.xml is used. See
2589 `org-e-odt-styles-dir' for more information.
2591 In case of option 3, the specified file is unzipped and the
2592 styles.xml embedded therein is used.
2594 In case of option 4, the specified ODT-OR-OTT-FILE is unzipped
2595 and FILE-MEMBER-1, FILE-MEMBER-2 etc are copied in to the
2596 generated odt file. Use relative path for specifying the
2597 FILE-MEMBERS. styles.xml must be specified as one of the
2600 Use options 1, 2 or 3 only if styles.xml alone suffices for
2601 achieving the desired formatting. Use option 4, if the styles.xml
2602 references additional files like header and footer images for
2603 achieving the desired formatting.
2605 Use \"#+ODT_STYLES_FILE: ...\" directive to set this variable on
2606 a per-file basis. For example,
2608 #+ODT_STYLES_FILE: \"/path/to/styles.xml\" or
2609 #+ODT_STYLES_FILE: (\"/path/to/file.ott\" (\"styles.xml\" \"image/hdr.png\"))."
2610 :group
'org-export-e-odt
2614 (const :tag
"Factory settings" nil
)
2615 (file :must-match t
:tag
"styles.xml")
2616 (file :must-match t
:tag
"ODT or OTT file")
2617 (list :tag
"ODT or OTT file + Members"
2618 (file :must-match t
:tag
"ODF Text or Text Template file")
2619 (cons :tag
"Members"
2620 (file :tag
" Member" "styles.xml")
2621 (repeat (file :tag
"Member"))))))
2624 (defcustom org-export-e-odt-inline-image-extensions
2625 '("png" "jpeg" "jpg" "gif")
2626 "Extensions of image files that can be inlined into HTML."
2627 :type
'(repeat (string :tag
"Extension"))
2628 :group
'org-export-e-odt
2631 (defcustom org-export-e-odt-pixels-per-inch display-pixels-per-inch
2632 "Scaling factor for converting images pixels to inches.
2633 Use this for sizing of embedded images. See Info node `(org)
2634 Images in ODT export' for more information."
2636 :group
'org-export-e-odt
2639 (defcustom org-export-e-odt-create-custom-styles-for-srcblocks t
2640 "Whether custom styles for colorized source blocks be automatically created.
2641 When this option is turned on, the exporter creates custom styles
2642 for source blocks based on the advice of `htmlfontify'. Creation
2643 of custom styles happen as part of `org-e-odt-hfy-face-to-css'.
2645 When this option is turned off exporter does not create such
2648 Use the latter option if you do not want the custom styles to be
2649 based on your current display settings. It is necessary that the
2650 styles.xml already contains needed styles for colorizing to work.
2652 This variable is effective only if
2653 `org-export-e-odt-fontify-srcblocks' is turned on."
2654 :group
'org-export-e-odt
2658 (defcustom org-export-e-odt-preferred-output-format nil
2659 "Automatically post-process to this format after exporting to \"odt\".
2660 Interactive commands `org-export-as-e-odt' and
2661 `org-export-as-e-odt-and-open' export first to \"odt\" format and
2662 then use `org-export-e-odt-convert-process' to convert the
2663 resulting document to this format. During customization of this
2664 variable, the list of valid values are populated based on
2665 `org-export-e-odt-convert-capabilities'."
2666 :group
'org-export-e-odt
2668 :type
'(choice :convert-widget
2670 (apply 'widget-convert
(widget-type w
)
2671 (eval (car (widget-get w
:args
)))))
2672 `((const :tag
"None" nil
)
2673 ,@(mapcar (lambda (c)
2674 `(const :tag
,c
,c
))
2675 (org-lparse-reachable-formats "odt")))))
2677 (defcustom org-export-e-odt-table-styles
2678 '(("OrgEquation" "OrgEquation"
2679 ((use-first-column-styles . t
)
2680 (use-last-column-styles . t
))))
2681 "Specify how Table Styles should be derived from a Table Template.
2682 This is a list where each element is of the
2683 form (TABLE-STYLE-NAME TABLE-TEMPLATE-NAME TABLE-CELL-OPTIONS).
2685 TABLE-STYLE-NAME is the style associated with the table through
2686 `org-e-odt-table-style'.
2688 TABLE-TEMPLATE-NAME is a set of - upto 9 - automatic
2689 TABLE-CELL-STYLE-NAMEs and PARAGRAPH-STYLE-NAMEs (as defined
2690 below) that is included in
2691 `org-export-e-odt-content-template-file'.
2693 TABLE-CELL-STYLE-NAME := TABLE-TEMPLATE-NAME + TABLE-CELL-TYPE +
2695 PARAGRAPH-STYLE-NAME := TABLE-TEMPLATE-NAME + TABLE-CELL-TYPE +
2697 TABLE-CELL-TYPE := \"FirstRow\" | \"LastColumn\" |
2698 \"FirstRow\" | \"LastRow\" |
2699 \"EvenRow\" | \"OddRow\" |
2700 \"EvenColumn\" | \"OddColumn\" | \"\"
2701 where \"+\" above denotes string concatenation.
2703 TABLE-CELL-OPTIONS is an alist where each element is of the
2704 form (TABLE-CELL-STYLE-SELECTOR . ON-OR-OFF).
2705 TABLE-CELL-STYLE-SELECTOR := `use-first-row-styles' |
2706 `use-last-row-styles' |
2707 `use-first-column-styles' |
2708 `use-last-column-styles' |
2709 `use-banding-rows-styles' |
2710 `use-banding-columns-styles' |
2711 `use-first-row-styles'
2712 ON-OR-OFF := `t' | `nil'
2714 For example, with the following configuration
2716 \(setq org-export-e-odt-table-styles
2717 '\(\(\"TableWithHeaderRowsAndColumns\" \"Custom\"
2718 \(\(use-first-row-styles . t\)
2719 \(use-first-column-styles . t\)\)\)
2720 \(\"TableWithHeaderColumns\" \"Custom\"
2721 \(\(use-first-column-styles . t\)\)\)\)\)
2723 1. A table associated with \"TableWithHeaderRowsAndColumns\"
2724 style will use the following table-cell styles -
2725 \"CustomFirstRowTableCell\", \"CustomFirstColumnTableCell\",
2726 \"CustomTableCell\" and the following paragraph styles
2727 \"CustomFirstRowTableParagraph\",
2728 \"CustomFirstColumnTableParagraph\", \"CustomTableParagraph\"
2731 2. A table associated with \"TableWithHeaderColumns\" style will
2732 use the following table-cell styles -
2733 \"CustomFirstColumnTableCell\", \"CustomTableCell\" and the
2734 following paragraph styles
2735 \"CustomFirstColumnTableParagraph\", \"CustomTableParagraph\"
2738 Note that TABLE-TEMPLATE-NAME corresponds to the
2739 \"<table:table-template>\" elements contained within
2740 \"<office:styles>\". The entries (TABLE-STYLE-NAME
2741 TABLE-TEMPLATE-NAME TABLE-CELL-OPTIONS) correspond to
2742 \"table:template-name\" and \"table:use-first-row-styles\" etc
2743 attributes of \"<table:table>\" element. Refer ODF-1.2
2744 specification for more information. Also consult the
2745 implementation filed under `org-e-odt-get-table-cell-styles'.
2747 The TABLE-STYLE-NAME \"OrgEquation\" is used internally for
2748 formatting of numbered display equations. Do not delete this
2749 style from the list."
2750 :group
'org-export-e-odt
2753 (const :tag
"None" nil
)
2754 (repeat :tag
"Table Styles"
2755 (list :tag
"Table Style Specification"
2756 (string :tag
"Table Style Name")
2757 (string :tag
"Table Template Name")
2758 (alist :options
(use-first-row-styles
2760 use-first-column-styles
2761 use-last-column-styles
2762 use-banding-rows-styles
2763 use-banding-columns-styles
)
2765 :value-type
(const :tag
"True" t
))))))
2766 (defcustom org-export-e-odt-fontify-srcblocks t
2767 "Specify whether or not source blocks need to be fontified.
2768 Turn this option on if you want to colorize the source code
2769 blocks in the exported file. For colorization to work, you need
2770 to make available an enhanced version of `htmlfontify' library."
2772 :group
'org-export-e-odt
2775 (defcustom org-export-e-odt-prettify-xml t
; FIXME
2776 "Specify whether or not the xml output should be prettified.
2777 When this option is turned on, `indent-region' is run on all
2778 component xml buffers before they are saved. Turn this off for
2779 regular use. Turn this on if you need to examine the xml
2781 :group
'org-export-e-odt
2785 (defcustom org-export-e-odt-convert-processes
2787 "soffice --headless --convert-to %f%x --outdir %d %i")
2789 "unoconv -f %f -o %d %i"))
2790 "Specify a list of document converters and their usage.
2791 The converters in this list are offered as choices while
2792 customizing `org-export-e-odt-convert-process'.
2794 This variable is a list where each element is of the
2795 form (CONVERTER-NAME CONVERTER-CMD). CONVERTER-NAME is the name
2796 of the converter. CONVERTER-CMD is the shell command for the
2797 converter and can contain format specifiers. These format
2798 specifiers are interpreted as below:
2800 %i input file name in full
2801 %I input file name as a URL
2802 %f format of the output file
2803 %o output file name in full
2804 %O output file name as a URL
2805 %d output dir in full
2806 %D output dir as a URL.
2807 %x extra options as set in `org-export-e-odt-convert-capabilities'."
2808 :group
'org-export-e-odt
2812 (const :tag
"None" nil
)
2813 (alist :tag
"Converters"
2814 :key-type
(string :tag
"Converter Name")
2815 :value-type
(group (string :tag
"Command line")))))
2817 (defcustom org-export-e-odt-convert-process
"LibreOffice"
2818 "Use this converter to convert from \"odt\" format to other formats.
2819 During customization, the list of converter names are populated
2820 from `org-export-e-odt-convert-processes'."
2821 :group
'org-export-e-odt
2823 :type
'(choice :convert-widget
2825 (apply 'widget-convert
(widget-type w
)
2826 (eval (car (widget-get w
:args
)))))
2827 `((const :tag
"None" nil
)
2828 ,@(mapcar (lambda (c)
2829 `(const :tag
,(car c
) ,(car c
)))
2830 org-export-e-odt-convert-processes
))))
2832 (defcustom org-export-e-odt-convert-capabilities
2834 ("odt" "ott" "doc" "rtf" "docx")
2835 (("pdf" "pdf") ("odt" "odt") ("rtf" "rtf") ("ott" "ott")
2836 ("doc" "doc" ":\"MS Word 97\"") ("docx" "docx") ("html" "html")))
2839 (("pdf" "pdf") ("odt" "odt") ("html" "html")))
2841 ("ods" "ots" "xls" "csv" "xlsx")
2842 (("pdf" "pdf") ("ots" "ots") ("html" "html") ("csv" "csv") ("ods" "ods")
2843 ("xls" "xls") ("xlsx" "xlsx")))
2845 ("odp" "otp" "ppt" "pptx")
2846 (("pdf" "pdf") ("swf" "swf") ("odp" "odp") ("otp" "otp") ("ppt" "ppt")
2847 ("pptx" "pptx") ("odg" "odg"))))
2848 "Specify input and output formats of `org-export-e-odt-convert-process'.
2849 More correctly, specify the set of input and output formats that
2850 the user is actually interested in.
2852 This variable is an alist where each element is of the
2853 form (DOCUMENT-CLASS INPUT-FMT-LIST OUTPUT-FMT-ALIST).
2854 INPUT-FMT-LIST is a list of INPUT-FMTs. OUTPUT-FMT-ALIST is an
2855 alist where each element is of the form (OUTPUT-FMT
2856 OUTPUT-FILE-EXTENSION EXTRA-OPTIONS).
2858 The variable is interpreted as follows:
2859 `org-export-e-odt-convert-process' can take any document that is in
2860 INPUT-FMT-LIST and produce any document that is in the
2861 OUTPUT-FMT-LIST. A document converted to OUTPUT-FMT will have
2862 OUTPUT-FILE-EXTENSION as the file name extension. OUTPUT-FMT
2863 serves dual purposes:
2864 - It is used for populating completion candidates during
2865 `org-export-e-odt-convert' commands.
2866 - It is used as the value of \"%f\" specifier in
2867 `org-export-e-odt-convert-process'.
2869 EXTRA-OPTIONS is used as the value of \"%x\" specifier in
2870 `org-export-e-odt-convert-process'.
2872 DOCUMENT-CLASS is used to group a set of file formats in
2873 INPUT-FMT-LIST in to a single class.
2875 Note that this variable inherently captures how LibreOffice based
2876 converters work. LibreOffice maps documents of various formats
2877 to classes like Text, Web, Spreadsheet, Presentation etc and
2878 allow document of a given class (irrespective of it's source
2879 format) to be converted to any of the export formats associated
2882 See default setting of this variable for an typical
2884 :group
'org-export-e-odt
2888 (const :tag
"None" nil
)
2889 (alist :tag
"Capabilities"
2890 :key-type
(string :tag
"Document Class")
2892 (group (repeat :tag
"Input formats" (string :tag
"Input format"))
2893 (alist :tag
"Output formats"
2894 :key-type
(string :tag
"Output format")
2896 (group (string :tag
"Output file extension")
2898 (const :tag
"None" nil
)
2899 (string :tag
"Extra options"))))))))
2906 ;;;; Document Header (Styles)
2908 ;;;; Document Header (Scripts)
2910 ;;;; Document Header (Mathjax)
2923 ;;;; Statistics Cookie
2943 ;;;; Horizontal Rule
2944 ;;;; Inline Babel Call
2945 ;;;; Inline Src Block
2949 ;;;; Latex Environment
2958 ;;;; Property Drawer
2984 ;;; User Configurable Variables (MAYBE)
2992 (defcustom org-e-odt-format-headline-function nil
2993 "Function to format headline text.
2995 This function will be called with 5 arguments:
2996 TODO the todo keyword \(string or nil\).
2997 TODO-TYPE the type of todo \(symbol: `todo', `done', nil\)
2998 PRIORITY the priority of the headline \(integer or nil\)
2999 TEXT the main headline text \(string\).
3000 TAGS the tags string, separated with colons \(string or nil\).
3002 The function result will be used in the section format string.
3004 As an example, one could set the variable to the following, in
3005 order to reproduce the default set-up:
3007 \(defun org-e-odt-format-headline \(todo todo-type priority text tags\)
3008 \"Default format function for an headline.\"
3009 \(concat \(when todo
3010 \(format \"\\\\textbf{\\\\textsc{\\\\textsf{%s}}} \" todo\)\)
3012 \(format \"\\\\framebox{\\\\#%c} \" priority\)\)
3014 \(when tags \(format \"\\\\hfill{}\\\\textsc{%s}\" tags\)\)\)\)"
3015 :group
'org-export-e-odt
3022 (defcustom org-e-odt-active-timestamp-format
"\\textit{%s}"
3023 "A printf format string to be applied to active time-stamps."
3024 :group
'org-export-e-odt
3027 (defcustom org-e-odt-inactive-timestamp-format
"\\textit{%s}"
3028 "A printf format string to be applied to inactive time-stamps."
3029 :group
'org-export-e-odt
3032 (defcustom org-e-odt-diary-timestamp-format
"\\textit{%s}"
3033 "A printf format string to be applied to diary time-stamps."
3034 :group
'org-export-e-odt
3040 (defcustom org-e-odt-image-default-option
"width=.9\\linewidth"
3041 "Default option for images."
3042 :group
'org-export-e-odt
3045 (defcustom org-e-odt-default-figure-position
"htb"
3046 "Default position for latex figures."
3047 :group
'org-export-e-odt
3050 (defcustom org-e-odt-inline-image-rules
3051 '(("file" .
"\\.\\(pdf\\|jpeg\\|jpg\\|png\\|ps\\|eps\\)\\'"))
3052 "Rules characterizing image files that can be inlined into HTML.
3054 A rule consists in an association whose key is the type of link
3055 to consider, and value is a regexp that will be matched against
3058 Note that, by default, the image extension *actually* allowed
3059 depend on the way the HTML file is processed. When used with
3060 pdflatex, pdf, jpg and png images are OK. When processing
3061 through dvi to Postscript, only ps and eps are allowed. The
3062 default we use here encompasses both."
3063 :group
'org-export-e-odt
3064 :type
'(alist :key-type
(string :tag
"Type")
3065 :value-type
(regexp :tag
"Path")))
3069 (defcustom org-e-odt-table-caption-above t
3070 "When non-nil, place caption string at the beginning of the table.
3071 Otherwise, place it near the end."
3072 :group
'org-export-e-odt
3077 (defcustom org-e-odt-format-drawer-function nil
3078 "Function called to format a drawer in HTML code.
3080 The function must accept two parameters:
3081 NAME the drawer name, like \"LOGBOOK\"
3082 CONTENTS the contents of the drawer.
3084 The function should return the string to be exported.
3086 For example, the variable could be set to the following function
3087 in order to mimic default behaviour:
3089 \(defun org-e-odt-format-drawer-default \(name contents\)
3090 \"Format a drawer element for HTML export.\"
3092 :group
'org-export-e-odt
3098 (defcustom org-e-odt-format-inlinetask-function nil
3099 "Function called to format an inlinetask in HTML code.
3101 The function must accept six parameters:
3102 TODO the todo keyword, as a string
3103 TODO-TYPE the todo type, a symbol among `todo', `done' and nil.
3104 PRIORITY the inlinetask priority, as a string
3105 NAME the inlinetask name, as a string.
3106 TAGS the inlinetask tags, as a string.
3107 CONTENTS the contents of the inlinetask, as a string.
3109 The function should return the string to be exported.
3111 For example, the variable could be set to the following function
3112 in order to mimic default behaviour:
3114 \(defun org-e-odt-format-inlinetask \(todo type priority name tags contents\)
3115 \"Format an inline task element for HTML export.\"
3116 \(let \(\(full-title
3119 \(format \"\\\\textbf{\\\\textsf{\\\\textsc{%s}}} \" todo\)\)
3120 \(when priority \(format \"\\\\framebox{\\\\#%c} \" priority\)\)
3122 \(when tags \(format \"\\\\hfill{}\\\\textsc{%s}\" tags\)\)\)\)\)
3123 \(format \(concat \"\\\\begin{center}\\n\"
3125 \"\\\\begin{minipage}[c]{.6\\\\textwidth}\\n\"
3127 \"\\\\rule[.8em]{\\\\textwidth}{2pt}\\n\\n\"
3129 \"\\\\end{minipage}}\"
3130 \"\\\\end{center}\"\)
3131 full-title contents\)\)"
3132 :group
'org-export-e-odt
3140 (defcustom org-e-odt-quotes
3141 '(("fr" ("\\(\\s-\\|[[(]\\)\"" .
"«~") ("\\(\\S-\\)\"" .
"~»") ("\\(\\s-\\|(\\)'" .
"'"))
3142 ("en" ("\\(\\s-\\|[[(]\\)\"" .
"``") ("\\(\\S-\\)\"" .
"''") ("\\(\\s-\\|(\\)'" .
"`")))
3143 "Alist for quotes to use when converting english double-quotes.
3145 The CAR of each item in this alist is the language code.
3146 The CDR of each item in this alist is a list of three CONS:
3147 - the first CONS defines the opening quote;
3148 - the second CONS defines the closing quote;
3149 - the last CONS defines single quotes.
3151 For each item in a CONS, the first string is a regexp
3152 for allowed characters before/after the quote, the second
3153 string defines the replacement string for this quote."
3154 :group
'org-export-e-odt
3156 (cons :tag
"Opening quote"
3157 (string :tag
"Regexp for char before")
3158 (string :tag
"Replacement quote "))
3159 (cons :tag
"Closing quote"
3160 (string :tag
"Regexp for char after ")
3161 (string :tag
"Replacement quote "))
3162 (cons :tag
"Single quote"
3163 (string :tag
"Regexp for char before")
3164 (string :tag
"Replacement quote "))))
3171 ;;; Internal Functions (HTML)
3173 ;; (defun org-e-odt-format-inline-image (path &optional caption label attr)
3174 ;; ;; FIXME: alt text missing here?
3175 ;; (let ((inline-image (format "<img src=\"%s\" alt=\"%s\"/>"
3176 ;; path (file-name-nondirectory path))))
3177 ;; (if (not label) inline-image
3178 ;; (org-e-odt-format-section inline-image "figure" label))))
3180 (defun org-e-odt-format-image (src)
3181 "Create image tag with source and attributes."
3183 (let* ((caption (org-find-text-property-in-string 'org-caption src
))
3184 (attr (org-find-text-property-in-string 'org-attributes src
))
3185 (label (org-find-text-property-in-string 'org-label src
))
3186 (caption (and caption
(org-xml-encode-org-text caption
)))
3187 (img-extras (if (string-match "^ltxpng/" src
)
3188 (format " alt=\"%s\""
3189 (org-find-text-property-in-string
3190 'org-latex-src src
))
3191 (if (string-match "\\<alt=" (or attr
""))
3193 (concat " " attr
" alt=\"" src
"\""))))
3194 (img (format "<img src=\"%s\"%s />" src img-extras
))
3197 (format "id=\"%s\" " (org-solidify-link-text label
)))
3198 "class=\"figure\"")))
3201 (with-org-lparse-preserve-paragraph-state
3204 '("<div %s>" .
"\n</div>")
3206 (org-lparse-format '("\n<p>" .
"</p>") img
)
3207 (org-lparse-format '("\n<p>" .
"</p>") caption
))
3214 (defun org-e-odt-bibliography ()
3215 "Find bibliography, cut it out and return it."
3217 (let (beg end
(cnt 1) bib
)
3219 (goto-char (point-min))
3220 (when (re-search-forward
3221 "^[ \t]*<div \\(id\\|class\\)=\"bibliography\"" nil t
)
3222 (setq beg
(match-beginning 0))
3223 (while (re-search-forward "</?div\\>" nil t
)
3224 (setq cnt
(+ cnt
(if (string= (match-string 0) "<div") +1 -
1)))
3226 (and (looking-at ">") (forward-char 1))
3227 (setq bib
(buffer-substring beg
(point)))
3228 (delete-region beg
(point))
3229 (throw 'exit bib
))))
3234 (defun org-e-odt-format-table (lines olines
)
3235 (let ((org-e-odt-format-table-no-css nil
))
3236 (org-lparse-format-table lines olines
)))
3238 (defun org-e-odt-splice-attributes (tag attributes
)
3239 "Read attributes in string ATTRIBUTES, add and replace in HTML tag TAG."
3240 (if (not attributes
)
3242 (let (oldatt newatt
)
3243 (setq oldatt
(org-extract-attributes-from-string tag
)
3245 newatt
(cdr (org-extract-attributes-from-string attributes
)))
3247 (setq oldatt
(plist-put oldatt
(pop newatt
) (pop newatt
))))
3248 (if (string-match ">" tag
)
3250 (replace-match (concat (org-attributes-to-string oldatt
) ">")
3254 (defun org-export-splice-style (style extra
)
3255 "Splice EXTRA into STYLE, just before \"</style>\"."
3256 (if (and (stringp extra
)
3257 (string-match "\\S-" extra
)
3258 (string-match "</style>" style
))
3259 (concat (substring style
0 (match-beginning 0))
3261 (substring style
(match-beginning 0)))
3264 (defun org-export-e-odtize-region-for-paste (beg end
)
3265 "Convert the region to HTML, using htmlize.el.
3266 This is much like `htmlize-region-for-paste', only that it uses
3267 the settings define in the org-... variables."
3268 (let* ((htmlize-output-type org-export-e-odtize-output-type
)
3269 (htmlize-css-name-prefix org-export-e-odtize-css-font-prefix
)
3270 (htmlbuf (htmlize-region beg end
)))
3272 (with-current-buffer htmlbuf
3273 (buffer-substring (plist-get htmlize-buffer-places
'content-start
)
3274 (plist-get htmlize-buffer-places
'content-end
)))
3275 (kill-buffer htmlbuf
))))
3278 (defun org-export-e-odtize-generate-css ()
3279 "Create the CSS for all font definitions in the current Emacs session.
3280 Use this to create face definitions in your CSS style file that can then
3281 be used by code snippets transformed by htmlize.
3282 This command just produces a buffer that contains class definitions for all
3283 faces used in the current Emacs session. You can copy and paste the ones you
3284 need into your CSS file.
3286 If you then set `org-export-e-odtize-output-type' to `css', calls to
3287 the function `org-export-e-odtize-region-for-paste' will produce code
3288 that uses these same face definitions."
3291 (and (get-buffer "*html*") (kill-buffer "*html*"))
3293 (let ((fl (face-list))
3294 (htmlize-css-name-prefix "org-")
3295 (htmlize-output-type 'css
)
3297 (while (setq f
(pop fl
)
3298 i
(and f
(face-attribute f
:inherit
)))
3299 (when (and (symbolp f
) (or (not i
) (not (listp i
))))
3300 (insert (org-add-props (copy-sequence "1") nil
'face f
))))
3301 (htmlize-region (point-min) (point-max))))
3302 (org-pop-to-buffer-same-window "*html*")
3303 (goto-char (point-min))
3304 (if (re-search-forward "<style" nil t
)
3305 (delete-region (point-min) (match-beginning 0)))
3306 (if (re-search-forward "</style>" nil t
)
3307 (delete-region (1+ (match-end 0)) (point-max)))
3308 (beginning-of-line 1)
3309 (if (looking-at " +") (replace-match ""))
3310 (goto-char (point-min)))
3312 ;; (defun org-e-odt-format-toc-entry (snumber todo headline tags href)
3313 ;; (setq headline (concat
3314 ;; ;; section number
3315 ;; (and org-export-with-section-numbers (concat snumber " "))
3319 ;; (and tags (concat
3320 ;; (org-e-odt-format-spaces 3)
3321 ;; (org-e-odt-format-fontify tags "tag")))))
3322 ;; ;; fontify headline based on TODO keyword
3323 ;; (when todo (setq headline (org-e-odt-format-fontify headline "todo")))
3324 ;; (org-e-odt-format-link headline (concat "#" href)))
3326 (defun org-e-odt-toc-entry-formatter
3327 (level snumber todo todo-type priority
3328 headline tags target extra-targets extra-class
)
3329 (org-e-odt-format-toc-entry snumber todo headline tags target
))
3331 (defun org-e-odt-make-string (n string
)
3332 (let (out) (dotimes (i n out
) (setq out
(concat string out
)))))
3334 (defun org-e-odt-toc-text (toc-entries)
3335 (let* ((prev-level (1- (nth 1 (car toc-entries
))))
3336 (start-level prev-level
))
3339 (let ((headline (nth 0 entry
))
3340 (level (nth 1 entry
)))
3341 (prog1 (org-e-odt-format-toc-item headline level prev-level
)
3342 (setq prev-level level
))))
3345 (defun org-e-odt-toc (depth info
)
3346 (assert (wholenump depth
))
3347 (let* ((headlines (org-export-collect-headlines info depth
))
3349 (loop for headline in headlines collect
3350 (list (org-e-odt-headline-text
3351 headline info
'org-e-odt-toc-entry-formatter
)
3352 (org-export-get-relative-level headline info
)))))
3354 (let* ((lang-specific-heading "Table of Contents")) ; FIXME
3356 (org-e-odt-begin-toc lang-specific-heading depth
)
3357 (org-e-odt-toc-text toc-entries
)
3358 (org-e-odt-end-toc))))))
3360 (defun org-e-odt-begin-outline (level1 snumber title tags
3361 target extra-targets extra-class
)
3362 (let* ((class (format "outline-%d" level1
))
3363 (class (if extra-class
(concat class
" " extra-class
) class
))
3364 (id (format "outline-container-%s"
3365 (org-lparse-suffix-from-snumber snumber
)))
3366 (extra (concat (when id
(format " id=\"%s\"" id
))
3367 (when class
(format " class=\"%s\"" class
)))))
3368 (org-lparse-insert-tag "<div%s>" extra
)
3370 (org-lparse-format 'HEADING
3372 'HEADLINE title extra-targets tags snumber level1
)
3375 (defun org-e-odt-end-outline ()
3376 (org-lparse-insert-tag "</div>"))
3379 ;; (defun org-e-odt-format-heading (text level &optional id)
3380 ;; (let* ((extra (concat (when id (format " id=\"%s\"" id)))))
3381 ;; (concat (format "<h%d%s>" level extra) text (format "</h%d>" level))))
3383 (defun org-e-odt-suffix-from-snumber (snumber)
3384 (let* ((snu (replace-regexp-in-string "\\." "-" snumber
))
3385 (href (cdr (assoc (concat "sec-" snu
)
3386 org-export-preferred-target-alist
))))
3387 (org-solidify-link-text (or href snu
))))
3389 (defun org-e-odt-format-outline (contents level1 snumber title
3390 tags target extra-targets extra-class
)
3392 (org-e-odt-format-heading
3393 (org-e-odt-format-headline title extra-targets tags snumber level1
)
3397 ;; (defun org-e-odt-begin-outline-text (level1 snumber extra-class)
3398 ;; (let* ((class (format "outline-text-%d" level1))
3399 ;; (class (if extra-class (concat class " " extra-class) class))
3400 ;; (id (format "text-%s" (org-lparse-suffix-from-snumber snumber)))
3401 ;; (extra (concat (when id (format " id=\"%s\"" id))
3402 ;; (when class (format " class=\"%s\"" class)))))
3403 ;; (org-lparse-insert-tag "<div%s>" extra)))
3405 ;; (defun org-e-odt-end-outline-text ()
3406 ;; (org-lparse-insert-tag "</div>"))
3408 ;; (defun org-e-odt-format-spaces (n)
3409 ;; (let (out) (dotimes (i n out) (setq out (concat out " ")))))
3411 (defun org-e-odt-format-tabs (&optional n
)
3414 ;; (defun org-e-odt-format-line (line)
3415 ;; (case org-lparse-dyn-current-environment
3416 ;; ((quote fixedwidth) (concat (org-e-odt-encode-plain-text line) "\n"))
3417 ;; (t (concat line "\n"))))
3419 (defun org-e-odt-format-comment (fmt &rest args
)
3420 (let ((comment (apply 'format fmt args
)))
3421 (format "\n<!-- %s -->\n" comment
)))
3423 (defun org-e-odt-fix-class-name (kwd) ; audit callers of this function
3424 "Turn todo keyword into a valid class name.
3425 Replaces invalid characters with \"_\"."
3427 (while (string-match "[^a-zA-Z0-9_]" kwd
)
3428 (setq kwd
(replace-match "_" t t kwd
))))
3431 ;; (defun org-e-odt-format-fontify (text style &optional id)
3432 ;; (let (class extra how)
3434 ;; ((eq style 'underline)
3435 ;; (setq extra " style=\"text-decoration:underline;\"" ))
3436 ;; ((setq how (cdr (assoc style
3437 ;; '((bold . ("<b>" . "</b>"))
3438 ;; (emphasis . ("<i>" . "</i>"))
3439 ;; (code . ("<code>" . "</code>"))
3440 ;; (verbatim . ("<code>" . "</code>"))
3441 ;; (strike . ("<del>" . "</del>"))
3442 ;; (subscript . ("<sub>" . "</sub>"))
3443 ;; (superscript . ("<sup>" . "</sup>")))))))
3445 ;; (setq class (mapconcat 'identity style " ")))
3447 ;; (setq class style))
3448 ;; (t (error "Unknown style %S" style)))
3450 ;; (setq extra (concat (when class (format " class=\"%s\"" class))
3451 ;; (when id (format " id=\"%s\"" id))
3454 ;; (let ((tags (or how '("<span%s>" . "</span>"))))
3455 ;; (concat (format (car tags) extra) text (cdr tags)))))
3457 ;; (defun org-e-odt-format-link (text href &optional extra)
3458 ;; (let ((extra (concat (format " href=\"%s\"" href)
3459 ;; (and extra (concat " " extra)))))
3460 ;; (format "<a%s>%s</a>" extra text)))
3462 (defun org-e-odt-format-internal-link (text href
&optional extra
)
3463 (org-e-odt-format-link text
(concat "#" href
) extra
))
3465 ;; (defun org-e-odt-format-heading (text level &optional id)
3466 ;; (let* ((extra (concat (when id (format " id=\"%s\"" id)))))
3467 ;; (concat (format "<h%d%s>" level extra) text (format "</h%d>\n" level))))
3469 ;; (defun org-e-odt-format-anchor (text name &optional class)
3472 ;; (when name (format " name=\"%s\"" name))
3473 ;; (when id (format " id=\"%s\"" id))
3474 ;; (when class (format " class=\"%s\"" class)))))
3475 ;; (format "<a%s>%s</a>" extra text)))
3477 (defun org-e-odt-format-extra-targets (extra-targets)
3478 (if (not extra-targets
) ""
3479 (mapconcat (lambda (x)
3481 (setq x
(org-solidify-link-text
3482 (if (org-uuidgen-p x
) (concat "ID-" x
) x
)))
3483 (org-e-odt-format-anchor "" x
))) extra-targets
"")))
3485 (defun org-e-odt-format-org-tags (tags)
3487 (org-e-odt-format-fontify
3490 (org-e-odt-format-fontify
3491 x
(concat "" ;; org-e-odt-tag-class-prefix
3492 (org-e-odt-fix-class-name x
))))
3493 (org-split-string tags
":")
3494 (org-e-odt-format-spaces 1)) "tag")))
3496 (defun org-e-odt-format-section-number (&optional snumber level
)
3498 (and nil org-export-with-section-numbers
3499 ;; (not org-lparse-body-only)
3501 (org-e-odt-format-fontify snumber
(format "section-number-%d" level
))))
3503 ;; (defun org-e-odt-format-headline (title extra-targets tags
3504 ;; &optional snumber level)
3506 ;; (org-e-odt-format-extra-targets extra-targets)
3507 ;; (concat (org-e-odt-format-section-number snumber level) " ")
3509 ;; (and tags (concat (org-e-odt-format-spaces 3)
3510 ;; (org-e-odt-format-org-tags tags)))))
3512 ;; (defun org-e-odt-format-footnote-reference (n def refcnt)
3513 ;; (let ((extra (if (= refcnt 1) "" (format ".%d" refcnt))))
3514 ;; (format org-e-odt-footnote-format
3516 ;; "<a class=\"footref\" name=\"fnr.%s%s\" href=\"#fn.%s\">%s</a>"
3519 (defun org-e-odt-format-footnotes-section (section-name definitions
)
3520 (if (not definitions
) ""
3521 (format org-e-odt-footnotes-section section-name definitions
)))
3523 ;; (defun org-e-odt-format-footnote-definition (fn)
3524 ;; (let ((n (car fn)) (def (cdr fn)))
3526 ;; "<tr>\n<td>%s</td>\n<td>%s</td>\n</tr>\n"
3528 ;; (format org-e-odt-footnote-format
3529 ;; "<a class=\"footnum\" name=\"fn.%s\" href=\"#fnr.%s\">%s</a>")
3532 (defun org-e-odt-get-coding-system-for-write ()
3533 (or org-e-odt-coding-system
3534 (and (boundp 'buffer-file-coding-system
) buffer-file-coding-system
)))
3536 (defun org-e-odt-get-coding-system-for-save ()
3537 (or org-e-odt-coding-system
3538 (and (boundp 'buffer-file-coding-system
) buffer-file-coding-system
)))
3540 ;; (defun org-e-odt-format-date (info)
3541 ;; (let ((date (plist-get info :date)))
3543 ;; ((and date (string-match "%" date))
3544 ;; (format-time-string date))
3546 ;; (t (format-time-string "%Y-%m-%d %T %Z")))))
3550 ;;; Internal Functions (Ngz)
3552 (defun org-e-odt--caption/label-string
(caption label info
)
3553 "Return caption and label HTML string for floats.
3555 CAPTION is a cons cell of secondary strings, the car being the
3556 standard caption and the cdr its short form. LABEL is a string
3557 representing the label. INFO is a plist holding contextual
3560 If there's no caption nor label, return the empty string.
3562 For non-floats, see `org-e-odt--wrap-label'."
3563 (setq label nil
) ;; FIXME
3565 (let ((label-str (if label
(format "\\label{%s}" label
) "")))
3567 ((and (not caption
) (not label
)) "")
3568 ((not caption
) (format "\\label{%s}\n" label
))
3569 ;; Option caption format with short name.
3571 (format "\\caption[%s]{%s%s}\n"
3572 (org-export-secondary-string (cdr caption
) 'e-odt info
)
3574 (org-export-secondary-string (car caption
) 'e-odt info
)))
3575 ;; Standard caption format.
3576 ;; (t (format "\\caption{%s%s}\n"
3578 ;; (org-export-secondary-string (car caption) 'e-odt info)))
3580 (t (org-export-secondary-string (car caption
) 'e-odt info
)))))
3582 (defun org-e-odt--find-verb-separator (s)
3583 "Return a character not used in string S.
3584 This is used to choose a separator for constructs like \\verb."
3585 (let ((ll "~,./?;':\"|!@#%^&-_=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<>()[]{}"))
3586 (loop for c across ll
3587 when
(not (string-match (regexp-quote (char-to-string c
)) s
))
3588 return
(char-to-string c
))))
3590 (defun org-e-odt--make-option-string (options)
3591 "Return a comma separated string of keywords and values.
3592 OPTIONS is an alist where the key is the options keyword as
3593 a string, and the value a list containing the keyword value, or
3595 (mapconcat (lambda (pair)
3596 (concat (first pair
)
3597 (when (> (length (second pair
)) 0)
3598 (concat "=" (second pair
)))))
3602 (defun org-e-odt--quotation-marks (text info
)
3603 "Export quotation marks depending on language conventions.
3604 TEXT is a string containing quotation marks to be replaced. INFO
3605 is a plist used as a communication channel."
3608 (while (setq start
(string-match (car l
) text start
))
3609 (let ((new-quote (concat (match-string 1 text
) (cdr l
))))
3610 (setq text
(replace-match new-quote t t text
))))))
3611 (cdr (or (assoc (plist-get info
:language
) org-e-odt-quotes
)
3612 ;; Falls back on English.
3613 (assoc "en" org-e-odt-quotes
))))
3616 (defun org-e-odt--wrap-label (element output
)
3617 "Wrap label associated to ELEMENT around OUTPUT, if appropriate.
3618 This function shouldn't be used for floats. See
3619 `org-e-odt--caption/label-string'."
3620 ;; (let ((label (org-element-property :name element)))
3621 ;; (if (or (not output) (not label) (string= output "") (string= label ""))
3623 ;; (concat (format "\\label{%s}\n" label) output)))
3630 (defun org-e-odt-template (contents info
)
3631 "Return complete document string after HTML conversion.
3632 CONTENTS is the transcoded contents string. RAW-DATA is the
3633 original parsed data. INFO is a plist holding export options."
3637 (org-e-odt-update-meta-file info
)
3641 (insert-file-contents
3642 (or org-export-e-odt-content-template-file
3643 (expand-file-name "OrgOdtContentTemplate.xml"
3644 org-e-odt-styles-dir
)))
3645 (goto-char (point-min))
3646 (re-search-forward "</office:text>" nil nil
)
3647 (goto-char (match-beginning 0))
3650 (insert (org-e-odt-format-preamble info
))
3651 ;; Table of Contents
3652 (let ((depth (plist-get info
:with-toc
)))
3653 (when (wholenump depth
) (org-e-odt-toc depth info
)))
3657 (buffer-substring-no-properties (point-min) (point-max))))
3661 ;;; Transcode Functions
3665 (defun org-e-odt-center-block (center-block contents info
)
3666 "Transcode a CENTER-BLOCK element from Org to HTML.
3667 CONTENTS holds the contents of the block. INFO is a plist
3668 holding contextual information."
3669 (org-e-odt--wrap-label
3671 (format "<div style=\"text-align: center\">\n%s</div>" contents
)))
3676 ;; Comments are ignored.
3681 ;; Comment Blocks are ignored.
3686 (defun org-e-odt-drawer (drawer contents info
)
3687 "Transcode a DRAWER element from Org to HTML.
3688 CONTENTS holds the contents of the block. INFO is a plist
3689 holding contextual information."
3690 (let* ((name (org-element-property :drawer-name drawer
))
3691 (output (if (functionp org-e-odt-format-drawer-function
)
3692 (funcall org-e-odt-format-drawer-function
3694 ;; If there's no user defined function: simply
3695 ;; display contents of the drawer.
3697 (org-e-odt--wrap-label drawer output
)))
3702 (defun org-e-odt-dynamic-block (dynamic-block contents info
)
3703 "Transcode a DYNAMIC-BLOCK element from Org to HTML.
3704 CONTENTS holds the contents of the block. INFO is a plist
3705 holding contextual information. See
3707 (org-e-odt--wrap-label dynamic-block contents
))
3712 (defun org-e-odt-emphasis (emphasis contents info
)
3713 "Transcode EMPHASIS from Org to HTML.
3714 CONTENTS is the contents of the emphasized text. INFO is a plist
3715 holding contextual information.."
3716 ;; (format (cdr (assoc (org-element-property :marker emphasis)
3717 ;; org-e-odt-emphasis-alist))
3719 (org-e-odt-format-fontify
3720 contents
(cadr (assoc
3721 (org-element-property :marker emphasis
)
3732 (defun org-e-odt-entity (entity contents info
)
3733 "Transcode an ENTITY object from Org to HTML.
3734 CONTENTS are the definition itself. INFO is a plist holding
3735 contextual information."
3736 ;; (let ((ent (org-element-property :latex entity)))
3737 ;; (if (org-element-property :latex-math-p entity)
3738 ;; (format "$%s$" ent)
3740 (org-element-property :utf-8 entity
))
3746 ;; (defun org-odt-format-source-code-or-example-colored
3747 ;; (lines lang caption textareap cols rows num cont rpllbl fmt))
3749 ;; (defun org-e-odt-format-source-code-or-example-plain
3750 ;; (lines lang caption textareap cols rows num cont rpllbl fmt)
3753 ;; "<pre class=\"example\">\n"
3757 ;; (format "<p>\n<textarea cols=\"%d\" rows=\"%d\">"
3759 ;; lines "</textarea>\n</p>\n"))
3761 ;; (with-temp-buffer
3763 ;; (goto-char (point-min))
3764 ;; (while (re-search-forward "[<>&]" nil t)
3765 ;; (replace-match (cdr (assq (char-before)
3766 ;; '((?&."&")(?<."<")(?>.">"))))
3768 ;; (buffer-string))))
3771 ;; (unless textareap
3772 ;; (setq lines (org-export-number-lines lines 1 1 num cont rpllbl fmt)))
3774 ;; ;; (when (string-match "\\(\\`<[^>]*>\\)\n" lines)
3775 ;; ;; (setq lines (replace-match "\\1" t nil lines)))
3779 ;; (defun org-e-odt-format-source-code-or-example-colored
3780 ;; (lines lang caption textareap cols rows num cont rpllbl fmt)
3781 ;; (let* ((lang-m (when lang
3782 ;; (or (cdr (assoc lang org-src-lang-modes))
3784 ;; (mode (and lang-m (intern
3786 ;; (if (symbolp lang-m)
3787 ;; (symbol-name lang-m)
3790 ;; (org-inhibit-startup t)
3791 ;; (org-startup-folded nil))
3793 ;; (with-temp-buffer
3795 ;; (if (functionp mode)
3797 ;; (fundamental-mode))
3798 ;; (font-lock-fontify-buffer)
3799 ;; ;; markup each line separately
3800 ;; (org-remove-formatting-on-newlines-in-region
3801 ;; (point-min) (point-max))
3803 ;; (set-buffer-modified-p nil)
3804 ;; (org-export-e-odtize-region-for-paste
3805 ;; (point-min) (point-max))))
3807 ;; (when (string-match "<pre\\([^>]*\\)>\n*" lines)
3808 ;; (setq lines (replace-match
3809 ;; (format "<pre class=\"src src-%s\">\n" lang) t t lines)))
3814 ;; "<div class=\"org-src-container\">"
3815 ;; (format "<label class=\"org-src-name\">%s</label>" caption)
3816 ;; lines "</div>")))
3818 ;; (unless textareap
3819 ;; (setq lines (org-export-number-lines lines 1 1 num cont rpllbl fmt)))
3821 ;; ;; (when (string-match "\\(\\`<[^>]*>\\)\n" lines)
3822 ;; ;; (setq lines (replace-match "\\1" t nil lines)))
3825 ;; (defun org-e-odt-format-source-code-or-example
3826 ;; (lang code &optional opts indent caption)
3827 ;; "Format CODE from language LANG and return it formatted for export.
3828 ;; The CODE is marked up in `org-export-current-backend' format.
3830 ;; Check if a function by name
3831 ;; \"org-<backend>-format-source-code-or-example\" is bound. If yes,
3832 ;; use it as the custom formatter. Otherwise, use the default
3833 ;; formatter. Default formatters are provided for docbook, html,
3834 ;; latex and ascii backends. For example, use
3835 ;; `org-e-odt-format-source-code-or-example' to provide a custom
3836 ;; formatter for export to \"html\".
3838 ;; If LANG is nil, do not add any fontification.
3839 ;; OPTS contains formatting options, like `-n' for triggering numbering lines,
3840 ;; and `+n' for continuing previous numbering.
3841 ;; Code formatting according to language currently only works for HTML.
3842 ;; Numbering lines works for all three major backends (html, latex, and ascii).
3843 ;; INDENT was the original indentation of the block."
3845 ;; (let* ((backend-formatter 'org-e-odt-format-source-code-or-example-plain)
3846 ;; num cont rtn rpllbl keepp textareap preserve-indentp cols rows fmt)
3847 ;; (setq opts (or opts "")
3848 ;; num (string-match "[-+]n\\>" opts)
3849 ;; cont (string-match "\\+n\\>" opts)
3850 ;; rpllbl (string-match "-r\\>" opts)
3851 ;; keepp (string-match "-k\\>" opts)
3852 ;; textareap (string-match "-t\\>" opts)
3853 ;; preserve-indentp (or org-src-preserve-indentation
3854 ;; (string-match "-i\\>" opts))
3855 ;; cols (if (string-match "-w[ \t]+\\([0-9]+\\)" opts)
3856 ;; (string-to-number (match-string 1 opts))
3858 ;; rows (if (string-match "-h[ \t]+\\([0-9]+\\)" opts)
3859 ;; (string-to-number (match-string 1 opts))
3860 ;; (org-count-lines code))
3861 ;; fmt (if (string-match "-l[ \t]+\"\\([^\"\n]+\\)\"" opts)
3862 ;; (match-string 1 opts)))
3863 ;; (when (and textareap
3864 ;; ;; (eq org-export-current-backend 'html)
3866 ;; ;; we cannot use numbering or highlighting.
3867 ;; (setq num nil cont nil lang nil))
3868 ;; (if keepp (setq rpllbl 'keep))
3869 ;; (setq rtn (if preserve-indentp code (org-remove-indentation code)))
3870 ;; (when (string-match "^," rtn)
3871 ;; (setq rtn (with-temp-buffer
3873 ;; ;; Free up the protected lines
3874 ;; (goto-char (point-min))
3875 ;; (while (re-search-forward "^," nil t)
3876 ;; (if (or (equal lang "org")
3878 ;; (looking-at "\\([*#]\\|[ \t]*#\\+\\)")))
3879 ;; (replace-match ""))
3881 ;; (buffer-string))))
3883 ;; (if (featurep 'xemacs)
3884 ;; (require 'htmlize)
3885 ;; (require 'htmlize nil t)))
3887 ;; (setq backend-formatter
3889 ;; ((fboundp 'htmlize-region-for-paste)
3890 ;; 'org-e-odt-format-source-code-or-example-colored)
3893 ;; "htmlize.el 1.34 or later is needed for source code formatting")
3894 ;; 'org-e-odt-format-source-code-or-example-plain)))
3895 ;; (funcall backend-formatter rtn lang caption textareap cols rows
3896 ;; num cont rpllbl fmt))))
3898 (defun org-e-odt-example-block (example-block contents info
)
3899 "Transcode a EXAMPLE-BLOCK element from Org to HTML.
3900 CONTENTS is nil. INFO is a plist holding contextual information."
3901 (let* ((options (or (org-element-property :options example-block
) ""))
3902 (value (org-export-handle-code example-block info
)))
3903 ;; (org-e-odt--wrap-label
3904 ;; example-block (format "\\begin{verbatim}\n%s\\end{verbatim}" value))
3905 (org-e-odt--wrap-label
3906 example-block
(org-e-odt-format-source-code-or-example value nil
))))
3911 (defun org-e-odt-export-snippet (export-snippet contents info
)
3912 "Transcode a EXPORT-SNIPPET object from Org to HTML.
3913 CONTENTS is nil. INFO is a plist holding contextual information."
3914 (org-element-property :value export-snippet
))
3919 (defun org-e-odt-export-block (export-block contents info
)
3920 "Transcode a EXPORT-BLOCK element from Org to HTML.
3921 CONTENTS is nil. INFO is a plist holding contextual information."
3922 (when (string= (org-element-property :type export-block
) "latex")
3923 (org-remove-indentation (org-element-property :value export-block
))))
3928 (defun org-e-odt-fixed-width (fixed-width contents info
)
3929 "Transcode a FIXED-WIDTH element from Org to HTML.
3930 CONTENTS is nil. INFO is a plist holding contextual information."
3931 (let* ((value (org-element-normalize-string
3932 (replace-regexp-in-string
3934 (org-element-property :value fixed-width
)))))
3935 (org-e-odt--wrap-label
3936 fixed-width
(org-e-odt-format-source-code-or-example value nil
))))
3939 ;;;; Footnote Definition
3941 ;; Footnote Definitions are ignored.
3944 ;;;; Footnote Reference
3946 (defun org-e-odt-footnote-def (raw info
) ; FIXME
3947 (if (equal (org-element-type raw
) 'org-data
)
3948 (org-trim (org-export-data raw
'e-odt info
))
3949 (org-odt-format-stylized-paragraph
3950 'footnote
(org-trim (org-export-secondary-string raw
'e-odt info
)))))
3952 (defvar org-e-odt-footnote-separator
3953 (org-e-odt-format-fontify "," 'superscript
))
3955 (defun org-e-odt-footnote-reference (footnote-reference contents info
)
3956 "Transcode a FOOTNOTE-REFERENCE element from Org to HTML.
3957 CONTENTS is nil. INFO is a plist holding contextual information."
3959 ;; Insert separator between two footnotes in a row.
3960 (let ((prev (org-export-get-previous-element footnote-reference info
)))
3961 (when (and (listp prev
) (eq (car prev
) 'footnote-reference
))
3962 org-e-odt-footnote-separator
))
3964 ((not (org-export-footnote-first-reference-p footnote-reference info
))
3965 (let* ((n (org-export-get-footnote-number footnote-reference info
)))
3966 (org-e-odt-format-footnote-reference n
"IGNORED" 100)))
3967 ;; Inline definitions are secondary strings.
3968 ((eq (org-element-property :type footnote-reference
) 'inline
)
3969 (let* ((raw (org-export-get-footnote-definition footnote-reference info
))
3970 (n (org-export-get-footnote-number footnote-reference info
))
3971 (def (org-e-odt-footnote-def raw info
)))
3972 (org-e-odt-format-footnote-reference n def
1)))
3973 ;; Non-inline footnotes definitions are full Org data.
3975 (let* ((raw (org-export-get-footnote-definition footnote-reference info
))
3976 (n (org-export-get-footnote-number footnote-reference info
))
3977 (def (org-e-odt-footnote-def raw info
)))
3978 (org-e-odt-format-footnote-reference n def
1))))))
3983 (defun org-e-odt-todo (todo)
3985 (org-e-odt-format-fontify
3987 "" ; org-e-odt-todo-kwd-class-prefix
3988 (org-e-odt-fix-class-name todo
))
3989 (list (if (member todo org-done-keywords
) "done" "todo")
3992 (defun org-e-odt-headline-text (headline info
&optional formatter
)
3993 "Transcode an HEADLINE element from Org to HTML.
3994 CONTENTS holds the contents of the headline. INFO is a plist
3995 holding contextual information."
3996 (let* ((numberedp (plist-get info
:section-numbers
))
3997 (level (org-export-get-relative-level headline info
))
3998 (todo (and (plist-get info
:with-todo-keywords
)
3999 (let ((todo (org-element-property
4000 :todo-keyword headline
)))
4002 (org-export-secondary-string todo
'e-odt info
)))))
4003 (todo-type (and todo
(org-element-property :todo-type headline
)))
4004 (priority (and (plist-get info
:with-priority
)
4005 (org-element-property :priority headline
)))
4006 (text (org-export-secondary-string
4007 (org-element-property :title headline
) 'e-odt info
))
4008 (tags (and (plist-get info
:with-tags
)
4009 (org-element-property :tags headline
)))
4011 (headline-no (org-export-get-headline-number headline info
))
4013 (format "sec-%s" (mapconcat 'number-to-string headline-no
"-")))
4014 (headline-labels (list headline-label
))
4015 (headline-no (org-export-get-headline-number headline info
))
4016 (section-no (mapconcat 'number-to-string headline-no
"."))
4017 (primary-target (car (last headline-labels
)))
4018 (secondary-targets (butlast headline-labels
))
4020 (formatter (or (and (functionp formatter
) formatter
)
4021 org-e-odt-headline-formatter
)))
4022 (funcall formatter level section-no todo todo-type priority
4023 text tags primary-target secondary-targets extra-class
)))
4025 (defun org-e-odt-headline (headline contents info
)
4026 "Transcode an HEADLINE element from Org to HTML.
4027 CONTENTS holds the contents of the headline. INFO is a plist
4028 holding contextual information."
4029 (let* ((class (plist-get info
:latex-class
))
4030 (numberedp (plist-get info
:section-numbers
))
4031 ;; Get level relative to current parsed data.
4032 (level (org-export-get-relative-level headline info
))
4033 ;; (class-sectionning (assoc class org-e-odt-classes))
4034 ;; Section formatting will set two placeholders: one for the
4035 ;; title and the other for the contents.
4037 ;; (let ((sec (if (and (symbolp (nth 2 class-sectionning))
4038 ;; (fboundp (nth 2 class-sectionning)))
4039 ;; (funcall (nth 2 class-sectionning) level numberedp)
4040 ;; (nth (1+ level) class-sectionning))))
4042 ;; ;; No section available for that LEVEL.
4044 ;; ;; Section format directly returned by a function.
4045 ;; ((stringp sec) sec)
4046 ;; ;; (numbered-section . unnumbered-section)
4047 ;; ((not (consp (cdr sec)))
4048 ;; (concat (funcall (if numberedp #'car #'cdr) sec) "\n%s"))
4049 ;; ;; (numbered-open numbered-close)
4050 ;; ((= (length sec) 2)
4051 ;; (when numberedp (concat (car sec) "\n%s" (nth 1 sec))))
4052 ;; ;; (num-in num-out no-num-in no-num-out)
4053 ;; ((= (length sec) 4)
4055 ;; (concat (car sec) "\n%s" (nth 1 sec))
4056 ;; (concat (nth 2 sec) "\n%s" (nth 3 sec)))))))
4057 (text (org-export-secondary-string
4058 (org-element-property :title headline
) 'e-odt info
))
4059 (todo (and (plist-get info
:with-todo-keywords
)
4060 (let ((todo (org-element-property
4061 :todo-keyword headline
)))
4063 (org-export-secondary-string todo
'e-odt info
)))))
4064 (todo-type (and todo
(org-element-property :todo-type headline
)))
4065 (tags (and (plist-get info
:with-tags
)
4066 (org-element-property :tags headline
)))
4067 (priority (and (plist-get info
:with-priority
)
4068 (org-element-property :priority headline
)))
4069 ;; Create the headline text.
4070 (full-text (if (functionp org-e-odt-format-headline-function
)
4071 ;; User-defined formatting function.
4072 (funcall org-e-odt-format-headline-function
4073 todo todo-type priority text tags
)
4074 ;; Default formatting.
4077 ;; (format "\\textbf{\\textsf{\\textsc{%s}}} " todo))
4078 (org-e-odt-todo todo
) " "
4079 (when priority
(format "\\framebox{\\#%c} " priority
))
4081 ;; (when tags (format "\\hfill{}\\textsc{%s}" tags))
4083 ;; Associate some \label to the headline for internal links.
4085 ;; (format "\\label{sec-%s}\n"
4086 ;; (mapconcat 'number-to-string
4087 ;; (org-export-get-headline-number headline info)
4091 (headline-no (org-export-get-headline-number headline info
))
4093 (format "sec-%s" (mapconcat 'number-to-string headline-no
"-")))
4094 (headline-labels (list headline-label
))
4095 (headline-no (org-export-get-headline-number headline info
))
4096 (section-no (mapconcat 'number-to-string headline-no
"."))
4099 (pre-blanks (make-string
4100 (org-element-property :pre-blank headline
) 10)))
4102 ;; Case 1: This is a footnote section: ignore it.
4103 ((org-element-property :footnote-section-p headline
) nil
)
4104 ;; Case 2. This is a deep sub-tree: export it as a list item.
4105 ;; Also export as items headlines for which no section
4106 ;; format has been found.
4107 ((org-export-low-level-p headline info
) ; FIXME (or (not section-fmt))
4108 ;; Build the real contents of the sub-tree.
4109 (let* ((type (if numberedp
'unordered
'unordered
)) ; FIXME
4110 (itemized-body (org-e-odt-format-list-item
4111 contents type nil nil full-text
)))
4113 (and (org-export-first-sibling-p headline info
)
4114 (org-e-odt-begin-plain-list type
))
4116 (and (org-export-last-sibling-p headline info
)
4117 (org-e-odt-end-plain-list type
)))))
4118 ;; Case 3. Standard headline. Export it as a section.
4120 ;; (format section-fmt full-text
4121 ;; (concat headline-label pre-blanks contents))
4123 (org-e-odt-format-outline contents level section-no full-text tags
4124 (car (last headline-labels
))
4125 (butlast headline-labels
) nil
)))))
4128 ;;;; Horizontal Rule
4130 (defun org-e-odt-horizontal-rule (horizontal-rule contents info
)
4131 "Transcode an HORIZONTAL-RULE object from Org to HTML.
4132 CONTENTS is nil. INFO is a plist holding contextual information."
4133 (let ((attr (mapconcat #'identity
4134 (org-element-property :attr_odt horizontal-rule
)
4136 (org-e-odt--wrap-label horizontal-rule
4137 (org-e-odt-format-horizontal-line))))
4140 ;;;; Inline Babel Call
4142 ;; Inline Babel Calls are ignored.
4145 ;;;; Inline Src Block
4147 (defun org-e-odt-inline-src-block (inline-src-block contents info
)
4148 "Transcode an INLINE-SRC-BLOCK element from Org to HTML.
4149 CONTENTS holds the contents of the item. INFO is a plist holding
4150 contextual information."
4151 (let* ((org-lang (org-element-property :language inline-src-block
))
4152 (code (org-element-property :value inline-src-block
))
4153 (separator (org-e-odt--find-verb-separator code
)))
4159 (defun org-e-odt-format-section (text class
&optional id
)
4160 (let ((extra (concat (when id
(format " id=\"%s\"" id
)))))
4161 (concat (format "<div class=\"%s\"%s>\n" class extra
) text
"</div>\n")))
4163 (defun org-e-odt-inlinetask (inlinetask contents info
)
4164 "Transcode an INLINETASK element from Org to HTML.
4165 CONTENTS holds the contents of the block. INFO is a plist
4166 holding contextual information."
4167 (let ((title (org-export-secondary-string
4168 (org-element-property :title inlinetask
) 'e-odt info
))
4169 (todo (and (plist-get info
:with-todo-keywords
)
4170 (let ((todo (org-element-property
4171 :todo-keyword inlinetask
)))
4173 (org-export-secondary-string todo
'e-odt info
)))))
4174 (todo-type (org-element-property :todo-type inlinetask
))
4175 (tags (and (plist-get info
:with-tags
)
4176 (org-element-property :tags inlinetask
)))
4177 (priority (and (plist-get info
:with-priority
)
4178 (org-element-property :priority inlinetask
))))
4179 ;; If `org-e-odt-format-inlinetask-function' is provided, call it
4180 ;; with appropriate arguments.
4181 (if (functionp org-e-odt-format-inlinetask-function
)
4182 (funcall org-e-odt-format-inlinetask-function
4183 todo todo-type priority title tags contents
)
4184 ;; Otherwise, use a default template.
4185 (org-e-odt--wrap-label
4189 (when todo
(format "\\textbf{\\textsf{\\textsc{%s}}} " todo
))
4190 (when priority
(format "\\framebox{\\#%c} " priority
))
4192 (when tags
(format "\\hfill{}\\textsc{%s}" tags
)))))
4193 (format (concat "\\begin{center}\n"
4195 "\\begin{minipage}[c]{.6\\textwidth}\n"
4197 "\\rule[.8em]{\\textwidth}{2pt}\n\n"
4202 full-title contents
))))))
4207 (defun org-e-odt-format-list-item (contents type checkbox
4208 &optional term-counter-id
4212 (org-e-odt-format-fontify (case checkbox
4215 (trans "[-]")) 'code
)))
4217 (org-e-odt-begin-list-item type term-counter-id headline
)
4218 ;; FIXME checkbox (and checkbox " ")
4220 (org-e-odt-end-list-item type
)))
4222 (defun org-e-odt-item (item contents info
)
4223 "Transcode an ITEM element from Org to HTML.
4224 CONTENTS holds the contents of the item. INFO is a plist holding
4225 contextual information."
4226 ;; Grab `:level' from plain-list properties, which is always the
4227 ;; first element above current item.
4228 (let* ((plain-list (org-export-get-parent item info
))
4229 (type (org-element-property :type plain-list
))
4230 (level (org-element-property :level plain-list
))
4231 (counter (org-element-property :counter item
))
4232 (checkbox (org-element-property :checkbox item
))
4233 (tag (let ((tag (org-element-property :tag item
)))
4234 (and tag
(org-export-secondary-string tag
'e-odt info
)))))
4235 (org-e-odt-format-list-item
4236 contents type checkbox
(or tag counter
))))
4241 (defun org-e-odt-keyword (keyword contents info
)
4242 "Transcode a KEYWORD element from Org to HTML.
4243 CONTENTS is nil. INFO is a plist holding contextual information."
4244 (let ((key (downcase (org-element-property :key keyword
)))
4245 (value (org-element-property :value keyword
)))
4247 ((string= key
"latex") value
)
4248 ((string= key
"index") (format "\\index{%s}" value
))
4249 ((string= key
"target")
4250 (format "\\label{%s}" (org-export-solidify-link-text value
)))
4251 ((string= key
"toc")
4252 (let ((value (downcase value
)))
4254 ((string-match "\\<headlines\\>" value
)
4255 (let ((depth (or (and (string-match "[0-9]+" value
)
4256 (string-to-number (match-string 0 value
)))
4257 (plist-get info
:with-toc
))))
4258 (when (wholenump depth
) (org-e-odt-toc depth info
))))
4259 ((string= "tables" value
) "\\listoftables")
4260 ((string= "figures" value
) "\\listoffigures")
4261 ((string= "listings" value
)
4263 ;; At the moment, src blocks with a caption are wrapped
4264 ;; into a figure environment.
4265 (t "\\listoffigures")))))))))
4268 ;;;; Latex Environment
4270 (defun org-e-odt-format-latex (latex-frag processing-type
)
4271 (let* ((prefix (case processing-type
4273 (mathml "ltxmathml/")))
4275 (concat prefix
(file-name-sans-extension
4276 (file-name-nondirectory (buffer-file-name)))))
4277 (cache-dir (file-name-directory (buffer-file-name )))
4278 (display-msg (case processing-type
4279 (dvipng "Creating LaTeX Image...")
4280 (mathml "Creating MathML snippet..."))))
4283 (org-format-latex cache-relpath cache-dir nil display-msg
4284 nil nil processing-type
)
4287 (defun org-e-odt-latex-environment (latex-environment contents info
)
4288 "Transcode a LATEX-ENVIRONMENT element from Org to HTML.
4289 CONTENTS is nil. INFO is a plist holding contextual information."
4290 (org-e-odt--wrap-label
4293 (org-remove-indentation
4294 (org-element-property :value latex-environment
)))
4295 (processing-type (plist-get info
:LaTeX-fragments
)))
4297 ((member processing-type
'(t mathjax
))
4298 (org-e-odt-format-latex latex-frag
'mathml
))
4299 ((equal processing-type
'dvipng
)
4300 (let* ((formula-link (org-e-odt-format-latex
4301 latex-frag processing-type
)))
4302 (when (and formula-link
4303 (string-match "file:\\([^]]*\\)" formula-link
))
4304 (org-e-odt-format-inline-image (match-string 1 formula-link
)))))
4311 (defun org-e-odt-latex-fragment (latex-fragment contents info
)
4312 "Transcode a LATEX-FRAGMENT object from Org to HTML.
4313 CONTENTS is nil. INFO is a plist holding contextual information."
4314 ;; (org-element-property :value latex-fragment)
4315 (let* ((latex-frag (org-element-property :value latex-fragment
)))
4317 ((string-match "\\\\ref{\\([^{}\n]+\\)}" latex-frag
)
4318 (let* ((label (match-string 1 latex-frag
))
4319 (href (and label
(org-export-solidify-link-text label
)))
4320 (text (if (string-match "\\`[a-z]\\{1,10\\}:\\(.+\\)" label
)
4321 (substring label
(match-beginning 1))
4323 (org-e-odt-format-internal-link text href
)))
4324 (t (let ((processing-type (plist-get info
:LaTeX-fragments
)))
4326 ((member processing-type
'(t mathjax
))
4327 (org-e-odt-format-latex latex-frag
'mathjax
))
4328 ((equal processing-type
'dvipng
)
4329 (let* ((formula-link (org-e-odt-format-latex
4330 latex-frag processing-type
)))
4331 (when (and formula-link
4332 (string-match "file:\\([^]]*\\)" formula-link
))
4333 (org-e-odt-format-inline-image
4334 (match-string 1 formula-link
)))))
4335 (t latex-frag
)))))))
4340 (defun org-e-odt-line-break (line-break contents info
)
4341 "Transcode a LINE-BREAK object from Org to HTML.
4342 CONTENTS is nil. INFO is a plist holding contextual information."
4348 (defun org-e-odt-link--inline-image (link info
)
4349 "Return HTML code for an inline image.
4350 LINK is the link pointing to the inline image. INFO is a plist
4351 used as a communication channel."
4352 (let* ((parent (org-export-get-parent-paragraph link info
))
4353 (path (let ((raw-path (org-element-property :path link
)))
4354 (if (not (file-name-absolute-p raw-path
)) raw-path
4355 (expand-file-name raw-path
))))
4356 (caption (org-e-odt--caption/label-string
4357 (org-element-property :caption parent
)
4358 (org-element-property :name parent
)
4360 (label (org-element-property :name parent
))
4361 ;; Retrieve latex attributes from the element around.
4362 (attr (let ((raw-attr
4363 (mapconcat #'identity
4364 (org-element-property :attr_odt parent
)
4366 (unless (string= raw-attr
"") raw-attr
))))
4367 ;; Now clear ATTR from any special keyword and set a default
4368 ;; value if nothing is left.
4369 (setq attr
(if (not attr
) "" (org-trim attr
)))
4370 ;; Return proper string, depending on DISPOSITION.
4371 (let ((href (and label
(org-export-solidify-link-text label
))))
4372 (org-e-odt-format-inline-image path caption href attr
))))
4374 (defun org-e-odt-link (link desc info
)
4375 "Transcode a LINK object from Org to HTML.
4377 DESC is the description part of the link, or the empty string.
4378 INFO is a plist holding contextual information. See
4380 (let* ((type (org-element-property :type link
))
4381 (raw-path (org-element-property :path link
))
4382 ;; Ensure DESC really exists, or set it to nil.
4383 (desc (and (not (string= desc
"")) desc
))
4384 (imagep (org-export-inline-image-p
4385 link org-e-odt-inline-image-rules
))
4387 ((member type
'("http" "https" "ftp" "mailto"))
4388 (concat type
":" raw-path
))
4389 ((string= type
"file")
4390 (when (string-match "\\(.+\\)::.+" raw-path
)
4391 (setq raw-path
(match-string 1 raw-path
)))
4392 (if (file-name-absolute-p raw-path
)
4393 (concat "file://" (expand-file-name raw-path
))
4394 ;; TODO: Not implemented yet. Concat also:
4395 ;; (org-export-directory :HTML info)
4396 (concat "file://" raw-path
)))
4401 (imagep (org-e-odt-link--inline-image link info
))
4402 ;; Target or radioed target: replace link with the normalized
4403 ;; custom-id/target name.
4404 ((member type
'("target" "radio"))
4405 (org-e-odt-format-internal-link
4406 (or desc
(org-export-secondary-string path
'e-odt info
))
4407 (org-export-solidify-link-text path
)))
4408 ;; Links pointing to an headline: Find destination and build
4409 ;; appropriate referencing commanding.
4410 ((member type
'("custom-id" "fuzzy" "id"))
4411 (let ((destination (if (string= type
"fuzzy")
4412 (org-export-resolve-fuzzy-link link info
)
4413 (org-export-resolve-id-link link info
))))
4414 ;; Fuzzy link points to a target. Do as above.
4415 (case (org-element-type destination
)
4417 (org-e-odt-format-internal-link
4419 (org-export-secondary-string
4420 (org-element-property :raw-link link
)
4422 (org-export-solidify-link-text
4423 (org-element-property :raw-value destination
))))
4424 ;; Fuzzy link points to an headline. If headlines are
4425 ;; numbered and the link has no description, display
4426 ;; headline's number. Otherwise, display description or
4427 ;; headline's title.
4433 (org-export-get-headline-number destination info
)
4435 (if (and (plist-get info
:section-numbers
) (not desc
))
4436 (format "\\ref{%s}" label
)
4437 (org-e-odt-format-internal-link
4439 (org-export-secondary-string
4440 (org-element-property :title destination
)
4441 'e-odt info
)) label
))))
4442 ;; Fuzzy link points nowhere.
4444 (org-e-odt-format-fontify
4446 (org-export-secondary-string
4447 (org-element-property :raw-link link
)
4448 'e-odt info
)) 'emphasis
)))))
4449 ;; Coderef: replace link with the reference name or the
4450 ;; equivalent line number.
4451 ((string= type
"coderef")
4452 (format (org-export-get-coderef-format path
(or desc
""))
4453 (org-export-resolve-coderef path info
)))
4454 ;; Link type is handled by a special function.
4455 ((functionp (setq protocol
(nth 2 (assoc type org-link-protocols
))))
4456 (funcall protocol
(org-link-unescape path
) desc
'html
))
4457 ;; External link with a description part.
4458 ((and path desc
) (org-e-odt-format-link desc path
))
4459 ;; External link without a description part.
4460 (path (org-e-odt-format-link path path
))
4461 ;; No path, only description. Try to do something useful.
4462 (t (org-e-odt-format-fontify desc
'emphasis
)))))
4467 ;; Babel Calls are ignored.
4472 (defun org-e-odt-macro (macro contents info
)
4473 "Transcode a MACRO element from Org to HTML.
4474 CONTENTS is nil. INFO is a plist holding contextual information."
4475 ;; Use available tools.
4476 (org-export-expand-macro macro info
))
4481 (defun org-e-odt-paragraph (paragraph contents info
)
4482 "Transcode a PARAGRAPH element from Org to HTML.
4483 CONTENTS is the contents of the paragraph, as a string. INFO is
4484 the plist used as a communication channel."
4485 (let* ((style nil
) ; FIXME
4486 (class (cdr (assoc style
'((footnote .
"footnote")
4488 (extra (if class
(format " class=\"%s\"" class
) ""))
4489 (parent (car (org-export-get-genealogy paragraph info
))))
4491 ;; ((and (equal (car parent) 'item)
4492 ;; (= (org-element-property :begin paragraph)
4493 ;; (org-element-property :contents-begin parent)))
4494 ;; ;; leading paragraph in a list item have no tags
4496 (t (org-e-odt-format-stylized-paragraph nil contents
)))))
4501 (defun org-e-odt-plain-list (plain-list contents info
)
4502 "Transcode a PLAIN-LIST element from Org to HTML.
4503 CONTENTS is the contents of the list. INFO is a plist holding
4504 contextual information."
4505 (let* (arg1 ;; FIXME
4506 (type (org-element-property :type plain-list
))
4507 (attr (mapconcat #'identity
4508 (org-element-property :attr_odt plain-list
)
4510 (org-e-odt--wrap-label
4511 plain-list
(format "%s\n%s%s"
4512 (org-e-odt-begin-plain-list type
)
4513 contents
(org-e-odt-end-plain-list type
)))))
4517 (defun org-e-odt-convert-special-strings (string)
4518 "Convert special characters in STRING to ODT."
4519 (let ((all org-export-e-odt-special-string-regexps
)
4521 (while (setq a
(pop all
))
4522 (setq re
(car a
) rpl
(cdr a
) start
0)
4523 (while (string-match re string start
)
4524 (setq string
(replace-match rpl t nil string
))))
4527 ;; (defun org-e-odt-encode-plain-text (s)
4528 ;; "Convert plain text characters to HTML equivalent.
4529 ;; Possible conversions are set in `org-export-html-protect-char-alist'."
4530 ;; (let ((cl org-e-odt-protect-char-alist) c)
4531 ;; (while (setq c (pop cl))
4533 ;; (while (string-match (car c) s start)
4534 ;; (setq s (replace-match (cdr c) t t s)
4535 ;; start (1+ (match-beginning 0))))))
4538 (defun org-e-odt-plain-text (text info
)
4539 "Transcode a TEXT string from Org to HTML.
4540 TEXT is the string to transcode. INFO is a plist holding
4541 contextual information."
4542 (setq text
(org-e-odt-encode-plain-text text t
))
4543 ;; Protect %, #, &, $, ~, ^, _, { and }.
4544 ;; (while (string-match "\\([^\\]\\|^\\)\\([%$#&{}~^_]\\)" text)
4546 ;; (replace-match (format "\\%s" (match-string 2 text)) nil t text 2)))
4548 ;; (setq text (replace-regexp-in-string
4549 ;; "\\(?:[^\\]\\|^\\)\\(\\\\\\)\\(?:[^%$#&{}~^_\\]\\|$\\)"
4550 ;; "$\\backslash$" text nil t 1))
4551 ;; HTML into \HTML{} and TeX into \TeX{}.
4552 ;; (let ((case-fold-search nil)
4554 ;; (while (string-match "\\<\\(\\(?:La\\)?TeX\\)\\>" text start)
4555 ;; (setq text (replace-match
4556 ;; (format "\\%s{}" (match-string 1 text)) nil t text)
4557 ;; start (match-end 0))))
4558 ;; Handle quotation marks
4559 ;; (setq text (org-e-odt--quotation-marks text info))
4560 ;; Convert special strings.
4561 ;; (when (plist-get info :with-special-strings)
4562 ;; (while (string-match (regexp-quote "...") text)
4563 ;; (setq text (replace-match "\\ldots{}" nil t text))))
4564 (when (plist-get info
:with-special-strings
)
4565 (setq text
(org-e-odt-convert-special-strings text
)))
4566 ;; Handle break preservation if required.
4567 (when (plist-get info
:preserve-breaks
)
4568 (setq text
(replace-regexp-in-string "\\(\\\\\\\\\\)?[ \t]*\n" " \\\\\\\\\n"
4574 ;;;; Property Drawer
4576 (defun org-e-odt-property-drawer (property-drawer contents info
)
4577 "Transcode a PROPERTY-DRAWER element from Org to HTML.
4578 CONTENTS is nil. INFO is a plist holding contextual
4580 ;; The property drawer isn't exported but we want separating blank
4581 ;; lines nonetheless.
4587 (defun org-e-odt-quote-block (quote-block contents info
)
4588 "Transcode a QUOTE-BLOCK element from Org to HTML.
4589 CONTENTS holds the contents of the block. INFO is a plist
4590 holding contextual information."
4591 (org-e-odt--wrap-label
4592 quote-block
(format "<blockquote>\n%s</blockquote>" contents
)))
4597 (defun org-e-odt-quote-section (quote-section contents info
)
4598 "Transcode a QUOTE-SECTION element from Org to HTML.
4599 CONTENTS is nil. INFO is a plist holding contextual information."
4600 (let ((value (org-remove-indentation
4601 (org-element-property :value quote-section
))))
4602 (when value
(format "<pre>\n%s</pre>" value
))))
4607 (defun org-e-odt-section (section contents info
) ; FIXME
4608 "Transcode a SECTION element from Org to HTML.
4609 CONTENTS holds the contents of the section. INFO is a plist
4610 holding contextual information."
4615 (defun org-e-odt-radio-target (radio-target text info
)
4616 "Transcode a RADIO-TARGET object from Org to HTML.
4617 TEXT is the text of the target. INFO is a plist holding
4618 contextual information."
4619 (org-e-odt-format-anchor
4620 text
(org-export-solidify-link-text
4621 (org-element-property :raw-value radio-target
))))
4626 (defun org-e-odt-special-block (special-block contents info
)
4627 "Transcode a SPECIAL-BLOCK element from Org to HTML.
4628 CONTENTS holds the contents of the block. INFO is a plist
4629 holding contextual information."
4630 (let ((type (downcase (org-element-property :type special-block
))))
4631 (org-e-odt--wrap-label
4633 (format "\\begin{%s}\n%s\\end{%s}" type contents type
))))
4638 (defun org-e-odt-src-block (src-block contents info
)
4639 "Transcode a SRC-BLOCK element from Org to HTML.
4640 CONTENTS holds the contents of the item. INFO is a plist holding
4641 contextual information."
4642 (let* ((lang (org-element-property :language src-block
))
4643 (code (org-export-handle-code src-block info
))
4644 (caption (org-element-property :caption src-block
))
4645 (label (org-element-property :name src-block
)))
4646 ;; FIXME: Handle caption
4648 ;; caption-str (when caption)
4649 ;; (main (org-export-secondary-string (car caption) 'e-odt info))
4650 ;; (secondary (org-export-secondary-string (cdr caption) 'e-odt info))
4651 ;; (caption-str (org-e-odt--caption/label-string caption label info))
4652 (org-e-odt-format-source-code-or-example code lang
)))
4655 ;;;; Statistics Cookie
4657 (defun org-e-odt-statistics-cookie (statistics-cookie contents info
)
4658 "Transcode a STATISTICS-COOKIE object from Org to HTML.
4659 CONTENTS is nil. INFO is a plist holding contextual information."
4660 (let ((cookie-value (org-element-property :value statistics-cookie
)))
4661 (org-e-odt-format-fontify cookie-value
'code
)))
4666 (defun org-e-odt-subscript (subscript contents info
)
4667 "Transcode a SUBSCRIPT object from Org to HTML.
4668 CONTENTS is the contents of the object. INFO is a plist holding
4669 contextual information."
4670 ;; (format (if (= (length contents) 1) "$_%s$" "$_{\\mathrm{%s}}$") contents)
4671 (org-e-odt-format-fontify contents
'subscript
))
4676 (defun org-e-odt-superscript (superscript contents info
)
4677 "Transcode a SUPERSCRIPT object from Org to HTML.
4678 CONTENTS is the contents of the object. INFO is a plist holding
4679 contextual information."
4680 ;; (format (if (= (length contents) 1) "$^%s$" "$^{\\mathrm{%s}}$") contents)
4681 (org-e-odt-format-fontify contents
'superscript
))
4686 ;; (defun org-e-odt-begin-table (caption label attributes)
4687 ;; (let* ((html-table-tag (or (plist-get info :html-table-tag) ; FIXME
4688 ;; org-e-odt-table-tag))
4690 ;; (org-e-odt-splice-attributes html-table-tag attributes)))
4692 ;; (setq html-table-tag
4693 ;; (org-e-odt-splice-attributes
4695 ;; (format "id=\"%s\"" (org-solidify-link-text label)))))
4696 ;; (concat "\n" html-table-tag
4697 ;; (format "\n<caption>%s</caption>" (or caption "")))))
4699 ;; (defun org-e-odt-end-table ()
4702 ;; (defun org-e-odt-format-table-cell (text r c horiz-span)
4703 ;; (let ((cell-style-cookie
4704 ;; (if org-e-odt-table-align-individual-fields
4705 ;; (format (if (and (boundp 'org-e-odt-format-table-no-css)
4706 ;; org-e-odt-format-table-no-css)
4707 ;; " align=\"%s\"" " class=\"%s\"")
4708 ;; (or (aref (plist-get table-info :alignment) c) "left")) ""))) ;; FIXME
4710 ;; (org-e-odt-table-cur-rowgrp-is-hdr
4712 ;; (format (car org-export-table-header-tags) "col" cell-style-cookie)
4713 ;; text (cdr org-export-table-header-tags)))
4714 ;; ((and (= c 0) org-e-odt-table-use-header-tags-for-first-column)
4716 ;; (format (car org-export-table-header-tags) "row" cell-style-cookie)
4717 ;; text (cdr org-export-table-header-tags)))
4720 ;; (format (car org-export-table-data-tags) cell-style-cookie)
4721 ;; text (cdr org-export-table-data-tags))))))
4723 (defun org-e-odt-table-row (fields &optional text-for-empty-fields
)
4724 (incf org-e-odt-table-rownum
)
4726 (org-e-odt-format-table-row
4729 (when (and (string= x
"") text-for-empty-fields
)
4730 (setq x text-for-empty-fields
))
4733 (org-e-odt-format-table-cell
4734 x org-e-odt-table-rownum i
(or horiz-span
0))))
4737 ;; (defun org-e-odt-end-table-rowgroup ()
4738 ;; (when org-e-odt-table-rowgrp-open
4739 ;; (setq org-e-odt-table-rowgrp-open nil)
4740 ;; (if org-e-odt-table-cur-rowgrp-is-hdr "</thead>" "</tbody>")))
4742 ;; (defun org-e-odt-begin-table-rowgroup (&optional is-header-row)
4744 ;; (when org-e-odt-table-rowgrp-open
4745 ;; (org-e-odt-end-table-rowgroup))
4747 ;; (setq org-e-odt-table-rowgrp-open t)
4748 ;; (setq org-e-odt-table-cur-rowgrp-is-hdr is-header-row)
4749 ;; (if is-header-row "<thead>" "<tbody>"))))
4751 (defun org-e-odt-table-preamble ()
4752 (let ((colgroup-vector (plist-get table-info
:column-groups
)) ;; FIXME
4753 c gr colgropen preamble
)
4754 (unless (aref colgroup-vector
0)
4755 (setf (aref colgroup-vector
0) 'start
))
4756 (dotimes (c columns-number preamble
)
4757 (setq gr
(aref colgroup-vector c
))
4761 (when (memq gr
'(start start-end
))
4762 (prog1 (if colgropen
"</colgroup>\n<colgroup>" "\n<colgroup>")
4763 (setq colgropen t
)))
4764 (let* ((colalign-vector (plist-get table-info
:alignment
)) ;; FIXME
4765 (align (cdr (assoc (aref colalign-vector c
)
4768 ("c" .
"center")))))
4769 (alignspec (if (and (boundp 'org-e-odt-format-table-no-css
)
4770 org-e-odt-format-table-no-css
)
4771 " align=\"%s\"" " class=\"%s\""))
4772 (extra (format alignspec align
)))
4773 (format "<col%s />" extra
))
4774 (when (memq gr
'(end start-end
))
4775 (setq colgropen nil
)
4777 (concat preamble
(if colgropen
"</colgroup>"))))
4779 (defun org-e-odt-list-table (lines caption label attributes
)
4780 (setq lines
(org-e-odt-org-table-to-list-table lines
))
4781 (let* ((splice nil
) head
4782 (org-e-odt-table-rownum -
1)
4785 org-e-odt-table-cur-rowgrp-is-hdr
4786 org-e-odt-table-rowgrp-open
4788 (org-lparse-table-style 'org-table
)
4789 org-lparse-table-is-styled
)
4792 (setq org-lparse-table-is-styled nil
)
4793 (mapconcat 'org-e-odt-table-row lines
"\n"))
4795 (setq org-lparse-table-is-styled t
)
4798 (org-e-odt-begin-table caption label attributes
)
4799 ;; FIXME (org-e-odt-table-preamble)
4800 (org-e-odt-begin-table-rowgroup head
)
4805 ((equal line
'hline
) (org-e-odt-begin-table-rowgroup))
4806 (t (org-e-odt-table-row line
))))
4809 (org-e-odt-end-table-rowgroup)
4810 (org-e-odt-end-table))))))
4812 (defun org-e-odt-transcode-table-row (row)
4813 (if (string-match org-table-hline-regexp row
) 'hline
4816 (org-export-secondary-string
4817 (let ((cell (org-element-parse-secondary-string
4819 (cdr (assq 'table org-element-string-restrictions
)))))
4822 (org-split-string row
"[ \t]*|[ \t]*"))))
4824 (defun org-e-odt-org-table-to-list-table (lines &optional splice
)
4825 "Convert org-table to list-table.
4826 LINES is a list of the form (ROW1 ROW2 ROW3 ...) where each
4827 element is a `string' representing a single row of org-table.
4828 Thus each ROW has vertical separators \"|\" separating the table
4829 fields. A ROW could also be a row-group separator of the form
4830 \"|---...|\". Return a list of the form (ROW1 ROW2 ROW3
4831 ...). ROW could either be symbol `'hline' or a list of the
4832 form (FIELD1 FIELD2 FIELD3 ...) as appropriate."
4836 (while (setq line
(pop lines
))
4837 (unless (string-match "^[ \t]*|-" line
)
4838 (push (org-e-odt-transcode-table-row line
) lines-1
))))
4839 (t (while (setq line
(pop lines
))
4841 ((string-match "^[ \t]*|-" line
)
4842 (when lines
(push 'hline lines-1
)))
4843 (t (push (org-e-odt-transcode-table-row line
) lines-1
))))))
4844 (nreverse lines-1
)))
4846 (defun org-e-odt-table-table (raw-table)
4848 (with-current-buffer (get-buffer-create "*org-export-table*")
4850 (let ((output (with-temp-buffer
4853 (re-search-forward "^[ \t]*|[^|]" nil t
)
4854 (table-generate-source 'html
"*org-export-table*")
4855 (with-current-buffer "*org-export-table*"
4856 (org-trim (buffer-string))))))
4857 (kill-buffer (get-buffer "*org-export-table*"))
4860 (defun org-e-odt-table (table contents info
)
4861 "Transcode a TABLE element from Org to HTML.
4862 CONTENTS is nil. INFO is a plist holding contextual information."
4863 (let* ((label (org-element-property :name table
))
4864 (caption (org-e-odt--caption/label-string
4865 (org-element-property :caption table
) label info
))
4866 (attr (mapconcat #'identity
4867 (org-element-property :attr_odt table
)
4869 (raw-table (org-element-property :raw-table table
))
4870 (table-type (org-element-property :type table
)))
4873 ;; (org-e-odt-table-table raw-table)
4876 (let* ((table-info (org-export-table-format-info raw-table
))
4877 (columns-number (length (plist-get table-info
:alignment
)))
4878 (lines (org-split-string
4879 (org-export-clean-table
4880 raw-table
(plist-get table-info
:special-column-p
)) "\n")))
4881 (org-e-odt-list-table lines caption label attr
))))))
4886 (defun org-e-odt-target (target text info
)
4887 "Transcode a TARGET object from Org to HTML.
4888 TEXT is the text of the target. INFO is a plist holding
4889 contextual information."
4890 (org-e-odt-format-anchor
4891 text
(org-export-solidify-link-text
4892 (org-element-property :raw-value target
))))
4897 (defun org-e-odt-time-stamp (time-stamp contents info
)
4898 "Transcode a TIME-STAMP object from Org to HTML.
4899 CONTENTS is nil. INFO is a plist holding contextual
4901 ;; (let ((value (org-element-property :value time-stamp))
4902 ;; (type (org-element-property :type time-stamp))
4903 ;; (appt-type (org-element-property :appt-type time-stamp)))
4904 ;; (concat (cond ((eq appt-type 'scheduled)
4905 ;; (format "\\textbf{\\textsc{%s}} " org-scheduled-string))
4906 ;; ((eq appt-type 'deadline)
4907 ;; (format "\\textbf{\\textsc{%s}} " org-deadline-string))
4908 ;; ((eq appt-type 'closed)
4909 ;; (format "\\textbf{\\textsc{%s}} " org-closed-string)))
4910 ;; (cond ((memq type '(active active-range))
4911 ;; (format org-e-odt-active-timestamp-format value))
4912 ;; ((memq type '(inactive inactive-range))
4913 ;; (format org-e-odt-inactive-timestamp-format value))
4915 ;; (format org-e-odt-diary-timestamp-format value)))))
4916 (let ((value (org-element-property :value time-stamp
))
4917 (type (org-element-property :type time-stamp
))
4918 (appt-type (org-element-property :appt-type time-stamp
)))
4919 (setq value
(org-export-secondary-string value
'e-odt info
))
4920 (org-e-odt-format-fontify
4922 (org-e-odt-format-fontify
4923 (cond ((eq appt-type
'scheduled
) org-scheduled-string
)
4924 ((eq appt-type
'deadline
) org-deadline-string
)
4925 ((eq appt-type
'closed
) org-closed-string
)) "timestamp-kwd")
4926 ;; FIXME: (org-translate-time value)
4927 (org-e-odt-format-fontify value
"timestamp"))
4928 "timestamp-wrapper")))
4933 (defun org-e-odt-verbatim (verbatim contents info
)
4934 "Transcode a VERBATIM object from Org to HTML.
4935 CONTENTS is nil. INFO is a plist used as a communication
4938 verbatim
(org-element-property :value verbatim
) info
))
4943 (defun org-e-odt-verse-block (verse-block contents info
)
4944 "Transcode a VERSE-BLOCK element from Org to HTML.
4945 CONTENTS is nil. INFO is a plist holding contextual information."
4946 ;; Replace each newline character with line break. Also replace
4947 ;; each blank line with a line break.
4948 (setq contents
(replace-regexp-in-string
4949 "^ *\\\\\\\\$" "<br/>\n"
4950 (replace-regexp-in-string
4951 "\\(\\\\\\\\\\)?[ \t]*\n" " <br/>\n"
4952 (org-remove-indentation
4953 (org-export-secondary-string
4954 (org-element-property :value verse-block
)
4957 ;; Replace each white space at beginning of a line with a
4958 ;; non-breaking space.
4959 (while (string-match "^[ \t]+" contents
)
4960 (let ((new-str (org-e-odt-format-spaces
4961 (length (match-string 0 contents
)))))
4962 (setq contents
(replace-match new-str nil t contents
))))
4964 (org-e-odt--wrap-label
4965 verse-block
(format "<p class=\"verse\">\n%s</p>" contents
)))
4970 ;;; Filter Functions
4972 ;;;; Filter Settings
4974 (defconst org-e-odt-filters-alist
4975 '((:filter-final-output . org-e-odt-final-function
))
4976 "Alist between filters keywords and back-end specific filters.
4977 See `org-export-filters-alist' for more information.")
4982 (defun org-e-odt-final-function (contents backend info
)
4983 (if (not org-export-e-odt-prettify-xml
) contents
4987 (indent-region (point-min) (point-max))
4988 (buffer-substring-no-properties (point-min) (point-max)))))
4991 ;;; Interactive functions
4993 (defun org-e-odt-export-to-odt
4994 (&optional subtreep visible-only body-only ext-plist pub-dir
)
4995 "Export current buffer to a HTML file.
4997 If narrowing is active in the current buffer, only export its
5000 If a region is active, export that region.
5002 When optional argument SUBTREEP is non-nil, export the sub-tree
5003 at point, extracting information from the headline properties
5006 When optional argument VISIBLE-ONLY is non-nil, don't export
5007 contents of hidden elements.
5009 When optional argument BODY-ONLY is non-nil, only write code
5010 between \"\\begin{document}\" and \"\\end{document}\".
5012 EXT-PLIST, when provided, is a property list with external
5013 parameters overriding Org default settings, but still inferior to
5014 file-local settings.
5016 When optional argument PUB-DIR is set, use it as the publishing
5019 Return output file's name."
5023 (with-current-buffer (get-buffer-create "*debug*")
5026 ;; (let* ((outfile (org-export-output-file-name ".html" subtreep pub-dir))
5027 ;; (outfile "content.xml"))
5028 ;; (org-export-to-file
5029 ;; 'e-odt outfile subtreep visible-only body-only ext-plist))
5031 (let* ((outbuf (org-e-odt-init-outfile))
5032 (target (org-export-output-file-name ".odt" subtreep pub-dir
))
5033 (outdir (file-name-directory (buffer-file-name outbuf
)))
5034 (default-directory outdir
))
5036 ;; FIXME: for copying embedded images
5037 (setq org-current-export-file
5038 (file-name-directory
5039 (org-export-output-file-name ".odt" subtreep nil
)))
5041 (org-export-to-buffer
5043 (memq 'subtree optns
) (memq 'visible optns
) (memq 'body optns
))
5045 (setq org-lparse-opt-plist nil
) ; FIXME
5046 (org-e-odt-save-as-outfile target
;; info
5056 ;;; FIXMES, TODOS, FOR REVIEW etc
5058 ;;;; org-format-table-html
5059 ;;;; org-format-org-table-html
5060 ;;;; org-format-table-table-html
5061 ;;;; org-table-number-fraction
5062 ;;;; org-table-number-regexp
5063 ;;;; org-e-odt-table-caption-above
5066 ;;;; "<span style=\"visibility:hidden;\">%s</span>"
5067 ;;;; Remove display properties
5068 ;;;; org-e-odt-final-hook
5070 ;;;; org-e-odt-with-timestamp
5071 ;;;; org-e-odt-html-helper-timestamp
5073 ;;;; org-export-as-html-and-open
5074 ;;;; org-export-as-html-batch
5075 ;;;; org-export-as-html-to-buffer
5076 ;;;; org-replace-region-by-html
5077 ;;;; org-export-region-as-html
5078 ;;;; org-export-as-html
5080 ;;;; (org-export-directory :html opt-plist)
5081 ;;;; (plist-get opt-plist :html-extension)
5082 ;;;; org-e-odt-toplevel-hlevel
5083 ;;;; org-e-odt-special-string-regexps
5084 ;;;; org-e-odt-coding-system
5085 ;;;; org-e-odt-coding-system
5086 ;;;; org-e-odt-inline-images
5087 ;;;; org-e-odt-inline-image-extensions
5088 ;;;; org-e-odt-protect-char-alist
5089 ;;;; org-e-odt-table-use-header-tags-for-first-column
5090 ;;;; org-e-odt-todo-kwd-class-prefix
5091 ;;;; org-e-odt-tag-class-prefix
5092 ;;;; org-e-odt-footnote-separator
5095 ;;; Library Initializations
5099 ;; Let Org open all OpenDocument files using system-registered app
5100 (add-to-list 'org-file-apps
5101 (cons (concat "\\." (car desc
) "\\'") 'system
))
5102 ;; Let Emacs open all OpenDocument files in archive mode
5103 (add-to-list 'auto-mode-alist
5104 (cons (concat "\\." (car desc
) "\\'") 'archive-mode
)))
5105 org-e-odt-file-extensions
)
5107 ;; register the odt exporter with the pre-processor
5108 (add-to-list 'org-export-backends
'odt
)
5110 ;; register the odt exporter with org-lparse library
5111 (org-lparse-register-backend 'odt
)
5113 (eval-after-load 'org-exp
5114 '(add-to-list 'org-export-inbuffer-options-extra
5115 '("ODT_STYLES_FILE" :odt-styles-file
)))
5117 (provide 'org-e-odt
)
5119 ;;; org-e-odt.el ends here