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-export-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-export-e-odt-org-styles-alist
))))
48 (cdr (assoc entity
(cdr (assoc category
49 org-export-e-odt-default-org-styles-alist
))))
50 (error "Cannot determine style name for entity %s of type %s"
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 (plist-get info
:title
))
59 (author (plist-get info
:author
))
60 (date (plist-get info
:date
))
61 (iso-date (org-e-odt-format-date date
))
62 (date (org-e-odt-format-date date
"%d %b %Y"))
63 (email (plist-get info
:email
))
64 ;; switch on or off above vars based on user settings
65 (author (and (plist-get info
:with-author
) (or author email
)))
66 (email (and (plist-get info
:with-email
) email
))
67 ;; (date (and (plist-get info :time-stamp-file) date))
73 (org-e-odt-format-stylized-paragraph
74 'title
(format "\n<text:title>%s</text:title>" title
))
76 "\n<text:p text:style-name=\"OrgTitle\"/>"))
78 ((and author
(not email
))
81 (org-e-odt-format-stylized-paragraph
83 (format "<text:initial-creator>%s</text:initial-creator>" author
))
85 "\n<text:p text:style-name=\"OrgSubtitle\"/>"))
89 (org-e-odt-format-stylized-paragraph
91 (org-e-odt-format-link
92 (format "<text:initial-creator>%s</text:initial-creator>" author
)
93 (concat "mailto:" email
)))
95 "\n<text:p text:style-name=\"OrgSubtitle\"/>")))
99 (org-e-odt-format-stylized-paragraph
102 '("<text:date style:data-style-name=\"%s\" text:date-value=\"%s\">"
104 date
"N75" iso-date
))
106 "<text:p text:style-name=\"OrgSubtitle\"/>")))))
108 (defun org-e-odt-begin-section (style &optional name
)
109 (let ((default-name (car (org-e-odt-add-automatic-style "Section"))))
110 (format "<text:section text:style-name=\"%s\" text:name=\"%s\">"
111 style
(or name default-name
))))
113 (defun org-e-odt-end-section ()
116 (defun org-e-odt-begin-paragraph (&optional style
)
117 (format "<text:p%s>" (org-e-odt-get-extra-attrs-for-paragraph-style style
)))
119 (defun org-e-odt-end-paragraph ()
122 (defun org-e-odt-get-extra-attrs-for-paragraph-style (style)
126 ((stringp style
) style
)
127 ((symbolp style
) (org-e-odt-get-style-name-for-entity
130 (error "Don't know how to handle paragraph style %s" style
))
131 (format " text:style-name=\"%s\"" style-name
)))
133 (defun org-e-odt-format-stylized-paragraph (style text
)
134 (format "\n<text:p%s>%s</text:p>"
135 (org-e-odt-get-extra-attrs-for-paragraph-style style
)
138 (defun org-e-odt-format-author (&optional author
)
139 (when (setq author
(or author
(plist-get org-lparse-opt-plist
:author
)))
140 (format "<dc:creator>%s</dc:creator>" author
)))
142 (defun org-e-odt-format-date (&optional org-ts fmt
)
145 (and (stringp org-ts
)
146 (string-match org-ts-regexp0 org-ts
)
148 (org-fix-decoded-time
149 (org-parse-time-string (match-string 0 org-ts
) t
)))))
152 (fmt (format-time-string fmt time
))
153 (t (setq date
(format-time-string "%Y-%m-%dT%H:%M:%S%z" time
))
154 (format "%s:%s" (substring date
0 -
2) (substring date -
2)))))))
156 (defun org-e-odt-begin-annotation (&optional author date
)
158 "<office:annotation>\n"
159 (and author
(org-e-odt-format-author author
))
160 (org-e-odt-format-tags
161 '("<dc:date>" .
"</dc:date>")
162 (org-e-odt-format-date
163 (or date
(plist-get org-lparse-opt-plist
:date
))))
164 (org-e-odt-begin-paragraph)))
166 (defun org-e-odt-end-annotation ()
167 "</office:annotation>")
169 (defun org-e-odt-begin-plain-list (ltype)
170 (let* ((style-name (org-e-odt-get-style-name-for-entity 'list ltype
))
172 ;; (if (or org-lparse-list-table-p
173 ;; (and (= 1 (length org-lparse-list-stack))
174 ;; (null org-e-odt-list-stack-stashed)))
175 ;; " text:continue-numbering=\"false\""
176 ;; " text:continue-numbering=\"true\"")
178 " text:continue-numbering=\"true\""
181 (format " text:style-name=\"%s\"" style-name
)))))
183 ((ordered unordered descriptive
)
185 ;; (org-e-odt-end-paragraph)
186 (format "<text:list%s>" extra
)))
187 (t (error "Unknown list type: %s" ltype
)))))
189 (defun org-e-odt-end-plain-list (ltype)
190 (if ltype
"</text:list>"
191 (error "Unknown list type: %s" ltype
)))
193 (defun org-e-odt-begin-list-item (ltype &optional arg headline
)
196 (assert (not headline
) t
)
197 (let* ((counter arg
) (extra ""))
198 (concat "<text:list-item>" ;; (org-e-odt-begin-paragraph)
200 ;; (if (= (length org-lparse-list-stack)
201 ;; (length org-e-odt-list-stack-stashed))
202 ;; "<text:list-header>" "<text:list-item>")
205 (let* ((id arg
) (extra ""))
208 ;; (org-e-odt-begin-paragraph)
209 (if headline
(org-e-odt-format-target headline id
)
210 (org-e-odt-format-bookmark "" id
)))
211 ;; (if (= (length org-lparse-list-stack)
212 ;; (length org-e-odt-list-stack-stashed))
213 ;; "<text:list-header>" "<text:list-item>")
216 (assert (not headline
) t
)
217 (let ((term (or arg
"(no term)")))
219 (org-e-odt-format-tags
220 '("<text:list-item>" .
"</text:list-item>")
221 (org-e-odt-format-stylized-paragraph 'definition-term term
))
222 (org-e-odt-begin-list-item 'unordered
)
223 (org-e-odt-begin-plain-list 'descriptive
)
224 (org-e-odt-begin-list-item 'unordered
))))
225 (t (error "Unknown list type"))))
227 (defun org-e-odt-end-list-item (ltype)
230 ;; (org-lparse-insert-tag
231 ;; (if (= (length org-lparse-list-stack)
232 ;; (length org-e-odt-list-stack-stashed))
233 ;; (prog1 "</text:list-header>"
234 ;; (setq org-e-odt-list-stack-stashed nil))
235 ;; "</text:list-item>")
241 (org-e-odt-end-list-item 'unordered
)
242 (org-e-odt-end-plain-list 'descriptive
)
243 (org-e-odt-end-list-item 'unordered
)
245 (t (error "Unknown list type"))))
247 (defun org-e-odt-discontinue-list ()
248 (let ((stashed-stack org-lparse-list-stack
))
249 (loop for list-type in stashed-stack
250 do
(org-lparse-end-list-item-1 list-type
)
251 (org-lparse-end-list list-type
))
252 (setq org-e-odt-list-stack-stashed stashed-stack
)))
254 (defun org-e-odt-continue-list ()
255 (setq org-e-odt-list-stack-stashed
(nreverse org-e-odt-list-stack-stashed
))
256 (loop for list-type in org-e-odt-list-stack-stashed
257 do
(org-lparse-begin-list list-type
)
258 (org-lparse-begin-list-item list-type
)))
260 (defun org-e-odt-write-automatic-styles ()
261 "Write automatic styles to \"content.xml\"."
263 (find-file-noselect (expand-file-name "content.xml") t
)
264 ;; position the cursor
265 (goto-char (point-min))
266 (re-search-forward " </office:automatic-styles>" nil t
)
267 (goto-char (match-beginning 0))
268 ;; write automatic table styles
269 (loop for
(style-name props
) in
270 (plist-get org-e-odt-automatic-styles
'Table
) do
271 (when (setq props
(or (plist-get props
:rel-width
) 96))
272 (insert (format org-e-odt-table-style-format style-name props
))))))
274 (defun org-e-odt-add-automatic-style (object-type &optional object-props
)
275 "Create an automatic style of type OBJECT-TYPE with param OBJECT-PROPS.
276 OBJECT-PROPS is (typically) a plist created by passing
277 \"#+ATTR_ODT: \" option of the object in question to
278 `org-lparse-get-block-params'.
280 Use `org-e-odt-object-counters' to generate an automatic
281 OBJECT-NAME and STYLE-NAME. If OBJECT-PROPS is non-nil, add a
282 new entry in `org-e-odt-automatic-styles'. Return (OBJECT-NAME
284 (assert (stringp object-type
))
285 (let* ((object (intern object-type
))
287 (seqno (1+ (or (plist-get org-e-odt-object-counters seqvar
) 0)))
288 (object-name (format "%s%d" object-type seqno
)) style-name
)
289 (setq org-e-odt-object-counters
290 (plist-put org-e-odt-object-counters seqvar seqno
))
292 (setq style-name
(format "Org%s" object-name
))
293 (setq org-e-odt-automatic-styles
294 (plist-put org-e-odt-automatic-styles object
295 (append (list (list style-name object-props
))
296 (plist-get org-e-odt-automatic-styles object
)))))
297 (cons object-name style-name
)))
299 (defun org-e-odt-format-table-columns ()
300 (let* ((num-cols (length (plist-get table-info
:alignment
)))
301 (col-nos (loop for i from
0 below num-cols collect i
))
303 (col-widths (plist-get table-info
:width
))
304 (style (or (nth 1 org-e-odt-table-style-spec
) "OrgTable")))
307 (let* ((width (or (and org-lparse-table-is-styled
(aref col-widths c
))
309 (org-e-odt-make-string
311 (org-e-odt-format-tags
312 "<table:table-column table:style-name=\"%sColumn\"/>" "" style
))))
316 (defun org-e-odt-begin-table (caption label attributes
)
317 ;; (setq org-e-odt-table-indentedp (not (null org-lparse-list-stack)))
318 (setq org-e-odt-table-indentedp nil
) ; FIXME
319 (when org-e-odt-table-indentedp
320 ;; Within the Org file, the table is appearing within a list item.
321 ;; OpenDocument doesn't allow table to appear within list items.
322 ;; Temporarily terminate the list, emit the table and then
323 ;; re-continue the list.
324 (org-e-odt-discontinue-list)
325 ;; Put the Table in an indented section.
326 (let ((level (length org-e-odt-list-stack-stashed
)))
327 (org-e-odt-begin-section (format "OrgIndentedSection-Level-%d" level
))))
328 (setq attributes
(org-lparse-get-block-params attributes
))
329 (setq org-e-odt-table-style
(plist-get attributes
:style
))
330 (setq org-e-odt-table-style-spec
331 (assoc org-e-odt-table-style org-export-e-odt-table-styles
))
333 (org-e-odt-format-stylized-paragraph
334 'table
(org-e-odt-format-entity-caption label caption
"__Table__"))
335 (let ((name-and-style (org-e-odt-add-automatic-style "Table" attributes
)))
337 "\n<table:table table:name=\"%s\" table:style-name=\"%s\">\n"
338 (car name-and-style
) (or (nth 1 org-e-odt-table-style-spec
)
339 (cdr name-and-style
) "OrgTable")))
340 (org-e-odt-format-table-columns) "\n")
342 ;; (org-e-html-pp table-info)
346 (defun org-e-odt-end-table ()
349 ;; (when org-e-odt-table-indentedp
350 ;; (org-e-odt-end-section)
351 ;; (org-e-odt-continue-list))
354 (defun org-e-odt-begin-table-rowgroup (&optional is-header-row
)
356 (concat (when org-e-odt-table-rowgrp-open
357 (org-e-odt-end-table-rowgroup))
358 (if is-header-row
"<table:table-header-rows>"
359 "<table:table-rows>"))
360 (setq org-e-odt-table-rowgrp-open t
)
361 (setq org-e-odt-table-cur-rowgrp-is-hdr is-header-row
)))
363 (defun org-e-odt-end-table-rowgroup ()
364 (when org-e-odt-table-rowgrp-open
365 (setq org-e-odt-table-rowgrp-open nil
)
366 (if org-e-odt-table-cur-rowgrp-is-hdr
367 "</table:table-header-rows>" "</table:table-rows>")))
369 (defun org-e-odt-format-table-row (row)
370 (org-e-odt-format-tags
371 '("<table:table-row>" .
"</table:table-row>") row
))
373 (defun org-e-odt-get-column-alignment (c)
374 (let ((colalign-vector (plist-get table-info
:alignment
)))
376 (assoc-default (aref colalign-vector c
)
381 (defun org-e-odt-get-table-cell-styles (r c
&optional style-spec
)
382 "Retrieve styles applicable to a table cell.
383 R and C are (zero-based) row and column numbers of the table
384 cell. STYLE-SPEC is an entry in `org-export-e-odt-table-styles'
385 applicable to the current table. It is `nil' if the table is not
386 associated with any style attributes.
388 Return a cons of (TABLE-CELL-STYLE-NAME . PARAGRAPH-STYLE-NAME).
390 When STYLE-SPEC is nil, style the table cell the conventional way
391 - choose cell borders based on row and column groupings and
392 choose paragraph alignment based on `org-col-cookies' text
394 `org-e-odt-get-paragraph-style-cookie-for-table-cell'.
396 When STYLE-SPEC is non-nil, ignore the above cookie and return
397 styles congruent with the ODF-1.2 specification."
401 ;; LibreOffice - particularly the Writer - honors neither table
402 ;; templates nor custom table-cell styles. Inorder to retain
403 ;; inter-operability with LibreOffice, only automatic styles are
404 ;; used for styling of table-cells. The current implementation is
405 ;; congruent with ODF-1.2 specification and hence is
406 ;; future-compatible.
408 ;; Additional Note: LibreOffice's AutoFormat facility for tables -
409 ;; which recognizes as many as 16 different cell types - is much
410 ;; richer. Unfortunately it is NOT amenable to easy configuration
413 (let* ((template-name (nth 1 style-spec
))
414 (cell-style-selectors (nth 2 style-spec
))
417 ((and (cdr (assoc 'use-first-column-styles cell-style-selectors
))
418 (= c
0)) "FirstColumn")
419 ((and (cdr (assoc 'use-last-column-styles cell-style-selectors
))
420 (= c
(1- org-lparse-table-ncols
))) "LastColumn")
421 ((and (cdr (assoc 'use-first-row-styles cell-style-selectors
))
423 ((and (cdr (assoc 'use-last-row-styles cell-style-selectors
))
424 (= r org-e-odt-table-rownum
))
426 ((and (cdr (assoc 'use-banding-rows-styles cell-style-selectors
))
427 (= (% r
2) 1)) "EvenRow")
428 ((and (cdr (assoc 'use-banding-rows-styles cell-style-selectors
))
429 (= (% r
2) 0)) "OddRow")
430 ((and (cdr (assoc 'use-banding-columns-styles cell-style-selectors
))
431 (= (% c
2) 1)) "EvenColumn")
432 ((and (cdr (assoc 'use-banding-columns-styles cell-style-selectors
))
433 (= (% c
2) 0)) "OddColumn")
436 (concat template-name cell-type
"TableCell")
437 (concat template-name cell-type
"TableParagraph"))))
444 ((eq (cdr (assoc r nil
;; org-lparse-table-rowgrp-info FIXME
447 (when (= r org-e-odt-table-rownum
) "B")
450 ((or (memq (nth c org-table-colgroup-info
) '(:start
:startend
))
451 (memq (nth (1- c
) org-table-colgroup-info
) '(:end
:startend
))) "L")
453 (capitalize (org-e-odt-get-column-alignment c
))))))
455 (defun org-e-odt-get-paragraph-style-cookie-for-table-cell (r c
)
457 (and (not org-e-odt-table-style-spec
)
459 (org-e-odt-table-cur-rowgrp-is-hdr "OrgTableHeading")
461 ;; (org-lparse-get 'TABLE-FIRST-COLUMN-AS-LABELS)
464 (t "OrgTableContents")))
465 (and org-lparse-table-is-styled
466 (cdr (org-e-odt-get-table-cell-styles
467 r c org-e-odt-table-style-spec
)))))
469 (defun org-e-odt-get-style-name-cookie-for-table-cell (r c
)
470 (when org-lparse-table-is-styled
471 (let* ((cell-styles (org-e-odt-get-table-cell-styles
472 r c org-e-odt-table-style-spec
))
473 (table-cell-style (car cell-styles
)))
476 (defun org-e-odt-format-table-cell (data r c horiz-span
)
478 (let* ((paragraph-style-cookie
479 (org-e-odt-get-paragraph-style-cookie-for-table-cell r c
))
481 (org-e-odt-get-style-name-cookie-for-table-cell r c
))
482 (extra (and style-name-cookie
483 (format " table:style-name=\"%s\"" style-name-cookie
)))
485 (and (> horiz-span
0)
486 (format " table:number-columns-spanned=\"%d\""
488 (org-e-odt-format-tags
489 '("<table:table-cell%s>" .
"</table:table-cell>")
490 (if org-lparse-list-table-p data
491 (org-e-odt-format-stylized-paragraph paragraph-style-cookie data
)) extra
))
493 (dotimes (i horiz-span
)
494 (setq s
(concat s
"\n<table:covered-table-cell/>"))) s
)
497 (defun org-e-odt-begin-toc (lang-specific-heading max-level
)
500 <text:table-of-content text:style-name=\"Sect2\" text:protected=\"true\" text:name=\"Table of Contents1\">
501 <text:table-of-content-source text:outline-level=\"%d\">
502 <text:index-title-template text:style-name=\"Contents_20_Heading\">%s</text:index-title-template>
503 " max-level lang-specific-heading
)
505 (let ((entry-templates ""))
506 (loop for level from
1 upto
10
507 do
(setq entry-templates
508 (concat entry-templates
511 <text:table-of-content-entry-template text:outline-level=\"%d\" text:style-name=\"Contents_20_%d\">
512 <text:index-entry-link-start text:style-name=\"Internet_20_link\"/>
513 <text:index-entry-chapter/>
514 <text:index-entry-text/>
515 <text:index-entry-link-end/>
516 </text:table-of-content-entry-template>
521 </text:table-of-content-source>
524 <text:index-title text:style-name=\"Sect1\" text:name=\"Table of Contents1_Head\">
525 <text:p text:style-name=\"Contents_20_Heading\">%s</text:p>
527 " lang-specific-heading
)))
529 (defun org-e-odt-end-toc ()
532 </text:table-of-content>
535 (defun org-e-odt-format-toc-entry (snumber todo headline tags href
)
538 (setq headline
(concat
539 (and org-export-with-section-numbers
540 (concat snumber
". "))
544 (org-e-odt-format-spaces 3)
545 (org-e-odt-format-fontify tags
"tag")))))
547 (setq headline
(org-e-odt-format-fontify headline
"todo")))
549 (let ((org-e-odt-suppress-xref t
))
550 (org-e-odt-format-link headline
(concat "#" href
))))
552 (defun org-e-odt-format-toc-item (toc-entry level org-last-level
)
553 (let ((style (format "Contents_20_%d"
554 (+ level
(or ;; (org-lparse-get 'TOPLEVEL-HLEVEL)
557 (concat "\n" (org-e-odt-format-stylized-paragraph style toc-entry
) "\n")))
559 ;; Following variable is let bound during 'ORG-LINK callback. See
562 (defun org-e-odt-format-link (desc href
&optional attr
)
564 ((and (= (string-to-char href
) ?
#) (not org-e-odt-suppress-xref
))
565 (setq href
(concat org-export-e-odt-bookmark-prefix
(substring href
1)))
566 (let ((xref-format "text"))
568 (setq desc
(format "%d" desc
) xref-format
"number"))
569 (org-e-odt-format-tags-simple
570 '("<text:bookmark-ref text:reference-format=\"%s\" text:ref-name=\"%s\">" .
571 "</text:bookmark-ref>")
572 desc xref-format href
)))
573 (org-lparse-link-description-is-image
574 (org-e-odt-format-tags
575 '("<draw:a xlink:type=\"simple\" xlink:href=\"%s\" %s>" .
"</draw:a>")
576 desc href
(or attr
"")))
578 (org-e-odt-format-tags-simple
579 '("<text:a xlink:type=\"simple\" xlink:href=\"%s\" %s>" .
"</text:a>")
580 desc href
(or attr
"")))))
582 (defun org-e-odt-format-spaces (n)
586 " " (org-e-odt-format-tags "<text:s text:c=\"%d\"/>" "" (1- n
))))
589 (defun org-e-odt-format-tabs (&optional n
)
590 (let ((tab "<text:tab/>")
594 (defun org-e-odt-format-line-break ()
595 (org-e-odt-format-tags "<text:line-break/>" ""))
597 (defun org-e-odt-format-horizontal-line ()
598 (org-e-odt-format-stylized-paragraph 'horizontal-line
""))
600 (defun org-e-odt-encode-plain-text (line &optional no-whitespace-filling
)
601 (setq line
(org-e-html-encode-plain-text line
))
602 (if no-whitespace-filling line
603 (org-e-odt-fill-tabs-and-spaces line
)))
605 (defun org-e-odt-format-line (line)
606 (case org-lparse-dyn-current-environment
608 (org-e-odt-format-stylized-paragraph
609 'fixedwidth
(org-e-odt-encode-plain-text line
)) "\n"))
610 (t (concat line
"\n"))))
612 (defun org-e-odt-format-comment (fmt &rest args
)
613 (let ((comment (apply 'format fmt args
)))
614 (format "\n<!-- %s -->\n" comment
)))
616 (defun org-e-odt-format-org-entity (wd)
617 (org-entity-get-representation wd
'utf8
))
619 (defun org-e-odt-fill-tabs-and-spaces (line)
620 (replace-regexp-in-string
621 "\\([\t]\\|\\([ ]+\\)\\)" (lambda (s)
623 ((string= s
"\t") (org-e-odt-format-tabs))
624 (t (org-e-odt-format-spaces (length s
))))) line
))
626 (defun org-e-odt-hfy-face-to-css (fn)
627 "Create custom style for face FN.
628 When FN is the default face, use it's foreground and background
629 properties to create \"OrgSrcBlock\" paragraph style. Otherwise
630 use it's color attribute to create a character style whose name
631 is obtained from FN. Currently all attributes of FN other than
634 The style name for a face FN is derived using the following
635 operations on the face name in that order - de-dash, CamelCase
636 and prefix with \"OrgSrc\". For example,
637 `font-lock-function-name-face' is associated with
638 \"OrgSrcFontLockFunctionNameFace\"."
639 (let* ((css-list (hfy-face-to-style fn
))
640 (style-name ((lambda (fn)
643 'capitalize
(split-string
644 (hfy-face-or-def-to-name fn
) "-")
646 (color-val (cdr (assoc "color" css-list
)))
647 (background-color-val (cdr (assoc "background" css-list
)))
648 (style (and org-export-e-odt-create-custom-styles-for-srcblocks
651 (format org-src-block-paragraph-format
652 background-color-val color-val
))
656 <style:style style:name=\"%s\" style:family=\"text\">
657 <style:text-properties fo:color=\"%s\"/>
658 </style:style>" style-name color-val
))))))
659 (cons style-name style
)))
661 (defun org-e-odt-insert-custom-styles-for-srcblocks (styles)
662 "Save STYLES used for colorizing of source blocks.
663 Update styles.xml with styles that were collected as part of
664 `org-e-odt-hfy-face-to-css' callbacks."
667 (find-file-noselect (expand-file-name "styles.xml") t
)
668 (goto-char (point-min))
669 (when (re-search-forward "</office:styles>" nil t
)
670 (goto-char (match-beginning 0))
671 (insert "\n<!-- Org Htmlfontify Styles -->\n" styles
"\n")))))
673 (defun org-e-odt-remap-stylenames (style-name)
675 (cdr (assoc style-name
'(("timestamp-wrapper" .
"OrgTimestampWrapper")
676 ("timestamp" .
"OrgTimestamp")
677 ("timestamp-kwd" .
"OrgTimestampKeyword")
681 ("target" .
"OrgTarget"))))
684 (defun org-e-odt-format-fontify (text style
&optional id
)
688 (org-e-odt-remap-stylenames style
))
690 (org-e-odt-get-style-name-for-entity 'character style
))
692 (assert (< 1 (length style
)))
693 (let ((parent-style (pop style
)))
694 (mapconcat (lambda (s)
695 ;; (assert (stringp s) t)
696 (org-e-odt-remap-stylenames s
)) style
"")
697 (org-e-odt-remap-stylenames parent-style
)))
698 (t (error "Don't how to handle style %s" style
)))))
699 (org-e-odt-format-tags
700 '("<text:span text:style-name=\"%s\">" .
"</text:span>")
703 (defun org-e-odt-relocate-relative-path (path dir
)
704 (if (file-name-absolute-p path
) path
705 (file-relative-name (expand-file-name path dir
)
706 (expand-file-name "eyecandy" dir
))))
708 (defun org-e-odt-format-inline-image (thefile
709 &optional caption label attrs
; FIXME - CLA
711 (let* ((thelink (if (file-name-absolute-p thefile
) thefile
713 (org-e-odt-relocate-relative-path
714 thefile org-current-export-file
))))
716 (org-e-odt-format-tags
717 "<draw:image xlink:href=\"%s\" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\"/>" ""
718 (if org-export-e-odt-embed-images
719 (org-e-odt-copy-image-file thefile
) thelink
))))
720 (org-export-e-odt-format-image thefile href
)))
722 (defun org-export-e-odt-format-formula (src href
)
724 (let* ((caption (org-find-text-property-in-string 'org-caption src
))
725 (caption (and caption
(org-xml-format-desc caption
)))
726 (label (org-find-text-property-in-string 'org-label src
))
727 (latex-frag (org-find-text-property-in-string 'org-latex-src src
))
728 (embed-as (or (and latex-frag
729 (org-find-text-property-in-string
730 'org-latex-src-embed-type src
))
731 (if (or caption label
) 'paragraph
'character
)))
734 (setq href
(org-propertize href
:title
"LaTeX Fragment"
735 :description latex-frag
)))
737 ((eq embed-as
'character
)
738 (org-e-odt-format-entity "InlineFormula" href width height
))
740 (org-lparse-end-paragraph)
741 (org-lparse-insert-list-table
742 `((,(org-e-odt-format-entity
743 (if caption
"CaptionedDisplayFormula" "DisplayFormula")
744 href width height
:caption caption
:label nil
)
746 (org-e-odt-format-entity-caption label nil
"__MathFormula__"))))
747 nil nil nil
":style \"OrgEquation\"" nil
'((1 "c" 8) (2 "c" 1)))
748 (throw 'nextline nil
))))))
750 (defun org-e-odt-copy-formula-file (path)
751 "Returns the internal name of the file"
752 (let* ((src-file (expand-file-name
753 path
(file-name-directory org-current-export-file
)))
754 (target-dir (format "Formula-%04d/"
755 (incf org-e-odt-embedded-formulas-count
)))
756 (target-file (concat target-dir
"content.xml")))
757 (message "Embedding %s as %s ..."
758 (substring-no-properties path
) target-file
)
760 (make-directory target-dir
)
761 (org-e-odt-create-manifest-file-entry
762 "application/vnd.oasis.opendocument.formula" target-dir
"1.2")
764 (case (org-e-odt-is-formula-link-p src-file
)
766 (copy-file src-file target-file
'overwrite
))
768 (org-e-odt-zip-extract-one src-file
"content.xml" target-dir
))
770 (error "%s is not a formula file" src-file
)))
772 (org-e-odt-create-manifest-file-entry "text/xml" target-file
)
775 (defun org-e-odt-format-inline-formula (thefile)
776 (let* ((thelink (if (file-name-absolute-p thefile
) thefile
778 (org-e-odt-relocate-relative-path
779 thefile org-current-export-file
))))
781 (org-e-odt-format-tags
782 "<draw:object xlink:href=\"%s\" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\"/>" ""
783 (file-name-directory (org-e-odt-copy-formula-file thefile
)))))
784 (org-export-e-odt-format-formula thefile href
)))
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-export-e-odt-inline-image-extensions
)
818 (or (eq t org-export-e-odt-inline-images
)
819 (and org-export-e-odt-inline-images
(not descp
))))
820 (org-e-odt-format-inline-image thefile
))
821 ;; check for embedded formulas
822 ((and (member type
'("file"))
824 (org-e-odt-is-formula-link-p filename
)
826 (org-e-odt-format-inline-formula thefile
))
827 ((string= type
"coderef")
828 (let* ((ref fragment
)
829 (lineno-or-ref (cdr (assoc ref org-export-code-refs
)))
830 (desc (and descp desc
))
831 (org-e-odt-suppress-xref nil
)
832 (href (org-xml-format-href (concat "#coderef-" ref
))))
834 ((and (numberp lineno-or-ref
) (not desc
))
835 (org-e-odt-format-link lineno-or-ref href
))
836 ((and (numberp lineno-or-ref
) desc
837 (string-match (regexp-quote (concat "(" ref
")")) desc
))
838 (format (replace-match "%s" t t desc
)
839 (org-e-odt-format-link lineno-or-ref href
)))
842 (if (and desc
(string-match
843 (regexp-quote (concat "(" ref
")"))
845 (replace-match "%s" t t desc
)
848 (org-e-odt-format-link (org-xml-format-desc desc
) href
)))))
850 (when (string= type
"file")
853 ((file-name-absolute-p path
)
854 (concat "file://" (expand-file-name path
)))
855 (t (org-e-odt-relocate-relative-path
856 thefile org-current-export-file
)))))
858 (when (and (member type
'("" "http" "https" "file")) fragment
)
859 (setq thefile
(concat thefile
"#" fragment
)))
861 (setq thefile
(org-xml-format-href thefile
))
863 (when (not (member type
'("" "file")))
864 (setq thefile
(concat type
":" thefile
)))
866 (let ((org-e-odt-suppress-xref nil
))
867 (org-e-odt-format-link
868 (org-xml-format-desc desc
) thefile attr
)))))))
870 (defun org-e-odt-format-heading (text level
&optional id
)
871 (let* ((text (if id
(org-e-odt-format-target text id
) text
)))
872 (org-e-odt-format-tags
873 '("<text:h text:style-name=\"Heading_20_%s\" text:outline-level=\"%s\">" .
874 "</text:h>") text level level
)))
876 (defun org-e-odt-format-headline (title extra-targets tags
877 &optional snumber level
)
879 (org-e-odt-format-extra-targets extra-targets
)
881 ;; No need to generate section numbers. They are auto-generated by
884 ;; (concat (org-lparse-format 'SECTION-NUMBER snumber level) " ")
886 (and tags
(concat (org-e-odt-format-spaces 3)
887 (org-e-odt-format-org-tags tags
)))))
889 (defun org-e-odt-format-anchor (text name
&optional class
)
890 (org-e-odt-format-target text name
))
892 (defun org-e-odt-format-bookmark (text id
)
894 (org-e-odt-format-tags "<text:bookmark text:name=\"%s\"/>" text id
)
897 (defun org-e-odt-format-target (text id
)
898 (let ((name (concat org-export-e-odt-bookmark-prefix id
)))
900 (and id
(org-e-odt-format-tags
901 "<text:bookmark-start text:name=\"%s\"/>" "" name
))
902 (org-e-odt-format-bookmark text id
)
903 (and id
(org-e-odt-format-tags
904 "<text:bookmark-end text:name=\"%s\"/>" "" name
)))))
906 (defun org-e-odt-format-footnote (n def
)
907 (setq n
(format "%d" n
))
908 (let ((id (concat "fn" n
))
909 (note-class "footnote")
910 (par-style "Footnote"))
911 (org-e-odt-format-tags
912 '("<text:note text:id=\"%s\" text:note-class=\"%s\">" .
915 (org-e-odt-format-tags
916 '("<text:note-citation>" .
"</text:note-citation>")
918 (org-e-odt-format-tags
919 '("<text:note-body>" .
"</text:note-body>")
923 (defun org-e-odt-format-footnote-reference (n def refcnt
)
925 (org-e-odt-format-footnote n def
)
926 (org-e-odt-format-footnote-ref n
)))
928 (defun org-e-odt-format-footnote-ref (n)
929 (setq n
(format "%d" n
))
930 (let ((note-class "footnote")
932 (ref-name (concat "fn" n
)))
933 (org-e-odt-format-tags
934 '("<text:span text:style-name=\"%s\">" .
"</text:span>")
935 (org-e-odt-format-tags
936 '("<text:note-ref text:note-class=\"%s\" text:reference-format=\"%s\" text:ref-name=\"%s\">" .
"</text:note-ref>")
937 n note-class ref-format ref-name
)
940 (defun org-e-odt-get-image-name (file-name)
944 (concat (sha1 file-name
) "." (file-name-extension file-name
)) "Pictures")))
946 (defun org-export-e-odt-format-image (src href
)
947 "Create image tag with source and attributes."
949 (let* ((caption (org-find-text-property-in-string 'org-caption src
))
950 (caption (and caption
(org-xml-format-desc caption
)))
951 (attr (org-find-text-property-in-string 'org-attributes src
))
952 (label (org-find-text-property-in-string 'org-label src
))
953 (latex-frag (org-find-text-property-in-string
955 (category (and latex-frag
"__DvipngImage__"))
956 (attr-plist (org-lparse-get-block-params attr
))
958 (car (assoc-string (plist-get attr-plist
:anchor
)
959 '(("as-char") ("paragraph") ("page")) t
)))
961 (and user-frame-anchor
(plist-get attr-plist
:style
)))
963 (and user-frame-anchor
(plist-get attr-plist
:attributes
)))
965 (list user-frame-style user-frame-attrs user-frame-anchor
))
969 (case (org-find-text-property-in-string
970 'org-latex-src-embed-type src
)
971 (paragraph 'paragraph
)
975 (size (org-e-odt-image-size-from-file
976 src
(plist-get attr-plist
:width
)
977 (plist-get attr-plist
:height
)
978 (plist-get attr-plist
:scale
) nil embed-as
))
979 (width (car size
)) (height (cdr size
)))
981 (setq href
(org-propertize href
:title
"LaTeX Fragment"
982 :description latex-frag
)))
983 (let ((frame-style-handle (concat (and (or caption label
) "Captioned")
985 (org-e-odt-format-entity
986 frame-style-handle href width height
987 :caption caption
:label label
:category category
988 :user-frame-params user-frame-params
)))))
990 (defun org-e-odt-format-object-description (title description
)
991 (concat (and title
(org-e-odt-format-tags
992 '("<svg:title>" .
"</svg:title>")
993 (org-e-odt-encode-plain-text title t
)))
994 (and description
(org-e-odt-format-tags
995 '("<svg:desc>" .
"</svg:desc>")
996 (org-e-odt-encode-plain-text description t
)))))
998 (defun org-e-odt-format-frame (text width height style
&optional
1002 (if width
(format " svg:width=\"%0.2fcm\"" width
) "")
1003 (if height
(format " svg:height=\"%0.2fcm\"" height
) "")
1005 (format " text:anchor-type=\"%s\"" (or anchor-type
"paragraph")))))
1006 (org-e-odt-format-tags
1007 '("<draw:frame draw:style-name=\"%s\"%s>" .
"</draw:frame>")
1008 (concat text
(org-e-odt-format-object-description
1009 (get-text-property 0 :title text
)
1010 (get-text-property 0 :description text
)))
1011 style frame-attrs
)))
1013 (defun org-e-odt-format-textbox (text width height style
&optional
1015 (org-e-odt-format-frame
1016 (org-e-odt-format-tags
1017 '("<draw:text-box %s>" .
"</draw:text-box>")
1018 text
(concat (format " fo:min-height=\"%0.2fcm\"" (or height
.2))
1020 (format " fo:min-width=\"%0.2fcm\"" (or width
.2)))))
1021 width nil style extra anchor-type
))
1023 (defun org-e-odt-format-inlinetask (heading content
1024 &optional todo priority tags
)
1025 (org-e-odt-format-stylized-paragraph
1026 nil
(org-e-odt-format-textbox
1027 (concat (org-e-odt-format-stylized-paragraph
1028 "OrgInlineTaskHeading"
1030 'HEADLINE
(concat (org-lparse-format-todo todo
) " " heading
)
1032 content
) nil nil
"OrgInlineTaskFrame" " style:rel-width=\"100%\"")))
1035 (defun org-e-odt-merge-frame-params(default-frame-params user-frame-params
)
1036 (if (not user-frame-params
) default-frame-params
1037 (assert (= (length default-frame-params
) 3))
1038 (assert (= (length user-frame-params
) 3))
1039 (loop for user-frame-param in user-frame-params
1040 for default-frame-param in default-frame-params
1041 collect
(or user-frame-param default-frame-param
))))
1043 (defun* org-e-odt-format-entity
(entity href width height
1044 &key caption label category
1046 (let* ((entity-style (assoc-string entity org-e-odt-entity-frame-styles t
))
1047 default-frame-params frame-params
)
1049 ((not (or caption label
))
1050 (setq default-frame-params
(nth 2 entity-style
))
1051 (setq frame-params
(org-e-odt-merge-frame-params
1052 default-frame-params user-frame-params
))
1053 (apply 'org-e-odt-format-frame href width height frame-params
))
1055 (setq default-frame-params
(nth 3 entity-style
))
1056 (setq frame-params
(org-e-odt-merge-frame-params
1057 default-frame-params user-frame-params
))
1058 (apply 'org-e-odt-format-textbox
1059 (org-e-odt-format-stylized-paragraph
1062 (apply 'org-e-odt-format-frame href width height
1063 (nth 2 entity-style
))
1064 (org-e-odt-format-entity-caption
1065 label caption
(or category
(nth 1 entity-style
)))))
1066 width height frame-params
)))))
1068 (defun org-e-odt-copy-image-file (path)
1069 "Returns the internal name of the file"
1070 (let* ((image-type (file-name-extension path
))
1071 (media-type (format "image/%s" image-type
))
1072 (src-file (expand-file-name
1073 path
(file-name-directory org-current-export-file
)))
1074 (target-dir "Images/")
1076 (format "%s%04d.%s" target-dir
1077 (incf org-e-odt-embedded-images-count
) image-type
)))
1078 (message "Embedding %s as %s ..."
1079 (substring-no-properties path
) target-file
)
1081 (when (= 1 org-e-odt-embedded-images-count
)
1082 (make-directory target-dir
)
1083 (org-e-odt-create-manifest-file-entry "" target-dir
))
1085 (copy-file src-file target-file
'overwrite
)
1086 (org-e-odt-create-manifest-file-entry media-type target-file
)
1089 (defun org-e-odt-do-image-size (probe-method file
&optional dpi anchor-type
)
1090 (setq dpi
(or dpi org-export-e-odt-pixels-per-inch
))
1091 (setq anchor-type
(or anchor-type
"paragraph"))
1092 (flet ((size-in-cms (size-in-pixels)
1093 (flet ((pixels-to-cms (pixels)
1094 (let* ((cms-per-inch 2.54)
1095 (inches (/ pixels dpi
)))
1096 (* cms-per-inch inches
))))
1098 (cons (pixels-to-cms (car size-in-pixels
))
1099 (pixels-to-cms (cdr size-in-pixels
)))))))
1102 (size-in-cms (ignore-errors ; Emacs could be in batch mode
1104 (image-size (create-image file
) 'pixels
))))
1107 (let ((dim (shell-command-to-string
1108 (format "identify -format \"%%w:%%h\" \"%s\"" file
))))
1109 (when (string-match "\\([0-9]+\\):\\([0-9]+\\)" dim
)
1110 (cons (string-to-number (match-string 1 dim
))
1111 (string-to-number (match-string 2 dim
)))))))
1113 (cdr (assoc-string anchor-type
1114 org-export-e-odt-default-image-sizes-alist
))))))
1116 (defun org-e-odt-image-size-from-file (file &optional user-width
1117 user-height scale dpi embed-as
)
1118 (unless (file-name-absolute-p file
)
1119 (setq file
(expand-file-name
1120 file
(file-name-directory org-current-export-file
))))
1121 (let* (size width height
)
1122 (unless (and user-height user-width
)
1123 (loop for probe-method in org-export-e-odt-image-size-probe-method
1125 do
(setq size
(org-e-odt-do-image-size
1126 probe-method file dpi embed-as
)))
1127 (or size
(error "Cannot determine Image size. Aborting ..."))
1128 (setq width
(car size
) height
(cdr size
)))
1131 (setq width
(* width scale
) height
(* height scale
)))
1132 ((and user-height user-width
)
1133 (setq width user-width height user-height
))
1135 (setq width
(* user-height
(/ width height
)) height user-height
))
1137 (setq height
(* user-width
(/ height width
)) width user-width
))
1139 ;; ensure that an embedded image fits comfortably within a page
1140 (let ((max-width (car org-export-e-odt-max-image-size
))
1141 (max-height (cdr org-export-e-odt-max-image-size
)))
1142 (when (or (> width max-width
) (> height max-height
))
1143 (let* ((scale1 (/ max-width width
))
1144 (scale2 (/ max-height height
))
1145 (scale (min scale1 scale2
)))
1146 (setq width
(* scale width
) height
(* scale height
)))))
1147 (cons width height
)))
1149 (defun org-e-odt-get-label-category-and-style (label default-category
)
1150 "See `org-export-e-odt-get-category-from-label'."
1151 (let ((default-category-map
1152 (assoc default-category org-e-odt-category-map-alist
))
1153 user-category user-category-map category
)
1155 ((not org-export-e-odt-get-category-from-label
)
1156 default-category-map
)
1157 ((not (setq user-category
1159 (and (string-match "\\`\\(.*\\):.+" label
)
1160 (match-string 1 label
)))))
1161 default-category-map
)
1163 (setq user-category-map
1164 (or (assoc user-category org-e-odt-category-map-alist
)
1165 (list nil user-category
"category-and-value"))
1166 category
(nth 1 user-category-map
))
1167 (if (member category org-export-e-odt-user-categories
)
1169 default-category-map
)))))
1171 (defun org-e-odt-add-label-definition (label default-category
)
1172 "Create an entry in `org-e-odt-entity-labels-alist' and return it."
1173 (setq label
(substring-no-properties label
))
1174 (let* ((label-props (org-e-odt-get-label-category-and-style
1175 label default-category
))
1176 (category (nth 1 label-props
))
1178 (label-style (nth 2 label-props
))
1179 (sequence-var (intern (mapconcat
1181 (org-split-string counter
) "-")))
1182 (seqno (1+ (or (plist-get org-e-odt-entity-counts-plist sequence-var
)
1184 (label-props (list label category seqno label-style
)))
1185 (setq org-e-odt-entity-counts-plist
1186 (plist-put org-e-odt-entity-counts-plist sequence-var seqno
))
1187 (push label-props org-e-odt-entity-labels-alist
)
1190 (defun org-e-odt-format-label-definition (caption label category seqno label-style
)
1193 (cadr (assoc-string label-style org-e-odt-label-styles t
))
1195 (?n .
,(org-e-odt-format-tags
1196 '("<text:sequence text:ref-name=\"%s\" text:name=\"%s\" text:formula=\"ooow:%s+1\" style:num-format=\"1\">" .
"</text:sequence>")
1197 (format "%d" seqno
) label category category
))
1198 (?c .
,(or (and caption
(concat ": " caption
)) "")))))
1200 (defun org-e-odt-format-label-reference (label category seqno label-style
)
1203 (let* ((fmt (cddr (assoc-string label-style org-e-odt-label-styles t
)))
1206 (org-e-odt-format-tags
1207 '("<text:sequence-ref text:reference-format=\"%s\" text:ref-name=\"%s\">"
1208 .
"</text:sequence-ref>")
1209 (format-spec fmt2
`((?e .
,category
)
1210 (?n .
,(format "%d" seqno
)))) fmt1 label
))))
1212 (defun org-e-odt-fixup-label-references ()
1213 (goto-char (point-min))
1214 (while (re-search-forward
1215 "<text:sequence-ref text:ref-name=\"\\([^\"]+\\)\">[ \t\n]*</text:sequence-ref>"
1217 (let* ((label (match-string 1))
1218 (label-def (assoc label org-e-odt-entity-labels-alist
))
1220 (apply 'org-e-odt-format-label-reference label-def
))))
1221 (if rpl
(replace-match rpl t t
)
1223 (format "Unable to resolve reference to label \"%s\"" label
))))))
1225 (defun org-e-odt-format-entity-caption (label caption category
)
1227 (apply 'org-e-odt-format-label-definition
1228 caption
(org-e-odt-add-label-definition label category
)))
1231 (defun org-e-odt-format-tags-1 (tag text prefix suffix
&rest args
)
1234 (concat prefix
(apply 'format
(car tag
) args
) text suffix
1235 (format (cdr tag
))))
1236 ((stringp tag
) ; singleton tag
1237 (concat prefix
(apply 'format tag args
) text
))))
1239 (defun org-e-odt-format-tags (tag text
&rest args
)
1240 (apply 'org-e-odt-format-tags-1 tag text
"\n" "\n" args
))
1242 (defun org-e-odt-format-tags-simple (tag text
&rest args
)
1243 (apply 'org-e-odt-format-tags-1 tag text nil nil args
))
1245 (defun org-e-odt-init-outfile ()
1246 (unless (executable-find "zip")
1247 ;; Not at all OSes ship with zip by default
1248 (error "Executable \"zip\" needed for creating OpenDocument files"))
1250 (let* ((outdir (make-temp-file
1251 (format org-export-e-odt-tmpdir-prefix org-lparse-backend
) t
))
1252 (content-file (expand-file-name "content.xml" outdir
)))
1255 (setq org-e-odt-manifest-file-entries nil
1256 org-e-odt-embedded-images-count
0
1257 org-e-odt-embedded-formulas-count
0
1258 org-e-odt-section-count
0
1259 org-e-odt-entity-labels-alist nil
1260 org-e-odt-list-stack-stashed nil
1261 org-e-odt-automatic-styles nil
1262 org-e-odt-object-counters nil
1263 org-e-odt-entity-counts-plist nil
)
1265 ;; let `htmlfontify' know that we are interested in collecting
1268 (setq hfy-user-sheet-assoc nil
)
1271 (with-current-buffer
1272 (find-file-noselect content-file t
)
1277 (defun org-e-odt-save-as-outfile (target opt-plist
)
1278 ;; write automatic styles
1279 (org-e-odt-write-automatic-styles)
1281 ;; write styles file
1282 ;; (when (equal org-lparse-backend 'odt) FIXME
1285 (org-e-odt-update-styles-file opt-plist
)
1287 ;; create mimetype file
1288 (let ((mimetype (org-e-odt-write-mimetype-file ;; org-lparse-backend FIXME
1290 (org-e-odt-create-manifest-file-entry mimetype
"/" "1.2"))
1292 ;; create a manifest entry for content.xml
1293 (org-e-odt-create-manifest-file-entry "text/xml" "content.xml")
1295 ;; write out the manifest entries before zipping
1296 (org-e-odt-write-manifest-file)
1298 (let ((xml-files '("mimetype" "META-INF/manifest.xml" "content.xml"
1300 (zipdir default-directory
))
1301 (when (or t
(equal org-lparse-backend
'odt
)) ; FIXME
1302 (push "styles.xml" xml-files
))
1303 (message "Switching to directory %s" (expand-file-name zipdir
))
1305 ;; save all xml files
1306 (mapc (lambda (file)
1307 (with-current-buffer
1308 (find-file-noselect (expand-file-name file
) t
)
1309 ;; prettify output if needed
1310 (when org-export-e-odt-prettify-xml
1311 (indent-region (point-min) (point-max)))
1315 (let* ((target-name (file-name-nondirectory target
))
1316 (target-dir (file-name-directory target
))
1317 (cmds `(("zip" "-mX0" ,target-name
"mimetype")
1318 ("zip" "-rmTq" ,target-name
"."))))
1319 (when (file-exists-p target
)
1320 ;; FIXME: If the file is locked this throws a cryptic error
1321 (delete-file target
))
1323 (let ((coding-system-for-write 'no-conversion
) exitcode err-string
)
1324 (message "Creating odt file...")
1327 (message "Running %s" (mapconcat 'identity cmd
" "))
1329 (with-output-to-string
1331 (apply 'call-process
(car cmd
)
1332 nil standard-output nil
(cdr cmd
)))))
1333 (or (zerop exitcode
)
1334 (ignore (message "%s" err-string
))
1335 (error "Unable to create odt file (%S)" exitcode
)))
1338 ;; move the file from outdir to target-dir
1339 (rename-file target-name target-dir
)
1341 ;; kill all xml buffers
1342 (mapc (lambda (file)
1344 (find-file-noselect (expand-file-name file zipdir
) t
)))
1347 (delete-directory zipdir
)))
1348 (message "Created %s" target
)
1349 (set-buffer (find-file-noselect target t
)))
1352 (defun org-e-odt-create-manifest-file-entry (&rest args
)
1353 (push args org-e-odt-manifest-file-entries
))
1355 (defun org-e-odt-write-manifest-file ()
1356 (make-directory "META-INF")
1357 (let ((manifest-file (expand-file-name "META-INF/manifest.xml")))
1358 (with-current-buffer
1359 (find-file-noselect manifest-file t
)
1361 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
1362 <manifest:manifest xmlns:manifest=\"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0\" manifest:version=\"1.2\">\n")
1364 (lambda (file-entry)
1365 (let* ((version (nth 2 file-entry
))
1367 (format " manifest:version=\"%s\"" version
)
1370 (format org-e-odt-manifest-file-entry-tag
1371 (nth 0 file-entry
) (nth 1 file-entry
) extra
))))
1372 org-e-odt-manifest-file-entries
)
1373 (insert "\n</manifest:manifest>"))))
1375 (defun org-e-odt-update-meta-file (info) ; FIXME opt-plist
1376 (let ((date (org-e-odt-format-date (plist-get info
:date
)))
1377 (author (or (plist-get info
:author
) ""))
1378 (email (plist-get info
:email
))
1379 (keywords (plist-get info
:keywords
))
1380 (description (plist-get info
:description
))
1381 (title (plist-get info
:title
)))
1384 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
1385 <office:document-meta
1386 xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"
1387 xmlns:xlink=\"http://www.w3.org/1999/xlink\"
1388 xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
1389 xmlns:meta=\"urn:oasis:names:tc:opendocument:xmlns:meta:1.0\"
1390 xmlns:ooo=\"http://openoffice.org/2004/office\"
1391 office:version=\"1.2\">
1393 (org-e-odt-format-author author
) "\n"
1394 (format "<meta:initial-creator>%s</meta:initial-creator>\n" author
)
1395 (format "<dc:date>%s</dc:date>\n" date
)
1396 (format "<meta:creation-date>%s</meta:creation-date>\n" date
)
1397 (format "<meta:generator>%s</meta:generator>\n"
1398 (when org-export-creator-info
1399 (format "Org-%s/Emacs-%s"
1400 org-version emacs-version
)))
1401 (format "<meta:keyword>%s</meta:keyword>\n" keywords
)
1402 (format "<dc:subject>%s</dc:subject>\n" description
)
1403 (format "<dc:title>%s</dc:title>\n" title
)
1405 " </office:meta>\n" "</office:document-meta>")
1406 nil
(expand-file-name "meta.xml")))
1408 ;; create a manifest entry for meta.xml
1409 (org-e-odt-create-manifest-file-entry "text/xml" "meta.xml"))
1411 (defun org-e-odt-update-styles-file (opt-plist)
1412 ;; write styles file
1413 (let ((styles-file (plist-get opt-plist
:odt-styles-file
)))
1414 (org-e-odt-copy-styles-file (and styles-file
1415 (read (org-trim styles-file
)))))
1417 ;; Update styles.xml - take care of outline numbering
1418 (with-current-buffer
1419 (find-file-noselect (expand-file-name "styles.xml") t
)
1420 ;; Don't make automatic backup of styles.xml file. This setting
1421 ;; prevents the backed-up styles.xml file from being zipped in to
1422 ;; odt file. This is more of a hackish fix. Better alternative
1423 ;; would be to fix the zip command so that the output odt file
1424 ;; includes only the needed files and excludes any auto-generated
1425 ;; extra files like backups and auto-saves etc etc. Note that
1426 ;; currently the zip command zips up the entire temp directory so
1427 ;; that any auto-generated files created under the hood ends up in
1428 ;; the resulting odt file.
1429 (set (make-local-variable 'backup-inhibited
) t
)
1431 ;; Import local setting of `org-export-with-section-numbers'
1432 (org-e-odt-configure-outline-numbering
1433 (if org-export-with-section-numbers org-export-headline-levels
0)))
1435 ;; Write custom styles for source blocks
1436 (org-e-odt-insert-custom-styles-for-srcblocks
1439 (format " %s\n" (cddr style
)))
1440 hfy-user-sheet-assoc
"")))
1442 (defun org-e-odt-write-mimetype-file (format)
1443 ;; create mimetype file
1446 (odt "application/vnd.oasis.opendocument.text")
1447 (odf "application/vnd.oasis.opendocument.formula")
1448 (t (error "Unknown OpenDocument backend %S" org-lparse-backend
)))))
1449 (write-region mimetype nil
(expand-file-name "mimetype"))
1452 (defun org-e-odt-finalize-outfile ()
1453 (org-e-odt-delete-empty-paragraphs))
1455 (defun org-e-odt-delete-empty-paragraphs ()
1456 (goto-char (point-min))
1457 (let ((open "<text:p[^>]*>")
1458 (close "</text:p>"))
1459 (while (re-search-forward (format "%s[ \r\n\t]*%s" open close
) nil t
)
1460 (replace-match ""))))
1462 (declare-function org-create-math-formula
"org"
1463 (latex-frag &optional mathml-file
))
1466 (defun org-export-e-odt-convert (&optional in-file out-fmt prefix-arg
)
1467 "Convert IN-FILE to format OUT-FMT using a command line converter.
1468 IN-FILE is the file to be converted. If unspecified, it defaults
1469 to variable `buffer-file-name'. OUT-FMT is the desired output
1470 format. Use `org-export-e-odt-convert-process' as the converter.
1471 If PREFIX-ARG is non-nil then the newly converted file is opened
1472 using `org-open-file'."
1474 (append (org-lparse-convert-read-params) current-prefix-arg
))
1475 (org-lparse-do-convert in-file out-fmt prefix-arg
))
1477 (defun org-e-odt-get (what &optional opt-plist
)
1480 (EXPORT-DIR (org-export-directory :html opt-plist
))
1481 (FILE-NAME-EXTENSION "odt")
1482 (EXPORT-BUFFER-NAME "*Org ODT Export*")
1483 (ENTITY-CONTROL org-e-odt-entity-control-callbacks-alist
)
1484 (ENTITY-FORMAT org-e-odt-entity-format-callbacks-alist
)
1485 (INIT-METHOD 'org-e-odt-init-outfile
)
1486 (FINAL-METHOD 'org-e-odt-finalize-outfile
)
1487 (SAVE-METHOD 'org-e-odt-save-as-outfile
)
1489 (and org-export-e-odt-convert-process
1490 (cadr (assoc-string org-export-e-odt-convert-process
1491 org-export-e-odt-convert-processes t
))))
1492 (CONVERT-CAPABILITIES
1493 (and org-export-e-odt-convert-process
1494 (cadr (assoc-string org-export-e-odt-convert-process
1495 org-export-e-odt-convert-processes t
))
1496 org-export-e-odt-convert-capabilities
))
1498 (SPECIAL-STRING-REGEXPS org-export-e-odt-special-string-regexps
)
1499 (INLINE-IMAGES 'maybe
)
1500 (INLINE-IMAGE-EXTENSIONS '("png" "jpeg" "jpg" "gif" "svg"))
1501 (PLAIN-TEXT-MAP '(("&" .
"&") ("<" .
"<") (">" .
">")))
1502 (TABLE-FIRST-COLUMN-AS-LABELS nil
)
1503 (FOOTNOTE-SEPARATOR )
1504 (CODING-SYSTEM-FOR-WRITE 'utf-8
)
1505 (CODING-SYSTEM-FOR-SAVE 'utf-8
)
1506 (t (error "Unknown property: %s" what
))))
1508 (defun org-export-e-odt-do-preprocess-latex-fragments ()
1509 "Convert LaTeX fragments to images."
1510 (let* ((latex-frag-opt (plist-get org-lparse-opt-plist
:LaTeX-fragments
))
1511 (latex-frag-opt ; massage the options
1512 (or (and (member latex-frag-opt
'(mathjax t
))
1513 (not (and (fboundp 'org-format-latex-mathml-available-p
)
1514 (org-format-latex-mathml-available-p)))
1515 (prog1 org-lparse-latex-fragment-fallback
1518 "LaTeX to MathML converter not available. "
1519 (format "Using %S instead."
1520 org-lparse-latex-fragment-fallback
)))))
1522 cache-dir display-msg
)
1524 ((eq latex-frag-opt
'dvipng
)
1525 (setq cache-dir
"ltxpng/")
1526 (setq display-msg
"Creating LaTeX image %s"))
1527 ((member latex-frag-opt
'(mathjax t
))
1528 (setq latex-frag-opt
'mathml
)
1529 (setq cache-dir
"ltxmathml/")
1530 (setq display-msg
"Creating MathML formula %s")))
1531 (when (and org-current-export-file
)
1533 (concat cache-dir
(file-name-sans-extension
1534 (file-name-nondirectory org-current-export-file
)))
1535 org-current-export-dir nil display-msg
1536 nil nil latex-frag-opt
))))
1538 (defadvice org-format-latex-as-mathml
1539 (after org-e-odt-protect-latex-fragment activate
)
1540 "Encode LaTeX fragment as XML.
1541 Do this when translation to MathML fails."
1542 (when (or (not (> (length ad-return-value
) 0))
1543 (get-text-property 0 'org-protected ad-return-value
))
1544 (setq ad-return-value
1545 (org-propertize (org-e-odt-encode-plain-text (ad-get-arg 0))
1546 'org-protected t
))))
1548 (defun org-export-e-odt-preprocess-latex-fragments ()
1549 (when (equal org-export-current-backend
'odt
)
1550 (org-export-e-odt-do-preprocess-latex-fragments)))
1552 (defun org-export-e-odt-preprocess-label-references ()
1553 (goto-char (point-min))
1554 (let (label label-components category value pretty-label
)
1555 (while (re-search-forward "\\\\ref{\\([^{}\n]+\\)}" nil t
)
1556 (org-if-unprotected-at (match-beginning 1)
1558 (let ((org-lparse-encode-pending t
)
1559 (label (match-string 1)))
1560 ;; markup generated below is mostly an eye-candy. At
1561 ;; pre-processing stage, there is no information on which
1562 ;; entity a label reference points to. The actual markup
1563 ;; is generated as part of `org-e-odt-fixup-label-references'
1564 ;; which gets called at the fag end of export. By this
1565 ;; time we would have seen and collected all the label
1566 ;; definitions in `org-e-odt-entity-labels-alist'.
1567 (org-e-odt-format-tags
1568 '("<text:sequence-ref text:ref-name=\"%s\">" .
1569 "</text:sequence-ref>")
1570 "" (org-add-props label
'(org-protected t
)))) t t
)))))
1572 ;; process latex fragments as part of
1573 ;; `org-export-preprocess-after-blockquote-hook'. Note that this hook
1574 ;; is the one that is closest and well before the call to
1575 ;; `org-export-attach-captions-and-attributes' in
1576 ;; `org-export-preprocess-string'. The above arrangement permits
1577 ;; captions, labels and attributes to be attached to png images
1578 ;; generated out of latex equations.
1579 (add-hook 'org-export-preprocess-after-blockquote-hook
1580 'org-export-e-odt-preprocess-latex-fragments
)
1582 (defun org-export-e-odt-preprocess (parameters)
1583 (org-export-e-odt-preprocess-label-references))
1586 (defun org-e-odt-zip-extract-one (archive member
&optional target
)
1588 (let* ((target (or target default-directory
))
1589 (archive (expand-file-name archive
))
1590 (archive-zip-extract
1591 (list "unzip" "-qq" "-o" "-d" target
))
1592 exit-code command-output
)
1593 (setq command-output
1595 (setq exit-code
(archive-zip-extract archive member
))
1597 (unless (zerop exit-code
)
1598 (message command-output
)
1599 (error "Extraction failed"))))
1601 (defun org-e-odt-zip-extract (archive members
&optional target
)
1602 (when (atom members
) (setq members
(list members
)))
1603 (mapc (lambda (member)
1604 (org-e-odt-zip-extract-one archive member target
))
1607 (defun org-e-odt-copy-styles-file (&optional styles-file
)
1608 ;; Non-availability of styles.xml is not a critical error. For now
1609 ;; throw an error purely for aesthetic reasons.
1610 (setq styles-file
(or styles-file
1611 org-export-e-odt-styles-file
1612 (expand-file-name "OrgOdtStyles.xml"
1613 org-e-odt-styles-dir
)
1614 (error "org-e-odt: Missing styles file?")))
1616 ((listp styles-file
)
1617 (let ((archive (nth 0 styles-file
))
1618 (members (nth 1 styles-file
)))
1619 (org-e-odt-zip-extract archive members
)
1622 (when (org-file-image-p member
)
1623 (let* ((image-type (file-name-extension member
))
1624 (media-type (format "image/%s" image-type
)))
1625 (org-e-odt-create-manifest-file-entry media-type member
))))
1627 ((and (stringp styles-file
) (file-exists-p styles-file
))
1628 (let ((styles-file-type (file-name-extension styles-file
)))
1630 ((string= styles-file-type
"xml")
1631 (copy-file styles-file
"styles.xml" t
))
1632 ((member styles-file-type
'("odt" "ott"))
1633 (org-e-odt-zip-extract styles-file
"styles.xml")))))
1635 (error (format "Invalid specification of styles.xml file: %S"
1636 org-export-e-odt-styles-file
))))
1638 ;; create a manifest entry for styles.xml
1639 (org-e-odt-create-manifest-file-entry "text/xml" "styles.xml"))
1641 (defun org-e-odt-configure-outline-numbering (level)
1642 "Outline numbering is retained only upto LEVEL.
1643 To disable outline numbering pass a LEVEL of 0."
1644 (goto-char (point-min))
1646 "<text:outline-level-style\\([^>]*\\)text:level=\"\\([^\"]*\\)\"\\([^>]*\\)>")
1648 "<text:outline-level-style\\1text:level=\"\\2\" style:num-format=\"\">"))
1649 (while (re-search-forward regex nil t
)
1650 (when (> (string-to-number (match-string 2)) level
)
1651 (replace-match replacement t nil
))))
1655 (defun org-export-as-odf (latex-frag &optional odf-file
)
1656 "Export LATEX-FRAG as OpenDocument formula file ODF-FILE.
1657 Use `org-create-math-formula' to convert LATEX-FRAG first to
1658 MathML. When invoked as an interactive command, use
1659 `org-latex-regexps' to infer LATEX-FRAG from currently active
1660 region. If no LaTeX fragments are found, prompt for it. Push
1661 MathML source to kill ring, if `org-export-copy-to-kill-ring' is
1665 (setq frag
(and (setq frag
(and (region-active-p)
1666 (buffer-substring (region-beginning)
1668 (loop for e in org-latex-regexps
1669 thereis
(when (string-match (nth 1 e
) frag
)
1670 (match-string (nth 2 e
) frag
)))))
1671 (read-string "LaTeX Fragment: " frag nil frag
))
1672 ,(let ((odf-filename (expand-file-name
1674 (file-name-sans-extension
1675 (or (file-name-nondirectory buffer-file-name
)))
1677 (file-name-directory buffer-file-name
))))
1678 (read-file-name "ODF filename: " nil odf-filename nil
1679 (file-name-nondirectory odf-filename
)))))
1680 (let* ((org-lparse-backend 'odf
)
1681 org-lparse-opt-plist
1682 (filename (or odf-file
1685 (file-name-sans-extension
1686 (or (file-name-nondirectory buffer-file-name
)))
1688 (file-name-directory buffer-file-name
))))
1689 (buffer (find-file-noselect (org-e-odt-init-outfile filename
)))
1690 (coding-system-for-write 'utf-8
)
1691 (save-buffer-coding-system 'utf-8
))
1693 (set-buffer-file-coding-system coding-system-for-write
)
1694 (let ((mathml (org-create-math-formula latex-frag
)))
1695 (unless mathml
(error "No Math formula created"))
1697 (or (org-export-push-to-kill-ring
1698 (upcase (symbol-name org-lparse-backend
)))
1699 (message "Exporting... done")))
1700 (org-e-odt-save-as-outfile filename nil
; FIXME
1704 (defun org-export-as-odf-and-open ()
1705 "Export LaTeX fragment as OpenDocument formula and immediately open it.
1706 Use `org-export-as-odf' to read LaTeX fragment and OpenDocument
1709 (org-lparse-and-open
1710 nil nil nil
(call-interactively 'org-export-as-odf
)))
1715 ;;; Driver Starts here
1718 (require 'format-spec
)
1719 (eval-when-compile (require 'cl
) (require 'table
))
1725 (defvar org-e-odt-after-blockquotes-hook nil
1726 "Hook run during HTML export, after blockquote, verse, center are done.")
1728 (defvar org-e-odt-final-hook nil
1729 "Hook run at the end of HTML export, in the new buffer.")
1731 ;; FIXME: it already exists in org-e-odt.el
1732 ;;; Function Declarations
1734 (declare-function org-element-property
"org-element" (property element
))
1735 (declare-function org-element-normalize-string
"org-element" (s))
1736 (declare-function org-element-parse-secondary-string
1737 "org-element" (string restriction
&optional buffer
))
1738 (defvar org-element-string-restrictions
)
1739 (defvar org-element-object-restrictions
)
1741 (declare-function org-export-clean-table
"org-export" (table specialp
))
1742 (declare-function org-export-data
"org-export" (data backend info
))
1743 (declare-function org-export-directory
"org-export" (type plist
))
1744 (declare-function org-export-expand-macro
"org-export" (macro info
))
1745 (declare-function org-export-first-sibling-p
"org-export" (headline info
))
1746 (declare-function org-export-footnote-first-reference-p
"org-export"
1747 (footnote-reference info
))
1748 (declare-function org-export-get-coderef-format
"org-export" (path desc
))
1749 (declare-function org-export-get-footnote-definition
"org-export"
1750 (footnote-reference info
))
1751 (declare-function org-export-get-footnote-number
"org-export" (footnote info
))
1752 (declare-function org-export-get-previous-element
"org-export" (blob info
))
1753 (declare-function org-export-get-relative-level
"org-export" (headline info
))
1754 (declare-function org-export-handle-code
1755 "org-export" (element info
&optional num-fmt ref-fmt delayed
))
1756 (declare-function org-export-included-file
"org-export" (keyword backend info
))
1757 (declare-function org-export-inline-image-p
"org-export"
1758 (link &optional extensions
))
1759 (declare-function org-export-last-sibling-p
"org-export" (headline info
))
1760 (declare-function org-export-low-level-p
"org-export" (headline info
))
1761 (declare-function org-export-output-file-name
1762 "org-export" (extension &optional subtreep pub-dir
))
1763 (declare-function org-export-resolve-coderef
"org-export" (ref info
))
1764 (declare-function org-export-resolve-fuzzy-link
"org-export" (link info
))
1765 (declare-function org-export-secondary-string
"org-export"
1766 (secondary backend info
))
1767 (declare-function org-export-solidify-link-text
"org-export" (s))
1768 (declare-function org-export-table-format-info
"org-export" (table))
1770 org-export-to-buffer
"org-export"
1771 (backend buffer
&optional subtreep visible-only body-only ext-plist
))
1773 org-export-to-file
"org-export"
1774 (backend file
&optional subtreep visible-only body-only ext-plist
))
1776 (declare-function org-id-find-id-file
"org-id" (id))
1777 (declare-function htmlize-region
"ext:htmlize" (beg end
))
1778 (declare-function org-pop-to-buffer-same-window
1779 "org-compat" (&optional buffer-or-name norecord label
))
1785 (declare-function hfy-face-to-style
"htmlfontify" (fn))
1786 (declare-function hfy-face-or-def-to-name
"htmlfontify" (fn))
1787 (declare-function archive-zip-extract
"arc-mode.el" (archive name
))
1789 ;;; Internal Variables
1791 ;;;; ODT Internal Variables
1793 (defconst org-e-odt-lib-dir
1794 (file-name-directory load-file-name
)
1795 "Location of ODT exporter.
1796 Use this to infer values of `org-e-odt-styles-dir' and
1797 `org-export-e-odt-schema-dir'.")
1799 (defvar org-e-odt-data-dir
1800 (expand-file-name "../etc/" org-e-odt-lib-dir
)
1801 "Data directory for ODT exporter.
1802 Use this to infer values of `org-e-odt-styles-dir' and
1803 `org-export-e-odt-schema-dir'.")
1808 (defconst org-export-e-odt-special-string-regexps
1809 '(("\\\\-" .
"­\\1") ; shy
1810 ("---\\([^-]\\)" .
"—\\1") ; mdash
1811 ("--\\([^-]\\)" .
"–\\1") ; ndash
1812 ("\\.\\.\\." .
"…")) ; hellip
1813 "Regular expressions for special string conversion.")
1815 (defconst org-e-odt-schema-dir-list
1817 (and org-e-odt-data-dir
1818 (expand-file-name "./schema/" org-e-odt-data-dir
)) ; bail out
1820 (and (boundp 'org-e-odt-data-dir
) org-e-odt-data-dir
; see make install
1821 (expand-file-name "./schema/" org-e-odt-data-dir
)))
1822 (expand-file-name "../contrib/odt/etc/schema/" org-e-odt-lib-dir
) ; git
1824 "List of directories to search for OpenDocument schema files.
1825 Use this list to set the default value of
1826 `org-export-e-odt-schema-dir'. The entries in this list are
1827 populated heuristically based on the values of `org-e-odt-lib-dir'
1828 and `org-e-odt-data-dir'.")
1831 (defconst org-e-odt-styles-dir-list
1833 (and org-e-odt-data-dir
1834 (expand-file-name "./styles/" org-e-odt-data-dir
)) ; bail out
1836 (and (boundp 'org-e-odt-data-dir
) org-e-odt-data-dir
; see make install
1837 (expand-file-name "./styles/" org-e-odt-data-dir
)))
1838 (expand-file-name "../etc/styles/" org-e-odt-lib-dir
) ; git
1839 (expand-file-name "./etc/styles/" org-e-odt-lib-dir
) ; elpa
1840 (expand-file-name "./org/" data-directory
) ; system
1842 "List of directories to search for OpenDocument styles files.
1843 See `org-e-odt-styles-dir'. The entries in this list are populated
1844 heuristically based on the values of `org-e-odt-lib-dir' and
1845 `org-e-odt-data-dir'.")
1847 (defconst org-e-odt-styles-dir
1850 (message "Debug (org-e-odt): Searching for OpenDocument styles files...")
1851 (mapc (lambda (styles-dir)
1853 (message "Debug (org-e-odt): Trying %s..." styles-dir
)
1854 (when (and (file-readable-p
1856 "OrgOdtContentTemplate.xml" styles-dir
))
1859 "OrgOdtStyles.xml" styles-dir
)))
1860 (message "Debug (org-e-odt): Using styles under %s"
1862 (throw 'styles-dir styles-dir
))))
1863 org-e-odt-styles-dir-list
)
1866 (error "Error (org-e-odt): Cannot find factory styles files. Aborting."))
1868 "Directory that holds auxiliary XML files used by the ODT exporter.
1870 This directory contains the following XML files -
1871 \"OrgOdtStyles.xml\" and \"OrgOdtContentTemplate.xml\". These
1872 XML files are used as the default values of
1873 `org-export-e-odt-styles-file' and
1874 `org-export-e-odt-content-template-file'.
1876 The default value of this variable varies depending on the
1877 version of org in use and is initialized from
1878 `org-e-odt-styles-dir-list'. Note that the user could be using org
1879 from one of: org's own private git repository, GNU ELPA tar or
1882 (defconst org-export-e-odt-tmpdir-prefix
"%s-")
1883 (defconst org-export-e-odt-bookmark-prefix
"OrgXref.")
1885 (defconst org-e-odt-manifest-file-entry-tag
1887 <manifest:file-entry manifest:media-type=\"%s\" manifest:full-path=\"%s\"%s/>")
1891 (defvar org-lparse-dyn-first-heading-pos
) ; let bound during org-do-lparse
1893 (defvar org-e-odt-suppress-xref nil
)
1894 (defvar org-e-odt-file-extensions
1895 '(("odt" .
"OpenDocument Text")
1896 ("ott" .
"OpenDocument Text Template")
1897 ("odm" .
"OpenDocument Master Document")
1898 ("ods" .
"OpenDocument Spreadsheet")
1899 ("ots" .
"OpenDocument Spreadsheet Template")
1900 ("odg" .
"OpenDocument Drawing (Graphics)")
1901 ("otg" .
"OpenDocument Drawing Template")
1902 ("odp" .
"OpenDocument Presentation")
1903 ("otp" .
"OpenDocument Presentation Template")
1904 ("odi" .
"OpenDocument Image")
1905 ("odf" .
"OpenDocument Formula")
1906 ("odc" .
"OpenDocument Chart")))
1908 (defvar org-export-e-odt-embed-images t
1909 "Should the images be copied in to the odt file or just linked?")
1911 (defvar org-export-e-odt-inline-images
'maybe
)
1912 (defvar org-export-e-odt-default-org-styles-alist
1913 '((paragraph .
((default .
"Text_20_body")
1914 (fixedwidth .
"OrgFixedWidthBlock")
1915 (verse .
"OrgVerse")
1916 (quote .
"Quotations")
1917 (blockquote .
"Quotations")
1918 (center .
"OrgCenter")
1920 (right .
"OrgRight")
1921 (title .
"OrgTitle")
1922 (subtitle .
"OrgSubtitle")
1923 (footnote .
"Footnote")
1924 (src .
"OrgSrcBlock")
1925 (illustration .
"Illustration")
1927 (definition-term .
"Text_20_body_20_bold")
1928 (horizontal-line .
"Horizontal_20_Line")))
1929 (character .
((bold .
"Bold")
1930 (emphasis .
"Emphasis")
1932 (verbatim .
"OrgCode")
1933 (strike .
"Strikethrough")
1934 (underline .
"Underline")
1935 (subscript .
"OrgSubscript")
1936 (superscript .
"OrgSuperscript")))
1937 (list .
((ordered .
"OrgNumberedList")
1938 (unordered .
"OrgBulletedList")
1939 (descriptive .
"OrgDescriptionList"))))
1940 "Default styles for various entities.")
1942 (defvar org-export-e-odt-org-styles-alist org-export-e-odt-default-org-styles-alist
)
1945 ;;;_. control callbacks
1946 ;;;_ , document body
1948 (defvar org-lparse-body-only
) ; let bound during org-do-lparse
1949 (defvar org-lparse-opt-plist
) ; bound during org-do-lparse
1950 (defvar org-lparse-list-stack
) ; dynamically bound in org-do-lparse
1951 (defvar org-e-odt-list-stack-stashed
)
1952 (defvar org-lparse-table-ncols
)
1953 (defvar org-e-odt-table-rowgrp-open
)
1954 (defvar org-e-odt-table-rownum
)
1955 (defvar org-e-odt-table-cur-rowgrp-is-hdr
)
1956 (defvar org-lparse-table-is-styled
)
1957 (defvar org-lparse-table-rowgrp-info
)
1958 (defvar org-lparse-table-colalign-vector
)
1960 (defvar org-e-odt-table-style nil
1961 "Table style specified by \"#+ATTR_ODT: <style-name>\" line.
1962 This is set during `org-e-odt-begin-table'.")
1964 (defvar org-e-odt-table-style-spec nil
1965 "Entry for `org-e-odt-table-style' in `org-export-e-odt-table-styles'.")
1968 (defvar org-e-odt-table-style-format
1970 <style:style style:name=\"%s\" style:family=\"table\">
1971 <style:table-properties style:rel-width=\"%d%%\" fo:margin-top=\"0cm\" fo:margin-bottom=\"0.20cm\" table:align=\"center\"/>
1974 "Template for auto-generated Table styles.")
1976 (defvar org-e-odt-automatic-styles
'()
1977 "Registry of automatic styles for various OBJECT-TYPEs.
1978 The variable has the following form:
1980 \(\(OBJECT-NAME-A.1 OBJECT-PROPS-A.1\)
1981 \(OBJECT-NAME-A.2 OBJECT-PROPS-A.2\) ...\)\)
1983 \(\(OBJECT-NAME-B.1 OBJECT-PROPS-B.1\)
1984 \(OBJECT-NAME-B.2 OBJECT-PROPS-B.2\) ...\)\)
1987 OBJECT-TYPEs could be \"Section\", \"Table\", \"Figure\" etc.
1988 OBJECT-PROPS is (typically) a plist created by passing
1989 \"#+ATTR_ODT: \" option to `org-lparse-get-block-params'.
1991 Use `org-e-odt-add-automatic-style' to add update this variable.'")
1993 (defvar org-e-odt-object-counters nil
1994 "Running counters for various OBJECT-TYPEs.
1995 Use this to generate automatic names and style-names. See
1996 `org-e-odt-add-automatic-style'.")
1998 (defvar org-e-odt-table-indentedp nil
)
1999 (defvar org-lparse-table-colalign-info
)
2000 (defvar org-lparse-link-description-is-image nil
)
2003 (defvar org-src-block-paragraph-format
2004 "<style:style style:name=\"OrgSrcBlock\" style:family=\"paragraph\" style:parent-style-name=\"Preformatted_20_Text\">
2005 <style:paragraph-properties fo:background-color=\"%s\" fo:padding=\"0.049cm\" fo:border=\"0.51pt solid #000000\" style:shadow=\"none\">
2006 <style:background-image/>
2007 </style:paragraph-properties>
2008 <style:text-properties fo:color=\"%s\"/>
2010 "Custom paragraph style for colorized source and example blocks.
2011 This style is much the same as that of \"OrgFixedWidthBlock\"
2012 except that the foreground and background colors are set
2013 according to the default face identified by the `htmlfontify'.")
2015 (defvar hfy-optimisations
)
2016 (defvar org-e-odt-embedded-formulas-count
0)
2017 (defvar org-e-odt-entity-frame-styles
2018 '(("As-CharImage" "__Figure__" ("OrgInlineImage" nil
"as-char"))
2019 ("ParagraphImage" "__Figure__" ("OrgDisplayImage" nil
"paragraph"))
2020 ("PageImage" "__Figure__" ("OrgPageImage" nil
"page"))
2021 ("CaptionedAs-CharImage" "__Figure__"
2022 ("OrgCaptionedImage"
2023 " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph")
2024 ("OrgInlineImage" nil
"as-char"))
2025 ("CaptionedParagraphImage" "__Figure__"
2026 ("OrgCaptionedImage"
2027 " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph")
2028 ("OrgImageCaptionFrame" nil
"paragraph"))
2029 ("CaptionedPageImage" "__Figure__"
2030 ("OrgCaptionedImage"
2031 " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph")
2032 ("OrgPageImageCaptionFrame" nil
"page"))
2033 ("InlineFormula" "__MathFormula__" ("OrgInlineFormula" nil
"as-char"))
2034 ("DisplayFormula" "__MathFormula__" ("OrgDisplayFormula" nil
"as-char"))
2035 ("CaptionedDisplayFormula" "__MathFormula__"
2036 ("OrgCaptionedFormula" nil
"paragraph")
2037 ("OrgFormulaCaptionFrame" nil
"as-char"))))
2039 (defvar org-e-odt-embedded-images-count
0)
2041 (defvar org-export-e-odt-image-size-probe-method
2042 (append (and (executable-find "identify") '(imagemagick)) ; See Bug#10675
2044 "Ordered list of methods for determining image sizes.")
2046 (defvar org-export-e-odt-default-image-sizes-alist
2047 '(("as-char" .
(5 .
0.4))
2048 ("paragraph" .
(5 .
5)))
2049 "Hardcoded image dimensions one for each of the anchor
2052 ;; A4 page size is 21.0 by 29.7 cms
2053 ;; The default page settings has 2cm margin on each of the sides. So
2054 ;; the effective text area is 17.0 by 25.7 cm
2055 (defvar org-export-e-odt-max-image-size
'(17.0 .
20.0)
2056 "Limiting dimensions for an embedded image.")
2058 (defvar org-e-odt-entity-labels-alist nil
2059 "Associate Labels with the Labeled entities.
2060 Each element of the alist is of the form (LABEL-NAME
2061 CATEGORY-NAME SEQNO LABEL-STYLE-NAME). LABEL-NAME is same as
2062 that specified by \"#+LABEL: ...\" line. CATEGORY-NAME is the
2063 type of the entity that LABEL-NAME is attached to. CATEGORY-NAME
2064 can be one of \"Table\", \"Figure\" or \"Equation\". SEQNO is
2065 the unique number assigned to the referenced entity on a
2066 per-CATEGORY basis. It is generated sequentially and is 1-based.
2067 LABEL-STYLE-NAME is a key `org-e-odt-label-styles'.
2069 See `org-e-odt-add-label-definition' and
2070 `org-e-odt-fixup-label-references'.")
2072 (defvar org-e-odt-entity-counts-plist nil
2073 "Plist of running counters of SEQNOs for each of the CATEGORY-NAMEs.
2074 See `org-e-odt-entity-labels-alist' for known CATEGORY-NAMEs.")
2076 (defvar org-e-odt-label-styles
2077 '(("text" "(%n)" "text" "(%n)")
2078 ("category-and-value" "%e %n%c" "category-and-value" "%e %n")
2079 ("value" "%e %n%c" "value" "%n"))
2080 "Specify how labels are applied and referenced.
2081 This is an alist where each element is of the
2082 form (LABEL-STYLE-NAME LABEL-ATTACH-FMT LABEL-REF-MODE
2085 LABEL-ATTACH-FMT controls how labels and captions are attached to
2086 an entity. It may contain following specifiers - %e, %n and %c.
2087 %e is replaced with the CATEGORY-NAME. %n is replaced with
2088 \"<text:sequence ...> SEQNO </text:sequence>\". %c is replaced
2089 with CAPTION. See `org-e-odt-format-label-definition'.
2091 LABEL-REF-MODE and LABEL-REF-FMT controls how label references
2092 are generated. The following XML is generated for a label
2093 reference - \"<text:sequence-ref
2094 text:reference-format=\"LABEL-REF-MODE\" ...> LABEL-REF-FMT
2095 </text:sequence-ref>\". LABEL-REF-FMT may contain following
2096 specifiers - %e and %n. %e is replaced with the CATEGORY-NAME.
2097 %n is replaced with SEQNO. See
2098 `org-e-odt-format-label-reference'.")
2100 (defvar org-e-odt-category-map-alist
2101 '(("__Table__" "Table" "value")
2102 ("__Figure__" "Figure" "value")
2103 ("__MathFormula__" "Equation" "text")
2104 ("__DvipngImage__" "Equation" "value")
2105 ;; ("__Table__" "Table" "category-and-value")
2106 ;; ("__Figure__" "Figure" "category-and-value")
2107 ;; ("__DvipngImage__" "Equation" "category-and-value")
2109 "Map a CATEGORY-HANDLE to CATEGORY-NAME and LABEL-STYLE.
2110 This is an alist where each element is of the form
2111 \\(CATEGORY-HANDLE CATEGORY-NAME LABEL-STYLE\\). CATEGORY_HANDLE
2112 could either be one of the internal handles (as seen above) or be
2113 derived from the \"#+LABEL:<label-name>\" specification. See
2114 `org-export-e-odt-get-category-from-label'. CATEGORY-NAME and
2115 LABEL-STYLE are used for generating ODT labels. See
2116 `org-e-odt-label-styles'.")
2118 (defvar org-export-e-odt-user-categories
2119 '("Illustration" "Table" "Text" "Drawing" "Equation" "Figure"))
2121 (defvar org-export-e-odt-get-category-from-label nil
2122 "Should category of label be inferred from label itself.
2123 When this option is non-nil, a label is parsed in to two
2124 component parts delimited by a \":\" (colon) as shown here -
2125 #+LABEL:[CATEGORY-HANDLE:]EXTRA. The CATEGORY-HANDLE is mapped
2126 to a CATEGORY-NAME and LABEL-STYLE using
2127 `org-e-odt-category-map-alist'. (If no such map is provided and
2128 CATEGORY-NAME is set to CATEGORY-HANDLE and LABEL-STYLE is set to
2129 \"category-and-value\"). If CATEGORY-NAME so obtained is listed
2130 under `org-export-e-odt-user-categories' then the user specified
2131 styles are used. Otherwise styles as determined by the internal
2132 CATEGORY-HANDLE is used. See
2133 `org-e-odt-get-label-category-and-style' for details.")
2135 (defvar org-e-odt-manifest-file-entries nil
)
2136 (defvar hfy-user-sheet-assoc
) ; bound during org-do-lparse
2137 (defvar org-lparse-latex-fragment-fallback
) ; set by org-do-lparse
2140 ;;;; HTML Internal Variables
2142 (defvar org-e-odt-option-alist
2144 ;; (:agenda-style nil nil org-agenda-export-html-style)
2145 ;; (:convert-org-links nil nil org-e-odt-link-org-files-as-html)
2146 ;; ;; FIXME Use (org-xml-encode-org-text-skip-links s) ??
2147 ;; ;; (:expand-quoted-html nil "@" org-e-odt-expand)
2148 ;; (:inline-images nil nil org-e-odt-inline-images)
2149 ;; ;; (:link-home nil nil org-e-odt-link-home) FIXME
2150 ;; ;; (:link-up nil nil org-e-odt-link-up) FIXME
2151 ;; (:style nil nil org-e-odt-style)
2152 ;; (:style-extra nil nil org-e-odt-style-extra)
2153 ;; (:style-include-default nil nil org-e-odt-style-include-default)
2154 ;; (:style-include-scripts nil nil org-e-odt-style-include-scripts)
2155 ;; ;; (:timestamp nil nil org-e-odt-with-timestamp)
2156 ;; (:html-extension nil nil org-e-odt-extension)
2157 ;; (:html-postamble nil nil org-e-odt-postamble)
2158 ;; (:html-preamble nil nil org-e-odt-preamble)
2159 ;; (:html-table-tag nil nil org-e-odt-table-tag)
2160 ;; (:xml-declaration nil nil org-e-odt-xml-declaration)
2161 (:LaTeX-fragments nil
"LaTeX" org-export-with-LaTeX-fragments
))
2162 "Alist between export properties and ways to set them.
2164 The car of the alist is the property name, and the cdr is a list
2165 like \(KEYWORD OPTION DEFAULT BEHAVIOUR\) where:
2167 KEYWORD is a string representing a buffer keyword, or nil.
2168 OPTION is a string that could be found in an #+OPTIONS: line.
2169 DEFAULT is the default value for the property.
2170 BEHAVIOUR determine how Org should handle multiple keywords for
2171 the same property. It is a symbol among:
2172 nil Keep old value and discard the new one.
2173 t Replace old value with the new one.
2174 `space' Concatenate the values, separating them with a space.
2175 `newline' Concatenate the values, separating them with
2177 `split' Split values at white spaces, and cons them to the
2180 KEYWORD and OPTION have precedence over DEFAULT.
2182 All these properties should be back-end agnostic. For back-end
2183 specific properties, define a similar variable named
2184 `org-BACKEND-option-alist', replacing BACKEND with the name of
2185 the appropriate back-end. You can also redefine properties
2186 there, as they have precedence over these.")
2188 (defvar html-table-tag nil
) ; dynamically scoped into this.
2190 ;; FIXME: it already exists in org-e-odt.el
2191 (defconst org-e-odt-cvt-link-fn
2193 "Function to convert link URLs to exportable URLs.
2194 Takes two arguments, TYPE and PATH.
2195 Returns exportable url as (TYPE PATH), or nil to signal that it
2196 didn't handle this case.
2197 Intended to be locally bound around a call to `org-export-as-html'." )
2202 (defvar org-e-odt-format-table-no-css
)
2203 (defvar htmlize-buffer-places
) ; from htmlize.el
2204 (defvar body-only
) ; dynamically scoped into this.
2206 (defvar org-e-odt-table-rowgrp-open
)
2207 (defvar org-e-odt-table-rownum
)
2208 (defvar org-e-odt-table-cur-rowgrp-is-hdr
)
2209 (defvar org-lparse-table-is-styled
)
2212 (defvar org-e-odt-headline-formatter
2213 (lambda (level snumber todo todo-type priority
2214 title tags target extra-targets extra-class
)
2215 (concat snumber
" " title
)))
2219 ;;; User Configuration Variables
2221 (defgroup org-export-e-odt nil
2222 "Options for exporting Org mode files to HTML."
2223 :tag
"Org Export HTML"
2226 (defcustom org-e-odt-protect-char-alist
2230 "Alist of characters to be converted by `org-e-html-protect'."
2231 :group
'org-export-e-html
2232 :type
'(repeat (cons (string :tag
"Character")
2233 (string :tag
"ODT equivalent"))))
2234 (defcustom org-export-e-odt-schema-dir
2237 (message "Debug (org-e-odt): Searching for OpenDocument schema files...")
2239 (lambda (schema-dir)
2241 (message "Debug (org-e-odt): Trying %s..." schema-dir
)
2242 (when (and (file-readable-p
2243 (expand-file-name "od-manifest-schema-v1.2-cs01.rnc"
2246 (expand-file-name "od-schema-v1.2-cs01.rnc"
2249 (expand-file-name "schemas.xml" schema-dir
)))
2250 (message "Debug (org-e-odt): Using schema files under %s"
2252 (throw 'schema-dir schema-dir
))))
2253 org-e-odt-schema-dir-list
)
2254 (message "Debug (org-e-odt): No OpenDocument schema files installed")
2257 "Directory that contains OpenDocument schema files.
2259 This directory contains:
2260 1. rnc files for OpenDocument schema
2261 2. a \"schemas.xml\" file that specifies locating rules needed
2262 for auto validation of OpenDocument XML files.
2264 Use the customize interface to set this variable. This ensures
2265 that `rng-schema-locating-files' is updated and auto-validation
2266 of OpenDocument XML takes place based on the value
2267 `rng-nxml-auto-validate-flag'.
2269 The default value of this variable varies depending on the
2270 version of org in use and is initialized from
2271 `org-e-odt-schema-dir-list'. The OASIS schema files are available
2272 only in the org's private git repository. It is *not* bundled
2273 with GNU ELPA tar or standard Emacs distribution."
2275 (const :tag
"Not set" nil
)
2276 (directory :tag
"Schema directory"))
2277 :group
'org-export-e-odt
2281 "Set `org-export-e-odt-schema-dir'.
2282 Also add it to `rng-schema-locating-files'."
2283 (let ((schema-dir value
))
2287 (expand-file-name "od-manifest-schema-v1.2-cs01.rnc" schema-dir
))
2289 (expand-file-name "od-schema-v1.2-cs01.rnc" schema-dir
))
2291 (expand-file-name "schemas.xml" schema-dir
)))
2294 (message "Error (org-e-odt): %s has no OpenDocument schema files"
2297 (when org-export-e-odt-schema-dir
2298 (eval-after-load 'rng-loc
2299 '(add-to-list 'rng-schema-locating-files
2300 (expand-file-name "schemas.xml"
2301 org-export-e-odt-schema-dir
))))))
2303 (defcustom org-export-e-odt-content-template-file nil
2304 "Template file for \"content.xml\".
2305 The exporter embeds the exported content just before
2306 \"</office:text>\" element.
2308 If unspecified, the file named \"OrgOdtContentTemplate.xml\"
2309 under `org-e-odt-styles-dir' is used."
2311 :group
'org-export-e-odt
2314 (defcustom org-export-e-odt-styles-file nil
2315 "Default styles file for use with ODT export.
2316 Valid values are one of:
2318 2. path to a styles.xml file
2319 3. path to a *.odt or a *.ott file
2320 4. list of the form (ODT-OR-OTT-FILE (FILE-MEMBER-1 FILE-MEMBER-2
2323 In case of option 1, an in-built styles.xml is used. See
2324 `org-e-odt-styles-dir' for more information.
2326 In case of option 3, the specified file is unzipped and the
2327 styles.xml embedded therein is used.
2329 In case of option 4, the specified ODT-OR-OTT-FILE is unzipped
2330 and FILE-MEMBER-1, FILE-MEMBER-2 etc are copied in to the
2331 generated odt file. Use relative path for specifying the
2332 FILE-MEMBERS. styles.xml must be specified as one of the
2335 Use options 1, 2 or 3 only if styles.xml alone suffices for
2336 achieving the desired formatting. Use option 4, if the styles.xml
2337 references additional files like header and footer images for
2338 achieving the desired formatting.
2340 Use \"#+ODT_STYLES_FILE: ...\" directive to set this variable on
2341 a per-file basis. For example,
2343 #+ODT_STYLES_FILE: \"/path/to/styles.xml\" or
2344 #+ODT_STYLES_FILE: (\"/path/to/file.ott\" (\"styles.xml\" \"image/hdr.png\"))."
2345 :group
'org-export-e-odt
2349 (const :tag
"Factory settings" nil
)
2350 (file :must-match t
:tag
"styles.xml")
2351 (file :must-match t
:tag
"ODT or OTT file")
2352 (list :tag
"ODT or OTT file + Members"
2353 (file :must-match t
:tag
"ODF Text or Text Template file")
2354 (cons :tag
"Members"
2355 (file :tag
" Member" "styles.xml")
2356 (repeat (file :tag
"Member"))))))
2359 (defcustom org-export-e-odt-inline-image-extensions
2360 '("png" "jpeg" "jpg" "gif")
2361 "Extensions of image files that can be inlined into HTML."
2362 :type
'(repeat (string :tag
"Extension"))
2363 :group
'org-export-e-odt
2366 (defcustom org-export-e-odt-pixels-per-inch display-pixels-per-inch
2367 "Scaling factor for converting images pixels to inches.
2368 Use this for sizing of embedded images. See Info node `(org)
2369 Images in ODT export' for more information."
2371 :group
'org-export-e-odt
2374 (defcustom org-export-e-odt-create-custom-styles-for-srcblocks t
2375 "Whether custom styles for colorized source blocks be automatically created.
2376 When this option is turned on, the exporter creates custom styles
2377 for source blocks based on the advice of `htmlfontify'. Creation
2378 of custom styles happen as part of `org-e-odt-hfy-face-to-css'.
2380 When this option is turned off exporter does not create such
2383 Use the latter option if you do not want the custom styles to be
2384 based on your current display settings. It is necessary that the
2385 styles.xml already contains needed styles for colorizing to work.
2387 This variable is effective only if
2388 `org-export-e-odt-fontify-srcblocks' is turned on."
2389 :group
'org-export-e-odt
2393 (defcustom org-export-e-odt-preferred-output-format nil
2394 "Automatically post-process to this format after exporting to \"odt\".
2395 Interactive commands `org-export-as-e-odt' and
2396 `org-export-as-e-odt-and-open' export first to \"odt\" format and
2397 then use `org-export-e-odt-convert-process' to convert the
2398 resulting document to this format. During customization of this
2399 variable, the list of valid values are populated based on
2400 `org-export-e-odt-convert-capabilities'."
2401 :group
'org-export-e-odt
2403 :type
'(choice :convert-widget
2405 (apply 'widget-convert
(widget-type w
)
2406 (eval (car (widget-get w
:args
)))))
2407 `((const :tag
"None" nil
)
2408 ,@(mapcar (lambda (c)
2409 `(const :tag
,c
,c
))
2410 (org-lparse-reachable-formats "odt")))))
2412 (defcustom org-export-e-odt-table-styles
2413 '(("OrgEquation" "OrgEquation"
2414 ((use-first-column-styles . t
)
2415 (use-last-column-styles . t
))))
2416 "Specify how Table Styles should be derived from a Table Template.
2417 This is a list where each element is of the
2418 form (TABLE-STYLE-NAME TABLE-TEMPLATE-NAME TABLE-CELL-OPTIONS).
2420 TABLE-STYLE-NAME is the style associated with the table through
2421 `org-e-odt-table-style'.
2423 TABLE-TEMPLATE-NAME is a set of - upto 9 - automatic
2424 TABLE-CELL-STYLE-NAMEs and PARAGRAPH-STYLE-NAMEs (as defined
2425 below) that is included in
2426 `org-export-e-odt-content-template-file'.
2428 TABLE-CELL-STYLE-NAME := TABLE-TEMPLATE-NAME + TABLE-CELL-TYPE +
2430 PARAGRAPH-STYLE-NAME := TABLE-TEMPLATE-NAME + TABLE-CELL-TYPE +
2432 TABLE-CELL-TYPE := \"FirstRow\" | \"LastColumn\" |
2433 \"FirstRow\" | \"LastRow\" |
2434 \"EvenRow\" | \"OddRow\" |
2435 \"EvenColumn\" | \"OddColumn\" | \"\"
2436 where \"+\" above denotes string concatenation.
2438 TABLE-CELL-OPTIONS is an alist where each element is of the
2439 form (TABLE-CELL-STYLE-SELECTOR . ON-OR-OFF).
2440 TABLE-CELL-STYLE-SELECTOR := `use-first-row-styles' |
2441 `use-last-row-styles' |
2442 `use-first-column-styles' |
2443 `use-last-column-styles' |
2444 `use-banding-rows-styles' |
2445 `use-banding-columns-styles' |
2446 `use-first-row-styles'
2447 ON-OR-OFF := `t' | `nil'
2449 For example, with the following configuration
2451 \(setq org-export-e-odt-table-styles
2452 '\(\(\"TableWithHeaderRowsAndColumns\" \"Custom\"
2453 \(\(use-first-row-styles . t\)
2454 \(use-first-column-styles . t\)\)\)
2455 \(\"TableWithHeaderColumns\" \"Custom\"
2456 \(\(use-first-column-styles . t\)\)\)\)\)
2458 1. A table associated with \"TableWithHeaderRowsAndColumns\"
2459 style will use the following table-cell styles -
2460 \"CustomFirstRowTableCell\", \"CustomFirstColumnTableCell\",
2461 \"CustomTableCell\" and the following paragraph styles
2462 \"CustomFirstRowTableParagraph\",
2463 \"CustomFirstColumnTableParagraph\", \"CustomTableParagraph\"
2466 2. A table associated with \"TableWithHeaderColumns\" style will
2467 use the following table-cell styles -
2468 \"CustomFirstColumnTableCell\", \"CustomTableCell\" and the
2469 following paragraph styles
2470 \"CustomFirstColumnTableParagraph\", \"CustomTableParagraph\"
2473 Note that TABLE-TEMPLATE-NAME corresponds to the
2474 \"<table:table-template>\" elements contained within
2475 \"<office:styles>\". The entries (TABLE-STYLE-NAME
2476 TABLE-TEMPLATE-NAME TABLE-CELL-OPTIONS) correspond to
2477 \"table:template-name\" and \"table:use-first-row-styles\" etc
2478 attributes of \"<table:table>\" element. Refer ODF-1.2
2479 specification for more information. Also consult the
2480 implementation filed under `org-e-odt-get-table-cell-styles'.
2482 The TABLE-STYLE-NAME \"OrgEquation\" is used internally for
2483 formatting of numbered display equations. Do not delete this
2484 style from the list."
2485 :group
'org-export-e-odt
2488 (const :tag
"None" nil
)
2489 (repeat :tag
"Table Styles"
2490 (list :tag
"Table Style Specification"
2491 (string :tag
"Table Style Name")
2492 (string :tag
"Table Template Name")
2493 (alist :options
(use-first-row-styles
2495 use-first-column-styles
2496 use-last-column-styles
2497 use-banding-rows-styles
2498 use-banding-columns-styles
)
2500 :value-type
(const :tag
"True" t
))))))
2501 (defcustom org-export-e-odt-fontify-srcblocks t
2502 "Specify whether or not source blocks need to be fontified.
2503 Turn this option on if you want to colorize the source code
2504 blocks in the exported file. For colorization to work, you need
2505 to make available an enhanced version of `htmlfontify' library."
2507 :group
'org-export-e-odt
2510 (defcustom org-export-e-odt-prettify-xml t
; FIXME
2511 "Specify whether or not the xml output should be prettified.
2512 When this option is turned on, `indent-region' is run on all
2513 component xml buffers before they are saved. Turn this off for
2514 regular use. Turn this on if you need to examine the xml
2516 :group
'org-export-e-odt
2520 (defcustom org-export-e-odt-convert-processes
2522 "soffice --headless --convert-to %f%x --outdir %d %i")
2524 "unoconv -f %f -o %d %i"))
2525 "Specify a list of document converters and their usage.
2526 The converters in this list are offered as choices while
2527 customizing `org-export-e-odt-convert-process'.
2529 This variable is a list where each element is of the
2530 form (CONVERTER-NAME CONVERTER-CMD). CONVERTER-NAME is the name
2531 of the converter. CONVERTER-CMD is the shell command for the
2532 converter and can contain format specifiers. These format
2533 specifiers are interpreted as below:
2535 %i input file name in full
2536 %I input file name as a URL
2537 %f format of the output file
2538 %o output file name in full
2539 %O output file name as a URL
2540 %d output dir in full
2541 %D output dir as a URL.
2542 %x extra options as set in `org-export-e-odt-convert-capabilities'."
2543 :group
'org-export-e-odt
2547 (const :tag
"None" nil
)
2548 (alist :tag
"Converters"
2549 :key-type
(string :tag
"Converter Name")
2550 :value-type
(group (string :tag
"Command line")))))
2552 (defcustom org-export-e-odt-convert-process
"LibreOffice"
2553 "Use this converter to convert from \"odt\" format to other formats.
2554 During customization, the list of converter names are populated
2555 from `org-export-e-odt-convert-processes'."
2556 :group
'org-export-e-odt
2558 :type
'(choice :convert-widget
2560 (apply 'widget-convert
(widget-type w
)
2561 (eval (car (widget-get w
:args
)))))
2562 `((const :tag
"None" nil
)
2563 ,@(mapcar (lambda (c)
2564 `(const :tag
,(car c
) ,(car c
)))
2565 org-export-e-odt-convert-processes
))))
2567 (defcustom org-export-e-odt-convert-capabilities
2569 ("odt" "ott" "doc" "rtf" "docx")
2570 (("pdf" "pdf") ("odt" "odt") ("rtf" "rtf") ("ott" "ott")
2571 ("doc" "doc" ":\"MS Word 97\"") ("docx" "docx") ("html" "html")))
2574 (("pdf" "pdf") ("odt" "odt") ("html" "html")))
2576 ("ods" "ots" "xls" "csv" "xlsx")
2577 (("pdf" "pdf") ("ots" "ots") ("html" "html") ("csv" "csv") ("ods" "ods")
2578 ("xls" "xls") ("xlsx" "xlsx")))
2580 ("odp" "otp" "ppt" "pptx")
2581 (("pdf" "pdf") ("swf" "swf") ("odp" "odp") ("otp" "otp") ("ppt" "ppt")
2582 ("pptx" "pptx") ("odg" "odg"))))
2583 "Specify input and output formats of `org-export-e-odt-convert-process'.
2584 More correctly, specify the set of input and output formats that
2585 the user is actually interested in.
2587 This variable is an alist where each element is of the
2588 form (DOCUMENT-CLASS INPUT-FMT-LIST OUTPUT-FMT-ALIST).
2589 INPUT-FMT-LIST is a list of INPUT-FMTs. OUTPUT-FMT-ALIST is an
2590 alist where each element is of the form (OUTPUT-FMT
2591 OUTPUT-FILE-EXTENSION EXTRA-OPTIONS).
2593 The variable is interpreted as follows:
2594 `org-export-e-odt-convert-process' can take any document that is in
2595 INPUT-FMT-LIST and produce any document that is in the
2596 OUTPUT-FMT-LIST. A document converted to OUTPUT-FMT will have
2597 OUTPUT-FILE-EXTENSION as the file name extension. OUTPUT-FMT
2598 serves dual purposes:
2599 - It is used for populating completion candidates during
2600 `org-export-e-odt-convert' commands.
2601 - It is used as the value of \"%f\" specifier in
2602 `org-export-e-odt-convert-process'.
2604 EXTRA-OPTIONS is used as the value of \"%x\" specifier in
2605 `org-export-e-odt-convert-process'.
2607 DOCUMENT-CLASS is used to group a set of file formats in
2608 INPUT-FMT-LIST in to a single class.
2610 Note that this variable inherently captures how LibreOffice based
2611 converters work. LibreOffice maps documents of various formats
2612 to classes like Text, Web, Spreadsheet, Presentation etc and
2613 allow document of a given class (irrespective of it's source
2614 format) to be converted to any of the export formats associated
2617 See default setting of this variable for an typical
2619 :group
'org-export-e-odt
2623 (const :tag
"None" nil
)
2624 (alist :tag
"Capabilities"
2625 :key-type
(string :tag
"Document Class")
2627 (group (repeat :tag
"Input formats" (string :tag
"Input format"))
2628 (alist :tag
"Output formats"
2629 :key-type
(string :tag
"Output format")
2631 (group (string :tag
"Output file extension")
2633 (const :tag
"None" nil
)
2634 (string :tag
"Extra options"))))))))
2641 ;;;; Document Header (Styles)
2643 ;;;; Document Header (Scripts)
2645 ;;;; Document Header (Mathjax)
2658 ;;;; Statistics Cookie
2678 ;;;; Horizontal Rule
2679 ;;;; Inline Babel Call
2680 ;;;; Inline Src Block
2684 ;;;; Latex Environment
2693 ;;;; Property Drawer
2719 ;;; User Configurable Variables (MAYBE)
2727 (defcustom org-e-odt-format-headline-function nil
2728 "Function to format headline text.
2730 This function will be called with 5 arguments:
2731 TODO the todo keyword \(string or nil\).
2732 TODO-TYPE the type of todo \(symbol: `todo', `done', nil\)
2733 PRIORITY the priority of the headline \(integer or nil\)
2734 TEXT the main headline text \(string\).
2735 TAGS the tags string, separated with colons \(string or nil\).
2737 The function result will be used in the section format string.
2739 As an example, one could set the variable to the following, in
2740 order to reproduce the default set-up:
2742 \(defun org-e-odt-format-headline \(todo todo-type priority text tags\)
2743 \"Default format function for an headline.\"
2744 \(concat \(when todo
2745 \(format \"\\\\textbf{\\\\textsc{\\\\textsf{%s}}} \" todo\)\)
2747 \(format \"\\\\framebox{\\\\#%c} \" priority\)\)
2749 \(when tags \(format \"\\\\hfill{}\\\\textsc{%s}\" tags\)\)\)\)"
2750 :group
'org-export-e-odt
2757 (defcustom org-e-odt-active-timestamp-format
"\\textit{%s}"
2758 "A printf format string to be applied to active time-stamps."
2759 :group
'org-export-e-odt
2762 (defcustom org-e-odt-inactive-timestamp-format
"\\textit{%s}"
2763 "A printf format string to be applied to inactive time-stamps."
2764 :group
'org-export-e-odt
2767 (defcustom org-e-odt-diary-timestamp-format
"\\textit{%s}"
2768 "A printf format string to be applied to diary time-stamps."
2769 :group
'org-export-e-odt
2775 (defcustom org-e-odt-image-default-option
"width=.9\\linewidth"
2776 "Default option for images."
2777 :group
'org-export-e-odt
2780 (defcustom org-e-odt-default-figure-position
"htb"
2781 "Default position for latex figures."
2782 :group
'org-export-e-odt
2785 (defcustom org-e-odt-inline-image-rules
2786 '(("file" .
"\\.\\(pdf\\|jpeg\\|jpg\\|png\\|ps\\|eps\\)\\'"))
2787 "Rules characterizing image files that can be inlined into HTML.
2789 A rule consists in an association whose key is the type of link
2790 to consider, and value is a regexp that will be matched against
2793 Note that, by default, the image extension *actually* allowed
2794 depend on the way the HTML file is processed. When used with
2795 pdflatex, pdf, jpg and png images are OK. When processing
2796 through dvi to Postscript, only ps and eps are allowed. The
2797 default we use here encompasses both."
2798 :group
'org-export-e-odt
2799 :type
'(alist :key-type
(string :tag
"Type")
2800 :value-type
(regexp :tag
"Path")))
2804 (defcustom org-e-odt-table-caption-above t
2805 "When non-nil, place caption string at the beginning of the table.
2806 Otherwise, place it near the end."
2807 :group
'org-export-e-odt
2812 (defcustom org-e-odt-format-drawer-function nil
2813 "Function called to format a drawer in HTML code.
2815 The function must accept two parameters:
2816 NAME the drawer name, like \"LOGBOOK\"
2817 CONTENTS the contents of the drawer.
2819 The function should return the string to be exported.
2821 For example, the variable could be set to the following function
2822 in order to mimic default behaviour:
2824 \(defun org-e-odt-format-drawer-default \(name contents\)
2825 \"Format a drawer element for HTML export.\"
2827 :group
'org-export-e-odt
2833 (defcustom org-e-odt-format-inlinetask-function nil
2834 "Function called to format an inlinetask in HTML code.
2836 The function must accept six parameters:
2837 TODO the todo keyword, as a string
2838 TODO-TYPE the todo type, a symbol among `todo', `done' and nil.
2839 PRIORITY the inlinetask priority, as a string
2840 NAME the inlinetask name, as a string.
2841 TAGS the inlinetask tags, as a string.
2842 CONTENTS the contents of the inlinetask, as a string.
2844 The function should return the string to be exported.
2846 For example, the variable could be set to the following function
2847 in order to mimic default behaviour:
2849 \(defun org-e-odt-format-inlinetask \(todo type priority name tags contents\)
2850 \"Format an inline task element for HTML export.\"
2851 \(let \(\(full-title
2854 \(format \"\\\\textbf{\\\\textsf{\\\\textsc{%s}}} \" todo\)\)
2855 \(when priority \(format \"\\\\framebox{\\\\#%c} \" priority\)\)
2857 \(when tags \(format \"\\\\hfill{}\\\\textsc{%s}\" tags\)\)\)\)\)
2858 \(format \(concat \"\\\\begin{center}\\n\"
2860 \"\\\\begin{minipage}[c]{.6\\\\textwidth}\\n\"
2862 \"\\\\rule[.8em]{\\\\textwidth}{2pt}\\n\\n\"
2864 \"\\\\end{minipage}}\"
2865 \"\\\\end{center}\"\)
2866 full-title contents\)\)"
2867 :group
'org-export-e-odt
2875 (defcustom org-e-odt-quotes
2876 '(("fr" ("\\(\\s-\\|[[(]\\)\"" .
"«~") ("\\(\\S-\\)\"" .
"~»") ("\\(\\s-\\|(\\)'" .
"'"))
2877 ("en" ("\\(\\s-\\|[[(]\\)\"" .
"``") ("\\(\\S-\\)\"" .
"''") ("\\(\\s-\\|(\\)'" .
"`")))
2878 "Alist for quotes to use when converting english double-quotes.
2880 The CAR of each item in this alist is the language code.
2881 The CDR of each item in this alist is a list of three CONS:
2882 - the first CONS defines the opening quote;
2883 - the second CONS defines the closing quote;
2884 - the last CONS defines single quotes.
2886 For each item in a CONS, the first string is a regexp
2887 for allowed characters before/after the quote, the second
2888 string defines the replacement string for this quote."
2889 :group
'org-export-e-odt
2891 (cons :tag
"Opening quote"
2892 (string :tag
"Regexp for char before")
2893 (string :tag
"Replacement quote "))
2894 (cons :tag
"Closing quote"
2895 (string :tag
"Regexp for char after ")
2896 (string :tag
"Replacement quote "))
2897 (cons :tag
"Single quote"
2898 (string :tag
"Regexp for char before")
2899 (string :tag
"Replacement quote "))))
2906 ;;; Internal Functions (HTML)
2908 ;; (defun org-e-odt-format-inline-image (path &optional caption label attr)
2909 ;; ;; FIXME: alt text missing here?
2910 ;; (let ((inline-image (format "<img src=\"%s\" alt=\"%s\"/>"
2911 ;; path (file-name-nondirectory path))))
2912 ;; (if (not label) inline-image
2913 ;; (org-e-odt-format-section inline-image "figure" label))))
2915 (defun org-e-odt-format-image (src)
2916 "Create image tag with source and attributes."
2918 (let* ((caption (org-find-text-property-in-string 'org-caption src
))
2919 (attr (org-find-text-property-in-string 'org-attributes src
))
2920 (label (org-find-text-property-in-string 'org-label src
))
2921 (caption (and caption
(org-xml-encode-org-text caption
)))
2922 (img-extras (if (string-match "^ltxpng/" src
)
2923 (format " alt=\"%s\""
2924 (org-find-text-property-in-string
2925 'org-latex-src src
))
2926 (if (string-match "\\<alt=" (or attr
""))
2928 (concat " " attr
" alt=\"" src
"\""))))
2929 (img (format "<img src=\"%s\"%s />" src img-extras
))
2932 (format "id=\"%s\" " (org-solidify-link-text label
)))
2933 "class=\"figure\"")))
2936 (with-org-lparse-preserve-paragraph-state
2939 '("<div %s>" .
"\n</div>")
2941 (org-lparse-format '("\n<p>" .
"</p>") img
)
2942 (org-lparse-format '("\n<p>" .
"</p>") caption
))
2949 (defun org-e-odt-bibliography ()
2950 "Find bibliography, cut it out and return it."
2952 (let (beg end
(cnt 1) bib
)
2954 (goto-char (point-min))
2955 (when (re-search-forward
2956 "^[ \t]*<div \\(id\\|class\\)=\"bibliography\"" nil t
)
2957 (setq beg
(match-beginning 0))
2958 (while (re-search-forward "</?div\\>" nil t
)
2959 (setq cnt
(+ cnt
(if (string= (match-string 0) "<div") +1 -
1)))
2961 (and (looking-at ">") (forward-char 1))
2962 (setq bib
(buffer-substring beg
(point)))
2963 (delete-region beg
(point))
2964 (throw 'exit bib
))))
2969 (defun org-e-odt-format-table (lines olines
)
2970 (let ((org-e-odt-format-table-no-css nil
))
2971 (org-lparse-format-table lines olines
)))
2973 (defun org-e-odt-splice-attributes (tag attributes
)
2974 "Read attributes in string ATTRIBUTES, add and replace in HTML tag TAG."
2975 (if (not attributes
)
2977 (let (oldatt newatt
)
2978 (setq oldatt
(org-extract-attributes-from-string tag
)
2980 newatt
(cdr (org-extract-attributes-from-string attributes
)))
2982 (setq oldatt
(plist-put oldatt
(pop newatt
) (pop newatt
))))
2983 (if (string-match ">" tag
)
2985 (replace-match (concat (org-attributes-to-string oldatt
) ">")
2989 (defun org-export-splice-style (style extra
)
2990 "Splice EXTRA into STYLE, just before \"</style>\"."
2991 (if (and (stringp extra
)
2992 (string-match "\\S-" extra
)
2993 (string-match "</style>" style
))
2994 (concat (substring style
0 (match-beginning 0))
2996 (substring style
(match-beginning 0)))
2999 ;; (defun org-e-odt-format-toc-entry (snumber todo headline tags href)
3000 ;; (setq headline (concat
3001 ;; ;; section number
3002 ;; (and org-export-with-section-numbers (concat snumber " "))
3006 ;; (and tags (concat
3007 ;; (org-e-odt-format-spaces 3)
3008 ;; (org-e-odt-format-fontify tags "tag")))))
3009 ;; ;; fontify headline based on TODO keyword
3010 ;; (when todo (setq headline (org-e-odt-format-fontify headline "todo")))
3011 ;; (org-e-odt-format-link headline (concat "#" href)))
3013 (defun org-e-odt-toc-entry-formatter
3014 (level snumber todo todo-type priority
3015 headline tags target extra-targets extra-class
)
3016 (org-e-odt-format-toc-entry snumber todo headline tags target
))
3018 (defun org-e-odt-make-string (n string
)
3019 (let (out) (dotimes (i n out
) (setq out
(concat string out
)))))
3021 (defun org-e-odt-toc-text (toc-entries)
3022 (let* ((prev-level (1- (nth 1 (car toc-entries
))))
3023 (start-level prev-level
))
3026 (let ((headline (nth 0 entry
))
3027 (level (nth 1 entry
)))
3028 (prog1 (org-e-odt-format-toc-item headline level prev-level
)
3029 (setq prev-level level
))))
3032 (defun org-e-odt-toc (depth info
)
3033 (assert (wholenump depth
))
3034 (let* ((headlines (org-export-collect-headlines info depth
))
3036 (loop for headline in headlines collect
3037 (list (org-e-odt-headline-text
3038 headline info
'org-e-odt-toc-entry-formatter
)
3039 (org-export-get-relative-level headline info
)))))
3041 (let* ((lang-specific-heading "Table of Contents")) ; FIXME
3043 (org-e-odt-begin-toc lang-specific-heading depth
)
3044 (org-e-odt-toc-text toc-entries
)
3045 (org-e-odt-end-toc))))))
3047 (defun org-e-odt-begin-outline (level1 snumber title tags
3048 target extra-targets extra-class
)
3049 (let* ((class (format "outline-%d" level1
))
3050 (class (if extra-class
(concat class
" " extra-class
) class
))
3051 (id (format "outline-container-%s"
3052 (org-lparse-suffix-from-snumber snumber
)))
3053 (extra (concat (when id
(format " id=\"%s\"" id
))
3054 (when class
(format " class=\"%s\"" class
)))))
3055 (org-lparse-insert-tag "<div%s>" extra
)
3057 (org-lparse-format 'HEADING
3059 'HEADLINE title extra-targets tags snumber level1
)
3062 (defun org-e-odt-end-outline ()
3063 (org-lparse-insert-tag "</div>"))
3065 (defun org-e-odt-suffix-from-snumber (snumber)
3066 (let* ((snu (replace-regexp-in-string "\\." "-" snumber
))
3067 (href (cdr (assoc (concat "sec-" snu
)
3068 org-export-preferred-target-alist
))))
3069 (org-solidify-link-text (or href snu
))))
3071 (defun org-e-odt-format-outline (contents level1 snumber title
3072 tags target extra-targets extra-class
)
3074 (org-e-odt-format-heading
3075 (org-e-odt-format-headline title extra-targets tags snumber level1
)
3079 ;; (defun org-e-odt-format-line (line)
3080 ;; (case org-lparse-dyn-current-environment
3081 ;; ((quote fixedwidth) (concat (org-e-odt-encode-plain-text line) "\n"))
3082 ;; (t (concat line "\n"))))
3084 (defun org-e-odt-fix-class-name (kwd) ; audit callers of this function
3085 "Turn todo keyword into a valid class name.
3086 Replaces invalid characters with \"_\"."
3088 (while (string-match "[^a-zA-Z0-9_]" kwd
)
3089 (setq kwd
(replace-match "_" t t kwd
))))
3092 (defun org-e-odt-format-internal-link (text href
&optional extra
)
3093 (org-e-odt-format-link text
(concat "#" href
) extra
))
3095 (defun org-e-odt-format-extra-targets (extra-targets)
3096 (if (not extra-targets
) ""
3097 (mapconcat (lambda (x)
3099 (setq x
(org-solidify-link-text
3100 (if (org-uuidgen-p x
) (concat "ID-" x
) x
)))
3101 (org-e-odt-format-anchor "" x
))) extra-targets
"")))
3103 (defun org-e-odt-format-org-tags (tags)
3105 (org-e-odt-format-fontify
3108 (org-e-odt-format-fontify
3109 x
(concat "" ;; org-e-odt-tag-class-prefix
3110 (org-e-odt-fix-class-name x
))))
3111 (org-split-string tags
":")
3112 (org-e-odt-format-spaces 1)) "tag")))
3114 (defun org-e-odt-format-section-number (&optional snumber level
)
3116 (and nil org-export-with-section-numbers
3117 ;; (not org-lparse-body-only)
3119 (org-e-odt-format-fontify snumber
(format "section-number-%d" level
))))
3121 ;; (defun org-e-odt-format-headline (title extra-targets tags
3122 ;; &optional snumber level)
3124 ;; (org-e-odt-format-extra-targets extra-targets)
3125 ;; (concat (org-e-odt-format-section-number snumber level) " ")
3127 ;; (and tags (concat (org-e-odt-format-spaces 3)
3128 ;; (org-e-odt-format-org-tags tags)))))
3130 (defun org-e-odt-get-coding-system-for-write ()
3131 (or org-e-odt-coding-system
3132 (and (boundp 'buffer-file-coding-system
) buffer-file-coding-system
)))
3134 (defun org-e-odt-get-coding-system-for-save ()
3135 (or org-e-odt-coding-system
3136 (and (boundp 'buffer-file-coding-system
) buffer-file-coding-system
)))
3138 ;; (defun org-e-odt-format-date (info)
3139 ;; (let ((date (plist-get info :date)))
3141 ;; ((and date (string-match "%" date))
3142 ;; (format-time-string date))
3144 ;; (t (format-time-string "%Y-%m-%d %T %Z")))))
3148 ;;; Internal Functions (Ngz)
3150 (defun org-e-odt--caption/label-string
(caption label info
)
3151 "Return caption and label HTML string for floats.
3153 CAPTION is a cons cell of secondary strings, the car being the
3154 standard caption and the cdr its short form. LABEL is a string
3155 representing the label. INFO is a plist holding contextual
3158 If there's no caption nor label, return the empty string.
3160 For non-floats, see `org-e-odt--wrap-label'."
3161 (setq label nil
) ;; FIXME
3163 (let ((label-str (if label
(format "\\label{%s}" label
) "")))
3165 ((and (not caption
) (not label
)) "")
3166 ((not caption
) (format "\\label{%s}\n" label
))
3167 ;; Option caption format with short name.
3169 (format "\\caption[%s]{%s%s}\n"
3170 (org-export-secondary-string (cdr caption
) 'e-odt info
)
3172 (org-export-secondary-string (car caption
) 'e-odt info
)))
3173 ;; Standard caption format.
3174 ;; (t (format "\\caption{%s%s}\n"
3176 ;; (org-export-secondary-string (car caption) 'e-odt info)))
3178 (t (org-export-secondary-string (car caption
) 'e-odt info
)))))
3180 (defun org-e-odt--find-verb-separator (s)
3181 "Return a character not used in string S.
3182 This is used to choose a separator for constructs like \\verb."
3183 (let ((ll "~,./?;':\"|!@#%^&-_=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<>()[]{}"))
3184 (loop for c across ll
3185 when
(not (string-match (regexp-quote (char-to-string c
)) s
))
3186 return
(char-to-string c
))))
3188 (defun org-e-odt--make-option-string (options)
3189 "Return a comma separated string of keywords and values.
3190 OPTIONS is an alist where the key is the options keyword as
3191 a string, and the value a list containing the keyword value, or
3193 (mapconcat (lambda (pair)
3194 (concat (first pair
)
3195 (when (> (length (second pair
)) 0)
3196 (concat "=" (second pair
)))))
3200 (defun org-e-odt--quotation-marks (text info
)
3201 "Export quotation marks depending on language conventions.
3202 TEXT is a string containing quotation marks to be replaced. INFO
3203 is a plist used as a communication channel."
3206 (while (setq start
(string-match (car l
) text start
))
3207 (let ((new-quote (concat (match-string 1 text
) (cdr l
))))
3208 (setq text
(replace-match new-quote t t text
))))))
3209 (cdr (or (assoc (plist-get info
:language
) org-e-odt-quotes
)
3210 ;; Falls back on English.
3211 (assoc "en" org-e-odt-quotes
))))
3214 (defun org-e-odt--wrap-label (element output
)
3215 "Wrap label associated to ELEMENT around OUTPUT, if appropriate.
3216 This function shouldn't be used for floats. See
3217 `org-e-odt--caption/label-string'."
3218 ;; (let ((label (org-element-property :name element)))
3219 ;; (if (or (not output) (not label) (string= output "") (string= label ""))
3221 ;; (concat (format "\\label{%s}\n" label) output)))
3226 ;;; Transcode Helpers
3230 (defun org-e-odt-htmlfontify-string (line)
3231 (let* ((hfy-html-quote-regex "\\([<\"&> ]\\)")
3232 (hfy-html-quote-map '(("\"" """)
3237 (" " "<text:tab/>")))
3238 (hfy-face-to-css 'org-e-odt-hfy-face-to-css
)
3239 (hfy-optimisations-1 (copy-seq hfy-optimisations
))
3240 (hfy-optimisations (add-to-list 'hfy-optimisations-1
3242 (hfy-begin-span-handler
3243 (lambda (style text-block text-id text-begins-block-p
)
3244 (insert (format "<text:span text:style-name=\"%s\">" style
))))
3245 (hfy-end-span-handler (lambda nil
(insert "</text:span>"))))
3246 (htmlfontify-string line
)))
3248 (defun org-e-odt-do-format-code
3249 (code &optional lang refs retain-labels num-start
)
3250 (let* ((lang (or (assoc-default lang org-src-lang-modes
) lang
))
3251 (lang-mode (and lang
(intern (format "%s-mode" lang
))))
3252 (code-lines (org-split-string code
"\n"))
3253 (code-length (length code-lines
))
3254 (use-htmlfontify-p (and (functionp lang-mode
)
3255 org-export-e-odt-fontify-srcblocks
3256 (require 'htmlfontify nil t
)
3257 (fboundp 'htmlfontify-string
)))
3258 (code (if (not use-htmlfontify-p
) code
3262 (font-lock-fontify-buffer)
3264 (fontifier (if use-htmlfontify-p
'org-e-odt-htmlfontify-string
3265 'org-e-odt-encode-plain-text
))
3266 (par-style (if use-htmlfontify-p
"OrgSrcBlock"
3267 "OrgFixedWidthBlock"))
3269 (assert (= code-length
(length (org-split-string code
"\n"))))
3271 (org-export-format-code
3273 (lambda (loc line-num ref
)
3275 (concat par-style
(and (= (incf i
) code-length
) "LastLine")))
3277 (setq loc
(concat loc
(and ref retain-labels
(format " (%s)" ref
))))
3278 (setq loc
(funcall fontifier loc
))
3280 (setq loc
(org-e-odt-format-target loc
(concat "coderef-" ref
))))
3281 (setq loc
(org-e-odt-format-stylized-paragraph par-style loc
))
3282 (if (not line-num
) loc
3283 (org-e-odt-format-tags
3284 '("<text:list-item>" .
"</text:list-item>") loc
)))
3287 ((not num-start
) code
)
3288 ((equal num-start
0)
3289 (org-e-odt-format-tags
3290 '("<text:list text:style-name=\"OrgSrcBlockNumberedLine\"%s>"
3291 .
"</text:list>") code
" text:continue-numbering=\"false\""))
3292 (t (org-e-odt-format-tags
3293 '("<text:list text:style-name=\"OrgSrcBlockNumberedLine\"%s>"
3294 .
"</text:list>") code
" text:continue-numbering=\"true\"")))))
3296 (defun org-e-odt-format-code (element info
)
3297 (let* ((lang (org-element-property :language element
))
3298 ;; Extract code and references.
3299 (code-info (org-export-unravel-code element
))
3300 (code (car code-info
))
3301 (refs (cdr code-info
))
3302 ;; Does the src block contain labels?
3303 (retain-labels (org-element-property :retain-labels element
))
3304 ;; Does it have line numbers?
3305 (num-start (case (org-element-property :number-lines element
)
3306 (continued (org-export-get-loc element info
))
3308 (org-e-odt-do-format-code code lang refs retain-labels num-start
)))
3314 (defun org-e-odt-template (contents info
)
3315 "Return complete document string after HTML conversion.
3316 CONTENTS is the transcoded contents string. RAW-DATA is the
3317 original parsed data. INFO is a plist holding export options."
3321 (org-e-odt-update-meta-file info
)
3325 (insert-file-contents
3326 (or org-export-e-odt-content-template-file
3327 (expand-file-name "OrgOdtContentTemplate.xml"
3328 org-e-odt-styles-dir
)))
3329 (goto-char (point-min))
3330 (re-search-forward "</office:text>" nil nil
)
3331 (goto-char (match-beginning 0))
3334 (insert (org-e-odt-format-preamble info
))
3335 ;; Table of Contents
3336 (let ((depth (plist-get info
:with-toc
)))
3337 (when (wholenump depth
) (org-e-odt-toc depth info
)))
3341 (buffer-substring-no-properties (point-min) (point-max))))
3345 ;;; Transcode Functions
3349 (defun org-e-odt-center-block (center-block contents info
)
3350 "Transcode a CENTER-BLOCK element from Org to HTML.
3351 CONTENTS holds the contents of the block. INFO is a plist
3352 holding contextual information."
3353 (org-e-odt--wrap-label center-block contents
))
3358 ;; Comments are ignored.
3363 ;; Comment Blocks are ignored.
3368 (defun org-e-odt-drawer (drawer contents info
)
3369 "Transcode a DRAWER element from Org to HTML.
3370 CONTENTS holds the contents of the block. INFO is a plist
3371 holding contextual information."
3372 (let* ((name (org-element-property :drawer-name drawer
))
3373 (output (if (functionp org-e-odt-format-drawer-function
)
3374 (funcall org-e-odt-format-drawer-function
3376 ;; If there's no user defined function: simply
3377 ;; display contents of the drawer.
3379 (org-e-odt--wrap-label drawer output
)))
3384 (defun org-e-odt-dynamic-block (dynamic-block contents info
)
3385 "Transcode a DYNAMIC-BLOCK element from Org to HTML.
3386 CONTENTS holds the contents of the block. INFO is a plist
3387 holding contextual information. See
3389 (org-e-odt--wrap-label dynamic-block contents
))
3394 (defun org-e-odt-emphasis (emphasis contents info
)
3395 "Transcode EMPHASIS from Org to HTML.
3396 CONTENTS is the contents of the emphasized text. INFO is a plist
3397 holding contextual information.."
3398 ;; (format (cdr (assoc (org-element-property :marker emphasis)
3399 ;; org-e-odt-emphasis-alist))
3401 (org-e-odt-format-fontify
3402 contents
(cadr (assoc
3403 (org-element-property :marker emphasis
)
3414 (defun org-e-odt-entity (entity contents info
)
3415 "Transcode an ENTITY object from Org to HTML.
3416 CONTENTS are the definition itself. INFO is a plist holding
3417 contextual information."
3418 ;; (let ((ent (org-element-property :latex entity)))
3419 ;; (if (org-element-property :latex-math-p entity)
3420 ;; (format "$%s$" ent)
3422 (org-element-property :utf-8 entity
))
3427 (defun org-e-odt-example-block (example-block contents info
)
3428 "Transcode a EXAMPLE-BLOCK element from Org to HTML.
3429 CONTENTS is nil. INFO is a plist holding contextual information."
3430 (let* ((options (or (org-element-property :options example-block
) ""))
3431 (value (org-export-handle-code example-block info nil nil t
)))
3432 (org-e-odt--wrap-label
3433 example-block
(org-e-odt-format-source-code-or-example value nil
))))
3438 (defun org-e-odt-export-snippet (export-snippet contents info
)
3439 "Transcode a EXPORT-SNIPPET object from Org to HTML.
3440 CONTENTS is nil. INFO is a plist holding contextual information."
3441 (when (eq (org-export-snippet-backend export-snippet
) 'e-odt
)
3442 (org-element-property :value export-snippet
)))
3447 (defun org-e-odt-export-block (export-block contents info
)
3448 "Transcode a EXPORT-BLOCK element from Org to HTML.
3449 CONTENTS is nil. INFO is a plist holding contextual information."
3450 (when (string= (org-element-property :type export-block
) "latex")
3451 (org-remove-indentation (org-element-property :value export-block
))))
3456 (defun org-e-odt-fixed-width (fixed-width contents info
)
3457 "Transcode a FIXED-WIDTH element from Org to HTML.
3458 CONTENTS is nil. INFO is a plist holding contextual information."
3459 (let* ((value (org-element-normalize-string
3460 (replace-regexp-in-string
3462 (org-element-property :value fixed-width
)))))
3463 (org-e-odt--wrap-label
3464 fixed-width
(org-e-odt-format-source-code-or-example value nil
))))
3467 ;;;; Footnote Definition
3469 ;; Footnote Definitions are ignored.
3472 ;;;; Footnote Reference
3474 (defun org-e-odt-footnote-def (raw info
) ; FIXME
3475 (if (equal (org-element-type raw
) 'org-data
)
3476 (org-trim (org-export-data raw
'e-odt info
)) ; fix paragraph
3478 (org-odt-format-stylized-paragraph
3479 'footnote
(org-trim (org-export-secondary-string raw
'e-odt info
)))))
3481 (defvar org-e-odt-footnote-separator
3482 (org-e-odt-format-fontify "," 'superscript
))
3484 (defun org-e-odt-footnote-reference (footnote-reference contents info
)
3485 "Transcode a FOOTNOTE-REFERENCE element from Org to HTML.
3486 CONTENTS is nil. INFO is a plist holding contextual information."
3488 ;; Insert separator between two footnotes in a row.
3489 (let ((prev (org-export-get-previous-element footnote-reference info
)))
3490 (when (eq (org-element-type prev
) 'footnote-reference
)
3491 org-e-odt-footnote-separator
))
3493 ((not (org-export-footnote-first-reference-p footnote-reference info
))
3494 (let* ((n (org-export-get-footnote-number footnote-reference info
)))
3495 (org-e-odt-format-footnote-reference n
"IGNORED" 100)))
3496 ;; Inline definitions are secondary strings.
3497 ((eq (org-element-property :type footnote-reference
) 'inline
)
3498 (let* ((raw (org-export-get-footnote-definition footnote-reference info
))
3499 (n (org-export-get-footnote-number footnote-reference info
))
3500 (def (org-e-odt-footnote-def raw info
)))
3501 (org-e-odt-format-footnote-reference n def
1)))
3502 ;; Non-inline footnotes definitions are full Org data.
3504 (let* ((raw (org-export-get-footnote-definition footnote-reference info
))
3505 (n (org-export-get-footnote-number footnote-reference info
))
3506 (def (org-e-odt-footnote-def raw info
)))
3507 (org-e-odt-format-footnote-reference n def
1))))))
3512 (defun org-e-odt-todo (todo)
3514 (org-e-odt-format-fontify
3516 "" ; org-e-odt-todo-kwd-class-prefix
3517 (org-e-odt-fix-class-name todo
))
3518 (list (if (member todo org-done-keywords
) "done" "todo")
3521 (defun org-e-odt-headline-text (headline info
&optional formatter
)
3522 "Transcode an HEADLINE element from Org to HTML.
3523 CONTENTS holds the contents of the headline. INFO is a plist
3524 holding contextual information."
3525 (let* ((numberedp (org-export-numbered-headline-p headline info
))
3526 (level (org-export-get-relative-level headline info
))
3527 (todo (and (plist-get info
:with-todo-keywords
)
3528 (let ((todo (org-element-property
3529 :todo-keyword headline
)))
3531 (org-export-secondary-string todo
'e-odt info
)))))
3532 (todo-type (and todo
(org-element-property :todo-type headline
)))
3533 (priority (and (plist-get info
:with-priority
)
3534 (org-element-property :priority headline
)))
3535 (text (org-export-secondary-string
3536 (org-element-property :title headline
) 'e-odt info
))
3537 (tags (and (plist-get info
:with-tags
)
3538 (org-element-property :tags headline
)))
3540 (headline-no (org-export-get-headline-number headline info
))
3542 (format "sec-%s" (mapconcat 'number-to-string headline-no
"-")))
3543 (headline-labels (list headline-label
))
3544 (headline-no (org-export-get-headline-number headline info
))
3545 (section-no (mapconcat 'number-to-string headline-no
"."))
3546 (primary-target (car (last headline-labels
)))
3547 (secondary-targets (butlast headline-labels
))
3549 (formatter (or (and (functionp formatter
) formatter
)
3550 org-e-odt-headline-formatter
)))
3551 (funcall formatter level section-no todo todo-type priority
3552 text tags primary-target secondary-targets extra-class
)))
3554 (defun org-e-odt-headline (headline contents info
)
3555 "Transcode an HEADLINE element from Org to HTML.
3556 CONTENTS holds the contents of the headline. INFO is a plist
3557 holding contextual information."
3558 (let* ((class (plist-get info
:latex-class
))
3559 (numberedp (org-export-numbered-headline-p headline info
))
3560 ;; Get level relative to current parsed data.
3561 (level (org-export-get-relative-level headline info
))
3562 ;; (class-sectionning (assoc class org-e-odt-classes))
3563 ;; Section formatting will set two placeholders: one for the
3564 ;; title and the other for the contents.
3566 ;; (let ((sec (if (and (symbolp (nth 2 class-sectionning))
3567 ;; (fboundp (nth 2 class-sectionning)))
3568 ;; (funcall (nth 2 class-sectionning) level numberedp)
3569 ;; (nth (1+ level) class-sectionning))))
3571 ;; ;; No section available for that LEVEL.
3573 ;; ;; Section format directly returned by a function.
3574 ;; ((stringp sec) sec)
3575 ;; ;; (numbered-section . unnumbered-section)
3576 ;; ((not (consp (cdr sec)))
3577 ;; (concat (funcall (if numberedp #'car #'cdr) sec) "\n%s"))
3578 ;; ;; (numbered-open numbered-close)
3579 ;; ((= (length sec) 2)
3580 ;; (when numberedp (concat (car sec) "\n%s" (nth 1 sec))))
3581 ;; ;; (num-in num-out no-num-in no-num-out)
3582 ;; ((= (length sec) 4)
3584 ;; (concat (car sec) "\n%s" (nth 1 sec))
3585 ;; (concat (nth 2 sec) "\n%s" (nth 3 sec)))))))
3586 (text (org-export-secondary-string
3587 (org-element-property :title headline
) 'e-odt info
))
3588 (todo (and (plist-get info
:with-todo-keywords
)
3589 (let ((todo (org-element-property
3590 :todo-keyword headline
)))
3592 (org-export-secondary-string todo
'e-odt info
)))))
3593 (todo-type (and todo
(org-element-property :todo-type headline
)))
3594 (tags (and (plist-get info
:with-tags
)
3595 (org-element-property :tags headline
)))
3596 (priority (and (plist-get info
:with-priority
)
3597 (org-element-property :priority headline
)))
3598 ;; Create the headline text.
3599 (full-text (if (functionp org-e-odt-format-headline-function
)
3600 ;; User-defined formatting function.
3601 (funcall org-e-odt-format-headline-function
3602 todo todo-type priority text tags
)
3603 ;; Default formatting.
3606 ;; (format "\\textbf{\\textsf{\\textsc{%s}}} " todo))
3607 (org-e-odt-todo todo
) " "
3608 (when priority
(format "\\framebox{\\#%c} " priority
))
3610 ;; (when tags (format "\\hfill{}\\textsc{%s}" tags))
3612 ;; Associate some \label to the headline for internal links.
3614 ;; (format "\\label{sec-%s}\n"
3615 ;; (mapconcat 'number-to-string
3616 ;; (org-export-get-headline-number headline info)
3620 (headline-no (org-export-get-headline-number headline info
))
3622 (format "sec-%s" (mapconcat 'number-to-string headline-no
"-")))
3623 (headline-labels (list headline-label
))
3624 (headline-no (org-export-get-headline-number headline info
))
3625 (section-no (mapconcat 'number-to-string headline-no
"."))
3628 (pre-blanks (make-string
3629 (org-element-property :pre-blank headline
) 10)))
3631 ;; Case 1: This is a footnote section: ignore it.
3632 ((org-element-property :footnote-section-p headline
) nil
)
3633 ;; Case 2. This is a deep sub-tree: export it as a list item.
3634 ;; Also export as items headlines for which no section
3635 ;; format has been found.
3636 ((org-export-low-level-p headline info
) ; FIXME (or (not section-fmt))
3637 ;; Build the real contents of the sub-tree.
3638 (let* ((type (if numberedp
'unordered
'unordered
)) ; FIXME
3639 (itemized-body (org-e-odt-format-list-item
3640 contents type nil nil full-text
)))
3642 (and (org-export-first-sibling-p headline info
)
3643 (org-e-odt-begin-plain-list type
))
3645 (and (org-export-last-sibling-p headline info
)
3646 (org-e-odt-end-plain-list type
)))))
3647 ;; Case 3. Standard headline. Export it as a section.
3649 ;; (format section-fmt full-text
3650 ;; (concat headline-label pre-blanks contents))
3652 (org-e-odt-format-outline contents level section-no full-text tags
3653 (car (last headline-labels
))
3654 (butlast headline-labels
) nil
)))))
3657 ;;;; Horizontal Rule
3659 (defun org-e-odt-horizontal-rule (horizontal-rule contents info
)
3660 "Transcode an HORIZONTAL-RULE object from Org to HTML.
3661 CONTENTS is nil. INFO is a plist holding contextual information."
3662 (let ((attr (mapconcat #'identity
3663 (org-element-property :attr_odt horizontal-rule
)
3665 (org-e-odt--wrap-label horizontal-rule
3666 (org-e-odt-format-horizontal-line))))
3669 ;;;; Inline Babel Call
3671 ;; Inline Babel Calls are ignored.
3674 ;;;; Inline Src Block
3676 (defun org-e-odt-inline-src-block (inline-src-block contents info
)
3677 "Transcode an INLINE-SRC-BLOCK element from Org to HTML.
3678 CONTENTS holds the contents of the item. INFO is a plist holding
3679 contextual information."
3680 (let* ((org-lang (org-element-property :language inline-src-block
))
3681 (code (org-element-property :value inline-src-block
))
3682 (separator (org-e-odt--find-verb-separator code
)))
3688 (defun org-e-odt-format-section (text class
&optional id
)
3689 (let ((extra (concat (when id
(format " id=\"%s\"" id
)))))
3690 (concat (format "<div class=\"%s\"%s>\n" class extra
) text
"</div>\n")))
3692 (defun org-e-odt-inlinetask (inlinetask contents info
)
3693 "Transcode an INLINETASK element from Org to HTML.
3694 CONTENTS holds the contents of the block. INFO is a plist
3695 holding contextual information."
3696 (let ((title (org-export-secondary-string
3697 (org-element-property :title inlinetask
) 'e-odt info
))
3698 (todo (and (plist-get info
:with-todo-keywords
)
3699 (let ((todo (org-element-property
3700 :todo-keyword inlinetask
)))
3702 (org-export-secondary-string todo
'e-odt info
)))))
3703 (todo-type (org-element-property :todo-type inlinetask
))
3704 (tags (and (plist-get info
:with-tags
)
3705 (org-element-property :tags inlinetask
)))
3706 (priority (and (plist-get info
:with-priority
)
3707 (org-element-property :priority inlinetask
))))
3708 ;; If `org-e-odt-format-inlinetask-function' is provided, call it
3709 ;; with appropriate arguments.
3710 (if (functionp org-e-odt-format-inlinetask-function
)
3711 (funcall org-e-odt-format-inlinetask-function
3712 todo todo-type priority title tags contents
)
3713 ;; Otherwise, use a default template.
3714 (org-e-odt--wrap-label
3718 (when todo
(format "\\textbf{\\textsf{\\textsc{%s}}} " todo
))
3719 (when priority
(format "\\framebox{\\#%c} " priority
))
3721 (when tags
(format "\\hfill{}\\textsc{%s}" tags
)))))
3722 (format (concat "\\begin{center}\n"
3724 "\\begin{minipage}[c]{.6\\textwidth}\n"
3726 "\\rule[.8em]{\\textwidth}{2pt}\n\n"
3731 full-title contents
))))))
3736 (defun org-e-odt-format-list-item (contents type checkbox
3737 &optional term-counter-id
3741 (org-e-odt-format-fontify (case checkbox
3744 (trans "[-]")) 'code
)))
3746 (org-e-odt-begin-list-item type term-counter-id headline
)
3747 ;; FIXME checkbox (and checkbox " ")
3749 (org-e-odt-end-list-item type
)))
3751 (defun org-e-odt-item (item contents info
)
3752 "Transcode an ITEM element from Org to HTML.
3753 CONTENTS holds the contents of the item. INFO is a plist holding
3754 contextual information."
3755 ;; Grab `:level' from plain-list properties, which is always the
3756 ;; first element above current item.
3757 (let* ((plain-list (org-export-get-parent item info
))
3758 (type (org-element-property :type plain-list
))
3759 (level (org-element-property :level plain-list
))
3760 (counter (org-element-property :counter item
))
3761 (checkbox (org-element-property :checkbox item
))
3762 (tag (let ((tag (org-element-property :tag item
)))
3763 (and tag
(org-export-secondary-string tag
'e-odt info
)))))
3764 (org-e-odt-format-list-item
3765 contents type checkbox
(or tag counter
))))
3770 (defun org-e-odt-keyword (keyword contents info
)
3771 "Transcode a KEYWORD element from Org to HTML.
3772 CONTENTS is nil. INFO is a plist holding contextual information."
3773 (let ((key (downcase (org-element-property :key keyword
)))
3774 (value (org-element-property :value keyword
)))
3776 ((string= key
"latex") value
)
3777 ((string= key
"index") (format "\\index{%s}" value
))
3778 ((string= key
"target") nil
; FIXME
3779 ;; (format "\\label{%s}" (org-export-solidify-link-text value))
3781 ((string= key
"toc")
3782 (let ((value (downcase value
)))
3784 ((string-match "\\<headlines\\>" value
)
3785 (let ((depth (or (and (string-match "[0-9]+" value
)
3786 (string-to-number (match-string 0 value
)))
3787 (plist-get info
:with-toc
))))
3788 (when (wholenump depth
) (org-e-odt-toc depth info
))))
3789 ((string= "tables" value
) "FIXME")
3790 ((string= "figures" value
) "FIXME")
3791 ((string= "listings" value
)
3793 ;; At the moment, src blocks with a caption are wrapped
3794 ;; into a figure environment.
3798 ;;;; Latex Environment
3800 (defun org-e-odt-format-latex (latex-frag processing-type
)
3801 (let* ((prefix (case processing-type
3803 (mathml "ltxmathml/")))
3805 (concat prefix
(file-name-sans-extension
3806 (file-name-nondirectory (buffer-file-name)))))
3807 (cache-dir (file-name-directory (buffer-file-name )))
3808 (display-msg (case processing-type
3809 (dvipng "Creating LaTeX Image...")
3810 (mathml "Creating MathML snippet..."))))
3813 (org-format-latex cache-relpath cache-dir nil display-msg
3814 nil nil processing-type
)
3817 (defun org-e-odt-latex-environment (latex-environment contents info
)
3818 "Transcode a LATEX-ENVIRONMENT element from Org to HTML.
3819 CONTENTS is nil. INFO is a plist holding contextual information."
3820 (org-e-odt--wrap-label
3823 (org-remove-indentation
3824 (org-element-property :value latex-environment
)))
3825 (processing-type (plist-get info
:LaTeX-fragments
)))
3827 ((member processing-type
'(t mathjax
))
3828 (org-e-odt-format-latex latex-frag
'mathml
))
3829 ((equal processing-type
'dvipng
)
3830 (let* ((formula-link (org-e-odt-format-latex
3831 latex-frag processing-type
)))
3832 (when (and formula-link
3833 (string-match "file:\\([^]]*\\)" formula-link
))
3834 (org-e-odt-format-inline-image (match-string 1 formula-link
)))))
3841 (defun org-e-odt-latex-fragment (latex-fragment contents info
)
3842 "Transcode a LATEX-FRAGMENT object from Org to HTML.
3843 CONTENTS is nil. INFO is a plist holding contextual information."
3844 ;; (org-element-property :value latex-fragment)
3845 (let* ((latex-frag (org-element-property :value latex-fragment
)))
3847 ((string-match "\\\\ref{\\([^{}\n]+\\)}" latex-frag
)
3848 (let* ((label (match-string 1 latex-frag
))
3849 (href (and label
(org-export-solidify-link-text label
)))
3850 (text (if (string-match "\\`[a-z]\\{1,10\\}:\\(.+\\)" label
)
3851 (substring label
(match-beginning 1))
3853 (org-e-odt-format-internal-link text href
)))
3854 (t (let ((processing-type (plist-get info
:LaTeX-fragments
)))
3856 ((member processing-type
'(t mathjax
))
3857 (org-e-odt-format-latex latex-frag
'mathjax
))
3858 ((equal processing-type
'dvipng
)
3859 (let* ((formula-link (org-e-odt-format-latex
3860 latex-frag processing-type
)))
3861 (when (and formula-link
3862 (string-match "file:\\([^]]*\\)" formula-link
))
3863 (org-e-odt-format-inline-image
3864 (match-string 1 formula-link
)))))
3865 (t latex-frag
)))))))
3870 (defun org-e-odt-line-break (line-break contents info
)
3871 "Transcode a LINE-BREAK object from Org to HTML.
3872 CONTENTS is nil. INFO is a plist holding contextual information."
3873 "<text:line-break/>\n")
3878 (defun org-e-odt-link--inline-image (link info
)
3879 "Return HTML code for an inline image.
3880 LINK is the link pointing to the inline image. INFO is a plist
3881 used as a communication channel."
3882 (let* ((parent (org-export-get-parent-paragraph link info
))
3883 (path (let ((raw-path (org-element-property :path link
)))
3884 (if (not (file-name-absolute-p raw-path
)) raw-path
3885 (expand-file-name raw-path
))))
3886 (caption (org-e-odt--caption/label-string
3887 (org-element-property :caption parent
)
3888 (org-element-property :name parent
)
3890 (label (org-element-property :name parent
))
3891 ;; Retrieve latex attributes from the element around.
3892 (attr (let ((raw-attr
3893 (mapconcat #'identity
3894 (org-element-property :attr_odt parent
)
3896 (unless (string= raw-attr
"") raw-attr
))))
3897 ;; Now clear ATTR from any special keyword and set a default
3898 ;; value if nothing is left.
3899 (setq attr
(if (not attr
) "" (org-trim attr
)))
3900 ;; Return proper string, depending on DISPOSITION.
3901 (let ((href (and label
(org-export-solidify-link-text label
))))
3902 (org-e-odt-format-inline-image path caption href attr
))))
3904 (defun org-e-odt-link (link desc info
)
3905 "Transcode a LINK object from Org to HTML.
3907 DESC is the description part of the link, or the empty string.
3908 INFO is a plist holding contextual information. See
3910 (let* ((type (org-element-property :type link
))
3911 (raw-path (org-element-property :path link
))
3912 ;; Ensure DESC really exists, or set it to nil.
3913 (desc (and (not (string= desc
"")) desc
))
3914 (imagep (org-export-inline-image-p
3915 link org-e-odt-inline-image-rules
))
3917 ((member type
'("http" "https" "ftp" "mailto"))
3918 (concat type
":" raw-path
))
3919 ((string= type
"file")
3920 (when (string-match "\\(.+\\)::.+" raw-path
)
3921 (setq raw-path
(match-string 1 raw-path
)))
3922 (if (file-name-absolute-p raw-path
)
3923 (concat "file://" (expand-file-name raw-path
))
3924 ;; TODO: Not implemented yet. Concat also:
3925 ;; (org-export-directory :HTML info)
3926 (concat "file://" raw-path
)))
3931 (imagep (org-e-odt-link--inline-image link info
))
3932 ;; Radioed target: Target's name is obtained from original raw
3933 ;; link. Path is parsed and transcoded in order to have a proper
3934 ;; display of the contents.
3935 ((string= type
"radio")
3936 (org-e-odt-format-internal-link
3937 (org-export-secondary-string
3938 (org-element-parse-secondary-string
3939 path
(cdr (assq 'radio-target org-element-object-restrictions
)))
3941 (org-export-solidify-link-text path
)))
3942 ;; Links pointing to an headline: Find destination and build
3943 ;; appropriate referencing command.
3944 ((member type
'("custom-id" "fuzzy" "id"))
3945 (let ((destination (if (string= type
"fuzzy")
3946 (org-export-resolve-fuzzy-link link info
)
3947 (org-export-resolve-id-link link info
))))
3948 (case (org-element-type destination
)
3949 ;; Fuzzy link points nowhere.
3951 (org-e-odt-format-fontify
3952 (or desc
(org-export-secondary-string
3953 (org-element-property :raw-link link
)
3954 'e-odt info
)) 'emphasis
))
3955 ;; Fuzzy link points to an invisible target.
3957 ;; LINK points to an headline. If headlines are numbered
3958 ;; and the link has no description, display headline's
3959 ;; number. Otherwise, display description or headline's
3962 (let* ((headline-no (org-export-get-headline-number destination info
))
3963 (label (format "sec-%s" (mapconcat 'number-to-string
3965 (section-no (mapconcat 'number-to-string headline-no
".")))
3969 ((plist-get info
:section-numbers
) section-no
)
3970 (t (org-export-secondary-string
3971 (org-element-property :title destination
)
3973 (org-e-odt-format-internal-link desc label
)))
3974 ;; Fuzzy link points to a target. Do as above.
3976 (let ((path (org-export-solidify-link-text path
)))
3978 (setq desc
(let ((number (org-export-get-ordinal
3981 (if (atom number
) (number-to-string number
)
3982 (mapconcat 'number-to-string number
"."))))))
3983 (org-e-odt-format-internal-link (or desc
"FIXME") path
))))))
3984 ;; Coderef: replace link with the reference name or the
3985 ;; equivalent line number.
3986 ((string= type
"coderef")
3987 (let* ((fmt (org-export-get-coderef-format path
(or desc
"%s")))
3988 (res (org-export-resolve-coderef path info
))
3989 (org-e-odt-suppress-xref nil
)
3990 (href (org-xml-format-href (concat "#coderef-" path
))))
3991 (format fmt
(org-e-odt-format-link res href
))))
3992 ;; Link type is handled by a special function.
3993 ((functionp (setq protocol
(nth 2 (assoc type org-link-protocols
))))
3994 (funcall protocol
(org-link-unescape path
) desc
'html
))
3995 ;; External link with a description part.
3996 ((and path desc
) (org-e-odt-format-link desc path
))
3997 ;; External link without a description part.
3998 (path (org-e-odt-format-link path path
))
3999 ;; No path, only description. Try to do something useful.
4000 (t (org-e-odt-format-fontify desc
'emphasis
)))))
4005 ;; Babel Calls are ignored.
4010 (defun org-e-odt-macro (macro contents info
)
4011 "Transcode a MACRO element from Org to HTML.
4012 CONTENTS is nil. INFO is a plist holding contextual information."
4013 ;; Use available tools.
4014 (org-export-expand-macro macro info
))
4019 (defun org-e-odt-paragraph (paragraph contents info
)
4020 "Transcode a PARAGRAPH element from Org to HTML.
4021 CONTENTS is the contents of the paragraph, as a string. INFO is
4022 the plist used as a communication channel."
4023 (let* ((style nil
) ; FIXME
4024 (class (cdr (assoc style
'((footnote .
"footnote")
4026 (extra (if class
(format " class=\"%s\"" class
) ""))
4027 (parent (org-export-get-parent paragraph info
))
4028 (parent-type (org-element-type parent
))
4029 (style (case parent-type
4030 (quote-block 'quote
)
4031 (center-block 'center
)
4033 (org-e-odt-format-stylized-paragraph style contents
)))
4038 (defun org-e-odt-plain-list (plain-list contents info
)
4039 "Transcode a PLAIN-LIST element from Org to HTML.
4040 CONTENTS is the contents of the list. INFO is a plist holding
4041 contextual information."
4042 (let* (arg1 ;; FIXME
4043 (type (org-element-property :type plain-list
))
4044 (attr (mapconcat #'identity
4045 (org-element-property :attr_odt plain-list
)
4047 (org-e-odt--wrap-label
4048 plain-list
(format "%s\n%s%s"
4049 (org-e-odt-begin-plain-list type
)
4050 contents
(org-e-odt-end-plain-list type
)))))
4054 (defun org-e-odt-convert-special-strings (string)
4055 "Convert special characters in STRING to ODT."
4056 (let ((all org-export-e-odt-special-string-regexps
)
4058 (while (setq a
(pop all
))
4059 (setq re
(car a
) rpl
(cdr a
) start
0)
4060 (while (string-match re string start
)
4061 (setq string
(replace-match rpl t nil string
))))
4064 ;; (defun org-e-odt-encode-plain-text (s)
4065 ;; "Convert plain text characters to HTML equivalent.
4066 ;; Possible conversions are set in `org-export-html-protect-char-alist'."
4067 ;; (let ((cl org-e-odt-protect-char-alist) c)
4068 ;; (while (setq c (pop cl))
4070 ;; (while (string-match (car c) s start)
4071 ;; (setq s (replace-match (cdr c) t t s)
4072 ;; start (1+ (match-beginning 0))))))
4075 (defun org-e-odt-plain-text (text info
)
4076 "Transcode a TEXT string from Org to HTML.
4077 TEXT is the string to transcode. INFO is a plist holding
4078 contextual information."
4079 (setq text
(org-e-odt-encode-plain-text text t
))
4080 ;; Protect %, #, &, $, ~, ^, _, { and }.
4081 ;; (while (string-match "\\([^\\]\\|^\\)\\([%$#&{}~^_]\\)" text)
4083 ;; (replace-match (format "\\%s" (match-string 2 text)) nil t text 2)))
4085 ;; (setq text (replace-regexp-in-string
4086 ;; "\\(?:[^\\]\\|^\\)\\(\\\\\\)\\(?:[^%$#&{}~^_\\]\\|$\\)"
4087 ;; "$\\backslash$" text nil t 1))
4088 ;; HTML into \HTML{} and TeX into \TeX{}.
4089 ;; (let ((case-fold-search nil)
4091 ;; (while (string-match "\\<\\(\\(?:La\\)?TeX\\)\\>" text start)
4092 ;; (setq text (replace-match
4093 ;; (format "\\%s{}" (match-string 1 text)) nil t text)
4094 ;; start (match-end 0))))
4095 ;; Handle quotation marks
4096 ;; (setq text (org-e-odt--quotation-marks text info))
4097 ;; Convert special strings.
4098 ;; (when (plist-get info :with-special-strings)
4099 ;; (while (string-match (regexp-quote "...") text)
4100 ;; (setq text (replace-match "\\ldots{}" nil t text))))
4101 (when (plist-get info
:with-special-strings
)
4102 (setq text
(org-e-odt-convert-special-strings text
)))
4103 ;; Handle break preservation if required.
4104 (when (plist-get info
:preserve-breaks
)
4105 (setq text
(replace-regexp-in-string "\\(\\\\\\\\\\)?[ \t]*\n" " \\\\\\\\\n"
4111 ;;;; Property Drawer
4113 (defun org-e-odt-property-drawer (property-drawer contents info
)
4114 "Transcode a PROPERTY-DRAWER element from Org to HTML.
4115 CONTENTS is nil. INFO is a plist holding contextual
4117 ;; The property drawer isn't exported but we want separating blank
4118 ;; lines nonetheless.
4124 (defun org-e-odt-quote-block (quote-block contents info
)
4125 "Transcode a QUOTE-BLOCK element from Org to HTML.
4126 CONTENTS holds the contents of the block. INFO is a plist
4127 holding contextual information."
4128 (org-e-odt--wrap-label quote-block contents
))
4133 (defun org-e-odt-quote-section (quote-section contents info
)
4134 "Transcode a QUOTE-SECTION element from Org to HTML.
4135 CONTENTS is nil. INFO is a plist holding contextual information."
4136 (let ((value (org-remove-indentation
4137 (org-element-property :value quote-section
))))
4138 (when value
(org-e-odt-format-source-code-or-example value nil
))))
4143 (defun org-e-odt-section (section contents info
) ; FIXME
4144 "Transcode a SECTION element from Org to HTML.
4145 CONTENTS holds the contents of the section. INFO is a plist
4146 holding contextual information."
4151 (defun org-e-odt-radio-target (radio-target text info
)
4152 "Transcode a RADIO-TARGET object from Org to HTML.
4153 TEXT is the text of the target. INFO is a plist holding
4154 contextual information."
4155 (org-e-odt-format-anchor
4156 text
(org-export-solidify-link-text
4157 (org-element-property :raw-value radio-target
))))
4162 (defun org-e-odt-special-block (special-block contents info
)
4163 "Transcode a SPECIAL-BLOCK element from Org to HTML.
4164 CONTENTS holds the contents of the block. INFO is a plist
4165 holding contextual information."
4166 (let ((type (downcase (org-element-property :type special-block
))))
4167 (org-e-odt--wrap-label
4169 (format "\\begin{%s}\n%s\\end{%s}" type contents type
))))
4174 (defun org-e-odt-src-block (src-block contents info
)
4175 "Transcode a SRC-BLOCK element from Org to HTML.
4176 CONTENTS holds the contents of the item. INFO is a plist holding
4177 contextual information."
4178 (let* ((lang (org-element-property :language src-block
))
4179 (caption (org-element-property :caption src-block
))
4180 (label (org-element-property :name src-block
)))
4181 ;; FIXME: Handle caption
4183 ;; caption-str (when caption)
4184 ;; (main (org-export-secondary-string (car caption) 'e-odt info))
4185 ;; (secondary (org-export-secondary-string (cdr caption) 'e-odt info))
4186 ;; (caption-str (org-e-odt--caption/label-string caption label info))
4187 (org-e-odt-format-code src-block info
)))
4190 ;;;; Statistics Cookie
4192 (defun org-e-odt-statistics-cookie (statistics-cookie contents info
)
4193 "Transcode a STATISTICS-COOKIE object from Org to HTML.
4194 CONTENTS is nil. INFO is a plist holding contextual information."
4195 (let ((cookie-value (org-element-property :value statistics-cookie
)))
4196 (org-e-odt-format-fontify cookie-value
'code
)))
4201 (defun org-e-odt-subscript (subscript contents info
)
4202 "Transcode a SUBSCRIPT object from Org to HTML.
4203 CONTENTS is the contents of the object. INFO is a plist holding
4204 contextual information."
4205 ;; (format (if (= (length contents) 1) "$_%s$" "$_{\\mathrm{%s}}$") contents)
4206 (org-e-odt-format-fontify contents
'subscript
))
4211 (defun org-e-odt-superscript (superscript contents info
)
4212 "Transcode a SUPERSCRIPT object from Org to HTML.
4213 CONTENTS is the contents of the object. INFO is a plist holding
4214 contextual information."
4215 ;; (format (if (= (length contents) 1) "$^%s$" "$^{\\mathrm{%s}}$") contents)
4216 (org-e-odt-format-fontify contents
'superscript
))
4221 (defun org-e-odt-get-colwidth (c)
4222 (let ((col-widths (plist-get table-info
:width
)))
4223 (or (and org-lparse-table-is-styled
(aref col-widths c
)) 0)))
4225 (defun org-e-odt-table-row (fields &optional text-for-empty-fields
)
4226 (incf org-e-odt-table-rownum
)
4228 (org-e-odt-format-table-row
4231 (when (and (string= x
"") text-for-empty-fields
)
4232 (setq x text-for-empty-fields
))
4234 (let ((horiz-span (org-e-odt-get-colwidth i
)))
4235 (org-e-odt-format-table-cell
4236 x org-e-odt-table-rownum i horiz-span
)))
4239 (defun org-e-odt-table-preamble ()
4240 (let ((colgroup-vector (plist-get table-info
:column-groups
)) ;; FIXME
4241 c gr colgropen preamble
)
4242 (unless (aref colgroup-vector
0)
4243 (setf (aref colgroup-vector
0) 'start
))
4244 (dotimes (c columns-number preamble
)
4245 (setq gr
(aref colgroup-vector c
))
4249 (when (memq gr
'(start start-end
))
4250 (prog1 (if colgropen
"</colgroup>\n<colgroup>" "\n<colgroup>")
4251 (setq colgropen t
)))
4252 (let* ((colalign-vector (plist-get table-info
:alignment
)) ;; FIXME
4253 (align (cdr (assoc (aref colalign-vector c
)
4256 ("c" .
"center")))))
4257 (alignspec (if (and (boundp 'org-e-odt-format-table-no-css
)
4258 org-e-odt-format-table-no-css
)
4259 " align=\"%s\"" " class=\"%s\""))
4260 (extra (format alignspec align
)))
4261 (format "<col%s />" extra
))
4262 (when (memq gr
'(end start-end
))
4263 (setq colgropen nil
)
4265 (concat preamble
(if colgropen
"</colgroup>"))))
4267 (defun org-e-odt-list-table (lines caption label attributes
)
4268 (setq lines
(org-e-odt-org-table-to-list-table lines
))
4269 (let* ((splice nil
) head
4270 (org-e-odt-table-rownum -
1)
4273 org-e-odt-table-cur-rowgrp-is-hdr
4274 org-e-odt-table-rowgrp-open
4276 (org-lparse-table-style 'org-table
)
4277 org-lparse-table-is-styled
)
4280 (setq org-lparse-table-is-styled nil
)
4281 (mapconcat 'org-e-odt-table-row lines
"\n"))
4283 (setq org-lparse-table-is-styled t
)
4286 (org-e-odt-begin-table caption label attributes
)
4287 ;; FIXME (org-e-odt-table-preamble)
4288 (org-e-odt-begin-table-rowgroup head
)
4293 ((equal line
'hline
) (org-e-odt-begin-table-rowgroup))
4294 (t (org-e-odt-table-row line
))))
4297 (org-e-odt-end-table-rowgroup)
4298 (org-e-odt-end-table))))))
4300 (defun org-e-odt-transcode-table-row (row)
4301 (if (string-match org-table-hline-regexp row
) 'hline
4304 (org-export-secondary-string
4305 (let ((cell (org-element-parse-secondary-string
4307 (cdr (assq 'table org-element-string-restrictions
)))))
4310 (org-split-string row
"[ \t]*|[ \t]*"))))
4312 (defun org-e-odt-org-table-to-list-table (lines &optional splice
)
4313 "Convert org-table to list-table.
4314 LINES is a list of the form (ROW1 ROW2 ROW3 ...) where each
4315 element is a `string' representing a single row of org-table.
4316 Thus each ROW has vertical separators \"|\" separating the table
4317 fields. A ROW could also be a row-group separator of the form
4318 \"|---...|\". Return a list of the form (ROW1 ROW2 ROW3
4319 ...). ROW could either be symbol `'hline' or a list of the
4320 form (FIELD1 FIELD2 FIELD3 ...) as appropriate."
4324 (while (setq line
(pop lines
))
4325 (unless (string-match "^[ \t]*|-" line
)
4326 (push (org-e-odt-transcode-table-row line
) lines-1
))))
4327 (t (while (setq line
(pop lines
))
4329 ((string-match "^[ \t]*|-" line
)
4330 (when lines
(push 'hline lines-1
)))
4331 (t (push (org-e-odt-transcode-table-row line
) lines-1
))))))
4332 (nreverse lines-1
)))
4334 (defun org-e-odt-table-table (raw-table)
4336 (with-current-buffer (get-buffer-create "*org-export-table*")
4338 (let ((output (with-temp-buffer
4341 (re-search-forward "^[ \t]*|[^|]" nil t
)
4342 (table-generate-source 'html
"*org-export-table*")
4343 (with-current-buffer "*org-export-table*"
4344 (org-trim (buffer-string))))))
4345 (kill-buffer (get-buffer "*org-export-table*"))
4348 (defun org-e-odt-table (table contents info
)
4349 "Transcode a TABLE element from Org to HTML.
4350 CONTENTS is nil. INFO is a plist holding contextual information."
4351 (let* ((label (org-element-property :name table
))
4352 (caption (org-e-odt--caption/label-string
4353 (org-element-property :caption table
) label info
))
4354 (attr (mapconcat #'identity
4355 (org-element-property :attr_odt table
)
4357 (raw-table (org-element-property :raw-table table
))
4358 (table-type (org-element-property :type table
)))
4361 ;; (org-e-odt-table-table raw-table)
4364 (let* ((table-info (org-export-table-format-info raw-table
))
4365 (columns-number (length (plist-get table-info
:alignment
)))
4366 (lines (org-split-string
4367 (org-export-clean-table
4368 raw-table
(plist-get table-info
:special-column-p
)) "\n"))
4370 (genealogy (org-export-get-genealogy table info
))
4371 (parent (car genealogy
))
4372 (parent-type (org-element-type parent
)))
4373 (org-e-odt-list-table lines caption label attr
))))))
4378 (defun org-e-odt-target (target contents info
)
4379 "Transcode a TARGET object from Org to HTML.
4380 CONTENTS is nil. INFO is a plist holding contextual
4382 (org-e-odt-format-anchor
4383 "" (org-export-solidify-link-text (org-element-property :value target
))))
4388 (defun org-e-odt-time-stamp (time-stamp contents info
)
4389 "Transcode a TIME-STAMP object from Org to HTML.
4390 CONTENTS is nil. INFO is a plist holding contextual
4392 ;; (let ((value (org-element-property :value time-stamp))
4393 ;; (type (org-element-property :type time-stamp))
4394 ;; (appt-type (org-element-property :appt-type time-stamp)))
4395 ;; (concat (cond ((eq appt-type 'scheduled)
4396 ;; (format "\\textbf{\\textsc{%s}} " org-scheduled-string))
4397 ;; ((eq appt-type 'deadline)
4398 ;; (format "\\textbf{\\textsc{%s}} " org-deadline-string))
4399 ;; ((eq appt-type 'closed)
4400 ;; (format "\\textbf{\\textsc{%s}} " org-closed-string)))
4401 ;; (cond ((memq type '(active active-range))
4402 ;; (format org-e-odt-active-timestamp-format value))
4403 ;; ((memq type '(inactive inactive-range))
4404 ;; (format org-e-odt-inactive-timestamp-format value))
4406 ;; (format org-e-odt-diary-timestamp-format value)))))
4407 (let ((value (org-element-property :value time-stamp
))
4408 (type (org-element-property :type time-stamp
))
4409 (appt-type (org-element-property :appt-type time-stamp
)))
4410 (setq value
(org-export-secondary-string value
'e-odt info
))
4411 (org-e-odt-format-fontify
4413 (org-e-odt-format-fontify
4414 (cond ((eq appt-type
'scheduled
) org-scheduled-string
)
4415 ((eq appt-type
'deadline
) org-deadline-string
)
4416 ((eq appt-type
'closed
) org-closed-string
)) "timestamp-kwd")
4417 ;; FIXME: (org-translate-time value)
4418 (org-e-odt-format-fontify value
"timestamp"))
4419 "timestamp-wrapper")))
4424 (defun org-e-odt-verbatim (verbatim contents info
)
4425 "Transcode a VERBATIM object from Org to HTML.
4426 CONTENTS is nil. INFO is a plist used as a communication
4429 verbatim
(org-element-property :value verbatim
) info
))
4434 (defun org-e-odt-verse-block (verse-block contents info
)
4435 "Transcode a VERSE-BLOCK element from Org to HTML.
4436 CONTENTS is nil. INFO is a plist holding contextual information."
4437 ;; Replace each newline character with line break. Also replace
4438 ;; each blank line with a line break.
4439 (setq contents
(replace-regexp-in-string
4440 "^ *\\\\\\\\$" "<br/>\n"
4441 (replace-regexp-in-string
4442 "\\(\\\\\\\\\\)?[ \t]*\n" " <br/>\n"
4443 (org-remove-indentation
4444 (org-export-secondary-string
4445 (org-element-property :value verse-block
)
4448 ;; Replace each white space at beginning of a line with a
4449 ;; non-breaking space.
4450 (while (string-match "^[ \t]+" contents
)
4451 (let ((new-str (org-e-odt-format-spaces
4452 (length (match-string 0 contents
)))))
4453 (setq contents
(replace-match new-str nil t contents
))))
4455 (org-e-odt--wrap-label
4456 verse-block
(format "<p class=\"verse\">\n%s</p>" contents
)))
4461 ;;; Filter Functions
4463 ;;;; Filter Settings
4466 ;;; Interactive functions
4468 (defun org-e-odt-export-to-odt
4469 (&optional subtreep visible-only body-only ext-plist pub-dir
)
4470 "Export current buffer to a HTML file.
4472 If narrowing is active in the current buffer, only export its
4475 If a region is active, export that region.
4477 When optional argument SUBTREEP is non-nil, export the sub-tree
4478 at point, extracting information from the headline properties
4481 When optional argument VISIBLE-ONLY is non-nil, don't export
4482 contents of hidden elements.
4484 When optional argument BODY-ONLY is non-nil, only write code
4485 between \"\\begin{document}\" and \"\\end{document}\".
4487 EXT-PLIST, when provided, is a property list with external
4488 parameters overriding Org default settings, but still inferior to
4489 file-local settings.
4491 When optional argument PUB-DIR is set, use it as the publishing
4494 Return output file's name."
4498 (with-current-buffer (get-buffer-create "*debug*")
4501 ;; (let* ((outfile (org-export-output-file-name ".html" subtreep pub-dir))
4502 ;; (outfile "content.xml"))
4503 ;; (org-export-to-file
4504 ;; 'e-odt outfile subtreep visible-only body-only ext-plist))
4506 (let* ((outbuf (org-e-odt-init-outfile))
4507 (target (org-export-output-file-name ".odt" subtreep pub-dir
))
4508 (outdir (file-name-directory (buffer-file-name outbuf
)))
4509 (default-directory outdir
))
4511 ;; FIXME: for copying embedded images
4512 (setq org-current-export-file
4513 (file-name-directory
4514 (org-export-output-file-name ".odt" subtreep nil
)))
4516 (org-export-to-buffer
4518 (memq 'subtree optns
) (memq 'visible optns
) (memq 'body optns
))
4520 (setq org-lparse-opt-plist nil
) ; FIXME
4521 (org-e-odt-save-as-outfile target
;; info
4531 ;;; FIXMES, TODOS, FOR REVIEW etc
4533 ;;;; org-format-table-html
4534 ;;;; org-format-org-table-html
4535 ;;;; org-format-table-table-html
4536 ;;;; org-table-number-fraction
4537 ;;;; org-table-number-regexp
4538 ;;;; org-e-odt-table-caption-above
4541 ;;;; "<span style=\"visibility:hidden;\">%s</span>"
4542 ;;;; Remove display properties
4543 ;;;; org-e-odt-final-hook
4545 ;;;; org-e-odt-with-timestamp
4546 ;;;; org-e-odt-html-helper-timestamp
4548 ;;;; org-export-as-html-and-open
4549 ;;;; org-export-as-html-batch
4550 ;;;; org-export-as-html-to-buffer
4551 ;;;; org-replace-region-by-html
4552 ;;;; org-export-region-as-html
4553 ;;;; org-export-as-html
4555 ;;;; (org-export-directory :html opt-plist)
4556 ;;;; (plist-get opt-plist :html-extension)
4557 ;;;; org-e-odt-toplevel-hlevel
4558 ;;;; org-e-odt-special-string-regexps
4559 ;;;; org-e-odt-coding-system
4560 ;;;; org-e-odt-coding-system
4561 ;;;; org-e-odt-inline-images
4562 ;;;; org-e-odt-inline-image-extensions
4563 ;;;; org-e-odt-protect-char-alist
4564 ;;;; org-e-odt-table-use-header-tags-for-first-column
4565 ;;;; org-e-odt-todo-kwd-class-prefix
4566 ;;;; org-e-odt-tag-class-prefix
4567 ;;;; org-e-odt-footnote-separator
4570 ;;; Library Initializations
4574 ;; Let Org open all OpenDocument files using system-registered app
4575 (add-to-list 'org-file-apps
4576 (cons (concat "\\." (car desc
) "\\'") 'system
))
4577 ;; Let Emacs open all OpenDocument files in archive mode
4578 (add-to-list 'auto-mode-alist
4579 (cons (concat "\\." (car desc
) "\\'") 'archive-mode
)))
4580 org-e-odt-file-extensions
)
4583 ;; (eval-after-load 'org-exp
4584 ;; '(add-to-list 'org-export-inbuffer-options-extra
4585 ;; '("ODT_STYLES_FILE" :odt-styles-file)))
4587 (provide 'org-e-odt
)
4589 ;;; org-e-odt.el ends here