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/>.
30 (defgroup org-export-e-odt nil
31 "Options specific for ODT export of Org-mode files."
37 ;; org-export-preprocess-after-blockquote-hook
38 ;; org-e-odt-preprocess-latex-fragments
39 ;; org-export-as-e-odt-and-open
40 ;; org-export-as-e-odt-batch
41 ;; org-export-as-e-odt
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-e-odt-org-styles-alist
))))
48 (cdr (assoc entity
(cdr (assoc category
49 org-e-odt-default-org-styles-alist
))))
50 (error "Cannot determine style name for entity %s of type %s"
54 ;; Following variable is let bound when `org-do-lparse' is in
55 ;; progress. See org-html.el.
57 (defun org-e-odt-format-preamble (info)
58 (let* ((title (org-export-secondary-string
59 (plist-get info
:title
) 'e-odt info
))
60 (author (and (plist-get info
:with-author
)
61 (let ((auth (plist-get info
:author
)))
62 (and auth
(org-export-secondary-string
64 (date (plist-get info
:date
))
65 (iso-date (org-e-odt-format-date date
))
66 (date (org-e-odt-format-date date
"%d %b %Y"))
67 (email (plist-get info
:email
))
68 ;; switch on or off above vars based on user settings
69 (author (and (plist-get info
:with-author
) (or author email
)))
70 ;; (date (and (plist-get info :time-stamp-file) date))
71 (email (and (plist-get info
:with-email
) email
)))
76 (org-e-odt-format-stylized-paragraph
77 'title
(format "\n<text:title>%s</text:title>" title
))
79 "\n<text:p text:style-name=\"OrgTitle\"/>"))
81 ((and author
(not email
))
84 (org-e-odt-format-stylized-paragraph
86 (format "<text:initial-creator>%s</text:initial-creator>" author
))
88 "\n<text:p text:style-name=\"OrgSubtitle\"/>"))
92 (org-e-odt-format-stylized-paragraph
94 (org-e-odt-format-link
95 (format "<text:initial-creator>%s</text:initial-creator>" author
)
96 (concat "mailto:" email
)))
98 "\n<text:p text:style-name=\"OrgSubtitle\"/>")))
102 (org-e-odt-format-stylized-paragraph
105 '("<text:date style:data-style-name=\"%s\" text:date-value=\"%s\">"
107 date
"N75" iso-date
))
109 "<text:p text:style-name=\"OrgSubtitle\"/>")))))
111 (defun org-e-odt-begin-section (style &optional name
)
112 (let ((default-name (car (org-e-odt-add-automatic-style "Section"))))
113 (format "<text:section text:style-name=\"%s\" text:name=\"%s\">"
114 style
(or name default-name
))))
116 (defun org-e-odt-end-section ()
119 (defun org-e-odt-begin-paragraph (&optional style
)
120 (format "<text:p%s>" (org-e-odt-get-extra-attrs-for-paragraph-style style
)))
122 (defun org-e-odt-end-paragraph ()
125 (defun org-e-odt-get-extra-attrs-for-paragraph-style (style)
129 ((stringp style
) style
)
130 ((symbolp style
) (org-e-odt-get-style-name-for-entity
133 (error "Don't know how to handle paragraph style %s" style
))
134 (format " text:style-name=\"%s\"" style-name
)))
136 (defun org-e-odt-format-stylized-paragraph (style text
)
137 (format "\n<text:p%s>%s</text:p>"
138 (org-e-odt-get-extra-attrs-for-paragraph-style style
)
141 (defun org-e-odt-format-author (&optional author
)
142 (when (setq author
(or author
(plist-get org-lparse-opt-plist
:author
)))
143 (format "<dc:creator>%s</dc:creator>" author
)))
145 (defun org-e-odt-format-date (&optional org-ts fmt
)
148 (and (stringp org-ts
)
149 (string-match org-ts-regexp0 org-ts
)
151 (org-fix-decoded-time
152 (org-parse-time-string (match-string 0 org-ts
) t
)))))
155 (fmt (format-time-string fmt time
))
156 (t (setq date
(format-time-string "%Y-%m-%dT%H:%M:%S%z" time
))
157 (format "%s:%s" (substring date
0 -
2) (substring date -
2)))))))
159 (defun org-e-odt-begin-annotation (&optional author date
)
161 "<office:annotation>\n"
162 (and author
(org-e-odt-format-author author
))
163 (org-e-odt-format-tags
164 '("<dc:date>" .
"</dc:date>")
165 (org-e-odt-format-date
166 (or date
(plist-get org-lparse-opt-plist
:date
))))
167 (org-e-odt-begin-paragraph)))
169 (defun org-e-odt-end-annotation ()
170 "</office:annotation>")
172 (defun org-e-odt-begin-plain-list (ltype)
173 (let* ((style-name (org-e-odt-get-style-name-for-entity 'list ltype
))
175 ;; (if (or org-lparse-list-table-p
176 ;; (and (= 1 (length org-lparse-list-stack))
177 ;; (null org-e-odt-list-stack-stashed)))
178 ;; " text:continue-numbering=\"false\""
179 ;; " text:continue-numbering=\"true\"")
181 " text:continue-numbering=\"true\""
184 (format " text:style-name=\"%s\"" style-name
)))))
186 ((ordered unordered descriptive
)
188 ;; (org-e-odt-end-paragraph)
189 (format "<text:list%s>" extra
)))
190 (t (error "Unknown list type: %s" ltype
)))))
192 (defun org-e-odt-end-plain-list (ltype)
193 (if ltype
"</text:list>"
194 (error "Unknown list type: %s" ltype
)))
196 (defun org-e-odt-begin-list-item (ltype &optional arg headline
)
199 (assert (not headline
) t
)
200 (let* ((counter arg
) (extra ""))
201 (concat "<text:list-item>" ;; (org-e-odt-begin-paragraph)
203 ;; (if (= (length org-lparse-list-stack)
204 ;; (length org-e-odt-list-stack-stashed))
205 ;; "<text:list-header>" "<text:list-item>")
208 (let* ((id arg
) (extra ""))
211 ;; (org-e-odt-begin-paragraph)
212 (if headline
(org-e-odt-format-target headline id
)
213 (org-e-odt-format-bookmark "" id
)))
214 ;; (if (= (length org-lparse-list-stack)
215 ;; (length org-e-odt-list-stack-stashed))
216 ;; "<text:list-header>" "<text:list-item>")
219 (assert (not headline
) t
)
220 (let ((term (or arg
"(no term)")))
222 (org-e-odt-format-tags
223 '("<text:list-item>" .
"</text:list-item>")
224 (org-e-odt-format-stylized-paragraph 'definition-term term
))
225 (org-e-odt-begin-list-item 'unordered
)
226 (org-e-odt-begin-plain-list 'descriptive
)
227 (org-e-odt-begin-list-item 'unordered
))))
228 (t (error "Unknown list type"))))
230 (defun org-e-odt-end-list-item (ltype)
233 ;; (org-lparse-insert-tag
234 ;; (if (= (length org-lparse-list-stack)
235 ;; (length org-e-odt-list-stack-stashed))
236 ;; (prog1 "</text:list-header>"
237 ;; (setq org-e-odt-list-stack-stashed nil))
238 ;; "</text:list-item>")
244 (org-e-odt-end-list-item 'unordered
)
245 (org-e-odt-end-plain-list 'descriptive
)
246 (org-e-odt-end-list-item 'unordered
)
248 (t (error "Unknown list type"))))
250 (defun org-e-odt-discontinue-list ()
251 (let ((stashed-stack org-lparse-list-stack
))
252 (loop for list-type in stashed-stack
253 do
(org-lparse-end-list-item-1 list-type
)
254 (org-lparse-end-list list-type
))
255 (setq org-e-odt-list-stack-stashed stashed-stack
)))
257 (defun org-e-odt-continue-list ()
258 (setq org-e-odt-list-stack-stashed
(nreverse org-e-odt-list-stack-stashed
))
259 (loop for list-type in org-e-odt-list-stack-stashed
260 do
(org-lparse-begin-list list-type
)
261 (org-lparse-begin-list-item list-type
)))
263 (defun org-e-odt-write-automatic-styles ()
264 "Write automatic styles to \"content.xml\"."
266 (find-file-noselect (expand-file-name "content.xml") t
)
267 ;; position the cursor
268 (goto-char (point-min))
269 (re-search-forward " </office:automatic-styles>" nil t
)
270 (goto-char (match-beginning 0))
271 ;; write automatic table styles
272 (loop for
(style-name props
) in
273 (plist-get org-e-odt-automatic-styles
'Table
) do
274 (when (setq props
(or (plist-get props
:rel-width
) 96))
275 (insert (format org-e-odt-table-style-format style-name props
))))))
277 (defun org-e-odt-add-automatic-style (object-type &optional object-props
)
278 "Create an automatic style of type OBJECT-TYPE with param OBJECT-PROPS.
279 OBJECT-PROPS is (typically) a plist created by passing
280 \"#+ATTR_ODT: \" option of the object in question to
281 `org-e-odt-parse-block-attributes'.
283 Use `org-e-odt-object-counters' to generate an automatic
284 OBJECT-NAME and STYLE-NAME. If OBJECT-PROPS is non-nil, add a
285 new entry in `org-e-odt-automatic-styles'. Return (OBJECT-NAME
287 (assert (stringp object-type
))
288 (let* ((object (intern object-type
))
290 (seqno (1+ (or (plist-get org-e-odt-object-counters seqvar
) 0)))
291 (object-name (format "%s%d" object-type seqno
)) style-name
)
292 (setq org-e-odt-object-counters
293 (plist-put org-e-odt-object-counters seqvar seqno
))
295 (setq style-name
(format "Org%s" object-name
))
296 (setq org-e-odt-automatic-styles
297 (plist-put org-e-odt-automatic-styles object
298 (append (list (list style-name object-props
))
299 (plist-get org-e-odt-automatic-styles object
)))))
300 (cons object-name style-name
)))
302 (defun org-e-odt-format-table-columns ()
303 (let* ((num-cols (length (plist-get table-info
:alignment
)))
304 (col-nos (loop for i from
0 below num-cols collect i
))
306 (col-widths (plist-get table-info
:width
))
307 (style (or (nth 1 org-e-odt-table-style-spec
) "OrgTable")))
310 (let* ((width (or (and org-lparse-table-is-styled
(aref col-widths c
))
312 (org-e-odt-make-string
314 (org-e-odt-format-tags
315 "<table:table-column table:style-name=\"%sColumn\"/>" "" style
))))
319 (defun org-e-odt-begin-table (caption label attributes
)
320 ;; (setq org-e-odt-table-indentedp (not (null org-lparse-list-stack)))
321 (setq org-e-odt-table-indentedp nil
) ; FIXME
322 (when org-e-odt-table-indentedp
323 ;; Within the Org file, the table is appearing within a list item.
324 ;; OpenDocument doesn't allow table to appear within list items.
325 ;; Temporarily terminate the list, emit the table and then
326 ;; re-continue the list.
327 (org-e-odt-discontinue-list)
328 ;; Put the Table in an indented section.
329 (let ((level (length org-e-odt-list-stack-stashed
)))
330 (org-e-odt-begin-section (format "OrgIndentedSection-Level-%d" level
))))
331 (setq attributes
(org-e-odt-parse-block-attributes attributes
))
332 (setq org-e-odt-table-style
(plist-get attributes
:style
))
333 (setq org-e-odt-table-style-spec
334 (assoc org-e-odt-table-style org-e-odt-table-styles
))
336 (org-e-odt-format-stylized-paragraph
337 'table
(org-e-odt-format-entity-caption label caption
"__Table__"))
338 (let ((name-and-style (org-e-odt-add-automatic-style "Table" attributes
)))
340 "\n<table:table table:name=\"%s\" table:style-name=\"%s\">\n"
341 (car name-and-style
) (or (nth 1 org-e-odt-table-style-spec
)
342 (cdr name-and-style
) "OrgTable")))
343 (org-e-odt-format-table-columns) "\n")
345 ;; (org-e-html-pp table-info)
349 (defun org-e-odt-end-table ()
352 ;; (when org-e-odt-table-indentedp
353 ;; (org-e-odt-end-section)
354 ;; (org-e-odt-continue-list))
357 (defun org-e-odt-begin-table-rowgroup (&optional is-header-row
)
359 (concat (when org-e-odt-table-rowgrp-open
360 (org-e-odt-end-table-rowgroup))
361 (if is-header-row
"<table:table-header-rows>"
362 "<table:table-rows>"))
363 (setq org-e-odt-table-rowgrp-open t
)
364 (setq org-e-odt-table-cur-rowgrp-is-hdr is-header-row
)))
366 (defun org-e-odt-end-table-rowgroup ()
367 (when org-e-odt-table-rowgrp-open
368 (setq org-e-odt-table-rowgrp-open nil
)
369 (if org-e-odt-table-cur-rowgrp-is-hdr
370 "</table:table-header-rows>" "</table:table-rows>")))
372 (defun org-e-odt-format-table-row (row)
373 (org-e-odt-format-tags
374 '("<table:table-row>" .
"</table:table-row>") row
))
376 (defun org-e-odt-get-column-alignment (c)
377 (let ((colalign-vector (plist-get table-info
:alignment
)))
379 (assoc-default (aref colalign-vector c
)
384 (defun org-e-odt-get-table-cell-styles (r c
&optional style-spec
)
385 "Retrieve styles applicable to a table cell.
386 R and C are (zero-based) row and column numbers of the table
387 cell. STYLE-SPEC is an entry in `org-e-odt-table-styles'
388 applicable to the current table. It is `nil' if the table is not
389 associated with any style attributes.
391 Return a cons of (TABLE-CELL-STYLE-NAME . PARAGRAPH-STYLE-NAME).
393 When STYLE-SPEC is nil, style the table cell the conventional way
394 - choose cell borders based on row and column groupings and
395 choose paragraph alignment based on `org-col-cookies' text
397 `org-e-odt-get-paragraph-style-cookie-for-table-cell'.
399 When STYLE-SPEC is non-nil, ignore the above cookie and return
400 styles congruent with the ODF-1.2 specification."
404 ;; LibreOffice - particularly the Writer - honors neither table
405 ;; templates nor custom table-cell styles. Inorder to retain
406 ;; inter-operability with LibreOffice, only automatic styles are
407 ;; used for styling of table-cells. The current implementation is
408 ;; congruent with ODF-1.2 specification and hence is
409 ;; future-compatible.
411 ;; Additional Note: LibreOffice's AutoFormat facility for tables -
412 ;; which recognizes as many as 16 different cell types - is much
413 ;; richer. Unfortunately it is NOT amenable to easy configuration
416 (let* ((template-name (nth 1 style-spec
))
417 (cell-style-selectors (nth 2 style-spec
))
420 ((and (cdr (assoc 'use-first-column-styles cell-style-selectors
))
421 (= c
0)) "FirstColumn")
422 ((and (cdr (assoc 'use-last-column-styles cell-style-selectors
))
423 (= c
(1- org-lparse-table-ncols
))) "LastColumn")
424 ((and (cdr (assoc 'use-first-row-styles cell-style-selectors
))
426 ((and (cdr (assoc 'use-last-row-styles cell-style-selectors
))
427 (= r org-e-odt-table-rownum
))
429 ((and (cdr (assoc 'use-banding-rows-styles cell-style-selectors
))
430 (= (% r
2) 1)) "EvenRow")
431 ((and (cdr (assoc 'use-banding-rows-styles cell-style-selectors
))
432 (= (% r
2) 0)) "OddRow")
433 ((and (cdr (assoc 'use-banding-columns-styles cell-style-selectors
))
434 (= (% c
2) 1)) "EvenColumn")
435 ((and (cdr (assoc 'use-banding-columns-styles cell-style-selectors
))
436 (= (% c
2) 0)) "OddColumn")
439 (concat template-name cell-type
"TableCell")
440 (concat template-name cell-type
"TableParagraph"))))
447 ((eq (cdr (assoc r nil
;; org-lparse-table-rowgrp-info FIXME
450 (when (= r org-e-odt-table-rownum
) "B")
453 ((or (memq (nth c org-table-colgroup-info
) '(:start
:startend
))
454 (memq (nth (1- c
) org-table-colgroup-info
) '(:end
:startend
))) "L")
456 (capitalize (org-e-odt-get-column-alignment c
))))))
458 (defun org-e-odt-get-paragraph-style-cookie-for-table-cell (r c
)
460 (and (not org-e-odt-table-style-spec
)
462 (org-e-odt-table-cur-rowgrp-is-hdr "OrgTableHeading")
464 ;; (org-lparse-get 'TABLE-FIRST-COLUMN-AS-LABELS)
467 (t "OrgTableContents")))
468 (and org-lparse-table-is-styled
469 (cdr (org-e-odt-get-table-cell-styles
470 r c org-e-odt-table-style-spec
)))))
472 (defun org-e-odt-get-style-name-cookie-for-table-cell (r c
)
473 (when org-lparse-table-is-styled
474 (let* ((cell-styles (org-e-odt-get-table-cell-styles
475 r c org-e-odt-table-style-spec
))
476 (table-cell-style (car cell-styles
)))
479 (defun org-e-odt-format-table-cell (data r c horiz-span
)
481 (let* ((paragraph-style-cookie
482 (org-e-odt-get-paragraph-style-cookie-for-table-cell r c
))
484 (org-e-odt-get-style-name-cookie-for-table-cell r c
))
485 (extra (and style-name-cookie
486 (format " table:style-name=\"%s\"" style-name-cookie
)))
488 (and (> horiz-span
0)
489 (format " table:number-columns-spanned=\"%d\""
491 (org-e-odt-format-tags
492 '("<table:table-cell%s>" .
"</table:table-cell>")
493 (if org-lparse-list-table-p data
494 (org-e-odt-format-stylized-paragraph paragraph-style-cookie data
)) extra
))
496 (dotimes (i horiz-span
)
497 (setq s
(concat s
"\n<table:covered-table-cell/>"))) s
)
500 (defun org-e-odt-begin-toc (lang-specific-heading max-level
)
503 <text:table-of-content text:style-name=\"Sect2\" text:protected=\"true\" text:name=\"Table of Contents1\">
504 <text:table-of-content-source text:outline-level=\"%d\">
505 <text:index-title-template text:style-name=\"Contents_20_Heading\">%s</text:index-title-template>
506 " max-level lang-specific-heading
)
508 (let ((entry-templates ""))
509 (loop for level from
1 upto
10
510 do
(setq entry-templates
511 (concat entry-templates
514 <text:table-of-content-entry-template text:outline-level=\"%d\" text:style-name=\"Contents_20_%d\">
515 <text:index-entry-link-start text:style-name=\"Internet_20_link\"/>
516 <text:index-entry-chapter/>
517 <text:index-entry-text/>
518 <text:index-entry-link-end/>
519 </text:table-of-content-entry-template>
524 </text:table-of-content-source>
527 <text:index-title text:style-name=\"Sect1\" text:name=\"Table of Contents1_Head\">
528 <text:p text:style-name=\"Contents_20_Heading\">%s</text:p>
530 " lang-specific-heading
)))
532 (defun org-e-odt-end-toc ()
535 </text:table-of-content>
538 (defun org-e-odt-format-toc-entry (snumber todo headline tags href
)
541 (setq headline
(concat
542 (and org-export-with-section-numbers
543 (concat snumber
". "))
547 (org-e-odt-format-spaces 3)
548 (org-e-odt-format-fontify tags
"tag")))))
550 (setq headline
(org-e-odt-format-fontify headline
"todo")))
552 (let ((org-e-odt-suppress-xref t
))
553 (org-e-odt-format-link headline
(concat "#" href
))))
555 (defun org-e-odt-format-toc-item (toc-entry level org-last-level
)
556 (let ((style (format "Contents_20_%d"
557 (+ level
(or ;; (org-lparse-get 'TOPLEVEL-HLEVEL)
560 (concat "\n" (org-e-odt-format-stylized-paragraph style toc-entry
) "\n")))
562 ;; Following variable is let bound during 'ORG-LINK callback. See
565 (defun org-e-odt-format-link (desc href
&optional attr
)
567 ((and (= (string-to-char href
) ?
#) (not org-e-odt-suppress-xref
))
568 (setq href
(substring href
1))
569 (let ((xref-format "text"))
571 (setq desc
(format "%d" desc
) xref-format
"number"))
573 (setq desc
(mapconcat 'identity desc
".") xref-format
"chapter"))
574 (setq href
(concat org-e-odt-bookmark-prefix href
))
575 (org-e-odt-format-tags-simple
576 '("<text:bookmark-ref text:reference-format=\"%s\" text:ref-name=\"%s\">" .
577 "</text:bookmark-ref>")
578 desc xref-format href
)))
579 (org-lparse-link-description-is-image
580 (org-e-odt-format-tags
581 '("<draw:a xlink:type=\"simple\" xlink:href=\"%s\" %s>" .
"</draw:a>")
582 desc href
(or attr
"")))
584 (org-e-odt-format-tags-simple
585 '("<text:a xlink:type=\"simple\" xlink:href=\"%s\" %s>" .
"</text:a>")
586 desc href
(or attr
"")))))
588 (defun org-e-odt-format-spaces (n)
592 " " (org-e-odt-format-tags "<text:s text:c=\"%d\"/>" "" (1- n
))))
595 (defun org-e-odt-format-tabs (&optional n
)
596 (let ((tab "<text:tab/>")
600 (defun org-e-odt-format-line-break ()
601 (org-e-odt-format-tags "<text:line-break/>" ""))
603 (defun org-e-odt-format-horizontal-line ()
604 (org-e-odt-format-stylized-paragraph 'horizontal-line
""))
606 (defun org-e-odt-encode-plain-text (line &optional no-whitespace-filling
)
607 (setq line
(org-e-html-encode-plain-text line
))
608 (if no-whitespace-filling line
609 (org-e-odt-fill-tabs-and-spaces line
)))
611 (defun org-e-odt-format-line (line)
612 (case org-lparse-dyn-current-environment
614 (org-e-odt-format-stylized-paragraph
615 'fixedwidth
(org-e-odt-encode-plain-text line
)) "\n"))
616 (t (concat line
"\n"))))
618 (defun org-e-odt-format-comment (fmt &rest args
)
619 (let ((comment (apply 'format fmt args
)))
620 (format "\n<!-- %s -->\n" comment
)))
622 (defun org-e-odt-format-org-entity (wd)
623 (org-entity-get-representation wd
'utf8
))
625 (defun org-e-odt-fill-tabs-and-spaces (line)
626 (replace-regexp-in-string
627 "\\([\t]\\|\\([ ]+\\)\\)" (lambda (s)
629 ((string= s
"\t") (org-e-odt-format-tabs))
630 (t (org-e-odt-format-spaces (length s
))))) line
))
632 (defun org-e-odt-hfy-face-to-css (fn)
633 "Create custom style for face FN.
634 When FN is the default face, use it's foreground and background
635 properties to create \"OrgSrcBlock\" paragraph style. Otherwise
636 use it's color attribute to create a character style whose name
637 is obtained from FN. Currently all attributes of FN other than
640 The style name for a face FN is derived using the following
641 operations on the face name in that order - de-dash, CamelCase
642 and prefix with \"OrgSrc\". For example,
643 `font-lock-function-name-face' is associated with
644 \"OrgSrcFontLockFunctionNameFace\"."
645 (let* ((css-list (hfy-face-to-style fn
))
646 (style-name ((lambda (fn)
649 'capitalize
(split-string
650 (hfy-face-or-def-to-name fn
) "-")
652 (color-val (cdr (assoc "color" css-list
)))
653 (background-color-val (cdr (assoc "background" css-list
)))
654 (style (and org-e-odt-create-custom-styles-for-srcblocks
657 (format org-src-block-paragraph-format
658 background-color-val color-val
))
662 <style:style style:name=\"%s\" style:family=\"text\">
663 <style:text-properties fo:color=\"%s\"/>
664 </style:style>" style-name color-val
))))))
665 (cons style-name style
)))
667 (defun org-e-odt-insert-custom-styles-for-srcblocks (styles)
668 "Save STYLES used for colorizing of source blocks.
669 Update styles.xml with styles that were collected as part of
670 `org-e-odt-hfy-face-to-css' callbacks."
673 (find-file-noselect (expand-file-name "styles.xml") t
)
674 (goto-char (point-min))
675 (when (re-search-forward "</office:styles>" nil t
)
676 (goto-char (match-beginning 0))
677 (insert "\n<!-- Org Htmlfontify Styles -->\n" styles
"\n")))))
679 (defun org-e-odt-remap-stylenames (style-name)
681 (cdr (assoc style-name
'(("timestamp-wrapper" .
"OrgTimestampWrapper")
682 ("timestamp" .
"OrgTimestamp")
683 ("timestamp-kwd" .
"OrgTimestampKeyword")
687 ("target" .
"OrgTarget"))))
690 (defun org-e-odt-format-fontify (text style
&optional id
)
694 (org-e-odt-remap-stylenames style
))
696 (org-e-odt-get-style-name-for-entity 'character style
))
698 (assert (< 1 (length style
)))
699 (let ((parent-style (pop style
)))
700 (mapconcat (lambda (s)
701 ;; (assert (stringp s) t)
702 (org-e-odt-remap-stylenames s
)) style
"")
703 (org-e-odt-remap-stylenames parent-style
)))
704 (t (error "Don't how to handle style %s" style
)))))
705 (org-e-odt-format-tags
706 '("<text:span text:style-name=\"%s\">" .
"</text:span>")
709 (defun org-e-odt-relocate-relative-path (path dir
)
710 (if (file-name-absolute-p path
) path
711 (file-relative-name (expand-file-name path dir
)
712 (expand-file-name "eyecandy" dir
))))
714 (defun org-e-odt-format-formula (src &optional caption label attr
)
716 (org-e-odt-format-tags
717 "<draw:object xlink:href=\"%s\" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\"/>" ""
718 (file-name-directory (org-e-odt-copy-formula-file src
))))
720 ;; (caption (org-find-text-property-in-string 'org-caption src))
721 ;; (caption (and caption (org-xml-format-desc caption)))
722 ;; (label (org-find-text-property-in-string 'org-label src))
723 ;; (latex-frag (org-find-text-property-in-string 'org-latex-src src))
727 ;; (org-find-text-property-in-string
728 ;; 'org-latex-src-embed-type src))
729 (if (or caption label
) 'paragraph
'character
)))
733 ;; (setq href (org-propertize href :title "LaTeX Fragment"
734 ;; :description latex-frag)))
736 ((eq embed-as
'character
)
737 (org-e-odt-format-entity "InlineFormula" href width height
))
739 ;; (org-lparse-end-paragraph)
741 (let ((table-info nil
)
743 '(:alignment
["c" "c"]
744 :column-groups
[nil nil
]
746 :special-column-p nil
:width
[8 1]))
747 (org-lparse-table-ncols 2)
749 (org-e-odt-list-table
750 `((,(org-e-odt-format-entity
751 (if caption
"CaptionedDisplayFormula" "DisplayFormula")
752 href width height
:caption caption
:label nil
)
754 (org-e-odt-format-entity-caption label nil
"__MathFormula__"))))
755 nil nil
":style \"OrgEquation\"" ;; nil '((1 "c" 8) (2 "c" 1)) FIXME
758 ;; (throw 'nextline nil)
761 (defun org-e-odt-copy-formula-file (path)
762 "Returns the internal name of the file"
763 (let* ((src-file (expand-file-name
764 path
(file-name-directory org-current-export-file
)))
765 (target-dir (format "Formula-%04d/"
766 (incf org-e-odt-embedded-formulas-count
)))
767 (target-file (concat target-dir
"content.xml")))
768 (message "Embedding %s as %s ..."
769 (substring-no-properties path
) target-file
)
771 (make-directory target-dir
)
772 (org-e-odt-create-manifest-file-entry
773 "application/vnd.oasis.opendocument.formula" target-dir
"1.2")
775 (case (org-e-odt-is-formula-link-p src-file
)
777 (copy-file src-file target-file
'overwrite
))
779 (org-e-odt-zip-extract-one src-file
"content.xml" target-dir
))
781 (error "%s is not a formula file" src-file
)))
783 (org-e-odt-create-manifest-file-entry "text/xml" target-file
)
786 (defun org-e-odt-is-formula-link-p (file)
787 (let ((case-fold-search nil
))
789 ((string-match "\\.\\(mathml\\|mml\\)\\'" file
)
791 ((string-match "\\.odf\\'" file
)
794 (defun org-e-odt-format-org-link (opt-plist type-1 path fragment desc attr
796 "Make a OpenDocument link.
797 OPT-PLIST is an options list.
798 TYPE-1 is the device-type of the link (THIS://foo.html).
799 PATH is the path of the link (http://THIS#location).
800 FRAGMENT is the fragment part of the link, if any (foo.html#THIS).
801 DESC is the link description, if any.
802 ATTR is a string of other attributes of the a element."
803 (declare (special org-lparse-par-open
))
806 (and (member type-1
'("http" "https" "file"))
807 (org-lparse-should-inline-p path descp
)
809 (type (if (equal type-1
"id") "file" type-1
))
813 ;; check for inlined images
814 ((and (member type
'("file"))
817 filename org-e-odt-inline-image-extensions
)
819 (org-e-odt-format-inline-image thefile
))
820 ;; check for embedded formulas
821 ((and (member type
'("file"))
823 (org-e-odt-is-formula-link-p filename
)
825 (org-e-odt-format-formula thefile
))
826 ((string= type
"coderef")
827 (let* ((ref fragment
)
828 (lineno-or-ref (cdr (assoc ref org-export-code-refs
)))
829 (desc (and descp desc
))
830 (org-e-odt-suppress-xref nil
)
831 (href (org-xml-format-href (concat "#coderef-" ref
))))
833 ((and (numberp lineno-or-ref
) (not desc
))
834 (org-e-odt-format-link lineno-or-ref href
))
835 ((and (numberp lineno-or-ref
) desc
836 (string-match (regexp-quote (concat "(" ref
")")) desc
))
837 (format (replace-match "%s" t t desc
)
838 (org-e-odt-format-link lineno-or-ref href
)))
841 (if (and desc
(string-match
842 (regexp-quote (concat "(" ref
")"))
844 (replace-match "%s" t t desc
)
847 (org-e-odt-format-link (org-xml-format-desc desc
) href
)))))
849 (when (string= type
"file")
852 ((file-name-absolute-p path
)
853 (concat "file://" (expand-file-name path
)))
854 (t (org-e-odt-relocate-relative-path
855 thefile org-current-export-file
)))))
857 (when (and (member type
'("" "http" "https" "file")) fragment
)
858 (setq thefile
(concat thefile
"#" fragment
)))
860 (setq thefile
(org-xml-format-href thefile
))
862 (when (not (member type
'("" "file")))
863 (setq thefile
(concat type
":" thefile
)))
865 (let ((org-e-odt-suppress-xref nil
))
866 (org-e-odt-format-link
867 (org-xml-format-desc desc
) thefile attr
)))))))
869 (defun org-e-odt-format-anchor (text name
&optional class
)
870 (org-e-odt-format-target text name
))
872 (defun org-e-odt-format-bookmark (text id
)
874 (org-e-odt-format-tags "<text:bookmark text:name=\"%s\"/>" text id
)
877 (defun org-e-odt-format-target (text id
)
878 (let ((name (concat org-e-odt-bookmark-prefix id
)))
880 (and id
(org-e-odt-format-tags
881 "<text:bookmark-start text:name=\"%s\"/>" "" name
))
882 (org-e-odt-format-bookmark text id
)
883 (and id
(org-e-odt-format-tags
884 "<text:bookmark-end text:name=\"%s\"/>" "" name
)))))
886 (defun org-e-odt-format-footnote (n def
)
887 (setq n
(format "%d" n
))
888 (let ((id (concat "fn" n
))
889 (note-class "footnote")
890 (par-style "Footnote"))
891 (org-e-odt-format-tags
892 '("<text:note text:id=\"%s\" text:note-class=\"%s\">" .
"</text:note>")
894 (org-e-odt-format-tags-simple
895 '("<text:note-citation>" .
"</text:note-citation>") n
)
896 (org-e-odt-format-tags
897 '("<text:note-body>" .
"</text:note-body>") def
))
900 (defun org-e-odt-format-footnote-reference (n def refcnt
)
902 (org-e-odt-format-footnote n def
)
903 (org-e-odt-format-footnote-ref n
)))
905 (defun org-e-odt-format-footnote-ref (n)
906 (setq n
(format "%d" n
))
907 (let ((note-class "footnote")
909 (ref-name (concat "fn" n
)))
910 (org-e-odt-format-tags
911 '("<text:span text:style-name=\"%s\">" .
"</text:span>")
912 (org-e-odt-format-tags-simple
913 '("<text:note-ref text:note-class=\"%s\" text:reference-format=\"%s\" text:ref-name=\"%s\">" .
"</text:note-ref>")
914 n note-class ref-format ref-name
)
917 (defun org-e-odt-parse-block-attributes (params)
920 (setq params
(org-trim params
))
921 (unless (string-match "\\`(.*)\\'" params
)
922 (setq params
(format "(%s)" params
)))
923 (ignore-errors (read params
)))))
925 (defun org-e-odt-format-image (src &optional
930 "Create image tag with source and attributes."
931 (let* ((href (org-e-odt-format-tags
932 "<draw:image xlink:href=\"%s\" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\"/>" ""
933 (org-e-odt-copy-image-file src
)))
934 ;; (caption (org-find-text-property-in-string 'org-caption src))
935 ;; (caption (and caption (org-xml-format-desc caption)))
936 ;; (attr (org-find-text-property-in-string 'org-attributes src))
937 ;; (label (org-find-text-property-in-string 'org-label src))
938 ;; (latex-frag (org-find-text-property-in-string
939 ;; 'org-latex-src src))
940 ;; (category (and latex-frag "__DvipngImage__")) ; FIXME
941 (attr-plist (org-e-odt-parse-block-attributes attr
))
943 (car (assoc-string (plist-get attr-plist
:anchor
)
944 '(("as-char") ("paragraph") ("page")) t
)))
946 (and user-frame-anchor
(plist-get attr-plist
:style
)))
948 (and user-frame-anchor
(plist-get attr-plist
:attributes
)))
950 (list user-frame-style user-frame-attrs user-frame-anchor
))
951 (embed-as (or embed-as user-frame-anchor
"paragraph"))
955 ;; (case (org-find-text-property-in-string ; FIXME
956 ;; 'org-latex-src-embed-type src)
957 ;; (paragraph 'paragraph)
959 ;; (user-frame-anchor)
961 (size (org-e-odt-image-size-from-file
962 src
(plist-get attr-plist
:width
)
963 (plist-get attr-plist
:height
)
964 (plist-get attr-plist
:scale
) nil embed-as
))
965 (width (car size
)) (height (cdr size
)))
966 ;; (when latex-frag ; FIXME
967 ;; (setq href (org-propertize href :title "LaTeX Fragment"
968 ;; :description latex-frag)))
969 (let ((frame-style-handle (concat (and (or caption label
) "Captioned")
971 (org-e-odt-format-entity
972 frame-style-handle href width height
973 :caption caption
:label label
:category category
974 :user-frame-params user-frame-params
))))
976 (defun org-e-odt-format-object-description (title description
)
977 (concat (and title
(org-e-odt-format-tags
978 '("<svg:title>" .
"</svg:title>")
979 (org-e-odt-encode-plain-text title t
)))
980 (and description
(org-e-odt-format-tags
981 '("<svg:desc>" .
"</svg:desc>")
982 (org-e-odt-encode-plain-text description t
)))))
984 (defun org-e-odt-format-frame (text width height style
&optional
988 (if width
(format " svg:width=\"%0.2fcm\"" width
) "")
989 (if height
(format " svg:height=\"%0.2fcm\"" height
) "")
991 (format " text:anchor-type=\"%s\"" (or anchor-type
"paragraph")))))
992 (org-e-odt-format-tags
993 '("<draw:frame draw:style-name=\"%s\"%s>" .
"</draw:frame>")
994 (concat text
(org-e-odt-format-object-description
995 (get-text-property 0 :title text
)
996 (get-text-property 0 :description text
)))
999 (defun org-e-odt-format-textbox (text width height style
&optional
1001 (org-e-odt-format-frame
1002 (org-e-odt-format-tags
1003 '("<draw:text-box %s>" .
"</draw:text-box>")
1004 text
(concat (format " fo:min-height=\"%0.2fcm\"" (or height
.2))
1006 (format " fo:min-width=\"%0.2fcm\"" (or width
.2)))))
1007 width nil style extra anchor-type
))
1009 (defun org-e-odt-merge-frame-params(default-frame-params user-frame-params
)
1010 (if (not user-frame-params
) default-frame-params
1011 (assert (= (length default-frame-params
) 3))
1012 (assert (= (length user-frame-params
) 3))
1013 (loop for user-frame-param in user-frame-params
1014 for default-frame-param in default-frame-params
1015 collect
(or user-frame-param default-frame-param
))))
1017 (defun* org-e-odt-format-entity
(entity href width height
1018 &key caption label category
1020 (let* ((entity-style (assoc-string entity org-e-odt-entity-frame-styles t
))
1021 default-frame-params frame-params
)
1023 ((not (or caption label
))
1024 (setq default-frame-params
(nth 2 entity-style
))
1025 (setq frame-params
(org-e-odt-merge-frame-params
1026 default-frame-params user-frame-params
))
1027 (apply 'org-e-odt-format-frame href width height frame-params
))
1029 (setq default-frame-params
(nth 3 entity-style
))
1030 (setq frame-params
(org-e-odt-merge-frame-params
1031 default-frame-params user-frame-params
))
1032 (apply 'org-e-odt-format-textbox
1033 (org-e-odt-format-stylized-paragraph
1036 (apply 'org-e-odt-format-frame href width height
1037 (nth 2 entity-style
))
1038 (org-e-odt-format-entity-caption
1039 label caption
(or category
(nth 1 entity-style
)))))
1040 width height frame-params
)))))
1042 (defun org-e-odt-copy-image-file (path)
1043 "Returns the internal name of the file"
1044 (let* ((image-type (file-name-extension path
))
1045 (media-type (format "image/%s" image-type
))
1046 (src-file (expand-file-name
1047 path
(file-name-directory org-current-export-file
)))
1048 (target-dir "Images/")
1050 (format "%s%04d.%s" target-dir
1051 (incf org-e-odt-embedded-images-count
) image-type
)))
1052 (message "Embedding %s as %s ..."
1053 (substring-no-properties path
) target-file
)
1055 (when (= 1 org-e-odt-embedded-images-count
)
1056 (make-directory target-dir
)
1057 (org-e-odt-create-manifest-file-entry "" target-dir
))
1059 (copy-file src-file target-file
'overwrite
)
1060 (org-e-odt-create-manifest-file-entry media-type target-file
)
1063 (defun org-e-odt-do-image-size (probe-method file
&optional dpi anchor-type
)
1064 (setq dpi
(or dpi org-e-odt-pixels-per-inch
))
1065 (setq anchor-type
(or anchor-type
"paragraph"))
1066 (flet ((size-in-cms (size-in-pixels)
1067 (flet ((pixels-to-cms (pixels)
1068 (let* ((cms-per-inch 2.54)
1069 (inches (/ pixels dpi
)))
1070 (* cms-per-inch inches
))))
1072 (cons (pixels-to-cms (car size-in-pixels
))
1073 (pixels-to-cms (cdr size-in-pixels
)))))))
1076 (size-in-cms (ignore-errors ; Emacs could be in batch mode
1078 (image-size (create-image file
) 'pixels
))))
1081 (let ((dim (shell-command-to-string
1082 (format "identify -format \"%%w:%%h\" \"%s\"" file
))))
1083 (when (string-match "\\([0-9]+\\):\\([0-9]+\\)" dim
)
1084 (cons (string-to-number (match-string 1 dim
))
1085 (string-to-number (match-string 2 dim
)))))))
1087 (cdr (assoc-string anchor-type
1088 org-e-odt-default-image-sizes-alist
))))))
1090 (defun org-e-odt-image-size-from-file (file &optional user-width
1091 user-height scale dpi embed-as
)
1092 (unless (file-name-absolute-p file
)
1093 (setq file
(expand-file-name
1094 file
(file-name-directory org-current-export-file
))))
1095 (let* (size width height
)
1096 (unless (and user-height user-width
)
1097 (loop for probe-method in org-e-odt-image-size-probe-method
1099 do
(setq size
(org-e-odt-do-image-size
1100 probe-method file dpi embed-as
)))
1101 (or size
(error "Cannot determine Image size. Aborting ..."))
1102 (setq width
(car size
) height
(cdr size
)))
1105 (setq width
(* width scale
) height
(* height scale
)))
1106 ((and user-height user-width
)
1107 (setq width user-width height user-height
))
1109 (setq width
(* user-height
(/ width height
)) height user-height
))
1111 (setq height
(* user-width
(/ height width
)) width user-width
))
1113 ;; ensure that an embedded image fits comfortably within a page
1114 (let ((max-width (car org-e-odt-max-image-size
))
1115 (max-height (cdr org-e-odt-max-image-size
)))
1116 (when (or (> width max-width
) (> height max-height
))
1117 (let* ((scale1 (/ max-width width
))
1118 (scale2 (/ max-height height
))
1119 (scale (min scale1 scale2
)))
1120 (setq width
(* scale width
) height
(* scale height
)))))
1121 (cons width height
)))
1123 (defun org-e-odt-add-label-definition (label default-category
)
1124 "Create an entry in `org-e-odt-entity-labels-alist' and return it."
1125 (setq label
(substring-no-properties label
))
1126 (let* ((label-props (assoc default-category org-e-odt-category-map-alist
))
1127 (category (nth 1 label-props
))
1129 (label-style (nth 2 label-props
))
1130 (sequence-var (intern (mapconcat
1132 (org-split-string counter
) "-")))
1133 (seqno (1+ (or (plist-get org-e-odt-entity-counts-plist sequence-var
)
1135 (label-props (list label category seqno label-style
)))
1136 (setq org-e-odt-entity-counts-plist
1137 (plist-put org-e-odt-entity-counts-plist sequence-var seqno
))
1138 (push label-props org-e-odt-entity-labels-alist
)
1141 (defun org-e-odt-format-label-reference (label default-category
1143 (let* ((label-props (assoc default-category org-e-odt-category-map-alist
))
1144 (category (nth 1 label-props
))
1145 (counter category
) ; FIXME
1146 (label-style (nth 2 label-props
)))
1148 (error "Unknown category: %S" default-category
))
1149 (org-e-odt-do-format-label-reference label category seqno label-style
)))
1151 (defun org-e-odt-format-label-definition (caption label category seqno label-style
)
1153 (setq label
(org-solidify-link-text label
))
1155 (cadr (assoc-string label-style org-e-odt-label-styles t
))
1157 (?n .
,(org-e-odt-format-tags-simple
1158 '("<text:sequence text:ref-name=\"%s\" text:name=\"%s\" text:formula=\"ooow:%s+1\" style:num-format=\"1\">" .
"</text:sequence>")
1159 (format "%d" seqno
) label category category
))
1160 (?c .
,(or (and caption
(concat ": " caption
)) "")))))
1162 (defun org-e-odt-do-format-label-reference (label category seqno label-style
)
1165 (let* ((fmt (cddr (assoc-string label-style org-e-odt-label-styles t
)))
1168 (org-e-odt-format-tags-simple
1169 '("<text:sequence-ref text:reference-format=\"%s\" text:ref-name=\"%s\">"
1170 .
"</text:sequence-ref>")
1171 (format-spec fmt2
`((?e .
,category
)
1172 (?n .
,(format "%d" seqno
)))) fmt1 label
))))
1174 (defun org-e-odt-format-entity-caption (label caption category
)
1176 (apply 'org-e-odt-format-label-definition
1177 caption
(org-e-odt-add-label-definition label category
)))
1180 (defun org-e-odt-format-tags-1 (tag text prefix suffix
&rest args
)
1183 (concat prefix
(apply 'format
(car tag
) args
) text suffix
1184 (format (cdr tag
))))
1185 ((stringp tag
) ; singleton tag
1186 (concat prefix
(apply 'format tag args
) text
))))
1188 (defun org-e-odt-format-tags (tag text
&rest args
)
1189 (apply 'org-e-odt-format-tags-1 tag text
"\n" "\n" args
))
1191 (defun org-e-odt-format-tags-simple (tag text
&rest args
)
1192 (apply 'org-e-odt-format-tags-1 tag text nil nil args
))
1194 (defun org-e-odt-init-outfile ()
1195 (unless (executable-find "zip")
1196 ;; Not at all OSes ship with zip by default
1197 (error "Executable \"zip\" needed for creating OpenDocument files"))
1199 (let* ((outdir (make-temp-file
1200 (format org-e-odt-tmpdir-prefix
'odt
) t
)) ; FIXME
1201 (content-file (expand-file-name "content.xml" outdir
)))
1204 (setq org-e-odt-manifest-file-entries nil
1205 org-e-odt-embedded-images-count
0
1206 org-e-odt-embedded-formulas-count
0
1207 org-e-odt-section-count
0
1208 org-e-odt-entity-labels-alist nil
1209 org-e-odt-list-stack-stashed nil
1210 org-e-odt-automatic-styles nil
1211 org-e-odt-object-counters nil
1212 org-e-odt-entity-counts-plist nil
)
1214 ;; let `htmlfontify' know that we are interested in collecting
1217 (setq hfy-user-sheet-assoc nil
)
1220 (with-current-buffer
1221 (find-file-noselect content-file t
)
1226 (defun org-e-odt-save-as-outfile (target opt-plist
)
1227 ;; write automatic styles
1228 (org-e-odt-write-automatic-styles)
1230 ;; write styles file
1231 ;; (when (equal org-lparse-backend 'odt) FIXME
1234 ;; (org-e-odt-update-styles-file opt-plist)
1236 ;; create mimetype file
1237 (let ((mimetype (org-e-odt-write-mimetype-file ;; org-lparse-backend FIXME
1239 (org-e-odt-create-manifest-file-entry mimetype
"/" "1.2"))
1241 ;; create a manifest entry for content.xml
1242 (org-e-odt-create-manifest-file-entry "text/xml" "content.xml")
1244 ;; write out the manifest entries before zipping
1245 (org-e-odt-write-manifest-file)
1247 (let ((xml-files '("mimetype" "META-INF/manifest.xml" "content.xml"
1249 (zipdir default-directory
))
1250 (when (or t
(equal org-lparse-backend
'odt
)) ; FIXME
1251 (push "styles.xml" xml-files
))
1252 (message "Switching to directory %s" (expand-file-name zipdir
))
1254 ;; save all xml files
1255 (mapc (lambda (file)
1256 (with-current-buffer
1257 (find-file-noselect (expand-file-name file
) t
)
1258 ;; prettify output if needed
1259 (when org-e-odt-prettify-xml
1260 (indent-region (point-min) (point-max)))
1264 (let* ((target-name (file-name-nondirectory target
))
1265 (target-dir (file-name-directory target
))
1266 (cmds `(("zip" "-mX0" ,target-name
"mimetype")
1267 ("zip" "-rmTq" ,target-name
"."))))
1268 (when (file-exists-p target
)
1269 ;; FIXME: If the file is locked this throws a cryptic error
1270 (delete-file target
))
1272 (let ((coding-system-for-write 'no-conversion
) exitcode err-string
)
1273 (message "Creating odt file...")
1276 (message "Running %s" (mapconcat 'identity cmd
" "))
1278 (with-output-to-string
1280 (apply 'call-process
(car cmd
)
1281 nil standard-output nil
(cdr cmd
)))))
1282 (or (zerop exitcode
)
1283 (ignore (message "%s" err-string
))
1284 (error "Unable to create odt file (%S)" exitcode
)))
1287 ;; move the file from outdir to target-dir
1288 (rename-file target-name target-dir
)
1290 ;; kill all xml buffers
1291 (mapc (lambda (file)
1293 (find-file-noselect (expand-file-name file zipdir
) t
)))
1296 (delete-directory zipdir
)))
1297 (message "Created %s" target
)
1298 (set-buffer (find-file-noselect target t
)))
1301 (defun org-e-odt-create-manifest-file-entry (&rest args
)
1302 (push args org-e-odt-manifest-file-entries
))
1304 (defun org-e-odt-write-manifest-file ()
1305 (make-directory "META-INF")
1306 (let ((manifest-file (expand-file-name "META-INF/manifest.xml")))
1307 (with-current-buffer
1308 (find-file-noselect manifest-file t
)
1310 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
1311 <manifest:manifest xmlns:manifest=\"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0\" manifest:version=\"1.2\">\n")
1313 (lambda (file-entry)
1314 (let* ((version (nth 2 file-entry
))
1316 (format " manifest:version=\"%s\"" version
)
1319 (format org-e-odt-manifest-file-entry-tag
1320 (nth 0 file-entry
) (nth 1 file-entry
) extra
))))
1321 org-e-odt-manifest-file-entries
)
1322 (insert "\n</manifest:manifest>"))))
1324 (defun org-e-odt-update-meta-file (info) ; FIXME opt-plist
1325 (let ((title (org-export-secondary-string
1326 (plist-get info
:title
) 'e-odt info
))
1327 (author (or (let ((auth (plist-get info
:author
)))
1328 (and auth
(org-export-secondary-string
1329 auth
'e-odt info
))) ""))
1330 (date (org-e-odt-format-date (plist-get info
:date
)))
1331 (email (plist-get info
:email
))
1332 (keywords (plist-get info
:keywords
))
1333 (description (plist-get info
:description
)))
1336 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
1337 <office:document-meta
1338 xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"
1339 xmlns:xlink=\"http://www.w3.org/1999/xlink\"
1340 xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
1341 xmlns:meta=\"urn:oasis:names:tc:opendocument:xmlns:meta:1.0\"
1342 xmlns:ooo=\"http://openoffice.org/2004/office\"
1343 office:version=\"1.2\">
1345 (org-e-odt-format-author author
) "\n"
1346 (format "<meta:initial-creator>%s</meta:initial-creator>\n" author
)
1347 (format "<dc:date>%s</dc:date>\n" date
)
1348 (format "<meta:creation-date>%s</meta:creation-date>\n" date
)
1349 (format "<meta:generator>%s</meta:generator>\n"
1350 (when org-export-creator-info
1351 (format "Org-%s/Emacs-%s"
1352 org-version emacs-version
)))
1353 (format "<meta:keyword>%s</meta:keyword>\n" keywords
)
1354 (format "<dc:subject>%s</dc:subject>\n" description
)
1355 (format "<dc:title>%s</dc:title>\n" title
)
1357 " </office:meta>\n" "</office:document-meta>")
1358 nil
(expand-file-name "meta.xml")))
1360 ;; create a manifest entry for meta.xml
1361 (org-e-odt-create-manifest-file-entry "text/xml" "meta.xml"))
1363 (defun org-e-odt-update-styles-file (info)
1364 ;; write styles file
1365 (let ((styles-file (plist-get info
:odt-styles-file
)))
1366 (org-e-odt-copy-styles-file (and styles-file
1367 (read (org-trim styles-file
))))
1369 ;; FIXME: Who is opening an empty styles.xml before this point?
1370 (with-current-buffer
1371 (find-file-noselect (expand-file-name "styles.xml") t
)
1372 (revert-buffer t t
)))
1374 ;; Write custom styles for source blocks
1375 (org-e-odt-insert-custom-styles-for-srcblocks
1378 (format " %s\n" (cddr style
)))
1379 hfy-user-sheet-assoc
"")))
1381 (defun org-e-odt-write-mimetype-file (format)
1382 ;; create mimetype file
1385 (odt "application/vnd.oasis.opendocument.text")
1386 (odf "application/vnd.oasis.opendocument.formula")
1387 (t (error "Unknown OpenDocument backend %S" org-lparse-backend
)))))
1388 (write-region mimetype nil
(expand-file-name "mimetype"))
1391 (defun org-e-odt-finalize-outfile ()
1392 (org-e-odt-delete-empty-paragraphs))
1394 (defun org-e-odt-delete-empty-paragraphs ()
1395 (goto-char (point-min))
1396 (let ((open "<text:p[^>]*>")
1397 (close "</text:p>"))
1398 (while (re-search-forward (format "%s[ \r\n\t]*%s" open close
) nil t
)
1399 (replace-match ""))))
1401 (declare-function org-create-math-formula
"org"
1402 (latex-frag &optional mathml-file
))
1405 (defun org-e-odt-convert (&optional in-file out-fmt prefix-arg
)
1406 "Convert IN-FILE to format OUT-FMT using a command line converter.
1407 IN-FILE is the file to be converted. If unspecified, it defaults
1408 to variable `buffer-file-name'. OUT-FMT is the desired output
1409 format. Use `org-e-odt-convert-process' as the converter.
1410 If PREFIX-ARG is non-nil then the newly converted file is opened
1411 using `org-open-file'."
1413 (append (org-lparse-convert-read-params) current-prefix-arg
))
1414 (org-lparse-do-convert in-file out-fmt prefix-arg
))
1416 (defun org-e-odt-get (what &optional opt-plist
)
1419 (EXPORT-DIR (org-export-directory :html opt-plist
))
1420 (FILE-NAME-EXTENSION "odt")
1421 (EXPORT-BUFFER-NAME "*Org ODT Export*")
1422 (ENTITY-CONTROL org-e-odt-entity-control-callbacks-alist
)
1423 (ENTITY-FORMAT org-e-odt-entity-format-callbacks-alist
)
1424 (INIT-METHOD 'org-e-odt-init-outfile
)
1425 (FINAL-METHOD 'org-e-odt-finalize-outfile
)
1426 (SAVE-METHOD 'org-e-odt-save-as-outfile
)
1428 (and org-e-odt-convert-process
1429 (cadr (assoc-string org-e-odt-convert-process
1430 org-e-odt-convert-processes t
))))
1431 (CONVERT-CAPABILITIES
1432 (and org-e-odt-convert-process
1433 (cadr (assoc-string org-e-odt-convert-process
1434 org-e-odt-convert-processes t
))
1435 org-e-odt-convert-capabilities
))
1437 (SPECIAL-STRING-REGEXPS org-e-odt-special-string-regexps
)
1438 (INLINE-IMAGES 'maybe
)
1439 (INLINE-IMAGE-EXTENSIONS '("png" "jpeg" "jpg" "gif" "svg"))
1440 (PLAIN-TEXT-MAP '(("&" .
"&") ("<" .
"<") (">" .
">")))
1441 (TABLE-FIRST-COLUMN-AS-LABELS nil
)
1442 (FOOTNOTE-SEPARATOR )
1443 (CODING-SYSTEM-FOR-WRITE 'utf-8
)
1444 (CODING-SYSTEM-FOR-SAVE 'utf-8
)
1445 (t (error "Unknown property: %s" what
))))
1447 (defun org-e-odt-do-preprocess-latex-fragments ()
1448 "Convert LaTeX fragments to images."
1449 (let* ((latex-frag-opt (plist-get org-lparse-opt-plist
:LaTeX-fragments
))
1450 (latex-frag-opt ; massage the options
1451 (or (and (member latex-frag-opt
'(mathjax t
))
1452 (not (and (fboundp 'org-format-latex-mathml-available-p
)
1453 (org-format-latex-mathml-available-p)))
1454 (prog1 org-lparse-latex-fragment-fallback
1457 "LaTeX to MathML converter not available. "
1458 (format "Using %S instead."
1459 org-lparse-latex-fragment-fallback
)))))
1461 cache-dir display-msg
)
1463 ((eq latex-frag-opt
'dvipng
)
1464 (setq cache-dir
"ltxpng/")
1465 (setq display-msg
"Creating LaTeX image %s"))
1466 ((member latex-frag-opt
'(mathjax t
))
1467 (setq latex-frag-opt
'mathml
)
1468 (setq cache-dir
"ltxmathml/")
1469 (setq display-msg
"Creating MathML formula %s")))
1470 (when (and org-current-export-file
)
1472 (concat cache-dir
(file-name-sans-extension
1473 (file-name-nondirectory org-current-export-file
)))
1474 org-current-export-dir nil display-msg
1475 nil nil latex-frag-opt
))))
1477 (eval-after-load 'org-odt
1478 '(ad-deactivate 'org-format-latex-as-mathml
))
1482 ;; (defadvice org-format-latex-as-mathml ; FIXME
1483 ;; (after org-e-odt-protect-latex-fragment activate)
1484 ;; "Encode LaTeX fragment as XML.
1485 ;; Do this when translation to MathML fails."
1486 ;; (when (or (not (> (length ad-return-value) 0))
1487 ;; (get-text-property 0 'org-protected ad-return-value))
1488 ;; (setq ad-return-value
1489 ;; (org-propertize (org-e-odt-encode-plain-text (ad-get-arg 0))
1490 ;; 'org-protected t))))
1492 (defun org-e-odt-preprocess-latex-fragments ()
1493 (when (equal org-export-current-backend
'odt
)
1494 (org-e-odt-do-preprocess-latex-fragments)))
1496 ;; process latex fragments as part of
1497 ;; `org-export-preprocess-after-blockquote-hook'. Note that this hook
1498 ;; is the one that is closest and well before the call to
1499 ;; `org-export-attach-captions-and-attributes' in
1500 ;; `org-export-preprocess-string'. The above arrangement permits
1501 ;; captions, labels and attributes to be attached to png images
1502 ;; generated out of latex equations.
1503 (add-hook 'org-export-preprocess-after-blockquote-hook
1504 'org-e-odt-preprocess-latex-fragments
)
1506 (defun org-e-odt-zip-extract-one (archive member
&optional target
)
1508 (let* ((target (or target default-directory
))
1509 (archive (expand-file-name archive
))
1510 (archive-zip-extract
1511 (list "unzip" "-qq" "-o" "-d" target
))
1512 exit-code command-output
)
1513 (setq command-output
1515 (setq exit-code
(archive-zip-extract archive member
))
1517 (unless (zerop exit-code
)
1518 (message command-output
)
1519 (error "Extraction failed"))))
1521 (defun org-e-odt-zip-extract (archive members
&optional target
)
1522 (when (atom members
) (setq members
(list members
)))
1523 (mapc (lambda (member)
1524 (org-e-odt-zip-extract-one archive member target
))
1527 (defun org-e-odt-copy-styles-file (&optional styles-file
)
1528 ;; Non-availability of styles.xml is not a critical error. For now
1529 ;; throw an error purely for aesthetic reasons.
1530 (setq styles-file
(or styles-file
1531 org-e-odt-styles-file
1532 (expand-file-name "OrgOdtStyles.xml"
1533 org-e-odt-styles-dir
)
1534 (error "org-e-odt: Missing styles file?")))
1536 ((listp styles-file
)
1537 (let ((archive (nth 0 styles-file
))
1538 (members (nth 1 styles-file
)))
1539 (org-e-odt-zip-extract archive members
)
1542 (when (org-file-image-p member
)
1543 (let* ((image-type (file-name-extension member
))
1544 (media-type (format "image/%s" image-type
)))
1545 (org-e-odt-create-manifest-file-entry media-type member
))))
1547 ((and (stringp styles-file
) (file-exists-p styles-file
))
1548 (let ((styles-file-type (file-name-extension styles-file
)))
1550 ((string= styles-file-type
"xml")
1551 (copy-file styles-file
(expand-file-name "styles.xml") t
))
1552 ((member styles-file-type
'("odt" "ott"))
1553 (org-e-odt-zip-extract styles-file
"styles.xml")))))
1555 (error (format "Invalid specification of styles.xml file: %S"
1556 org-e-odt-styles-file
))))
1558 ;; create a manifest entry for styles.xml
1559 (org-e-odt-create-manifest-file-entry "text/xml" "styles.xml"))
1561 (defun org-e-odt-configure-outline-numbering ()
1562 "Outline numbering is retained only upto LEVEL.
1563 To disable outline numbering pass a LEVEL of 0."
1564 (goto-char (point-min))
1566 "<text:outline-level-style\\([^>]*\\)text:level=\"\\([^\"]*\\)\"\\([^>]*\\)>")
1568 "<text:outline-level-style\\1text:level=\"\\2\" style:num-format=\"\">"))
1569 (while (re-search-forward regex nil t
)
1570 (unless (let ((sec-num (plist-get info
:section-numbers
))
1571 (level (string-to-number (match-string 2))))
1572 (if (wholenump sec-num
) (<= level sec-num
) sec-num
))
1573 (replace-match replacement t nil
))))
1577 (defun org-export-as-odf (latex-frag &optional odf-file
)
1578 "Export LATEX-FRAG as OpenDocument formula file ODF-FILE.
1579 Use `org-create-math-formula' to convert LATEX-FRAG first to
1580 MathML. When invoked as an interactive command, use
1581 `org-latex-regexps' to infer LATEX-FRAG from currently active
1582 region. If no LaTeX fragments are found, prompt for it. Push
1583 MathML source to kill ring, if `org-export-copy-to-kill-ring' is
1587 (setq frag
(and (setq frag
(and (region-active-p)
1588 (buffer-substring (region-beginning)
1590 (loop for e in org-latex-regexps
1591 thereis
(when (string-match (nth 1 e
) frag
)
1592 (match-string (nth 2 e
) frag
)))))
1593 (read-string "LaTeX Fragment: " frag nil frag
))
1594 ,(let ((odf-filename (expand-file-name
1596 (file-name-sans-extension
1597 (or (file-name-nondirectory buffer-file-name
)))
1599 (file-name-directory buffer-file-name
))))
1600 (read-file-name "ODF filename: " nil odf-filename nil
1601 (file-name-nondirectory odf-filename
)))))
1602 (let* ((org-lparse-backend 'odf
)
1603 org-lparse-opt-plist
1604 (filename (or odf-file
1607 (file-name-sans-extension
1608 (or (file-name-nondirectory buffer-file-name
)))
1610 (file-name-directory buffer-file-name
))))
1611 (buffer (find-file-noselect (org-e-odt-init-outfile filename
)))
1612 (coding-system-for-write 'utf-8
)
1613 (save-buffer-coding-system 'utf-8
))
1615 (set-buffer-file-coding-system coding-system-for-write
)
1616 (let ((mathml (org-create-math-formula latex-frag
)))
1617 (unless mathml
(error "No Math formula created"))
1619 (or (org-export-push-to-kill-ring
1620 (upcase (symbol-name org-lparse-backend
)))
1621 (message "Exporting... done")))
1622 (org-e-odt-save-as-outfile filename nil
; FIXME
1626 (defun org-export-as-odf-and-open ()
1627 "Export LaTeX fragment as OpenDocument formula and immediately open it.
1628 Use `org-export-as-odf' to read LaTeX fragment and OpenDocument
1631 (org-lparse-and-open
1632 nil nil nil
(call-interactively 'org-export-as-odf
)))
1637 ;;; Driver Starts here
1640 (require 'format-spec
)
1641 (eval-when-compile (require 'cl
) (require 'table
))
1647 ;; FIXME: it already exists in org-e-odt.el
1648 ;;; Function Declarations
1650 (declare-function org-element-property
"org-element" (property element
))
1651 (declare-function org-element-normalize-string
"org-element" (s))
1652 (declare-function org-element-parse-secondary-string
1653 "org-element" (string restriction
&optional buffer
))
1654 (defvar org-element-string-restrictions
)
1655 (defvar org-element-object-restrictions
)
1657 (declare-function org-export-clean-table
"org-export" (table specialp
))
1658 (declare-function org-export-data
"org-export" (data backend info
))
1659 (declare-function org-export-directory
"org-export" (type plist
))
1660 (declare-function org-export-expand-macro
"org-export" (macro info
))
1661 (declare-function org-export-first-sibling-p
"org-export" (headline info
))
1662 (declare-function org-export-footnote-first-reference-p
"org-export"
1663 (footnote-reference info
))
1664 (declare-function org-export-get-coderef-format
"org-export" (path desc
))
1665 (declare-function org-export-get-footnote-definition
"org-export"
1666 (footnote-reference info
))
1667 (declare-function org-export-get-footnote-number
"org-export" (footnote info
))
1668 (declare-function org-export-get-previous-element
"org-export" (blob info
))
1669 (declare-function org-export-get-relative-level
"org-export" (headline info
))
1670 (declare-function org-export-handle-code
1671 "org-export" (element info
&optional num-fmt ref-fmt delayed
))
1672 (declare-function org-export-included-file
"org-export" (keyword backend info
))
1673 (declare-function org-export-inline-image-p
"org-export"
1674 (link &optional extensions
))
1675 (declare-function org-export-last-sibling-p
"org-export" (headline info
))
1676 (declare-function org-export-low-level-p
"org-export" (headline info
))
1677 (declare-function org-export-output-file-name
1678 "org-export" (extension &optional subtreep pub-dir
))
1679 (declare-function org-export-resolve-coderef
"org-export" (ref info
))
1680 (declare-function org-export-resolve-fuzzy-link
"org-export" (link info
))
1681 (declare-function org-export-secondary-string
"org-export"
1682 (secondary backend info
))
1683 (declare-function org-export-solidify-link-text
"org-export" (s))
1684 (declare-function org-export-table-format-info
"org-export" (table))
1686 org-export-to-buffer
"org-export"
1687 (backend buffer
&optional subtreep visible-only body-only ext-plist
))
1689 org-export-to-file
"org-export"
1690 (backend file
&optional subtreep visible-only body-only ext-plist
))
1692 (declare-function org-id-find-id-file
"org-id" (id))
1693 (declare-function htmlize-region
"ext:htmlize" (beg end
))
1694 (declare-function org-pop-to-buffer-same-window
1695 "org-compat" (&optional buffer-or-name norecord label
))
1701 (declare-function hfy-face-to-style
"htmlfontify" (fn))
1702 (declare-function hfy-face-or-def-to-name
"htmlfontify" (fn))
1703 (declare-function archive-zip-extract
"arc-mode.el" (archive name
))
1705 ;;; Internal Variables
1707 ;;;; ODT Internal Variables
1709 (defconst org-e-odt-lib-dir
1710 (file-name-directory load-file-name
)
1711 "Location of ODT exporter.
1712 Use this to infer values of `org-e-odt-styles-dir' and
1713 `org-e-odt-schema-dir'.")
1715 (defvar org-e-odt-data-dir
1716 (expand-file-name "../etc/" org-e-odt-lib-dir
)
1717 "Data directory for ODT exporter.
1718 Use this to infer values of `org-e-odt-styles-dir' and
1719 `org-e-odt-schema-dir'.")
1724 (defconst org-e-odt-special-string-regexps
1725 '(("\\\\-" .
"­\\1") ; shy
1726 ("---\\([^-]\\)" .
"—\\1") ; mdash
1727 ("--\\([^-]\\)" .
"–\\1") ; ndash
1728 ("\\.\\.\\." .
"…")) ; hellip
1729 "Regular expressions for special string conversion.")
1731 (defconst org-e-odt-schema-dir-list
1733 (and org-e-odt-data-dir
1734 (expand-file-name "./schema/" org-e-odt-data-dir
)) ; bail out
1736 (and (boundp 'org-e-odt-data-dir
) org-e-odt-data-dir
; see make install
1737 (expand-file-name "./schema/" org-e-odt-data-dir
)))
1738 (expand-file-name "../contrib/odt/etc/schema/" org-e-odt-lib-dir
) ; git
1740 "List of directories to search for OpenDocument schema files.
1741 Use this list to set the default value of
1742 `org-e-odt-schema-dir'. The entries in this list are
1743 populated heuristically based on the values of `org-e-odt-lib-dir'
1744 and `org-e-odt-data-dir'.")
1747 (defconst org-e-odt-styles-dir-list
1749 (and org-e-odt-data-dir
1750 (expand-file-name "./styles/" org-e-odt-data-dir
)) ; bail out
1752 (and (boundp 'org-e-odt-data-dir
) org-e-odt-data-dir
; see make install
1753 (expand-file-name "./styles/" org-e-odt-data-dir
)))
1754 (expand-file-name "../etc/styles/" org-e-odt-lib-dir
) ; git
1755 (expand-file-name "./etc/styles/" org-e-odt-lib-dir
) ; elpa
1756 (expand-file-name "./org/" data-directory
) ; system
1758 "List of directories to search for OpenDocument styles files.
1759 See `org-e-odt-styles-dir'. The entries in this list are populated
1760 heuristically based on the values of `org-e-odt-lib-dir' and
1761 `org-e-odt-data-dir'.")
1763 (defconst org-e-odt-styles-dir
1766 (message "Debug (org-e-odt): Searching for OpenDocument styles files...")
1767 (mapc (lambda (styles-dir)
1769 (message "Debug (org-e-odt): Trying %s..." styles-dir
)
1770 (when (and (file-readable-p
1772 "OrgOdtContentTemplate.xml" styles-dir
))
1775 "OrgOdtStyles.xml" styles-dir
)))
1776 (message "Debug (org-e-odt): Using styles under %s"
1778 (throw 'styles-dir styles-dir
))))
1779 org-e-odt-styles-dir-list
)
1782 (error "Error (org-e-odt): Cannot find factory styles files. Aborting."))
1784 "Directory that holds auxiliary XML files used by the ODT exporter.
1786 This directory contains the following XML files -
1787 \"OrgOdtStyles.xml\" and \"OrgOdtContentTemplate.xml\". These
1788 XML files are used as the default values of
1789 `org-e-odt-styles-file' and
1790 `org-e-odt-content-template-file'.
1792 The default value of this variable varies depending on the
1793 version of org in use and is initialized from
1794 `org-e-odt-styles-dir-list'. Note that the user could be using org
1795 from one of: org's own private git repository, GNU ELPA tar or
1798 (defconst org-e-odt-tmpdir-prefix
"%s-")
1799 (defconst org-e-odt-bookmark-prefix
"OrgXref.")
1801 (defconst org-e-odt-manifest-file-entry-tag
1803 <manifest:file-entry manifest:media-type=\"%s\" manifest:full-path=\"%s\"%s/>")
1807 (defvar org-lparse-dyn-first-heading-pos
) ; let bound during org-do-lparse
1809 (defvar org-e-odt-suppress-xref nil
)
1810 (defvar org-e-odt-file-extensions
1811 '(("odt" .
"OpenDocument Text")
1812 ("ott" .
"OpenDocument Text Template")
1813 ("odm" .
"OpenDocument Master Document")
1814 ("ods" .
"OpenDocument Spreadsheet")
1815 ("ots" .
"OpenDocument Spreadsheet Template")
1816 ("odg" .
"OpenDocument Drawing (Graphics)")
1817 ("otg" .
"OpenDocument Drawing Template")
1818 ("odp" .
"OpenDocument Presentation")
1819 ("otp" .
"OpenDocument Presentation Template")
1820 ("odi" .
"OpenDocument Image")
1821 ("odf" .
"OpenDocument Formula")
1822 ("odc" .
"OpenDocument Chart")))
1824 (defvar org-e-odt-default-org-styles-alist
1825 '((paragraph .
((default .
"Text_20_body")
1826 (fixedwidth .
"OrgFixedWidthBlock")
1827 (verse .
"OrgVerse")
1828 (quote .
"Quotations")
1829 (blockquote .
"Quotations")
1830 (center .
"OrgCenter")
1832 (right .
"OrgRight")
1833 (title .
"OrgTitle")
1834 (subtitle .
"OrgSubtitle")
1835 (footnote .
"Footnote")
1836 (src .
"OrgSrcBlock")
1837 (illustration .
"Illustration")
1839 (definition-term .
"Text_20_body_20_bold")
1840 (horizontal-line .
"Horizontal_20_Line")))
1841 (character .
((bold .
"Bold")
1842 (emphasis .
"Emphasis")
1844 (verbatim .
"OrgCode")
1845 (strike .
"Strikethrough")
1846 (underline .
"Underline")
1847 (subscript .
"OrgSubscript")
1848 (superscript .
"OrgSuperscript")))
1849 (list .
((ordered .
"OrgNumberedList")
1850 (unordered .
"OrgBulletedList")
1851 (descriptive .
"OrgDescriptionList"))))
1852 "Default styles for various entities.")
1854 (defvar org-e-odt-org-styles-alist org-e-odt-default-org-styles-alist
)
1857 ;;;_. control callbacks
1858 ;;;_ , document body
1860 (defvar org-lparse-body-only
) ; let bound during org-do-lparse
1861 (defvar org-lparse-opt-plist
) ; bound during org-do-lparse
1862 (defvar org-lparse-list-stack
) ; dynamically bound in org-do-lparse
1863 (defvar org-e-odt-list-stack-stashed
)
1864 (defvar org-lparse-table-ncols
)
1865 (defvar org-e-odt-table-rowgrp-open
)
1866 (defvar org-e-odt-table-rownum
)
1867 (defvar org-e-odt-table-cur-rowgrp-is-hdr
)
1868 (defvar org-lparse-table-is-styled
)
1869 (defvar org-lparse-table-rowgrp-info
)
1870 (defvar org-lparse-table-colalign-vector
)
1872 (defvar org-e-odt-table-style nil
1873 "Table style specified by \"#+ATTR_ODT: <style-name>\" line.
1874 This is set during `org-e-odt-begin-table'.")
1876 (defvar org-e-odt-table-style-spec nil
1877 "Entry for `org-e-odt-table-style' in `org-e-odt-table-styles'.")
1880 (defvar org-e-odt-table-style-format
1882 <style:style style:name=\"%s\" style:family=\"table\">
1883 <style:table-properties style:rel-width=\"%d%%\" fo:margin-top=\"0cm\" fo:margin-bottom=\"0.20cm\" table:align=\"center\"/>
1886 "Template for auto-generated Table styles.")
1888 (defvar org-e-odt-automatic-styles
'()
1889 "Registry of automatic styles for various OBJECT-TYPEs.
1890 The variable has the following form:
1892 \(\(OBJECT-NAME-A.1 OBJECT-PROPS-A.1\)
1893 \(OBJECT-NAME-A.2 OBJECT-PROPS-A.2\) ...\)\)
1895 \(\(OBJECT-NAME-B.1 OBJECT-PROPS-B.1\)
1896 \(OBJECT-NAME-B.2 OBJECT-PROPS-B.2\) ...\)\)
1899 OBJECT-TYPEs could be \"Section\", \"Table\", \"Figure\" etc.
1900 OBJECT-PROPS is (typically) a plist created by passing
1901 \"#+ATTR_ODT: \" option to `org-e-odt-parse-block-attributes'.
1903 Use `org-e-odt-add-automatic-style' to add update this variable.'")
1905 (defvar org-e-odt-object-counters nil
1906 "Running counters for various OBJECT-TYPEs.
1907 Use this to generate automatic names and style-names. See
1908 `org-e-odt-add-automatic-style'.")
1910 (defvar org-e-odt-table-indentedp nil
)
1911 (defvar org-lparse-table-colalign-info
)
1912 (defvar org-lparse-link-description-is-image nil
)
1915 (defvar org-src-block-paragraph-format
1916 "<style:style style:name=\"OrgSrcBlock\" style:family=\"paragraph\" style:parent-style-name=\"Preformatted_20_Text\">
1917 <style:paragraph-properties fo:background-color=\"%s\" fo:padding=\"0.049cm\" fo:border=\"0.51pt solid #000000\" style:shadow=\"none\">
1918 <style:background-image/>
1919 </style:paragraph-properties>
1920 <style:text-properties fo:color=\"%s\"/>
1922 "Custom paragraph style for colorized source and example blocks.
1923 This style is much the same as that of \"OrgFixedWidthBlock\"
1924 except that the foreground and background colors are set
1925 according to the default face identified by the `htmlfontify'.")
1927 (defvar hfy-optimisations
)
1928 (defvar org-e-odt-embedded-formulas-count
0)
1929 (defvar org-e-odt-entity-frame-styles
1930 '(("As-CharImage" "__Figure__" ("OrgInlineImage" nil
"as-char"))
1931 ("ParagraphImage" "__Figure__" ("OrgDisplayImage" nil
"paragraph"))
1932 ("PageImage" "__Figure__" ("OrgPageImage" nil
"page"))
1933 ("CaptionedAs-CharImage" "__Figure__"
1934 ("OrgCaptionedImage"
1935 " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph")
1936 ("OrgInlineImage" nil
"as-char"))
1937 ("CaptionedParagraphImage" "__Figure__"
1938 ("OrgCaptionedImage"
1939 " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph")
1940 ("OrgImageCaptionFrame" nil
"paragraph"))
1941 ("CaptionedPageImage" "__Figure__"
1942 ("OrgCaptionedImage"
1943 " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph")
1944 ("OrgPageImageCaptionFrame" nil
"page"))
1945 ("InlineFormula" "__MathFormula__" ("OrgInlineFormula" nil
"as-char"))
1946 ("DisplayFormula" "__MathFormula__" ("OrgDisplayFormula" nil
"as-char"))
1947 ("CaptionedDisplayFormula" "__MathFormula__"
1948 ("OrgCaptionedFormula" nil
"paragraph")
1949 ("OrgFormulaCaptionFrame" nil
"as-char"))))
1951 (defvar org-e-odt-embedded-images-count
0)
1953 (defvar org-e-odt-image-size-probe-method
1954 (append (and (executable-find "identify") '(imagemagick)) ; See Bug#10675
1956 "Ordered list of methods for determining image sizes.")
1958 (defvar org-e-odt-default-image-sizes-alist
1959 '(("as-char" .
(5 .
0.4))
1960 ("paragraph" .
(5 .
5)))
1961 "Hardcoded image dimensions one for each of the anchor
1964 ;; A4 page size is 21.0 by 29.7 cms
1965 ;; The default page settings has 2cm margin on each of the sides. So
1966 ;; the effective text area is 17.0 by 25.7 cm
1967 (defvar org-e-odt-max-image-size
'(17.0 .
20.0)
1968 "Limiting dimensions for an embedded image.")
1970 (defvar org-e-odt-entity-labels-alist nil
1971 "Associate Labels with the Labeled entities.
1972 Each element of the alist is of the form (LABEL-NAME
1973 CATEGORY-NAME SEQNO LABEL-STYLE-NAME). LABEL-NAME is same as
1974 that specified by \"#+LABEL: ...\" line. CATEGORY-NAME is the
1975 type of the entity that LABEL-NAME is attached to. CATEGORY-NAME
1976 can be one of \"Table\", \"Figure\" or \"Equation\". SEQNO is
1977 the unique number assigned to the referenced entity on a
1978 per-CATEGORY basis. It is generated sequentially and is 1-based.
1979 LABEL-STYLE-NAME is a key `org-e-odt-label-styles'.
1981 See `org-e-odt-add-label-definition' and
1982 `org-e-odt-fixup-label-references'.")
1984 (defvar org-e-odt-entity-counts-plist nil
1985 "Plist of running counters of SEQNOs for each of the CATEGORY-NAMEs.
1986 See `org-e-odt-entity-labels-alist' for known CATEGORY-NAMEs.")
1988 (defvar org-e-odt-label-styles
1989 '(("text" "(%n)" "text" "(%n)")
1990 ("category-and-value" "%e %n%c" "category-and-value" "%e %n")
1991 ("value" "%e %n%c" "value" "%n"))
1992 "Specify how labels are applied and referenced.
1993 This is an alist where each element is of the
1994 form (LABEL-STYLE-NAME LABEL-ATTACH-FMT LABEL-REF-MODE
1997 LABEL-ATTACH-FMT controls how labels and captions are attached to
1998 an entity. It may contain following specifiers - %e, %n and %c.
1999 %e is replaced with the CATEGORY-NAME. %n is replaced with
2000 \"<text:sequence ...> SEQNO </text:sequence>\". %c is replaced
2001 with CAPTION. See `org-e-odt-format-label-definition'.
2003 LABEL-REF-MODE and LABEL-REF-FMT controls how label references
2004 are generated. The following XML is generated for a label
2005 reference - \"<text:sequence-ref
2006 text:reference-format=\"LABEL-REF-MODE\" ...> LABEL-REF-FMT
2007 </text:sequence-ref>\". LABEL-REF-FMT may contain following
2008 specifiers - %e and %n. %e is replaced with the CATEGORY-NAME.
2009 %n is replaced with SEQNO. See
2010 `org-e-odt-format-label-reference'.")
2012 (defvar org-e-odt-category-map-alist
2013 '(("__Table__" "Table" "value")
2014 ("__Figure__" "Figure" "value")
2015 ("__MathFormula__" "Equation" "text")
2016 ("__DvipngImage__" "Equation" "value")
2017 ;; ("__Table__" "Table" "category-and-value")
2018 ;; ("__Figure__" "Figure" "category-and-value")
2019 ;; ("__DvipngImage__" "Equation" "category-and-value")
2021 "Map a CATEGORY-HANDLE to CATEGORY-NAME and LABEL-STYLE.
2022 This is an alist where each element is of the form
2023 \\(CATEGORY-HANDLE CATEGORY-NAME LABEL-STYLE\\). CATEGORY_HANDLE
2024 could either be one of the internal handles (as seen above) or be
2025 derived from the \"#+LABEL:<label-name>\" specification. See
2026 `org-e-odt-get-category-from-label'. CATEGORY-NAME and
2027 LABEL-STYLE are used for generating ODT labels. See
2028 `org-e-odt-label-styles'.")
2030 (defvar org-e-odt-manifest-file-entries nil
)
2031 (defvar hfy-user-sheet-assoc
) ; bound during org-do-lparse
2032 (defvar org-lparse-latex-fragment-fallback
) ; set by org-do-lparse
2035 ;;;; HTML Internal Variables
2037 (defvar org-e-odt-option-alist
2039 ;; (:agenda-style nil nil org-agenda-export-html-style)
2040 ;; (:convert-org-links nil nil org-e-odt-link-org-files-as-html)
2041 ;; ;; FIXME Use (org-xml-encode-org-text-skip-links s) ??
2042 ;; ;; (:expand-quoted-html nil "@" org-e-odt-expand)
2043 ;; (:inline-images nil nil org-e-odt-inline-images)
2044 ;; ;; (:link-home nil nil org-e-odt-link-home) FIXME
2045 ;; ;; (:link-up nil nil org-e-odt-link-up) FIXME
2046 ;; (:style nil nil org-e-odt-style)
2047 ;; (:style-extra nil nil org-e-odt-style-extra)
2048 ;; (:style-include-default nil nil org-e-odt-style-include-default)
2049 ;; (:style-include-scripts nil nil org-e-odt-style-include-scripts)
2050 ;; ;; (:timestamp nil nil org-e-odt-with-timestamp)
2051 ;; (:html-extension nil nil org-e-odt-extension)
2052 ;; (:html-postamble nil nil org-e-odt-postamble)
2053 ;; (:html-preamble nil nil org-e-odt-preamble)
2054 ;; (:html-table-tag nil nil org-e-odt-table-tag)
2055 ;; (:xml-declaration nil nil org-e-odt-xml-declaration)
2056 (:odt-styles-file
"ODT_STYLES_FILE" nil nil t
)
2057 (:LaTeX-fragments nil
"LaTeX" org-export-with-LaTeX-fragments
))
2058 "Alist between export properties and ways to set them.
2060 The car of the alist is the property name, and the cdr is a list
2061 like \(KEYWORD OPTION DEFAULT BEHAVIOUR\) where:
2063 KEYWORD is a string representing a buffer keyword, or nil.
2064 OPTION is a string that could be found in an #+OPTIONS: line.
2065 DEFAULT is the default value for the property.
2066 BEHAVIOUR determine how Org should handle multiple keywords for
2067 the same property. It is a symbol among:
2068 nil Keep old value and discard the new one.
2069 t Replace old value with the new one.
2070 `space' Concatenate the values, separating them with a space.
2071 `newline' Concatenate the values, separating them with
2073 `split' Split values at white spaces, and cons them to the
2076 KEYWORD and OPTION have precedence over DEFAULT.
2078 All these properties should be back-end agnostic. For back-end
2079 specific properties, define a similar variable named
2080 `org-BACKEND-option-alist', replacing BACKEND with the name of
2081 the appropriate back-end. You can also redefine properties
2082 there, as they have precedence over these.")
2084 (defvar html-table-tag nil
) ; dynamically scoped into this.
2086 ;; FIXME: it already exists in org-e-odt.el
2087 (defconst org-e-odt-cvt-link-fn
2089 "Function to convert link URLs to exportable URLs.
2090 Takes two arguments, TYPE and PATH.
2091 Returns exportable url as (TYPE PATH), or nil to signal that it
2092 didn't handle this case.
2093 Intended to be locally bound around a call to `org-export-as-html'." )
2098 (defvar org-e-odt-format-table-no-css
)
2099 (defvar htmlize-buffer-places
) ; from htmlize.el
2100 (defvar body-only
) ; dynamically scoped into this.
2102 (defvar org-e-odt-table-rowgrp-open
)
2103 (defvar org-e-odt-table-rownum
)
2104 (defvar org-e-odt-table-cur-rowgrp-is-hdr
)
2105 (defvar org-lparse-table-is-styled
)
2108 (defvar org-e-odt-headline-formatter
2109 (lambda (level snumber todo todo-type priority
2110 title tags target extra-targets extra-class
)
2111 (concat snumber
" " title
)))
2115 ;;; User Configuration Variables
2117 (defgroup org-export-e-odt nil
2118 "Options for exporting Org mode files to HTML."
2119 :tag
"Org Export HTML"
2122 (defcustom org-e-odt-protect-char-alist
2126 "Alist of characters to be converted by `org-e-html-protect'."
2127 :group
'org-export-e-html
2128 :type
'(repeat (cons (string :tag
"Character")
2129 (string :tag
"ODT equivalent"))))
2130 (defcustom org-e-odt-schema-dir
2133 (message "Debug (org-e-odt): Searching for OpenDocument schema files...")
2135 (lambda (schema-dir)
2137 (message "Debug (org-e-odt): Trying %s..." schema-dir
)
2138 (when (and (file-readable-p
2139 (expand-file-name "od-manifest-schema-v1.2-cs01.rnc"
2142 (expand-file-name "od-schema-v1.2-cs01.rnc"
2145 (expand-file-name "schemas.xml" schema-dir
)))
2146 (message "Debug (org-e-odt): Using schema files under %s"
2148 (throw 'schema-dir schema-dir
))))
2149 org-e-odt-schema-dir-list
)
2150 (message "Debug (org-e-odt): No OpenDocument schema files installed")
2153 "Directory that contains OpenDocument schema files.
2155 This directory contains:
2156 1. rnc files for OpenDocument schema
2157 2. a \"schemas.xml\" file that specifies locating rules needed
2158 for auto validation of OpenDocument XML files.
2160 Use the customize interface to set this variable. This ensures
2161 that `rng-schema-locating-files' is updated and auto-validation
2162 of OpenDocument XML takes place based on the value
2163 `rng-nxml-auto-validate-flag'.
2165 The default value of this variable varies depending on the
2166 version of org in use and is initialized from
2167 `org-e-odt-schema-dir-list'. The OASIS schema files are available
2168 only in the org's private git repository. It is *not* bundled
2169 with GNU ELPA tar or standard Emacs distribution."
2171 (const :tag
"Not set" nil
)
2172 (directory :tag
"Schema directory"))
2173 :group
'org-export-e-odt
2177 "Set `org-e-odt-schema-dir'.
2178 Also add it to `rng-schema-locating-files'."
2179 (let ((schema-dir value
))
2183 (expand-file-name "od-manifest-schema-v1.2-cs01.rnc" schema-dir
))
2185 (expand-file-name "od-schema-v1.2-cs01.rnc" schema-dir
))
2187 (expand-file-name "schemas.xml" schema-dir
)))
2190 (message "Error (org-e-odt): %s has no OpenDocument schema files"
2193 (when org-e-odt-schema-dir
2194 (eval-after-load 'rng-loc
2195 '(add-to-list 'rng-schema-locating-files
2196 (expand-file-name "schemas.xml"
2197 org-e-odt-schema-dir
))))))
2199 (defcustom org-e-odt-content-template-file nil
2200 "Template file for \"content.xml\".
2201 The exporter embeds the exported content just before
2202 \"</office:text>\" element.
2204 If unspecified, the file named \"OrgOdtContentTemplate.xml\"
2205 under `org-e-odt-styles-dir' is used."
2207 :group
'org-export-e-odt
2210 (defcustom org-e-odt-styles-file nil
2211 "Default styles file for use with ODT export.
2212 Valid values are one of:
2214 2. path to a styles.xml file
2215 3. path to a *.odt or a *.ott file
2216 4. list of the form (ODT-OR-OTT-FILE (FILE-MEMBER-1 FILE-MEMBER-2
2219 In case of option 1, an in-built styles.xml is used. See
2220 `org-e-odt-styles-dir' for more information.
2222 In case of option 3, the specified file is unzipped and the
2223 styles.xml embedded therein is used.
2225 In case of option 4, the specified ODT-OR-OTT-FILE is unzipped
2226 and FILE-MEMBER-1, FILE-MEMBER-2 etc are copied in to the
2227 generated odt file. Use relative path for specifying the
2228 FILE-MEMBERS. styles.xml must be specified as one of the
2231 Use options 1, 2 or 3 only if styles.xml alone suffices for
2232 achieving the desired formatting. Use option 4, if the styles.xml
2233 references additional files like header and footer images for
2234 achieving the desired formatting.
2236 Use \"#+ODT_STYLES_FILE: ...\" directive to set this variable on
2237 a per-file basis. For example,
2239 #+ODT_STYLES_FILE: \"/path/to/styles.xml\" or
2240 #+ODT_STYLES_FILE: (\"/path/to/file.ott\" (\"styles.xml\" \"image/hdr.png\"))."
2241 :group
'org-export-e-odt
2245 (const :tag
"Factory settings" nil
)
2246 (file :must-match t
:tag
"styles.xml")
2247 (file :must-match t
:tag
"ODT or OTT file")
2248 (list :tag
"ODT or OTT file + Members"
2249 (file :must-match t
:tag
"ODF Text or Text Template file")
2250 (cons :tag
"Members"
2251 (file :tag
" Member" "styles.xml")
2252 (repeat (file :tag
"Member"))))))
2255 (defcustom org-e-odt-inline-image-extensions
2256 '("png" "jpeg" "jpg" "gif")
2257 "Extensions of image files that can be inlined into HTML."
2258 :type
'(repeat (string :tag
"Extension"))
2259 :group
'org-export-e-odt
2262 (defcustom org-e-odt-pixels-per-inch display-pixels-per-inch
2263 "Scaling factor for converting images pixels to inches.
2264 Use this for sizing of embedded images. See Info node `(org)
2265 Images in ODT export' for more information."
2267 :group
'org-export-e-odt
2270 (defcustom org-e-odt-create-custom-styles-for-srcblocks t
2271 "Whether custom styles for colorized source blocks be automatically created.
2272 When this option is turned on, the exporter creates custom styles
2273 for source blocks based on the advice of `htmlfontify'. Creation
2274 of custom styles happen as part of `org-e-odt-hfy-face-to-css'.
2276 When this option is turned off exporter does not create such
2279 Use the latter option if you do not want the custom styles to be
2280 based on your current display settings. It is necessary that the
2281 styles.xml already contains needed styles for colorizing to work.
2283 This variable is effective only if
2284 `org-e-odt-fontify-srcblocks' is turned on."
2285 :group
'org-export-e-odt
2289 (defcustom org-e-odt-preferred-output-format nil
2290 "Automatically post-process to this format after exporting to \"odt\".
2291 Interactive commands `org-export-as-e-odt' and
2292 `org-export-as-e-odt-and-open' export first to \"odt\" format and
2293 then use `org-e-odt-convert-process' to convert the
2294 resulting document to this format. During customization of this
2295 variable, the list of valid values are populated based on
2296 `org-e-odt-convert-capabilities'."
2297 :group
'org-export-e-odt
2299 :type
'(choice :convert-widget
2301 (apply 'widget-convert
(widget-type w
)
2302 (eval (car (widget-get w
:args
)))))
2303 `((const :tag
"None" nil
)
2304 ,@(mapcar (lambda (c)
2305 `(const :tag
,c
,c
))
2306 (org-lparse-reachable-formats "odt")))))
2308 (defcustom org-e-odt-table-styles
2309 '(("OrgEquation" "OrgEquation"
2310 ((use-first-column-styles . t
)
2311 (use-last-column-styles . t
))))
2312 "Specify how Table Styles should be derived from a Table Template.
2313 This is a list where each element is of the
2314 form (TABLE-STYLE-NAME TABLE-TEMPLATE-NAME TABLE-CELL-OPTIONS).
2316 TABLE-STYLE-NAME is the style associated with the table through
2317 `org-e-odt-table-style'.
2319 TABLE-TEMPLATE-NAME is a set of - upto 9 - automatic
2320 TABLE-CELL-STYLE-NAMEs and PARAGRAPH-STYLE-NAMEs (as defined
2321 below) that is included in
2322 `org-e-odt-content-template-file'.
2324 TABLE-CELL-STYLE-NAME := TABLE-TEMPLATE-NAME + TABLE-CELL-TYPE +
2326 PARAGRAPH-STYLE-NAME := TABLE-TEMPLATE-NAME + TABLE-CELL-TYPE +
2328 TABLE-CELL-TYPE := \"FirstRow\" | \"LastColumn\" |
2329 \"FirstRow\" | \"LastRow\" |
2330 \"EvenRow\" | \"OddRow\" |
2331 \"EvenColumn\" | \"OddColumn\" | \"\"
2332 where \"+\" above denotes string concatenation.
2334 TABLE-CELL-OPTIONS is an alist where each element is of the
2335 form (TABLE-CELL-STYLE-SELECTOR . ON-OR-OFF).
2336 TABLE-CELL-STYLE-SELECTOR := `use-first-row-styles' |
2337 `use-last-row-styles' |
2338 `use-first-column-styles' |
2339 `use-last-column-styles' |
2340 `use-banding-rows-styles' |
2341 `use-banding-columns-styles' |
2342 `use-first-row-styles'
2343 ON-OR-OFF := `t' | `nil'
2345 For example, with the following configuration
2347 \(setq org-e-odt-table-styles
2348 '\(\(\"TableWithHeaderRowsAndColumns\" \"Custom\"
2349 \(\(use-first-row-styles . t\)
2350 \(use-first-column-styles . t\)\)\)
2351 \(\"TableWithHeaderColumns\" \"Custom\"
2352 \(\(use-first-column-styles . t\)\)\)\)\)
2354 1. A table associated with \"TableWithHeaderRowsAndColumns\"
2355 style will use the following table-cell styles -
2356 \"CustomFirstRowTableCell\", \"CustomFirstColumnTableCell\",
2357 \"CustomTableCell\" and the following paragraph styles
2358 \"CustomFirstRowTableParagraph\",
2359 \"CustomFirstColumnTableParagraph\", \"CustomTableParagraph\"
2362 2. A table associated with \"TableWithHeaderColumns\" style will
2363 use the following table-cell styles -
2364 \"CustomFirstColumnTableCell\", \"CustomTableCell\" and the
2365 following paragraph styles
2366 \"CustomFirstColumnTableParagraph\", \"CustomTableParagraph\"
2369 Note that TABLE-TEMPLATE-NAME corresponds to the
2370 \"<table:table-template>\" elements contained within
2371 \"<office:styles>\". The entries (TABLE-STYLE-NAME
2372 TABLE-TEMPLATE-NAME TABLE-CELL-OPTIONS) correspond to
2373 \"table:template-name\" and \"table:use-first-row-styles\" etc
2374 attributes of \"<table:table>\" element. Refer ODF-1.2
2375 specification for more information. Also consult the
2376 implementation filed under `org-e-odt-get-table-cell-styles'.
2378 The TABLE-STYLE-NAME \"OrgEquation\" is used internally for
2379 formatting of numbered display equations. Do not delete this
2380 style from the list."
2381 :group
'org-export-e-odt
2384 (const :tag
"None" nil
)
2385 (repeat :tag
"Table Styles"
2386 (list :tag
"Table Style Specification"
2387 (string :tag
"Table Style Name")
2388 (string :tag
"Table Template Name")
2389 (alist :options
(use-first-row-styles
2391 use-first-column-styles
2392 use-last-column-styles
2393 use-banding-rows-styles
2394 use-banding-columns-styles
)
2396 :value-type
(const :tag
"True" t
))))))
2397 (defcustom org-e-odt-fontify-srcblocks t
2398 "Specify whether or not source blocks need to be fontified.
2399 Turn this option on if you want to colorize the source code
2400 blocks in the exported file. For colorization to work, you need
2401 to make available an enhanced version of `htmlfontify' library."
2403 :group
'org-export-e-odt
2406 (defcustom org-e-odt-prettify-xml t
; FIXME
2407 "Specify whether or not the xml output should be prettified.
2408 When this option is turned on, `indent-region' is run on all
2409 component xml buffers before they are saved. Turn this off for
2410 regular use. Turn this on if you need to examine the xml
2412 :group
'org-export-e-odt
2416 (defcustom org-e-odt-convert-processes
2418 "soffice --headless --convert-to %f%x --outdir %d %i")
2420 "unoconv -f %f -o %d %i"))
2421 "Specify a list of document converters and their usage.
2422 The converters in this list are offered as choices while
2423 customizing `org-e-odt-convert-process'.
2425 This variable is a list where each element is of the
2426 form (CONVERTER-NAME CONVERTER-CMD). CONVERTER-NAME is the name
2427 of the converter. CONVERTER-CMD is the shell command for the
2428 converter and can contain format specifiers. These format
2429 specifiers are interpreted as below:
2431 %i input file name in full
2432 %I input file name as a URL
2433 %f format of the output file
2434 %o output file name in full
2435 %O output file name as a URL
2436 %d output dir in full
2437 %D output dir as a URL.
2438 %x extra options as set in `org-e-odt-convert-capabilities'."
2439 :group
'org-export-e-odt
2443 (const :tag
"None" nil
)
2444 (alist :tag
"Converters"
2445 :key-type
(string :tag
"Converter Name")
2446 :value-type
(group (string :tag
"Command line")))))
2448 (defcustom org-e-odt-convert-process
"LibreOffice"
2449 "Use this converter to convert from \"odt\" format to other formats.
2450 During customization, the list of converter names are populated
2451 from `org-e-odt-convert-processes'."
2452 :group
'org-export-e-odt
2454 :type
'(choice :convert-widget
2456 (apply 'widget-convert
(widget-type w
)
2457 (eval (car (widget-get w
:args
)))))
2458 `((const :tag
"None" nil
)
2459 ,@(mapcar (lambda (c)
2460 `(const :tag
,(car c
) ,(car c
)))
2461 org-e-odt-convert-processes
))))
2463 (defcustom org-e-odt-convert-capabilities
2465 ("odt" "ott" "doc" "rtf" "docx")
2466 (("pdf" "pdf") ("odt" "odt") ("rtf" "rtf") ("ott" "ott")
2467 ("doc" "doc" ":\"MS Word 97\"") ("docx" "docx") ("html" "html")))
2470 (("pdf" "pdf") ("odt" "odt") ("html" "html")))
2472 ("ods" "ots" "xls" "csv" "xlsx")
2473 (("pdf" "pdf") ("ots" "ots") ("html" "html") ("csv" "csv") ("ods" "ods")
2474 ("xls" "xls") ("xlsx" "xlsx")))
2476 ("odp" "otp" "ppt" "pptx")
2477 (("pdf" "pdf") ("swf" "swf") ("odp" "odp") ("otp" "otp") ("ppt" "ppt")
2478 ("pptx" "pptx") ("odg" "odg"))))
2479 "Specify input and output formats of `org-e-odt-convert-process'.
2480 More correctly, specify the set of input and output formats that
2481 the user is actually interested in.
2483 This variable is an alist where each element is of the
2484 form (DOCUMENT-CLASS INPUT-FMT-LIST OUTPUT-FMT-ALIST).
2485 INPUT-FMT-LIST is a list of INPUT-FMTs. OUTPUT-FMT-ALIST is an
2486 alist where each element is of the form (OUTPUT-FMT
2487 OUTPUT-FILE-EXTENSION EXTRA-OPTIONS).
2489 The variable is interpreted as follows:
2490 `org-e-odt-convert-process' can take any document that is in
2491 INPUT-FMT-LIST and produce any document that is in the
2492 OUTPUT-FMT-LIST. A document converted to OUTPUT-FMT will have
2493 OUTPUT-FILE-EXTENSION as the file name extension. OUTPUT-FMT
2494 serves dual purposes:
2495 - It is used for populating completion candidates during
2496 `org-e-odt-convert' commands.
2497 - It is used as the value of \"%f\" specifier in
2498 `org-e-odt-convert-process'.
2500 EXTRA-OPTIONS is used as the value of \"%x\" specifier in
2501 `org-e-odt-convert-process'.
2503 DOCUMENT-CLASS is used to group a set of file formats in
2504 INPUT-FMT-LIST in to a single class.
2506 Note that this variable inherently captures how LibreOffice based
2507 converters work. LibreOffice maps documents of various formats
2508 to classes like Text, Web, Spreadsheet, Presentation etc and
2509 allow document of a given class (irrespective of it's source
2510 format) to be converted to any of the export formats associated
2513 See default setting of this variable for an typical
2515 :group
'org-export-e-odt
2519 (const :tag
"None" nil
)
2520 (alist :tag
"Capabilities"
2521 :key-type
(string :tag
"Document Class")
2523 (group (repeat :tag
"Input formats" (string :tag
"Input format"))
2524 (alist :tag
"Output formats"
2525 :key-type
(string :tag
"Output format")
2527 (group (string :tag
"Output file extension")
2529 (const :tag
"None" nil
)
2530 (string :tag
"Extra options"))))))))
2537 ;;;; Document Header (Styles)
2539 ;;;; Document Header (Scripts)
2541 ;;;; Document Header (Mathjax)
2554 ;;;; Statistics Cookie
2574 ;;;; Horizontal Rule
2575 ;;;; Inline Babel Call
2576 ;;;; Inline Src Block
2580 ;;;; Latex Environment
2589 ;;;; Property Drawer
2615 ;;; User Configurable Variables (MAYBE)
2623 (defcustom org-e-odt-format-headline-function nil
2624 "Function to format headline text.
2626 This function will be called with 5 arguments:
2627 TODO the todo keyword \(string or nil\).
2628 TODO-TYPE the type of todo \(symbol: `todo', `done', nil\)
2629 PRIORITY the priority of the headline \(integer or nil\)
2630 TEXT the main headline text \(string\).
2631 TAGS the tags string, separated with colons \(string or nil\).
2633 The function result will be used in the section format string.
2635 As an example, one could set the variable to the following, in
2636 order to reproduce the default set-up:
2638 \(defun org-e-odt-format-headline \(todo todo-type priority text tags\)
2639 \"Default format function for an headline.\"
2640 \(concat \(when todo
2641 \(format \"\\\\textbf{\\\\textsc{\\\\textsf{%s}}} \" todo\)\)
2643 \(format \"\\\\framebox{\\\\#%c} \" priority\)\)
2645 \(when tags \(format \"\\\\hfill{}\\\\textsc{%s}\" tags\)\)\)\)"
2646 :group
'org-export-e-odt
2653 (defcustom org-e-odt-active-timestamp-format
"\\textit{%s}"
2654 "A printf format string to be applied to active time-stamps."
2655 :group
'org-export-e-odt
2658 (defcustom org-e-odt-inactive-timestamp-format
"\\textit{%s}"
2659 "A printf format string to be applied to inactive time-stamps."
2660 :group
'org-export-e-odt
2663 (defcustom org-e-odt-diary-timestamp-format
"\\textit{%s}"
2664 "A printf format string to be applied to diary time-stamps."
2665 :group
'org-export-e-odt
2671 (defcustom org-e-odt-inline-image-rules
2672 '(("file" .
"\\.\\(jpeg\\|jpg\\|png\\|gif\\)\\'"))
2673 "Rules characterizing image files that can be inlined into HTML.
2675 A rule consists in an association whose key is the type of link
2676 to consider, and value is a regexp that will be matched against
2679 Note that, by default, the image extension *actually* allowed
2680 depend on the way the HTML file is processed. When used with
2681 pdflatex, pdf, jpg and png images are OK. When processing
2682 through dvi to Postscript, only ps and eps are allowed. The
2683 default we use here encompasses both."
2684 :group
'org-export-e-odt
2685 :type
'(alist :key-type
(string :tag
"Type")
2686 :value-type
(regexp :tag
"Path")))
2690 (defcustom org-e-odt-table-caption-above t
2691 "When non-nil, place caption string at the beginning of the table.
2692 Otherwise, place it near the end."
2693 :group
'org-export-e-odt
2698 (defcustom org-e-odt-format-drawer-function nil
2699 "Function called to format a drawer in HTML code.
2701 The function must accept two parameters:
2702 NAME the drawer name, like \"LOGBOOK\"
2703 CONTENTS the contents of the drawer.
2705 The function should return the string to be exported.
2707 For example, the variable could be set to the following function
2708 in order to mimic default behaviour:
2710 \(defun org-e-odt-format-drawer-default \(name contents\)
2711 \"Format a drawer element for HTML export.\"
2713 :group
'org-export-e-odt
2719 (defcustom org-e-odt-format-inlinetask-function nil
2720 "Function called to format an inlinetask in HTML code.
2722 The function must accept six parameters:
2723 TODO the todo keyword, as a string
2724 TODO-TYPE the todo type, a symbol among `todo', `done' and nil.
2725 PRIORITY the inlinetask priority, as a string
2726 NAME the inlinetask name, as a string.
2727 TAGS the inlinetask tags, as a string.
2728 CONTENTS the contents of the inlinetask, as a string.
2730 The function should return the string to be exported.
2732 For example, the variable could be set to the following function
2733 in order to mimic default behaviour:
2735 \(defun org-e-odt-format-inlinetask \(todo type priority name tags contents\)
2736 \"Format an inline task element for HTML export.\"
2737 \(let \(\(full-title
2740 \(format \"\\\\textbf{\\\\textsf{\\\\textsc{%s}}} \" todo\)\)
2741 \(when priority \(format \"\\\\framebox{\\\\#%c} \" priority\)\)
2743 \(when tags \(format \"\\\\hfill{}\\\\textsc{%s}\" tags\)\)\)\)\)
2744 \(format \(concat \"\\\\begin{center}\\n\"
2746 \"\\\\begin{minipage}[c]{.6\\\\textwidth}\\n\"
2748 \"\\\\rule[.8em]{\\\\textwidth}{2pt}\\n\\n\"
2750 \"\\\\end{minipage}}\"
2751 \"\\\\end{center}\"\)
2752 full-title contents\)\)"
2753 :group
'org-export-e-odt
2761 (defcustom org-e-odt-quotes
2762 '(("fr" ("\\(\\s-\\|[[(]\\)\"" .
"«~") ("\\(\\S-\\)\"" .
"~»") ("\\(\\s-\\|(\\)'" .
"'"))
2763 ("en" ("\\(\\s-\\|[[(]\\)\"" .
"``") ("\\(\\S-\\)\"" .
"''") ("\\(\\s-\\|(\\)'" .
"`")))
2764 "Alist for quotes to use when converting english double-quotes.
2766 The CAR of each item in this alist is the language code.
2767 The CDR of each item in this alist is a list of three CONS:
2768 - the first CONS defines the opening quote;
2769 - the second CONS defines the closing quote;
2770 - the last CONS defines single quotes.
2772 For each item in a CONS, the first string is a regexp
2773 for allowed characters before/after the quote, the second
2774 string defines the replacement string for this quote."
2775 :group
'org-export-e-odt
2777 (cons :tag
"Opening quote"
2778 (string :tag
"Regexp for char before")
2779 (string :tag
"Replacement quote "))
2780 (cons :tag
"Closing quote"
2781 (string :tag
"Regexp for char after ")
2782 (string :tag
"Replacement quote "))
2783 (cons :tag
"Single quote"
2784 (string :tag
"Regexp for char before")
2785 (string :tag
"Replacement quote "))))
2792 ;;; Internal Functions (HTML)
2794 ;; (defun org-e-odt-format-inline-image (path &optional caption label attr)
2795 ;; ;; FIXME: alt text missing here?
2796 ;; (let ((inline-image (format "<img src=\"%s\" alt=\"%s\"/>"
2797 ;; path (file-name-nondirectory path))))
2798 ;; (if (not label) inline-image
2799 ;; (org-e-odt-format-section inline-image "figure" label))))
2803 (defun org-e-odt-bibliography ()
2804 "Find bibliography, cut it out and return it."
2806 (let (beg end
(cnt 1) bib
)
2808 (goto-char (point-min))
2809 (when (re-search-forward
2810 "^[ \t]*<div \\(id\\|class\\)=\"bibliography\"" nil t
)
2811 (setq beg
(match-beginning 0))
2812 (while (re-search-forward "</?div\\>" nil t
)
2813 (setq cnt
(+ cnt
(if (string= (match-string 0) "<div") +1 -
1)))
2815 (and (looking-at ">") (forward-char 1))
2816 (setq bib
(buffer-substring beg
(point)))
2817 (delete-region beg
(point))
2818 (throw 'exit bib
))))
2823 (defun org-e-odt-format-table (lines olines
)
2824 (let ((org-e-odt-format-table-no-css nil
))
2825 (org-lparse-format-table lines olines
)))
2827 (defun org-e-odt-splice-attributes (tag attributes
)
2828 "Read attributes in string ATTRIBUTES, add and replace in HTML tag TAG."
2829 (if (not attributes
)
2831 (let (oldatt newatt
)
2832 (setq oldatt
(org-extract-attributes-from-string tag
)
2834 newatt
(cdr (org-extract-attributes-from-string attributes
)))
2836 (setq oldatt
(plist-put oldatt
(pop newatt
) (pop newatt
))))
2837 (if (string-match ">" tag
)
2839 (replace-match (concat (org-attributes-to-string oldatt
) ">")
2843 (defun org-export-splice-style (style extra
)
2844 "Splice EXTRA into STYLE, just before \"</style>\"."
2845 (if (and (stringp extra
)
2846 (string-match "\\S-" extra
)
2847 (string-match "</style>" style
))
2848 (concat (substring style
0 (match-beginning 0))
2850 (substring style
(match-beginning 0)))
2853 (defun org-e-odt-toc-entry-formatter
2854 (level snumber todo todo-type priority
2855 headline tags target extra-targets extra-class
)
2856 (org-e-odt-format-toc-entry snumber todo headline tags target
))
2858 (defun org-e-odt-make-string (n string
)
2859 (let (out) (dotimes (i n out
) (setq out
(concat string out
)))))
2861 (defun org-e-odt-toc-text (toc-entries)
2862 (let* ((prev-level (1- (nth 1 (car toc-entries
))))
2863 (start-level prev-level
))
2866 (let ((headline (nth 0 entry
))
2867 (level (nth 1 entry
)))
2868 (prog1 (org-e-odt-format-toc-item headline level prev-level
)
2869 (setq prev-level level
))))
2872 (defun* org-e-odt-format-toc-headline
2873 (todo todo-type priority text tags
2874 &key level section-number headline-label
&allow-other-keys
)
2877 (and org-export-with-section-numbers
2878 (concat section-number
". "))
2882 (org-e-odt-format-spaces 3)
2883 (org-e-odt-format-fontify tags
"tag")))))
2885 (setq text
(org-e-odt-format-fontify text
"todo")))
2887 (let ((org-e-odt-suppress-xref t
))
2888 (org-e-odt-format-link text
(concat "#" headline-label
))))
2890 (defun org-e-odt-toc (depth info
)
2891 (assert (wholenump depth
))
2892 (let* ((headlines (org-export-collect-headlines info depth
))
2894 (loop for headline in headlines collect
2895 (list (org-e-odt-format-headline--wrap
2896 headline info
'org-e-odt-format-toc-headline
)
2897 (org-export-get-relative-level headline info
)))))
2899 (let* ((lang-specific-heading "Table of Contents")) ; FIXME
2901 (org-e-odt-begin-toc lang-specific-heading depth
)
2902 (org-e-odt-toc-text toc-entries
)
2903 (org-e-odt-end-toc))))))
2905 (defun org-e-odt-begin-outline (level1 snumber title tags
2906 target extra-targets extra-class
)
2907 (let* ((class (format "outline-%d" level1
))
2908 (class (if extra-class
(concat class
" " extra-class
) class
))
2909 (id (format "outline-container-%s"
2910 (org-lparse-suffix-from-snumber snumber
)))
2911 (extra (concat (when id
(format " id=\"%s\"" id
))
2912 (when class
(format " class=\"%s\"" class
)))))
2913 (org-lparse-insert-tag "<div%s>" extra
)
2915 (org-lparse-format 'HEADING
2917 'HEADLINE title extra-targets tags snumber level1
)
2920 (defun org-e-odt-end-outline ()
2921 (org-lparse-insert-tag "</div>"))
2923 (defun org-e-odt-suffix-from-snumber (snumber)
2924 (let* ((snu (replace-regexp-in-string "\\." "-" snumber
))
2925 (href (cdr (assoc (concat "sec-" snu
)
2926 org-export-preferred-target-alist
))))
2927 (org-solidify-link-text (or href snu
))))
2929 (defun org-e-odt-format-outline (contents level1 snumber title
2930 tags target extra-targets extra-class
)
2933 ;; (defun org-e-odt-format-line (line)
2934 ;; (case org-lparse-dyn-current-environment
2935 ;; ((quote fixedwidth) (concat (org-e-odt-encode-plain-text line) "\n"))
2936 ;; (t (concat line "\n"))))
2938 (defun org-e-odt-fix-class-name (kwd) ; audit callers of this function
2939 "Turn todo keyword into a valid class name.
2940 Replaces invalid characters with \"_\"."
2942 (while (string-match "[^a-zA-Z0-9_]" kwd
)
2943 (setq kwd
(replace-match "_" t t kwd
))))
2946 (defun org-e-odt-format-internal-link (text href
&optional extra
)
2947 (org-e-odt-format-link text
(concat "#" href
) extra
))
2949 (defun org-e-odt-format-extra-targets (extra-targets)
2950 (if (not extra-targets
) ""
2951 (mapconcat (lambda (x)
2953 (setq x
(org-solidify-link-text
2954 (if (org-uuidgen-p x
) (concat "ID-" x
) x
)))
2955 (org-e-odt-format-anchor "" x
))) extra-targets
"")))
2957 (defun org-e-odt-format-org-tags (tags)
2959 (org-e-odt-format-fontify
2962 (org-e-odt-format-fontify
2963 x
(concat "" ;; org-e-odt-tag-class-prefix
2964 (org-e-odt-fix-class-name x
))))
2965 (org-split-string tags
":")
2966 (org-e-odt-format-spaces 1)) "tag")))
2968 (defun org-e-odt-format-section-number (&optional snumber level
)
2970 (and nil org-export-with-section-numbers
2971 ;; (not org-lparse-body-only)
2973 (org-e-odt-format-fontify snumber
(format "section-number-%d" level
))))
2975 ;; (defun org-e-odt-format-headline (title extra-targets tags
2976 ;; &optional snumber level)
2978 ;; (org-e-odt-format-extra-targets extra-targets)
2979 ;; (concat (org-e-odt-format-section-number snumber level) " ")
2981 ;; (and tags (concat (org-e-odt-format-spaces 3)
2982 ;; (org-e-odt-format-org-tags tags)))))
2984 (defun org-e-odt-get-coding-system-for-write ()
2985 (or org-e-odt-coding-system
2986 (and (boundp 'buffer-file-coding-system
) buffer-file-coding-system
)))
2988 (defun org-e-odt-get-coding-system-for-save ()
2989 (or org-e-odt-coding-system
2990 (and (boundp 'buffer-file-coding-system
) buffer-file-coding-system
)))
2992 ;; (defun org-e-odt-format-date (info)
2993 ;; (let ((date (plist-get info :date)))
2995 ;; ((and date (string-match "%" date))
2996 ;; (format-time-string date))
2998 ;; (t (format-time-string "%Y-%m-%d %T %Z")))))
3002 ;;; Internal Functions (Ngz)
3004 (defun org-e-odt--caption/label-string
(caption label info
)
3005 "Return caption and label HTML string for floats.
3007 CAPTION is a cons cell of secondary strings, the car being the
3008 standard caption and the cdr its short form. LABEL is a string
3009 representing the label. INFO is a plist holding contextual
3012 If there's no caption nor label, return the empty string.
3014 For non-floats, see `org-e-odt--wrap-label'."
3015 (setq label nil
) ;; FIXME
3017 (let ((label-str (if label
(format "\\label{%s}" label
) "")))
3019 ((and (not caption
) (not label
)) "")
3020 ((not caption
) (format "\\label{%s}\n" label
))
3021 ;; Option caption format with short name.
3023 (format "\\caption[%s]{%s%s}\n"
3024 (org-export-secondary-string (cdr caption
) 'e-odt info
)
3026 (org-export-secondary-string (car caption
) 'e-odt info
)))
3027 ;; Standard caption format.
3028 ;; (t (format "\\caption{%s%s}\n"
3030 ;; (org-export-secondary-string (car caption) 'e-odt info)))
3032 (t (org-export-secondary-string (car caption
) 'e-odt info
)))))
3034 (defun org-e-odt--find-verb-separator (s)
3035 "Return a character not used in string S.
3036 This is used to choose a separator for constructs like \\verb."
3037 (let ((ll "~,./?;':\"|!@#%^&-_=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<>()[]{}"))
3038 (loop for c across ll
3039 when
(not (string-match (regexp-quote (char-to-string c
)) s
))
3040 return
(char-to-string c
))))
3042 (defun org-e-odt--quotation-marks (text info
)
3043 "Export quotation marks depending on language conventions.
3044 TEXT is a string containing quotation marks to be replaced. INFO
3045 is a plist used as a communication channel."
3048 (while (setq start
(string-match (car l
) text start
))
3049 (let ((new-quote (concat (match-string 1 text
) (cdr l
))))
3050 (setq text
(replace-match new-quote t t text
))))))
3051 (cdr (or (assoc (plist-get info
:language
) org-e-odt-quotes
)
3052 ;; Falls back on English.
3053 (assoc "en" org-e-odt-quotes
))))
3056 (defun org-e-odt--wrap-label (element output
)
3057 "Wrap label associated to ELEMENT around OUTPUT, if appropriate.
3058 This function shouldn't be used for floats. See
3059 `org-e-odt--caption/label-string'."
3060 ;; (let ((label (org-element-property :name element)))
3061 ;; (if (or (not output) (not label) (string= output "") (string= label ""))
3063 ;; (concat (format "\\label{%s}\n" label) output)))
3068 ;;; Transcode Helpers
3070 (defun* org-e-odt-format-headline
3071 (todo todo-type priority text tags
3072 &key level section-number headline-label
&allow-other-keys
)
3073 (concat (org-e-odt-todo todo
) (and todo
" ") text
3074 (and tags
(org-e-odt-format-spaces 3))
3075 (and tags
(org-e-odt-format-org-tags tags
))))
3079 (defun org-e-odt-htmlfontify-string (line)
3080 (let* ((hfy-html-quote-regex "\\([<\"&> ]\\)")
3081 (hfy-html-quote-map '(("\"" """)
3086 (" " "<text:tab/>")))
3087 (hfy-face-to-css 'org-e-odt-hfy-face-to-css
)
3088 (hfy-optimisations-1 (copy-seq hfy-optimisations
))
3089 (hfy-optimisations (add-to-list 'hfy-optimisations-1
3091 (hfy-begin-span-handler
3092 (lambda (style text-block text-id text-begins-block-p
)
3093 (insert (format "<text:span text:style-name=\"%s\">" style
))))
3094 (hfy-end-span-handler (lambda nil
(insert "</text:span>"))))
3095 (htmlfontify-string line
)))
3097 (defun org-e-odt-do-format-code
3098 (code &optional lang refs retain-labels num-start
)
3099 (let* ((lang (or (assoc-default lang org-src-lang-modes
) lang
))
3100 (lang-mode (and lang
(intern (format "%s-mode" lang
))))
3101 (code-lines (org-split-string code
"\n"))
3102 (code-length (length code-lines
))
3103 (use-htmlfontify-p (and (functionp lang-mode
)
3104 org-e-odt-fontify-srcblocks
3105 (require 'htmlfontify nil t
)
3106 (fboundp 'htmlfontify-string
)))
3107 (code (if (not use-htmlfontify-p
) code
3111 (font-lock-fontify-buffer)
3113 (fontifier (if use-htmlfontify-p
'org-e-odt-htmlfontify-string
3114 'org-e-odt-encode-plain-text
))
3115 (par-style (if use-htmlfontify-p
"OrgSrcBlock"
3116 "OrgFixedWidthBlock"))
3118 (assert (= code-length
(length (org-split-string code
"\n"))))
3120 (org-export-format-code
3122 (lambda (loc line-num ref
)
3124 (concat par-style
(and (= (incf i
) code-length
) "LastLine")))
3126 (setq loc
(concat loc
(and ref retain-labels
(format " (%s)" ref
))))
3127 (setq loc
(funcall fontifier loc
))
3129 (setq loc
(org-e-odt-format-target loc
(concat "coderef-" ref
))))
3130 (setq loc
(org-e-odt-format-stylized-paragraph par-style loc
))
3131 (if (not line-num
) loc
3132 (org-e-odt-format-tags
3133 '("<text:list-item>" .
"</text:list-item>") loc
)))
3136 ((not num-start
) code
)
3137 ((equal num-start
0)
3138 (org-e-odt-format-tags
3139 '("<text:list text:style-name=\"OrgSrcBlockNumberedLine\"%s>"
3140 .
"</text:list>") code
" text:continue-numbering=\"false\""))
3141 (t (org-e-odt-format-tags
3142 '("<text:list text:style-name=\"OrgSrcBlockNumberedLine\"%s>"
3143 .
"</text:list>") code
" text:continue-numbering=\"true\"")))))
3145 (defun org-e-odt-format-code (element info
)
3146 (let* ((lang (org-element-property :language element
))
3147 ;; Extract code and references.
3148 (code-info (org-export-unravel-code element
))
3149 (code (car code-info
))
3150 (refs (cdr code-info
))
3151 ;; Does the src block contain labels?
3152 (retain-labels (org-element-property :retain-labels element
))
3153 ;; Does it have line numbers?
3154 (num-start (case (org-element-property :number-lines element
)
3155 (continued (org-export-get-loc element info
))
3157 (org-e-odt-do-format-code code lang refs retain-labels num-start
)))
3163 (defun org-e-odt-template (contents info
)
3164 "Return complete document string after HTML conversion.
3165 CONTENTS is the transcoded contents string. RAW-DATA is the
3166 original parsed data. INFO is a plist holding export options."
3168 (org-e-odt-update-meta-file info
)
3170 (insert-file-contents
3171 (or org-e-odt-content-template-file
3172 (expand-file-name "OrgOdtContentTemplate.xml"
3173 org-e-odt-styles-dir
)))
3174 (goto-char (point-min))
3175 (re-search-forward "</office:text>" nil nil
)
3176 (goto-char (match-beginning 0))
3179 (insert (org-e-odt-format-preamble info
))
3180 ;; Table of Contents
3181 (let ((depth (plist-get info
:with-toc
)))
3182 (when (wholenump depth
) (insert (org-e-odt-toc depth info
))))
3184 ;; Copy styles.xml. Also dump htmlfontify styles, if there is any.
3185 (org-e-odt-update-styles-file info
)
3187 ;; Update styles.xml - take care of outline numbering
3188 (with-current-buffer
3189 (find-file-noselect (expand-file-name "styles.xml") t
)
3190 ;; Don't make automatic backup of styles.xml file. This setting
3191 ;; prevents the backed-up styles.xml file from being zipped in to
3192 ;; odt file. This is more of a hackish fix. Better alternative
3193 ;; would be to fix the zip command so that the output odt file
3194 ;; includes only the needed files and excludes any auto-generated
3195 ;; extra files like backups and auto-saves etc etc. Note that
3196 ;; currently the zip command zips up the entire temp directory so
3197 ;; that any auto-generated files created under the hood ends up in
3198 ;; the resulting odt file.
3199 (set (make-local-variable 'backup-inhibited
) t
)
3200 (org-e-odt-configure-outline-numbering))
3204 (buffer-substring-no-properties (point-min) (point-max))))
3208 ;;; Transcode Functions
3212 (defun org-e-odt-center-block (center-block contents info
)
3213 "Transcode a CENTER-BLOCK element from Org to HTML.
3214 CONTENTS holds the contents of the block. INFO is a plist
3215 holding contextual information."
3216 (org-e-odt--wrap-label center-block contents
))
3221 ;; Comments are ignored.
3226 ;; Comment Blocks are ignored.
3231 (defun org-e-odt-drawer (drawer contents info
)
3232 "Transcode a DRAWER element from Org to HTML.
3233 CONTENTS holds the contents of the block. INFO is a plist
3234 holding contextual information."
3235 (let* ((name (org-element-property :drawer-name drawer
))
3236 (output (if (functionp org-e-odt-format-drawer-function
)
3237 (funcall org-e-odt-format-drawer-function
3239 ;; If there's no user defined function: simply
3240 ;; display contents of the drawer.
3242 (org-e-odt--wrap-label drawer output
)))
3247 (defun org-e-odt-dynamic-block (dynamic-block contents info
)
3248 "Transcode a DYNAMIC-BLOCK element from Org to HTML.
3249 CONTENTS holds the contents of the block. INFO is a plist
3250 holding contextual information. See
3252 (org-e-odt--wrap-label dynamic-block contents
))
3257 (defun org-e-odt-emphasis (emphasis contents info
)
3258 "Transcode EMPHASIS from Org to HTML.
3259 CONTENTS is the contents of the emphasized text. INFO is a plist
3260 holding contextual information.."
3261 ;; (format (cdr (assoc (org-element-property :marker emphasis)
3262 ;; org-e-odt-emphasis-alist))
3264 (org-e-odt-format-fontify
3265 contents
(cadr (assoc
3266 (org-element-property :marker emphasis
)
3277 (defun org-e-odt-entity (entity contents info
)
3278 "Transcode an ENTITY object from Org to HTML.
3279 CONTENTS are the definition itself. INFO is a plist holding
3280 contextual information."
3281 ;; (let ((ent (org-element-property :latex entity)))
3282 ;; (if (org-element-property :latex-math-p entity)
3283 ;; (format "$%s$" ent)
3285 (org-element-property :utf-8 entity
))
3290 (defun org-e-odt-example-block (example-block contents info
)
3291 "Transcode a EXAMPLE-BLOCK element from Org to HTML.
3292 CONTENTS is nil. INFO is a plist holding contextual information."
3293 (let* ((options (or (org-element-property :options example-block
) ""))
3294 (value (org-export-handle-code example-block info nil nil t
)))
3295 (org-e-odt--wrap-label
3296 example-block
(org-e-odt-format-source-code-or-example value nil
))))
3301 (defun org-e-odt-export-snippet (export-snippet contents info
)
3302 "Transcode a EXPORT-SNIPPET object from Org to HTML.
3303 CONTENTS is nil. INFO is a plist holding contextual information."
3304 (when (eq (org-export-snippet-backend export-snippet
) 'e-odt
)
3305 (org-element-property :value export-snippet
)))
3310 (defun org-e-odt-export-block (export-block contents info
)
3311 "Transcode a EXPORT-BLOCK element from Org to HTML.
3312 CONTENTS is nil. INFO is a plist holding contextual information."
3313 (when (string= (org-element-property :type export-block
) "latex")
3314 (org-remove-indentation (org-element-property :value export-block
))))
3319 (defun org-e-odt-fixed-width (fixed-width contents info
)
3320 "Transcode a FIXED-WIDTH element from Org to HTML.
3321 CONTENTS is nil. INFO is a plist holding contextual information."
3322 (let* ((value (org-element-normalize-string
3323 (replace-regexp-in-string
3325 (org-element-property :value fixed-width
)))))
3326 (org-e-odt--wrap-label
3327 fixed-width
(org-e-odt-format-source-code-or-example value nil
))))
3330 ;;;; Footnote Definition
3332 ;; Footnote Definitions are ignored.
3335 ;;;; Footnote Reference
3337 (defun org-e-odt-footnote-def (raw info
) ; FIXME
3338 (if (equal (org-element-type raw
) 'org-data
)
3339 (org-trim (org-export-data raw
'e-odt info
)) ; fix paragraph
3341 (org-odt-format-stylized-paragraph
3342 'footnote
(org-trim (org-export-secondary-string raw
'e-odt info
)))))
3344 (defvar org-e-odt-footnote-separator
3345 (org-e-odt-format-fontify "," 'superscript
))
3347 (defun org-e-odt-footnote-reference (footnote-reference contents info
)
3348 "Transcode a FOOTNOTE-REFERENCE element from Org to HTML.
3349 CONTENTS is nil. INFO is a plist holding contextual information."
3351 ;; Insert separator between two footnotes in a row.
3352 (let ((prev (org-export-get-previous-element footnote-reference info
)))
3353 (when (eq (org-element-type prev
) 'footnote-reference
)
3354 org-e-odt-footnote-separator
))
3356 ((not (org-export-footnote-first-reference-p footnote-reference info
))
3357 (let* ((n (org-export-get-footnote-number footnote-reference info
)))
3358 (org-e-odt-format-footnote-reference n
"IGNORED" 100)))
3359 ;; Inline definitions are secondary strings.
3360 ((eq (org-element-property :type footnote-reference
) 'inline
)
3361 (let* ((raw (org-export-get-footnote-definition footnote-reference info
))
3362 (n (org-export-get-footnote-number footnote-reference info
))
3363 (def (org-e-odt-footnote-def raw info
)))
3364 (org-e-odt-format-footnote-reference n def
1)))
3365 ;; Non-inline footnotes definitions are full Org data.
3367 (let* ((raw (org-export-get-footnote-definition footnote-reference info
))
3368 (n (org-export-get-footnote-number footnote-reference info
))
3369 (def (org-e-odt-footnote-def raw info
)))
3370 (org-e-odt-format-footnote-reference n def
1))))))
3375 (defun org-e-odt-todo (todo)
3377 (org-e-odt-format-fontify
3379 "" ; org-e-odt-todo-kwd-class-prefix
3380 (org-e-odt-fix-class-name todo
))
3381 (list (if (member todo org-done-keywords
) "done" "todo")
3384 (defun org-e-odt-format-headline--wrap (headline info
3385 &optional format-function
3387 "Transcode an HEADLINE element from Org to ODT.
3388 CONTENTS holds the contents of the headline. INFO is a plist
3389 holding contextual information."
3390 (let* ((level (+ (org-export-get-relative-level headline info
)))
3391 (headline-number (org-export-get-headline-number headline info
))
3392 (section-number (and (org-export-numbered-headline-p headline info
)
3393 (mapconcat 'number-to-string
3394 headline-number
".")))
3395 (todo (and (plist-get info
:with-todo-keywords
)
3396 (let ((todo (org-element-property
3397 :todo-keyword headline
)))
3399 (org-export-secondary-string todo
'e-odt info
)))))
3400 (todo-type (and todo
(org-element-property :todo-type headline
)))
3401 (priority (and (plist-get info
:with-priority
)
3402 (org-element-property :priority headline
)))
3403 (text (org-export-secondary-string
3404 (org-element-property :title headline
) 'e-odt info
))
3405 (tags (and (plist-get info
:with-tags
)
3406 (org-element-property :tags headline
)))
3407 (headline-label (concat "sec-" (mapconcat 'number-to-string
3408 headline-number
"-")))
3409 (format-function (cond
3410 ((functionp format-function
) format-function
)
3411 ((functionp org-e-odt-format-headline-function
)
3413 (lambda (todo todo-type priority text tags
3415 (funcall org-e-odt-format-headline-function
3416 todo todo-type priority text tags
))))
3417 (t 'org-e-odt-format-headline
))))
3418 (apply format-function
3419 todo todo-type priority text tags
3420 :headline-label headline-label
:level level
3421 :section-number section-number extra-keys
)))
3423 (defun org-e-odt-headline (headline contents info
)
3424 "Transcode an HEADLINE element from Org to HTML.
3425 CONTENTS holds the contents of the headline. INFO is a plist
3426 holding contextual information."
3427 (let* ((numberedp (org-export-numbered-headline-p headline info
))
3428 ;; Get level relative to current parsed data.
3429 (level (org-export-get-relative-level headline info
))
3430 (text (org-export-secondary-string
3431 (org-element-property :title headline
) 'e-odt info
))
3432 ;; Create the headline text.
3433 (full-text (org-e-odt-format-headline--wrap headline info
)))
3435 ;; Case 1: This is a footnote section: ignore it.
3436 ((org-element-property :footnote-section-p headline
) nil
)
3437 ;; Case 2. This is a deep sub-tree: export it as a list item.
3438 ;; Also export as items headlines for which no section
3439 ;; format has been found.
3440 ((org-export-low-level-p headline info
) ; FIXME (or (not section-fmt))
3441 ;; Build the real contents of the sub-tree.
3442 (let* ((type (if numberedp
'unordered
'unordered
)) ; FIXME
3443 (itemized-body (org-e-odt-format-list-item
3444 contents type nil nil full-text
)))
3446 (and (org-export-first-sibling-p headline info
)
3447 (org-e-odt-begin-plain-list type
))
3449 (and (org-export-last-sibling-p headline info
)
3450 (org-e-odt-end-plain-list type
)))))
3451 ;; Case 3. Standard headline. Export it as a section.
3453 (let* ((extra-ids (list (org-element-property :custom-id headline
)
3454 (org-element-property :id headline
)))
3455 (extra-ids nil
) ; FIXME
3456 (id (concat "sec-" (mapconcat 'number-to-string
3457 (org-export-get-headline-number
3458 headline info
) "-"))))
3460 (org-e-odt-format-tags
3461 '("<text:h text:style-name=\"Heading_20_%s\" text:outline-level=\"%s\">" .
3463 (concat (org-e-odt-format-extra-targets extra-ids
)
3464 (if (not id
) full-text
(org-e-odt-format-target full-text id
) ))
3469 ;;;; Horizontal Rule
3471 (defun org-e-odt-horizontal-rule (horizontal-rule contents info
)
3472 "Transcode an HORIZONTAL-RULE object from Org to HTML.
3473 CONTENTS is nil. INFO is a plist holding contextual information."
3474 (let ((attr (mapconcat #'identity
3475 (org-element-property :attr_odt horizontal-rule
)
3477 (org-e-odt--wrap-label horizontal-rule
3478 (org-e-odt-format-horizontal-line))))
3481 ;;;; Inline Babel Call
3483 ;; Inline Babel Calls are ignored.
3486 ;;;; Inline Src Block
3488 (defun org-e-odt-inline-src-block (inline-src-block contents info
)
3489 "Transcode an INLINE-SRC-BLOCK element from Org to HTML.
3490 CONTENTS holds the contents of the item. INFO is a plist holding
3491 contextual information."
3492 (let* ((org-lang (org-element-property :language inline-src-block
))
3493 (code (org-element-property :value inline-src-block
))
3494 (separator (org-e-odt--find-verb-separator code
)))
3500 (defun org-e-odt-format-section (text class
&optional id
)
3501 (let ((extra (concat (when id
(format " id=\"%s\"" id
)))))
3502 (concat (format "<div class=\"%s\"%s>\n" class extra
) text
"</div>\n")))
3504 (defun org-e-odt-inlinetask (inlinetask contents info
)
3505 "Transcode an INLINETASK element from Org to ODT.
3506 CONTENTS holds the contents of the block. INFO is a plist
3507 holding contextual information."
3509 ;; If `org-e-odt-format-inlinetask-function' is provided, call it
3510 ;; with appropriate arguments.
3511 ((functionp org-e-odt-format-inlinetask-function
)
3512 (let ((format-function
3514 (lambda (todo todo-type priority text tags
3515 &key contents
&allow-other-keys
)
3516 (funcall org-e-odt-format-inlinetask-function
3517 todo todo-type priority text tags contents
)))))
3518 (org-e-odt-format-headline--wrap
3519 inlinetask info format-function
:contents contents
)))
3520 ;; Otherwise, use a default template.
3521 (t (org-e-odt--wrap-label
3523 (org-e-odt-format-stylized-paragraph
3524 nil
(org-e-odt-format-textbox
3525 (concat (org-e-odt-format-stylized-paragraph
3526 "OrgInlineTaskHeading" (org-e-odt-format-headline--wrap
3529 nil nil
"OrgInlineTaskFrame" " style:rel-width=\"100%\""))))))
3533 (defun org-e-odt-format-list-item (contents type checkbox
3534 &optional term-counter-id
3538 (org-e-odt-format-fontify (case checkbox
3541 (trans "[-]")) 'code
)))
3543 (org-e-odt-begin-list-item type term-counter-id headline
)
3544 ;; FIXME checkbox (and checkbox " ")
3546 (org-e-odt-end-list-item type
)))
3548 (defun org-e-odt-item (item contents info
)
3549 "Transcode an ITEM element from Org to HTML.
3550 CONTENTS holds the contents of the item. INFO is a plist holding
3551 contextual information."
3552 ;; Grab `:level' from plain-list properties, which is always the
3553 ;; first element above current item.
3554 (let* ((plain-list (org-export-get-parent item info
))
3555 (type (org-element-property :type plain-list
))
3556 (level (org-element-property :level plain-list
))
3557 (counter (org-element-property :counter item
))
3558 (checkbox (org-element-property :checkbox item
))
3559 (tag (let ((tag (org-element-property :tag item
)))
3560 (and tag
(org-export-secondary-string tag
'e-odt info
)))))
3561 (org-e-odt-format-list-item
3562 contents type checkbox
(or tag counter
))))
3567 (defun org-e-odt-keyword (keyword contents info
)
3568 "Transcode a KEYWORD element from Org to HTML.
3569 CONTENTS is nil. INFO is a plist holding contextual information."
3570 (let ((key (org-element-property :key keyword
))
3571 (value (org-element-property :value keyword
)))
3573 ((string= key
"LATEX") value
)
3574 ((string= key
"INDEX") (format "\\index{%s}" value
))
3575 ((string= key
"TARGET") nil
; FIXME
3576 ;; (format "\\label{%s}" (org-export-solidify-link-text value))
3578 ((string= key
"toc")
3579 (let ((value (downcase value
)))
3581 ((string-match "\\<headlines\\>" value
)
3582 (let ((depth (or (and (string-match "[0-9]+" value
)
3583 (string-to-number (match-string 0 value
)))
3584 (plist-get info
:with-toc
))))
3585 (when (wholenump depth
) (org-e-odt-toc depth info
))))
3586 ((string= "tables" value
) "FIXME")
3587 ((string= "figures" value
) "FIXME")
3588 ((string= "listings" value
)
3590 ;; At the moment, src blocks with a caption are wrapped
3591 ;; into a figure environment.
3595 ;;;; Latex Environment
3597 (defun org-e-odt-format-latex (latex-frag processing-type
)
3598 (let* ((prefix (case processing-type
3600 (mathml "ltxmathml/")))
3602 (concat prefix
(file-name-sans-extension
3603 (file-name-nondirectory (buffer-file-name)))))
3604 (cache-dir (file-name-directory (buffer-file-name )))
3605 (display-msg (case processing-type
3606 (dvipng "Creating LaTeX Image...")
3607 (mathml "Creating MathML snippet..."))))
3610 (org-format-latex cache-relpath cache-dir nil display-msg
3611 nil nil processing-type
)
3614 (defun org-e-odt-latex-environment (latex-environment contents info
)
3615 "Transcode a LATEX-ENVIRONMENT element from Org to HTML.
3616 CONTENTS is nil. INFO is a plist holding contextual information."
3617 (org-e-odt--wrap-label
3620 (org-remove-indentation
3621 (org-element-property :value latex-environment
)))
3622 (processing-type (plist-get info
:LaTeX-fragments
))
3623 (caption (org-element-property :caption latex-environment
))
3624 (short-caption (and (cdr caption
) (org-export-secondary-string
3625 (cdr caption
) 'e-odt info
)))
3626 (caption (and (car caption
) (org-export-secondary-string
3627 (car caption
) 'e-odt info
)))
3628 (label (org-element-property :name latex-environment
))
3630 (label (org-element-property :name latex-environment
)))
3632 ((member processing-type
'(t mathjax
))
3633 (let* ((formula-link (org-e-odt-format-latex latex-frag
'mathml
)))
3634 (when (and formula-link
3635 (string-match "file:\\([^]]*\\)" formula-link
))
3636 (org-e-odt-format-formula
3637 (match-string 1 formula-link
) caption label attr
))))
3638 ((equal processing-type
'dvipng
)
3639 (let* ((formula-link (org-e-odt-format-latex
3640 latex-frag processing-type
)))
3641 (when (and formula-link
3642 (string-match "file:\\([^]]*\\)" formula-link
))
3643 (org-e-odt-format-image
3644 (match-string 1 formula-link
) caption label attr
"paragraph"
3645 "__DvipngImage__"))))
3651 (defun org-e-odt-latex-fragment (latex-fragment contents info
)
3652 "Transcode a LATEX-FRAGMENT object from Org to HTML.
3653 CONTENTS is nil. INFO is a plist holding contextual information."
3654 (let* ((latex-frag (org-element-property :value latex-fragment
))
3655 (processing-type (plist-get info
:LaTeX-fragments
)))
3657 ((member processing-type
'(t mathjax
))
3658 (let* ((formula-link (org-e-odt-format-latex latex-frag
'mathml
))
3659 (src (and formula-link
3660 (string-match "file:\\([^]]*\\)" formula-link
)
3661 (match-string 1 formula-link
))))
3663 (org-e-odt-format-formula src
)))
3664 ((equal processing-type
'dvipng
)
3665 (let* ((formula-link (org-e-odt-format-latex latex-frag processing-type
))
3666 (src (and formula-link
3667 (string-match "file:\\([^]]*\\)" formula-link
)
3668 (match-string 1 formula-link
))))
3670 (org-e-odt-format-image src
)))
3676 (defun org-e-odt-line-break (line-break contents info
)
3677 "Transcode a LINE-BREAK object from Org to HTML.
3678 CONTENTS is nil. INFO is a plist holding contextual information."
3679 "<text:line-break/>\n")
3684 (defun org-e-odt-link--inline-image (link desc info
)
3685 "Return HTML code for an inline image.
3686 LINK is the link pointing to the inline image. INFO is a plist
3687 used as a communication channel."
3688 (let* ((type (org-element-property :type link
))
3689 (raw-path (org-element-property :path link
))
3690 (path (cond ((member type
'("http" "https"))
3691 (concat type
":" raw-path
))
3692 ((file-name-absolute-p raw-path
)
3693 (expand-file-name raw-path
))
3695 (parent (org-export-get-parent-paragraph link info
))
3696 (caption (org-element-property :caption parent
))
3697 (short-caption (and (cdr caption
) (org-export-secondary-string
3698 (cdr caption
) 'e-odt info
)))
3699 (caption (and (car caption
) (org-export-secondary-string
3700 (car caption
) 'e-odt info
)))
3701 (label (org-element-property :name parent
))
3702 ;; Retrieve latex attributes from the element around.
3703 (attr (let ((raw-attr
3704 (mapconcat #'identity
3705 (org-element-property :attr_odt parent
)
3707 (unless (string= raw-attr
"") raw-attr
))))
3708 ;; Now clear ATTR from any special keyword and set a default
3709 ;; value if nothing is left.
3710 (setq attr
(if (not attr
) "" (org-trim attr
)))
3711 ;; Return proper string, depending on DISPOSITION.
3712 (org-e-odt-format-image
3713 path caption label attr
(if (org-e-html-standalone-image-p link info
)
3714 "paragraph" "as-char"))))
3716 (defvar org-e-odt-standalone-image-predicate
3717 (function (lambda (paragraph)
3718 (or (org-element-property :caption paragraph
)
3719 (org-element-property :name paragraph
)))))
3721 (defun org-e-odt-standalone-image-p (element info
&optional predicate
)
3722 "Test if ELEMENT is a standalone image for the purpose ODT export.
3723 INFO is a plist holding contextual information.
3725 Return non-nil, if ELEMENT is of type paragraph and it's sole
3726 content, save for whitespaces, is a link that qualifies as an
3729 Return non-nil, if ELEMENT is of type link and it's containing
3730 paragraph has no other content save for leading and trailing
3733 Return nil, otherwise.
3735 Bind `org-e-odt-standalone-image-predicate' to constrain
3736 paragraph further. For example, to check for only captioned
3737 standalone images, do the following.
3739 \(setq org-e-odt-standalone-image-predicate
3740 \(lambda \(paragraph\)
3741 \(org-element-property :caption paragraph\)\)\)
3743 (let ((paragraph (case (org-element-type element
)
3745 (link (and (org-export-inline-image-p
3746 element org-e-odt-inline-image-rules
)
3747 (org-export-get-parent element info
)))
3750 (assert (eq (org-element-type paragraph
) 'paragraph
))
3751 (when (or (not (and (boundp 'org-e-odt-standalone-image-predicate
)
3752 (functionp org-e-odt-standalone-image-predicate
)))
3753 (funcall org-e-odt-standalone-image-predicate paragraph
))
3754 (let ((contents (org-element-contents paragraph
)))
3755 (loop for x in contents
3756 with inline-image-count
= 0
3758 ((eq (org-element-type x
) 'plain-text
)
3759 (not (org-string-nw-p x
)))
3760 ((eq (org-element-type x
) 'link
)
3761 (when (org-export-inline-image-p
3762 x org-e-odt-inline-image-rules
)
3763 (= (incf inline-image-count
) 1)))
3766 (defun org-e-odt-link (link desc info
)
3767 "Transcode a LINK object from Org to HTML.
3769 DESC is the description part of the link, or the empty string.
3770 INFO is a plist holding contextual information. See
3772 (let* ((type (org-element-property :type link
))
3773 (raw-path (org-element-property :path link
))
3774 ;; Ensure DESC really exists, or set it to nil.
3775 (desc (and (not (string= desc
"")) desc
))
3776 (imagep (org-export-inline-image-p
3777 link org-e-odt-inline-image-rules
))
3779 ((member type
'("http" "https" "ftp" "mailto"))
3780 (concat type
":" raw-path
))
3781 ((string= type
"file")
3782 (when (string-match "\\(.+\\)::.+" raw-path
)
3783 (setq raw-path
(match-string 1 raw-path
)))
3784 (if (file-name-absolute-p raw-path
)
3785 (concat "file://" (expand-file-name raw-path
))
3786 ;; TODO: Not implemented yet. Concat also:
3787 ;; (org-export-directory :HTML info)
3788 (concat "file://" raw-path
)))
3793 ((and (not desc
) (org-export-inline-image-p
3794 link org-e-odt-inline-image-rules
))
3795 (org-e-odt-link--inline-image link desc info
))
3796 ;; Radioed target: Target's name is obtained from original raw
3797 ;; link. Path is parsed and transcoded in order to have a proper
3798 ;; display of the contents.
3799 ((string= type
"radio")
3800 (org-e-odt-format-internal-link
3801 (org-export-secondary-string
3802 (org-element-parse-secondary-string
3803 path
(cdr (assq 'radio-target org-element-object-restrictions
)))
3805 (org-export-solidify-link-text path
)))
3806 ;; Links pointing to an headline: Find destination and build
3807 ;; appropriate referencing command.
3808 ((member type
'("custom-id" "fuzzy" "id"))
3809 (let ((destination (if (string= type
"fuzzy")
3810 (org-export-resolve-fuzzy-link link info
)
3811 (org-export-resolve-id-link link info
))))
3812 (case (org-element-type destination
)
3813 ;; Fuzzy link points nowhere.
3815 (org-e-odt-format-fontify
3816 (or desc
(org-export-secondary-string
3817 (org-element-property :raw-link link
)
3818 'e-odt info
)) 'emphasis
))
3819 ;; Fuzzy link points to an invisible target.
3821 ;; LINK points to an headline. If headlines are numbered
3822 ;; and the link has no description, display headline's
3823 ;; number. Otherwise, display description or headline's
3826 (let* ((headline-no (org-export-get-headline-number destination info
))
3827 (label (format "sec-%s" (mapconcat 'number-to-string
3829 (section-no (mapconcat 'number-to-string headline-no
".")))
3833 ((plist-get info
:section-numbers
) section-no
)
3834 (t (org-export-secondary-string
3835 (org-element-property :title destination
)
3837 (org-e-odt-format-internal-link desc label
)))
3838 ;; Fuzzy link points to a target. Do as above.
3842 ;; "__MathFormula__"
3843 ;; "__DvipngImage__"
3844 (let ((path (org-export-solidify-link-text path
)))
3847 ((org-e-odt-standalone-image-p destination info
)
3848 (org-export-get-ordinal
3849 (assoc 'link
(org-element-contents destination
))
3850 info
'link
'org-e-odt-standalone-image-p
))
3851 (t (org-export-get-ordinal destination info
))))
3852 (setq desc
(when number
3853 (if (atom number
) (number-to-string number
)
3854 (mapconcat 'number-to-string number
".")))))
3858 ((eq (org-element-type destination
) 'table
)
3860 ((org-e-odt-standalone-image-p destination info
)
3862 ((eq (org-element-type destination
) 'latex-environment
)
3863 ; FIXME: Check if it is
3864 ; acutally latex eqn.
3866 (t (error "Handle enumeration of %S" destination
)))))
3867 (org-e-odt-format-label-reference label default-category number
)))))))
3868 ;; Coderef: replace link with the reference name or the
3869 ;; equivalent line number.
3870 ((string= type
"coderef")
3871 (let* ((fmt (org-export-get-coderef-format path
(or desc
"%s")))
3872 (res (org-export-resolve-coderef path info
))
3873 (org-e-odt-suppress-xref nil
)
3874 (href (org-xml-format-href (concat "#coderef-" path
))))
3875 (format fmt
(org-e-odt-format-link res href
))))
3876 ;; Link type is handled by a special function.
3877 ((functionp (setq protocol
(nth 2 (assoc type org-link-protocols
))))
3878 (funcall protocol
(org-link-unescape path
) desc
'html
))
3879 ;; External link with a description part.
3880 ((and path desc
) (org-e-odt-format-link desc path
))
3881 ;; External link without a description part.
3882 (path (org-e-odt-format-link path path
))
3883 ;; No path, only description. Try to do something useful.
3884 (t (org-e-odt-format-fontify desc
'emphasis
)))))
3889 ;; Babel Calls are ignored.
3894 (defun org-e-odt-macro (macro contents info
)
3895 "Transcode a MACRO element from Org to HTML.
3896 CONTENTS is nil. INFO is a plist holding contextual information."
3897 ;; Use available tools.
3898 (org-export-expand-macro macro info
))
3903 (defun org-e-odt-paragraph (paragraph contents info
)
3904 "Transcode a PARAGRAPH element from Org to HTML.
3905 CONTENTS is the contents of the paragraph, as a string. INFO is
3906 the plist used as a communication channel."
3907 (let* ((style nil
) ; FIXME
3908 (class (cdr (assoc style
'((footnote .
"footnote")
3910 (extra (if class
(format " class=\"%s\"" class
) ""))
3911 (parent (org-export-get-parent paragraph info
))
3912 (parent-type (org-element-type parent
))
3913 (style (case parent-type
3914 (quote-block 'quote
)
3915 (center-block 'center
)
3916 (footnote-definition 'footnote
)
3918 (org-e-odt-format-stylized-paragraph style contents
)))
3923 (defun org-e-odt-plain-list (plain-list contents info
)
3924 "Transcode a PLAIN-LIST element from Org to HTML.
3925 CONTENTS is the contents of the list. INFO is a plist holding
3926 contextual information."
3927 (let* (arg1 ;; FIXME
3928 (type (org-element-property :type plain-list
))
3929 (attr (mapconcat #'identity
3930 (org-element-property :attr_odt plain-list
)
3932 (org-e-odt--wrap-label
3933 plain-list
(format "%s\n%s%s"
3934 (org-e-odt-begin-plain-list type
)
3935 contents
(org-e-odt-end-plain-list type
)))))
3939 (defun org-e-odt-convert-special-strings (string)
3940 "Convert special characters in STRING to ODT."
3941 (let ((all org-e-odt-special-string-regexps
)
3943 (while (setq a
(pop all
))
3944 (setq re
(car a
) rpl
(cdr a
) start
0)
3945 (while (string-match re string start
)
3946 (setq string
(replace-match rpl t nil string
))))
3949 ;; (defun org-e-odt-encode-plain-text (s)
3950 ;; "Convert plain text characters to HTML equivalent.
3951 ;; Possible conversions are set in `org-export-html-protect-char-alist'."
3952 ;; (let ((cl org-e-odt-protect-char-alist) c)
3953 ;; (while (setq c (pop cl))
3955 ;; (while (string-match (car c) s start)
3956 ;; (setq s (replace-match (cdr c) t t s)
3957 ;; start (1+ (match-beginning 0))))))
3960 (defun org-e-odt-plain-text (text info
)
3961 "Transcode a TEXT string from Org to HTML.
3962 TEXT is the string to transcode. INFO is a plist holding
3963 contextual information."
3964 (setq text
(org-e-odt-encode-plain-text text t
))
3965 ;; Protect %, #, &, $, ~, ^, _, { and }.
3966 ;; (while (string-match "\\([^\\]\\|^\\)\\([%$#&{}~^_]\\)" text)
3968 ;; (replace-match (format "\\%s" (match-string 2 text)) nil t text 2)))
3970 ;; (setq text (replace-regexp-in-string
3971 ;; "\\(?:[^\\]\\|^\\)\\(\\\\\\)\\(?:[^%$#&{}~^_\\]\\|$\\)"
3972 ;; "$\\backslash$" text nil t 1))
3973 ;; HTML into \HTML{} and TeX into \TeX{}.
3974 ;; (let ((case-fold-search nil)
3976 ;; (while (string-match "\\<\\(\\(?:La\\)?TeX\\)\\>" text start)
3977 ;; (setq text (replace-match
3978 ;; (format "\\%s{}" (match-string 1 text)) nil t text)
3979 ;; start (match-end 0))))
3980 ;; Handle quotation marks
3981 ;; (setq text (org-e-odt--quotation-marks text info))
3982 ;; Convert special strings.
3983 ;; (when (plist-get info :with-special-strings)
3984 ;; (while (string-match (regexp-quote "...") text)
3985 ;; (setq text (replace-match "\\ldots{}" nil t text))))
3986 (when (plist-get info
:with-special-strings
)
3987 (setq text
(org-e-odt-convert-special-strings text
)))
3988 ;; Handle break preservation if required.
3989 (when (plist-get info
:preserve-breaks
)
3990 (setq text
(replace-regexp-in-string "\\(\\\\\\\\\\)?[ \t]*\n" " \\\\\\\\\n"
3996 ;;;; Property Drawer
3998 (defun org-e-odt-property-drawer (property-drawer contents info
)
3999 "Transcode a PROPERTY-DRAWER element from Org to HTML.
4000 CONTENTS is nil. INFO is a plist holding contextual
4002 ;; The property drawer isn't exported but we want separating blank
4003 ;; lines nonetheless.
4009 (defun org-e-odt-quote-block (quote-block contents info
)
4010 "Transcode a QUOTE-BLOCK element from Org to HTML.
4011 CONTENTS holds the contents of the block. INFO is a plist
4012 holding contextual information."
4013 (org-e-odt--wrap-label quote-block contents
))
4018 (defun org-e-odt-quote-section (quote-section contents info
)
4019 "Transcode a QUOTE-SECTION element from Org to HTML.
4020 CONTENTS is nil. INFO is a plist holding contextual information."
4021 (let ((value (org-remove-indentation
4022 (org-element-property :value quote-section
))))
4023 (when value
(org-e-odt-format-source-code-or-example value nil
))))
4028 (defun org-e-odt-section (section contents info
) ; FIXME
4029 "Transcode a SECTION element from Org to HTML.
4030 CONTENTS holds the contents of the section. INFO is a plist
4031 holding contextual information."
4036 (defun org-e-odt-radio-target (radio-target text info
)
4037 "Transcode a RADIO-TARGET object from Org to HTML.
4038 TEXT is the text of the target. INFO is a plist holding
4039 contextual information."
4040 (org-e-odt-format-anchor
4041 text
(org-export-solidify-link-text
4042 (org-element-property :value radio-target
))))
4047 (defun org-e-odt-special-block (special-block contents info
)
4048 "Transcode a SPECIAL-BLOCK element from Org to HTML.
4049 CONTENTS holds the contents of the block. INFO is a plist
4050 holding contextual information."
4051 (let ((type (downcase (org-element-property :type special-block
))))
4052 (org-e-odt--wrap-label
4054 (format "\\begin{%s}\n%s\\end{%s}" type contents type
))))
4059 (defun org-e-odt-src-block (src-block contents info
)
4060 "Transcode a SRC-BLOCK element from Org to HTML.
4061 CONTENTS holds the contents of the item. INFO is a plist holding
4062 contextual information."
4063 (let* ((lang (org-element-property :language src-block
))
4064 (caption (org-element-property :caption src-block
))
4065 (label (org-element-property :name src-block
)))
4066 ;; FIXME: Handle caption
4067 ;; caption-str (when caption)
4068 ;; (main (org-export-secondary-string (car caption) 'e-odt info))
4069 ;; (secondary (org-export-secondary-string (cdr caption) 'e-odt info))
4070 ;; (caption-str (org-e-odt--caption/label-string caption label info))
4071 (org-e-odt-format-code src-block info
)))
4074 ;;;; Statistics Cookie
4076 (defun org-e-odt-statistics-cookie (statistics-cookie contents info
)
4077 "Transcode a STATISTICS-COOKIE object from Org to HTML.
4078 CONTENTS is nil. INFO is a plist holding contextual information."
4079 (let ((cookie-value (org-element-property :value statistics-cookie
)))
4080 (org-e-odt-format-fontify cookie-value
'code
)))
4085 (defun org-e-odt-subscript (subscript contents info
)
4086 "Transcode a SUBSCRIPT object from Org to HTML.
4087 CONTENTS is the contents of the object. INFO is a plist holding
4088 contextual information."
4089 ;; (format (if (= (length contents) 1) "$_%s$" "$_{\\mathrm{%s}}$") contents)
4090 (org-e-odt-format-fontify contents
'subscript
))
4095 (defun org-e-odt-superscript (superscript contents info
)
4096 "Transcode a SUPERSCRIPT object from Org to HTML.
4097 CONTENTS is the contents of the object. INFO is a plist holding
4098 contextual information."
4099 ;; (format (if (= (length contents) 1) "$^%s$" "$^{\\mathrm{%s}}$") contents)
4100 (org-e-odt-format-fontify contents
'superscript
))
4105 (defun org-e-odt-get-colwidth (c)
4106 (let ((col-widths (plist-get table-info
:width
)))
4107 (or (and org-lparse-table-is-styled
(aref col-widths c
)) 0)))
4109 (defun org-e-odt-table-row (fields &optional text-for-empty-fields
)
4110 (incf org-e-odt-table-rownum
)
4112 (org-e-odt-format-table-row
4115 (when (and (string= x
"") text-for-empty-fields
)
4116 (setq x text-for-empty-fields
))
4118 (let ((horiz-span (org-e-odt-get-colwidth i
)))
4119 (org-e-odt-format-table-cell
4120 x org-e-odt-table-rownum i horiz-span
)))
4123 (defun org-e-odt-table-preamble ()
4124 (let ((colgroup-vector (plist-get table-info
:column-groups
)) ;; FIXME
4125 c gr colgropen preamble
)
4126 (unless (aref colgroup-vector
0)
4127 (setf (aref colgroup-vector
0) 'start
))
4128 (dotimes (c columns-number preamble
)
4129 (setq gr
(aref colgroup-vector c
))
4133 (when (memq gr
'(start start-end
))
4134 (prog1 (if colgropen
"</colgroup>\n<colgroup>" "\n<colgroup>")
4135 (setq colgropen t
)))
4136 (let* ((colalign-vector (plist-get table-info
:alignment
)) ;; FIXME
4137 (align (cdr (assoc (aref colalign-vector c
)
4140 ("c" .
"center")))))
4141 (alignspec (if (and (boundp 'org-e-odt-format-table-no-css
)
4142 org-e-odt-format-table-no-css
)
4143 " align=\"%s\"" " class=\"%s\""))
4144 (extra (format alignspec align
)))
4145 (format "<col%s />" extra
))
4146 (when (memq gr
'(end start-end
))
4147 (setq colgropen nil
)
4149 (concat preamble
(if colgropen
"</colgroup>"))))
4151 (defun org-e-odt-list-table (lines caption label attributes
)
4152 (let* ((splice nil
) head
4153 (org-e-odt-table-rownum -
1)
4156 org-e-odt-table-cur-rowgrp-is-hdr
4157 org-e-odt-table-rowgrp-open
4159 (org-lparse-table-style 'org-table
)
4160 org-lparse-table-is-styled
)
4163 (setq org-lparse-table-is-styled nil
)
4164 (mapconcat 'org-e-odt-table-row lines
"\n"))
4166 (setq org-lparse-table-is-styled t
)
4169 (org-e-odt-begin-table caption label attributes
)
4170 ;; FIXME (org-e-odt-table-preamble)
4171 (org-e-odt-begin-table-rowgroup head
)
4176 ((equal line
'hline
) (org-e-odt-begin-table-rowgroup))
4177 (t (org-e-odt-table-row line
))))
4180 (org-e-odt-end-table-rowgroup)
4181 (org-e-odt-end-table))))))
4183 (defun org-e-odt-transcode-table-row (row)
4184 (if (string-match org-table-hline-regexp row
) 'hline
4187 (org-export-secondary-string
4188 (let ((cell (org-element-parse-secondary-string
4190 (cdr (assq 'table org-element-string-restrictions
)))))
4193 (org-split-string row
"[ \t]*|[ \t]*"))))
4195 (defun org-e-odt-org-table-to-list-table (lines &optional splice
)
4196 "Convert org-table to list-table.
4197 LINES is a list of the form (ROW1 ROW2 ROW3 ...) where each
4198 element is a `string' representing a single row of org-table.
4199 Thus each ROW has vertical separators \"|\" separating the table
4200 fields. A ROW could also be a row-group separator of the form
4201 \"|---...|\". Return a list of the form (ROW1 ROW2 ROW3
4202 ...). ROW could either be symbol `'hline' or a list of the
4203 form (FIELD1 FIELD2 FIELD3 ...) as appropriate."
4207 (while (setq line
(pop lines
))
4208 (unless (string-match "^[ \t]*|-" line
)
4209 (push (org-e-odt-transcode-table-row line
) lines-1
))))
4210 (t (while (setq line
(pop lines
))
4212 ((string-match "^[ \t]*|-" line
)
4213 (when lines
(push 'hline lines-1
)))
4214 (t (push (org-e-odt-transcode-table-row line
) lines-1
))))))
4215 (nreverse lines-1
)))
4217 (defun org-e-odt-table-table (raw-table)
4219 (with-current-buffer (get-buffer-create "*org-export-table*")
4221 (let ((output (with-temp-buffer
4224 (re-search-forward "^[ \t]*|[^|]" nil t
)
4225 (table-generate-source 'html
"*org-export-table*")
4226 (with-current-buffer "*org-export-table*"
4227 (org-trim (buffer-string))))))
4228 (kill-buffer (get-buffer "*org-export-table*"))
4231 (defun org-e-odt-table (table contents info
)
4232 "Transcode a TABLE element from Org to HTML.
4233 CONTENTS is nil. INFO is a plist holding contextual information."
4234 (let* ((caption (org-element-property :caption table
))
4235 (short-caption (and (cdr caption
) (org-export-secondary-string
4236 (cdr caption
) 'e-odt info
)))
4237 (caption (and (car caption
) (org-export-secondary-string
4238 (car caption
) 'e-odt info
)))
4239 (label (org-element-property :name table
))
4240 (attr (mapconcat #'identity
4241 (org-element-property :attr_odt table
)
4243 (raw-table (org-element-property :raw-table table
))
4244 (table-type (org-element-property :type table
)))
4247 ;; (org-e-odt-table-table raw-table)
4250 (let* ((table-info (org-export-table-format-info raw-table
))
4251 (columns-number (length (plist-get table-info
:alignment
)))
4252 (lines (org-split-string
4253 (org-export-clean-table
4254 raw-table
(plist-get table-info
:special-column-p
)) "\n"))
4256 (genealogy (org-export-get-genealogy table info
))
4257 (parent (car genealogy
))
4258 (parent-type (org-element-type parent
)))
4259 (org-e-odt-list-table
4260 (org-e-odt-org-table-to-list-table lines
) caption label attr
))))))
4265 (defun org-e-odt-target (target contents info
)
4266 "Transcode a TARGET object from Org to HTML.
4267 CONTENTS is nil. INFO is a plist holding contextual
4269 (org-e-odt-format-anchor
4270 "" (org-export-solidify-link-text (org-element-property :value target
))))
4275 (defun org-e-odt-time-stamp (time-stamp contents info
)
4276 "Transcode a TIME-STAMP object from Org to HTML.
4277 CONTENTS is nil. INFO is a plist holding contextual
4279 ;; (let ((value (org-element-property :value time-stamp))
4280 ;; (type (org-element-property :type time-stamp))
4281 ;; (appt-type (org-element-property :appt-type time-stamp)))
4282 ;; (concat (cond ((eq appt-type 'scheduled)
4283 ;; (format "\\textbf{\\textsc{%s}} " org-scheduled-string))
4284 ;; ((eq appt-type 'deadline)
4285 ;; (format "\\textbf{\\textsc{%s}} " org-deadline-string))
4286 ;; ((eq appt-type 'closed)
4287 ;; (format "\\textbf{\\textsc{%s}} " org-closed-string)))
4288 ;; (cond ((memq type '(active active-range))
4289 ;; (format org-e-odt-active-timestamp-format value))
4290 ;; ((memq type '(inactive inactive-range))
4291 ;; (format org-e-odt-inactive-timestamp-format value))
4293 ;; (format org-e-odt-diary-timestamp-format value)))))
4294 (let ((value (org-element-property :value time-stamp
))
4295 (type (org-element-property :type time-stamp
))
4296 (appt-type (org-element-property :appt-type time-stamp
)))
4297 (setq value
(org-export-secondary-string value
'e-odt info
))
4298 (org-e-odt-format-fontify
4300 (org-e-odt-format-fontify
4301 (cond ((eq appt-type
'scheduled
) org-scheduled-string
)
4302 ((eq appt-type
'deadline
) org-deadline-string
)
4303 ((eq appt-type
'closed
) org-closed-string
)) "timestamp-kwd")
4304 ;; FIXME: (org-translate-time value)
4305 (org-e-odt-format-fontify value
"timestamp"))
4306 "timestamp-wrapper")))
4311 (defun org-e-odt-verbatim (verbatim contents info
)
4312 "Transcode a VERBATIM object from Org to HTML.
4313 CONTENTS is nil. INFO is a plist used as a communication
4316 verbatim
(org-element-property :value verbatim
) info
))
4321 (defun org-e-odt-verse-block (verse-block contents info
)
4322 "Transcode a VERSE-BLOCK element from Org to HTML.
4323 CONTENTS is nil. INFO is a plist holding contextual information."
4324 ;; Replace each newline character with line break. Also replace
4325 ;; each blank line with a line break.
4326 (setq contents
(replace-regexp-in-string
4327 "^ *\\\\\\\\$" "<br/>\n"
4328 (replace-regexp-in-string
4329 "\\(\\\\\\\\\\)?[ \t]*\n" " <br/>\n"
4330 (org-remove-indentation
4331 (org-export-secondary-string
4332 (org-element-property :value verse-block
)
4335 ;; Replace each white space at beginning of a line with a
4336 ;; non-breaking space.
4337 (while (string-match "^[ \t]+" contents
)
4338 (let ((new-str (org-e-odt-format-spaces
4339 (length (match-string 0 contents
)))))
4340 (setq contents
(replace-match new-str nil t contents
))))
4342 (org-e-odt--wrap-label
4343 verse-block
(format "<p class=\"verse\">\n%s</p>" contents
)))
4348 ;;; Filter Functions
4350 ;;;; Filter Settings
4353 ;;; Interactive functions
4355 (defun org-e-odt-export-to-odt
4356 (&optional subtreep visible-only body-only ext-plist pub-dir
)
4357 "Export current buffer to a HTML file.
4359 If narrowing is active in the current buffer, only export its
4362 If a region is active, export that region.
4364 When optional argument SUBTREEP is non-nil, export the sub-tree
4365 at point, extracting information from the headline properties
4368 When optional argument VISIBLE-ONLY is non-nil, don't export
4369 contents of hidden elements.
4371 When optional argument BODY-ONLY is non-nil, only write code
4372 between \"\\begin{document}\" and \"\\end{document}\".
4374 EXT-PLIST, when provided, is a property list with external
4375 parameters overriding Org default settings, but still inferior to
4376 file-local settings.
4378 When optional argument PUB-DIR is set, use it as the publishing
4381 Return output file's name."
4383 (setq debug-on-error t
)
4385 ;; (let* ((outfile (org-export-output-file-name ".html" subtreep pub-dir))
4386 ;; (outfile "content.xml"))
4387 ;; (org-export-to-file
4388 ;; 'e-odt outfile subtreep visible-only body-only ext-plist))
4390 (let* ((outbuf (org-e-odt-init-outfile))
4391 (target (org-export-output-file-name ".odt" subtreep pub-dir
))
4392 (outdir (file-name-directory (buffer-file-name outbuf
)))
4393 (default-directory outdir
))
4395 ;; FIXME: for copying embedded images
4396 (setq org-current-export-file
4397 (file-name-directory
4398 (org-export-output-file-name ".odt" subtreep nil
)))
4400 (org-export-to-buffer
4402 (memq 'subtree optns
) (memq 'visible optns
) (memq 'body optns
))
4404 (setq org-lparse-opt-plist nil
) ; FIXME
4405 (org-e-odt-save-as-outfile target
;; info
4415 ;;; FIXMES, TODOS, FOR REVIEW etc
4417 ;;;; org-format-table-html
4418 ;;;; org-format-org-table-html
4419 ;;;; org-format-table-table-html
4420 ;;;; org-table-number-fraction
4421 ;;;; org-table-number-regexp
4422 ;;;; org-e-odt-table-caption-above
4425 ;;;; "<span style=\"visibility:hidden;\">%s</span>"
4426 ;;;; Remove display properties
4428 ;;;; org-e-odt-with-timestamp
4429 ;;;; org-e-odt-html-helper-timestamp
4431 ;;;; org-export-as-html-and-open
4432 ;;;; org-export-as-html-batch
4433 ;;;; org-export-as-html-to-buffer
4434 ;;;; org-replace-region-by-html
4435 ;;;; org-export-region-as-html
4436 ;;;; org-export-as-html
4438 ;;;; (org-export-directory :html opt-plist)
4439 ;;;; (plist-get opt-plist :html-extension)
4440 ;;;; org-e-odt-toplevel-hlevel
4441 ;;;; org-e-odt-special-string-regexps
4442 ;;;; org-e-odt-coding-system
4443 ;;;; org-e-odt-coding-system
4444 ;;;; org-e-odt-inline-image-extensions
4445 ;;;; org-e-odt-protect-char-alist
4446 ;;;; org-e-odt-table-use-header-tags-for-first-column
4447 ;;;; org-e-odt-todo-kwd-class-prefix
4448 ;;;; org-e-odt-tag-class-prefix
4449 ;;;; org-e-odt-footnote-separator
4452 ;;; Library Initializations
4456 ;; Let Org open all OpenDocument files using system-registered app
4457 (add-to-list 'org-file-apps
4458 (cons (concat "\\." (car desc
) "\\'") 'system
))
4459 ;; Let Emacs open all OpenDocument files in archive mode
4460 (add-to-list 'auto-mode-alist
4461 (cons (concat "\\." (car desc
) "\\'") 'archive-mode
)))
4462 org-e-odt-file-extensions
)
4465 ;; (eval-after-load 'org-exp
4466 ;; '(add-to-list 'org-export-inbuffer-options-extra
4467 ;; '("ODT_STYLES_FILE" :odt-styles-file)))
4469 (provide 'org-e-odt
)
4471 ;;; org-e-odt.el ends here