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
))
627 (defun org-e-odt-format-source-line-with-line-number-and-label
628 (line fontifier par-style
)
629 (let (;; (keep-label (not (numberp rpllbl)))
630 (ref (org-find-text-property-in-string 'org-coderef line
))
631 (num (org-find-text-property-in-string 'org-loc line
)))
632 (setq line
(concat line
(and ref
(format "(%s)" ref
))))
633 (setq line
(funcall fontifier line
))
635 (setq line
(org-e-odt-format-target line
(concat "coderef-" ref
))))
636 (setq line
(org-e-odt-format-stylized-paragraph par-style line
))
638 (org-e-odt-format-tags
639 '("<text:list-item>" .
"</text:list-item>") line
))))
641 (defun org-e-odt-format-source-code-or-example-plain
642 (lines lang caption textareap cols rows num cont rpllbl fmt
)
643 "Format source or example blocks much like fixedwidth blocks.
644 Use this when `org-export-e-odt-fontify-srcblocks' option is turned
646 (let* ((lines (org-split-string lines
"[\r\n]"))
647 (line-count (length lines
))
652 (org-e-odt-format-source-line-with-line-number-and-label
653 line
'org-e-odt-encode-plain-text
654 (if (= i line-count
) "OrgFixedWidthBlockLastLine"
655 "OrgFixedWidthBlock")))
658 (defun org-e-odt-hfy-face-to-css (fn)
659 "Create custom style for face FN.
660 When FN is the default face, use it's foreground and background
661 properties to create \"OrgSrcBlock\" paragraph style. Otherwise
662 use it's color attribute to create a character style whose name
663 is obtained from FN. Currently all attributes of FN other than
666 The style name for a face FN is derived using the following
667 operations on the face name in that order - de-dash, CamelCase
668 and prefix with \"OrgSrc\". For example,
669 `font-lock-function-name-face' is associated with
670 \"OrgSrcFontLockFunctionNameFace\"."
671 (let* ((css-list (hfy-face-to-style fn
))
672 (style-name ((lambda (fn)
675 'capitalize
(split-string
676 (hfy-face-or-def-to-name fn
) "-")
678 (color-val (cdr (assoc "color" css-list
)))
679 (background-color-val (cdr (assoc "background" css-list
)))
680 (style (and org-export-e-odt-create-custom-styles-for-srcblocks
683 (format org-src-block-paragraph-format
684 background-color-val color-val
))
688 <style:style style:name=\"%s\" style:family=\"text\">
689 <style:text-properties fo:color=\"%s\"/>
690 </style:style>" style-name color-val
))))))
691 (cons style-name style
)))
693 (defun org-e-odt-insert-custom-styles-for-srcblocks (styles)
694 "Save STYLES used for colorizing of source blocks.
695 Update styles.xml with styles that were collected as part of
696 `org-e-odt-hfy-face-to-css' callbacks."
699 (find-file-noselect (expand-file-name "styles.xml") t
)
700 (goto-char (point-min))
701 (when (re-search-forward "</office:styles>" nil t
)
702 (goto-char (match-beginning 0))
703 (insert "\n<!-- Org Htmlfontify Styles -->\n" styles
"\n")))))
705 (defun org-e-odt-format-source-code-or-example-colored (lines lang caption
)
706 "Format source or example blocks using `htmlfontify-string'.
707 Use this routine when `org-export-e-odt-fontify-srcblocks' option
709 (let* ((lang-m (and lang
(or (cdr (assoc lang org-src-lang-modes
)) lang
)))
710 (mode (and lang-m
(intern (concat (if (symbolp lang-m
)
713 (org-inhibit-startup t
)
714 (org-startup-folded nil
)
715 (lines (with-temp-buffer
717 (if (functionp mode
) (funcall mode
) (fundamental-mode))
718 (font-lock-fontify-buffer)
720 (hfy-html-quote-regex "\\([<\"&> ]\\)")
721 (hfy-html-quote-map '(("\"" """)
726 (" " "<text:tab/>")))
727 (hfy-face-to-css 'org-e-odt-hfy-face-to-css
)
728 (hfy-optimisations-1 (copy-seq hfy-optimisations
))
729 (hfy-optimisations (add-to-list 'hfy-optimisations-1
731 (hfy-begin-span-handler
732 (lambda (style text-block text-id text-begins-block-p
)
733 (insert (format "<text:span text:style-name=\"%s\">" style
))))
734 (hfy-end-span-handler (lambda nil
(insert "</text:span>"))))
735 (when (fboundp 'htmlfontify-string
)
736 (let* ((lines (org-split-string lines
"[\r\n]"))
737 (line-count (length lines
))
742 (org-e-odt-format-source-line-with-line-number-and-label
743 line
'htmlfontify-string
744 (if (= i line-count
) "OrgSrcBlockLastLine" "OrgSrcBlock")))
747 (defun org-e-odt-format-source-code-or-example (lines lang
748 &optional caption
; FIXME
750 "Format source or example blocks for export.
751 Use `org-e-odt-format-source-code-or-example-plain' or
752 `org-e-odt-format-source-code-or-example-colored' depending on the
753 value of `org-export-e-odt-fontify-srcblocks."
754 (setq ;; lines (org-export-number-lines
755 ;; lines 0 0 num cont rpllbl fmt 'preprocess) FIXME
757 (or (and org-export-e-odt-fontify-srcblocks
758 (or (featurep 'htmlfontify
)
759 ;; htmlfontify.el was introduced in Emacs 23.2
760 ;; So load it with some caution
761 (require 'htmlfontify nil t
))
762 (fboundp 'htmlfontify-string
)
763 'org-e-odt-format-source-code-or-example-colored
)
764 'org-e-odt-format-source-code-or-example-plain
)
766 (let ((num (org-find-text-property-in-string 'org-loc lines
)))
768 (let* ((cont (not (equal num
1)))
769 (extra (format " text:continue-numbering=\"%s\""
770 (if cont
"true" "false"))))
771 (org-e-odt-format-tags
772 '("<text:list text:style-name=\"OrgSrcBlockNumberedLine\"%s>"
773 .
"</text:list>") lines extra
)))))
775 (defun org-e-odt-remap-stylenames (style-name)
777 (cdr (assoc style-name
'(("timestamp-wrapper" .
"OrgTimestampWrapper")
778 ("timestamp" .
"OrgTimestamp")
779 ("timestamp-kwd" .
"OrgTimestampKeyword")
783 ("target" .
"OrgTarget"))))
786 (defun org-e-odt-format-fontify (text style
&optional id
)
790 (org-e-odt-remap-stylenames style
))
792 (org-e-odt-get-style-name-for-entity 'character style
))
794 (assert (< 1 (length style
)))
795 (let ((parent-style (pop style
)))
796 (mapconcat (lambda (s)
797 ;; (assert (stringp s) t)
798 (org-e-odt-remap-stylenames s
)) style
"")
799 (org-e-odt-remap-stylenames parent-style
)))
800 (t (error "Don't how to handle style %s" style
)))))
801 (org-e-odt-format-tags
802 '("<text:span text:style-name=\"%s\">" .
"</text:span>")
805 (defun org-e-odt-relocate-relative-path (path dir
)
806 (if (file-name-absolute-p path
) path
807 (file-relative-name (expand-file-name path dir
)
808 (expand-file-name "eyecandy" dir
))))
810 (defun org-e-odt-format-inline-image (thefile
811 &optional caption label attrs
; FIXME - CLA
813 (let* ((thelink (if (file-name-absolute-p thefile
) thefile
815 (org-e-odt-relocate-relative-path
816 thefile org-current-export-file
))))
818 (org-e-odt-format-tags
819 "<draw:image xlink:href=\"%s\" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\"/>" ""
820 (if org-export-e-odt-embed-images
821 (org-e-odt-copy-image-file thefile
) thelink
))))
822 (org-export-e-odt-format-image thefile href
)))
824 (defun org-export-e-odt-format-formula (src href
)
826 (let* ((caption (org-find-text-property-in-string 'org-caption src
))
827 (caption (and caption
(org-xml-format-desc caption
)))
828 (label (org-find-text-property-in-string 'org-label src
))
829 (latex-frag (org-find-text-property-in-string 'org-latex-src src
))
830 (embed-as (or (and latex-frag
831 (org-find-text-property-in-string
832 'org-latex-src-embed-type src
))
833 (if (or caption label
) 'paragraph
'character
)))
836 (setq href
(org-propertize href
:title
"LaTeX Fragment"
837 :description latex-frag
)))
839 ((eq embed-as
'character
)
840 (org-e-odt-format-entity "InlineFormula" href width height
))
842 (org-lparse-end-paragraph)
843 (org-lparse-insert-list-table
844 `((,(org-e-odt-format-entity
845 (if caption
"CaptionedDisplayFormula" "DisplayFormula")
846 href width height
:caption caption
:label nil
)
848 (org-e-odt-format-entity-caption label nil
"__MathFormula__"))))
849 nil nil nil
":style \"OrgEquation\"" nil
'((1 "c" 8) (2 "c" 1)))
850 (throw 'nextline nil
))))))
852 (defun org-e-odt-copy-formula-file (path)
853 "Returns the internal name of the file"
854 (let* ((src-file (expand-file-name
855 path
(file-name-directory org-current-export-file
)))
856 (target-dir (format "Formula-%04d/"
857 (incf org-e-odt-embedded-formulas-count
)))
858 (target-file (concat target-dir
"content.xml")))
859 (message "Embedding %s as %s ..."
860 (substring-no-properties path
) target-file
)
862 (make-directory target-dir
)
863 (org-e-odt-create-manifest-file-entry
864 "application/vnd.oasis.opendocument.formula" target-dir
"1.2")
866 (case (org-e-odt-is-formula-link-p src-file
)
868 (copy-file src-file target-file
'overwrite
))
870 (org-e-odt-zip-extract-one src-file
"content.xml" target-dir
))
872 (error "%s is not a formula file" src-file
)))
874 (org-e-odt-create-manifest-file-entry "text/xml" target-file
)
877 (defun org-e-odt-format-inline-formula (thefile)
878 (let* ((thelink (if (file-name-absolute-p thefile
) thefile
880 (org-e-odt-relocate-relative-path
881 thefile org-current-export-file
))))
883 (org-e-odt-format-tags
884 "<draw:object xlink:href=\"%s\" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\"/>" ""
885 (file-name-directory (org-e-odt-copy-formula-file thefile
)))))
886 (org-export-e-odt-format-formula thefile href
)))
888 (defun org-e-odt-is-formula-link-p (file)
889 (let ((case-fold-search nil
))
891 ((string-match "\\.\\(mathml\\|mml\\)\\'" file
)
893 ((string-match "\\.odf\\'" file
)
896 (defun org-e-odt-format-org-link (opt-plist type-1 path fragment desc attr
898 "Make a OpenDocument link.
899 OPT-PLIST is an options list.
900 TYPE-1 is the device-type of the link (THIS://foo.html).
901 PATH is the path of the link (http://THIS#location).
902 FRAGMENT is the fragment part of the link, if any (foo.html#THIS).
903 DESC is the link description, if any.
904 ATTR is a string of other attributes of the a element."
905 (declare (special org-lparse-par-open
))
908 (and (member type-1
'("http" "https" "file"))
909 (org-lparse-should-inline-p path descp
)
911 (type (if (equal type-1
"id") "file" type-1
))
915 ;; check for inlined images
916 ((and (member type
'("file"))
919 filename org-export-e-odt-inline-image-extensions
)
920 (or (eq t org-export-e-odt-inline-images
)
921 (and org-export-e-odt-inline-images
(not descp
))))
922 (org-e-odt-format-inline-image thefile
))
923 ;; check for embedded formulas
924 ((and (member type
'("file"))
926 (org-e-odt-is-formula-link-p filename
)
928 (org-e-odt-format-inline-formula thefile
))
929 ((string= type
"coderef")
930 (let* ((ref fragment
)
931 (lineno-or-ref (cdr (assoc ref org-export-code-refs
)))
932 (desc (and descp desc
))
933 (org-e-odt-suppress-xref nil
)
934 (href (org-xml-format-href (concat "#coderef-" ref
))))
936 ((and (numberp lineno-or-ref
) (not desc
))
937 (org-e-odt-format-link lineno-or-ref href
))
938 ((and (numberp lineno-or-ref
) desc
939 (string-match (regexp-quote (concat "(" ref
")")) desc
))
940 (format (replace-match "%s" t t desc
)
941 (org-e-odt-format-link lineno-or-ref href
)))
944 (if (and desc
(string-match
945 (regexp-quote (concat "(" ref
")"))
947 (replace-match "%s" t t desc
)
950 (org-e-odt-format-link (org-xml-format-desc desc
) href
)))))
952 (when (string= type
"file")
955 ((file-name-absolute-p path
)
956 (concat "file://" (expand-file-name path
)))
957 (t (org-e-odt-relocate-relative-path
958 thefile org-current-export-file
)))))
960 (when (and (member type
'("" "http" "https" "file")) fragment
)
961 (setq thefile
(concat thefile
"#" fragment
)))
963 (setq thefile
(org-xml-format-href thefile
))
965 (when (not (member type
'("" "file")))
966 (setq thefile
(concat type
":" thefile
)))
968 (let ((org-e-odt-suppress-xref nil
))
969 (org-e-odt-format-link
970 (org-xml-format-desc desc
) thefile attr
)))))))
972 (defun org-e-odt-format-heading (text level
&optional id
)
973 (let* ((text (if id
(org-e-odt-format-target text id
) text
)))
974 (org-e-odt-format-tags
975 '("<text:h text:style-name=\"Heading_20_%s\" text:outline-level=\"%s\">" .
976 "</text:h>") text level level
)))
978 (defun org-e-odt-format-headline (title extra-targets tags
979 &optional snumber level
)
981 (org-e-odt-format-extra-targets extra-targets
)
983 ;; No need to generate section numbers. They are auto-generated by
986 ;; (concat (org-lparse-format 'SECTION-NUMBER snumber level) " ")
988 (and tags
(concat (org-e-odt-format-spaces 3)
989 (org-e-odt-format-org-tags tags
)))))
991 (defun org-e-odt-format-anchor (text name
&optional class
)
992 (org-e-odt-format-target text name
))
994 (defun org-e-odt-format-bookmark (text id
)
996 (org-e-odt-format-tags "<text:bookmark text:name=\"%s\"/>" text id
)
999 (defun org-e-odt-format-target (text id
)
1000 (let ((name (concat org-export-e-odt-bookmark-prefix id
)))
1002 (and id
(org-e-odt-format-tags
1003 "<text:bookmark-start text:name=\"%s\"/>" "" name
))
1004 (org-e-odt-format-bookmark text id
)
1005 (and id
(org-e-odt-format-tags
1006 "<text:bookmark-end text:name=\"%s\"/>" "" name
)))))
1008 (defun org-e-odt-format-footnote (n def
)
1009 (setq n
(format "%d" n
))
1010 (let ((id (concat "fn" n
))
1011 (note-class "footnote")
1012 (par-style "Footnote"))
1013 (org-e-odt-format-tags
1014 '("<text:note text:id=\"%s\" text:note-class=\"%s\">" .
1017 (org-e-odt-format-tags
1018 '("<text:note-citation>" .
"</text:note-citation>")
1020 (org-e-odt-format-tags
1021 '("<text:note-body>" .
"</text:note-body>")
1025 (defun org-e-odt-format-footnote-reference (n def refcnt
)
1027 (org-e-odt-format-footnote n def
)
1028 (org-e-odt-format-footnote-ref n
)))
1030 (defun org-e-odt-format-footnote-ref (n)
1031 (setq n
(format "%d" n
))
1032 (let ((note-class "footnote")
1034 (ref-name (concat "fn" n
)))
1035 (org-e-odt-format-tags
1036 '("<text:span text:style-name=\"%s\">" .
"</text:span>")
1037 (org-e-odt-format-tags
1038 '("<text:note-ref text:note-class=\"%s\" text:reference-format=\"%s\" text:ref-name=\"%s\">" .
"</text:note-ref>")
1039 n note-class ref-format ref-name
)
1042 (defun org-e-odt-get-image-name (file-name)
1046 (concat (sha1 file-name
) "." (file-name-extension file-name
)) "Pictures")))
1048 (defun org-export-e-odt-format-image (src href
)
1049 "Create image tag with source and attributes."
1051 (let* ((caption (org-find-text-property-in-string 'org-caption src
))
1052 (caption (and caption
(org-xml-format-desc caption
)))
1053 (attr (org-find-text-property-in-string 'org-attributes src
))
1054 (label (org-find-text-property-in-string 'org-label src
))
1055 (latex-frag (org-find-text-property-in-string
1056 'org-latex-src src
))
1057 (category (and latex-frag
"__DvipngImage__"))
1058 (attr-plist (org-lparse-get-block-params attr
))
1060 (car (assoc-string (plist-get attr-plist
:anchor
)
1061 '(("as-char") ("paragraph") ("page")) t
)))
1063 (and user-frame-anchor
(plist-get attr-plist
:style
)))
1065 (and user-frame-anchor
(plist-get attr-plist
:attributes
)))
1067 (list user-frame-style user-frame-attrs user-frame-anchor
))
1071 (case (org-find-text-property-in-string
1072 'org-latex-src-embed-type src
)
1073 (paragraph 'paragraph
)
1077 (size (org-e-odt-image-size-from-file
1078 src
(plist-get attr-plist
:width
)
1079 (plist-get attr-plist
:height
)
1080 (plist-get attr-plist
:scale
) nil embed-as
))
1081 (width (car size
)) (height (cdr size
)))
1083 (setq href
(org-propertize href
:title
"LaTeX Fragment"
1084 :description latex-frag
)))
1085 (let ((frame-style-handle (concat (and (or caption label
) "Captioned")
1087 (org-e-odt-format-entity
1088 frame-style-handle href width height
1089 :caption caption
:label label
:category category
1090 :user-frame-params user-frame-params
)))))
1092 (defun org-e-odt-format-object-description (title description
)
1093 (concat (and title
(org-e-odt-format-tags
1094 '("<svg:title>" .
"</svg:title>")
1095 (org-e-odt-encode-plain-text title t
)))
1096 (and description
(org-e-odt-format-tags
1097 '("<svg:desc>" .
"</svg:desc>")
1098 (org-e-odt-encode-plain-text description t
)))))
1100 (defun org-e-odt-format-frame (text width height style
&optional
1104 (if width
(format " svg:width=\"%0.2fcm\"" width
) "")
1105 (if height
(format " svg:height=\"%0.2fcm\"" height
) "")
1107 (format " text:anchor-type=\"%s\"" (or anchor-type
"paragraph")))))
1108 (org-e-odt-format-tags
1109 '("<draw:frame draw:style-name=\"%s\"%s>" .
"</draw:frame>")
1110 (concat text
(org-e-odt-format-object-description
1111 (get-text-property 0 :title text
)
1112 (get-text-property 0 :description text
)))
1113 style frame-attrs
)))
1115 (defun org-e-odt-format-textbox (text width height style
&optional
1117 (org-e-odt-format-frame
1118 (org-e-odt-format-tags
1119 '("<draw:text-box %s>" .
"</draw:text-box>")
1120 text
(concat (format " fo:min-height=\"%0.2fcm\"" (or height
.2))
1122 (format " fo:min-width=\"%0.2fcm\"" (or width
.2)))))
1123 width nil style extra anchor-type
))
1125 (defun org-e-odt-format-inlinetask (heading content
1126 &optional todo priority tags
)
1127 (org-e-odt-format-stylized-paragraph
1128 nil
(org-e-odt-format-textbox
1129 (concat (org-e-odt-format-stylized-paragraph
1130 "OrgInlineTaskHeading"
1132 'HEADLINE
(concat (org-lparse-format-todo todo
) " " heading
)
1134 content
) nil nil
"OrgInlineTaskFrame" " style:rel-width=\"100%\"")))
1137 (defun org-e-odt-merge-frame-params(default-frame-params user-frame-params
)
1138 (if (not user-frame-params
) default-frame-params
1139 (assert (= (length default-frame-params
) 3))
1140 (assert (= (length user-frame-params
) 3))
1141 (loop for user-frame-param in user-frame-params
1142 for default-frame-param in default-frame-params
1143 collect
(or user-frame-param default-frame-param
))))
1145 (defun* org-e-odt-format-entity
(entity href width height
1146 &key caption label category
1148 (let* ((entity-style (assoc-string entity org-e-odt-entity-frame-styles t
))
1149 default-frame-params frame-params
)
1151 ((not (or caption label
))
1152 (setq default-frame-params
(nth 2 entity-style
))
1153 (setq frame-params
(org-e-odt-merge-frame-params
1154 default-frame-params user-frame-params
))
1155 (apply 'org-e-odt-format-frame href width height frame-params
))
1157 (setq default-frame-params
(nth 3 entity-style
))
1158 (setq frame-params
(org-e-odt-merge-frame-params
1159 default-frame-params user-frame-params
))
1160 (apply 'org-e-odt-format-textbox
1161 (org-e-odt-format-stylized-paragraph
1164 (apply 'org-e-odt-format-frame href width height
1165 (nth 2 entity-style
))
1166 (org-e-odt-format-entity-caption
1167 label caption
(or category
(nth 1 entity-style
)))))
1168 width height frame-params
)))))
1170 (defun org-e-odt-copy-image-file (path)
1171 "Returns the internal name of the file"
1172 (let* ((image-type (file-name-extension path
))
1173 (media-type (format "image/%s" image-type
))
1174 (src-file (expand-file-name
1175 path
(file-name-directory org-current-export-file
)))
1176 (target-dir "Images/")
1178 (format "%s%04d.%s" target-dir
1179 (incf org-e-odt-embedded-images-count
) image-type
)))
1180 (message "Embedding %s as %s ..."
1181 (substring-no-properties path
) target-file
)
1183 (when (= 1 org-e-odt-embedded-images-count
)
1184 (make-directory target-dir
)
1185 (org-e-odt-create-manifest-file-entry "" target-dir
))
1187 (copy-file src-file target-file
'overwrite
)
1188 (org-e-odt-create-manifest-file-entry media-type target-file
)
1191 (defun org-e-odt-do-image-size (probe-method file
&optional dpi anchor-type
)
1192 (setq dpi
(or dpi org-export-e-odt-pixels-per-inch
))
1193 (setq anchor-type
(or anchor-type
"paragraph"))
1194 (flet ((size-in-cms (size-in-pixels)
1195 (flet ((pixels-to-cms (pixels)
1196 (let* ((cms-per-inch 2.54)
1197 (inches (/ pixels dpi
)))
1198 (* cms-per-inch inches
))))
1200 (cons (pixels-to-cms (car size-in-pixels
))
1201 (pixels-to-cms (cdr size-in-pixels
)))))))
1204 (size-in-cms (ignore-errors ; Emacs could be in batch mode
1206 (image-size (create-image file
) 'pixels
))))
1209 (let ((dim (shell-command-to-string
1210 (format "identify -format \"%%w:%%h\" \"%s\"" file
))))
1211 (when (string-match "\\([0-9]+\\):\\([0-9]+\\)" dim
)
1212 (cons (string-to-number (match-string 1 dim
))
1213 (string-to-number (match-string 2 dim
)))))))
1215 (cdr (assoc-string anchor-type
1216 org-export-e-odt-default-image-sizes-alist
))))))
1218 (defun org-e-odt-image-size-from-file (file &optional user-width
1219 user-height scale dpi embed-as
)
1220 (unless (file-name-absolute-p file
)
1221 (setq file
(expand-file-name
1222 file
(file-name-directory org-current-export-file
))))
1223 (let* (size width height
)
1224 (unless (and user-height user-width
)
1225 (loop for probe-method in org-export-e-odt-image-size-probe-method
1227 do
(setq size
(org-e-odt-do-image-size
1228 probe-method file dpi embed-as
)))
1229 (or size
(error "Cannot determine Image size. Aborting ..."))
1230 (setq width
(car size
) height
(cdr size
)))
1233 (setq width
(* width scale
) height
(* height scale
)))
1234 ((and user-height user-width
)
1235 (setq width user-width height user-height
))
1237 (setq width
(* user-height
(/ width height
)) height user-height
))
1239 (setq height
(* user-width
(/ height width
)) width user-width
))
1241 ;; ensure that an embedded image fits comfortably within a page
1242 (let ((max-width (car org-export-e-odt-max-image-size
))
1243 (max-height (cdr org-export-e-odt-max-image-size
)))
1244 (when (or (> width max-width
) (> height max-height
))
1245 (let* ((scale1 (/ max-width width
))
1246 (scale2 (/ max-height height
))
1247 (scale (min scale1 scale2
)))
1248 (setq width
(* scale width
) height
(* scale height
)))))
1249 (cons width height
)))
1251 (defun org-e-odt-get-label-category-and-style (label default-category
)
1252 "See `org-export-e-odt-get-category-from-label'."
1253 (let ((default-category-map
1254 (assoc default-category org-e-odt-category-map-alist
))
1255 user-category user-category-map category
)
1257 ((not org-export-e-odt-get-category-from-label
)
1258 default-category-map
)
1259 ((not (setq user-category
1261 (and (string-match "\\`\\(.*\\):.+" label
)
1262 (match-string 1 label
)))))
1263 default-category-map
)
1265 (setq user-category-map
1266 (or (assoc user-category org-e-odt-category-map-alist
)
1267 (list nil user-category
"category-and-value"))
1268 category
(nth 1 user-category-map
))
1269 (if (member category org-export-e-odt-user-categories
)
1271 default-category-map
)))))
1273 (defun org-e-odt-add-label-definition (label default-category
)
1274 "Create an entry in `org-e-odt-entity-labels-alist' and return it."
1275 (setq label
(substring-no-properties label
))
1276 (let* ((label-props (org-e-odt-get-label-category-and-style
1277 label default-category
))
1278 (category (nth 1 label-props
))
1280 (label-style (nth 2 label-props
))
1281 (sequence-var (intern (mapconcat
1283 (org-split-string counter
) "-")))
1284 (seqno (1+ (or (plist-get org-e-odt-entity-counts-plist sequence-var
)
1286 (label-props (list label category seqno label-style
)))
1287 (setq org-e-odt-entity-counts-plist
1288 (plist-put org-e-odt-entity-counts-plist sequence-var seqno
))
1289 (push label-props org-e-odt-entity-labels-alist
)
1292 (defun org-e-odt-format-label-definition (caption label category seqno label-style
)
1295 (cadr (assoc-string label-style org-e-odt-label-styles t
))
1297 (?n .
,(org-e-odt-format-tags
1298 '("<text:sequence text:ref-name=\"%s\" text:name=\"%s\" text:formula=\"ooow:%s+1\" style:num-format=\"1\">" .
"</text:sequence>")
1299 (format "%d" seqno
) label category category
))
1300 (?c .
,(or (and caption
(concat ": " caption
)) "")))))
1302 (defun org-e-odt-format-label-reference (label category seqno label-style
)
1305 (let* ((fmt (cddr (assoc-string label-style org-e-odt-label-styles t
)))
1308 (org-e-odt-format-tags
1309 '("<text:sequence-ref text:reference-format=\"%s\" text:ref-name=\"%s\">"
1310 .
"</text:sequence-ref>")
1311 (format-spec fmt2
`((?e .
,category
)
1312 (?n .
,(format "%d" seqno
)))) fmt1 label
))))
1314 (defun org-e-odt-fixup-label-references ()
1315 (goto-char (point-min))
1316 (while (re-search-forward
1317 "<text:sequence-ref text:ref-name=\"\\([^\"]+\\)\">[ \t\n]*</text:sequence-ref>"
1319 (let* ((label (match-string 1))
1320 (label-def (assoc label org-e-odt-entity-labels-alist
))
1322 (apply 'org-e-odt-format-label-reference label-def
))))
1323 (if rpl
(replace-match rpl t t
)
1325 (format "Unable to resolve reference to label \"%s\"" label
))))))
1327 (defun org-e-odt-format-entity-caption (label caption category
)
1329 (apply 'org-e-odt-format-label-definition
1330 caption
(org-e-odt-add-label-definition label category
)))
1333 (defun org-e-odt-format-tags-1 (tag text prefix suffix
&rest args
)
1336 (concat prefix
(apply 'format
(car tag
) args
) text suffix
1337 (format (cdr tag
))))
1338 ((stringp tag
) ; singleton tag
1339 (concat prefix
(apply 'format tag args
) text
))))
1341 (defun org-e-odt-format-tags (tag text
&rest args
)
1342 (apply 'org-e-odt-format-tags-1 tag text
"\n" "\n" args
))
1344 (defun org-e-odt-format-tags-simple (tag text
&rest args
)
1345 (apply 'org-e-odt-format-tags-1 tag text nil nil args
))
1347 (defun org-e-odt-init-outfile ()
1348 (unless (executable-find "zip")
1349 ;; Not at all OSes ship with zip by default
1350 (error "Executable \"zip\" needed for creating OpenDocument files"))
1352 (let* ((outdir (make-temp-file
1353 (format org-export-e-odt-tmpdir-prefix org-lparse-backend
) t
))
1354 (content-file (expand-file-name "content.xml" outdir
)))
1357 (setq org-e-odt-manifest-file-entries nil
1358 org-e-odt-embedded-images-count
0
1359 org-e-odt-embedded-formulas-count
0
1360 org-e-odt-section-count
0
1361 org-e-odt-entity-labels-alist nil
1362 org-e-odt-list-stack-stashed nil
1363 org-e-odt-automatic-styles nil
1364 org-e-odt-object-counters nil
1365 org-e-odt-entity-counts-plist nil
)
1367 ;; let `htmlfontify' know that we are interested in collecting
1370 (setq hfy-user-sheet-assoc nil
)
1373 (with-current-buffer
1374 (find-file-noselect content-file t
)
1379 (defun org-e-odt-save-as-outfile (target opt-plist
)
1380 ;; write automatic styles
1381 (org-e-odt-write-automatic-styles)
1383 ;; write styles file
1384 ;; (when (equal org-lparse-backend 'odt) FIXME
1387 (org-e-odt-update-styles-file opt-plist
)
1389 ;; create mimetype file
1390 (let ((mimetype (org-e-odt-write-mimetype-file ;; org-lparse-backend FIXME
1392 (org-e-odt-create-manifest-file-entry mimetype
"/" "1.2"))
1394 ;; create a manifest entry for content.xml
1395 (org-e-odt-create-manifest-file-entry "text/xml" "content.xml")
1397 ;; write out the manifest entries before zipping
1398 (org-e-odt-write-manifest-file)
1400 (let ((xml-files '("mimetype" "META-INF/manifest.xml" "content.xml"
1402 (zipdir default-directory
))
1403 (when (or t
(equal org-lparse-backend
'odt
)) ; FIXME
1404 (push "styles.xml" xml-files
))
1405 (message "Switching to directory %s" (expand-file-name zipdir
))
1407 ;; save all xml files
1408 (mapc (lambda (file)
1409 (with-current-buffer
1410 (find-file-noselect (expand-file-name file
) t
)
1411 ;; prettify output if needed
1412 (when org-export-e-odt-prettify-xml
1413 (indent-region (point-min) (point-max)))
1417 (let* ((target-name (file-name-nondirectory target
))
1418 (target-dir (file-name-directory target
))
1419 (cmds `(("zip" "-mX0" ,target-name
"mimetype")
1420 ("zip" "-rmTq" ,target-name
"."))))
1421 (when (file-exists-p target
)
1422 ;; FIXME: If the file is locked this throws a cryptic error
1423 (delete-file target
))
1425 (let ((coding-system-for-write 'no-conversion
) exitcode err-string
)
1426 (message "Creating odt file...")
1429 (message "Running %s" (mapconcat 'identity cmd
" "))
1431 (with-output-to-string
1433 (apply 'call-process
(car cmd
)
1434 nil standard-output nil
(cdr cmd
)))))
1435 (or (zerop exitcode
)
1436 (ignore (message "%s" err-string
))
1437 (error "Unable to create odt file (%S)" exitcode
)))
1440 ;; move the file from outdir to target-dir
1441 (rename-file target-name target-dir
)
1443 ;; kill all xml buffers
1444 (mapc (lambda (file)
1446 (find-file-noselect (expand-file-name file zipdir
) t
)))
1449 (delete-directory zipdir
)))
1450 (message "Created %s" target
)
1451 (set-buffer (find-file-noselect target t
)))
1454 (defun org-e-odt-create-manifest-file-entry (&rest args
)
1455 (push args org-e-odt-manifest-file-entries
))
1457 (defun org-e-odt-write-manifest-file ()
1458 (make-directory "META-INF")
1459 (let ((manifest-file (expand-file-name "META-INF/manifest.xml")))
1460 (with-current-buffer
1461 (find-file-noselect manifest-file t
)
1463 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
1464 <manifest:manifest xmlns:manifest=\"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0\" manifest:version=\"1.2\">\n")
1466 (lambda (file-entry)
1467 (let* ((version (nth 2 file-entry
))
1469 (format " manifest:version=\"%s\"" version
)
1472 (format org-e-odt-manifest-file-entry-tag
1473 (nth 0 file-entry
) (nth 1 file-entry
) extra
))))
1474 org-e-odt-manifest-file-entries
)
1475 (insert "\n</manifest:manifest>"))))
1477 (defun org-e-odt-update-meta-file (info) ; FIXME opt-plist
1478 (let ((date (org-e-odt-format-date (plist-get info
:date
)))
1479 (author (or (plist-get info
:author
) ""))
1480 (email (plist-get info
:email
))
1481 (keywords (plist-get info
:keywords
))
1482 (description (plist-get info
:description
))
1483 (title (plist-get info
:title
)))
1486 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
1487 <office:document-meta
1488 xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"
1489 xmlns:xlink=\"http://www.w3.org/1999/xlink\"
1490 xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
1491 xmlns:meta=\"urn:oasis:names:tc:opendocument:xmlns:meta:1.0\"
1492 xmlns:ooo=\"http://openoffice.org/2004/office\"
1493 office:version=\"1.2\">
1495 (org-e-odt-format-author author
) "\n"
1496 (format "<meta:initial-creator>%s</meta:initial-creator>\n" author
)
1497 (format "<dc:date>%s</dc:date>\n" date
)
1498 (format "<meta:creation-date>%s</meta:creation-date>\n" date
)
1499 (format "<meta:generator>%s</meta:generator>\n"
1500 (when org-export-creator-info
1501 (format "Org-%s/Emacs-%s"
1502 org-version emacs-version
)))
1503 (format "<meta:keyword>%s</meta:keyword>\n" keywords
)
1504 (format "<dc:subject>%s</dc:subject>\n" description
)
1505 (format "<dc:title>%s</dc:title>\n" title
)
1507 " </office:meta>\n" "</office:document-meta>")
1508 nil
(expand-file-name "meta.xml")))
1510 ;; create a manifest entry for meta.xml
1511 (org-e-odt-create-manifest-file-entry "text/xml" "meta.xml"))
1513 (defun org-e-odt-update-styles-file (opt-plist)
1514 ;; write styles file
1515 (let ((styles-file (plist-get opt-plist
:odt-styles-file
)))
1516 (org-e-odt-copy-styles-file (and styles-file
1517 (read (org-trim styles-file
)))))
1519 ;; Update styles.xml - take care of outline numbering
1520 (with-current-buffer
1521 (find-file-noselect (expand-file-name "styles.xml") t
)
1522 ;; Don't make automatic backup of styles.xml file. This setting
1523 ;; prevents the backed-up styles.xml file from being zipped in to
1524 ;; odt file. This is more of a hackish fix. Better alternative
1525 ;; would be to fix the zip command so that the output odt file
1526 ;; includes only the needed files and excludes any auto-generated
1527 ;; extra files like backups and auto-saves etc etc. Note that
1528 ;; currently the zip command zips up the entire temp directory so
1529 ;; that any auto-generated files created under the hood ends up in
1530 ;; the resulting odt file.
1531 (set (make-local-variable 'backup-inhibited
) t
)
1533 ;; Import local setting of `org-export-with-section-numbers'
1534 (org-e-odt-configure-outline-numbering
1535 (if org-export-with-section-numbers org-export-headline-levels
0)))
1537 ;; Write custom styles for source blocks
1538 (org-e-odt-insert-custom-styles-for-srcblocks
1541 (format " %s\n" (cddr style
)))
1542 hfy-user-sheet-assoc
"")))
1544 (defun org-e-odt-write-mimetype-file (format)
1545 ;; create mimetype file
1548 (odt "application/vnd.oasis.opendocument.text")
1549 (odf "application/vnd.oasis.opendocument.formula")
1550 (t (error "Unknown OpenDocument backend %S" org-lparse-backend
)))))
1551 (write-region mimetype nil
(expand-file-name "mimetype"))
1554 (defun org-e-odt-finalize-outfile ()
1555 (org-e-odt-delete-empty-paragraphs))
1557 (defun org-e-odt-delete-empty-paragraphs ()
1558 (goto-char (point-min))
1559 (let ((open "<text:p[^>]*>")
1560 (close "</text:p>"))
1561 (while (re-search-forward (format "%s[ \r\n\t]*%s" open close
) nil t
)
1562 (replace-match ""))))
1564 (declare-function org-create-math-formula
"org"
1565 (latex-frag &optional mathml-file
))
1568 (defun org-export-e-odt-convert (&optional in-file out-fmt prefix-arg
)
1569 "Convert IN-FILE to format OUT-FMT using a command line converter.
1570 IN-FILE is the file to be converted. If unspecified, it defaults
1571 to variable `buffer-file-name'. OUT-FMT is the desired output
1572 format. Use `org-export-e-odt-convert-process' as the converter.
1573 If PREFIX-ARG is non-nil then the newly converted file is opened
1574 using `org-open-file'."
1576 (append (org-lparse-convert-read-params) current-prefix-arg
))
1577 (org-lparse-do-convert in-file out-fmt prefix-arg
))
1579 (defun org-e-odt-get (what &optional opt-plist
)
1582 (EXPORT-DIR (org-export-directory :html opt-plist
))
1583 (FILE-NAME-EXTENSION "odt")
1584 (EXPORT-BUFFER-NAME "*Org ODT Export*")
1585 (ENTITY-CONTROL org-e-odt-entity-control-callbacks-alist
)
1586 (ENTITY-FORMAT org-e-odt-entity-format-callbacks-alist
)
1587 (INIT-METHOD 'org-e-odt-init-outfile
)
1588 (FINAL-METHOD 'org-e-odt-finalize-outfile
)
1589 (SAVE-METHOD 'org-e-odt-save-as-outfile
)
1591 (and org-export-e-odt-convert-process
1592 (cadr (assoc-string org-export-e-odt-convert-process
1593 org-export-e-odt-convert-processes t
))))
1594 (CONVERT-CAPABILITIES
1595 (and org-export-e-odt-convert-process
1596 (cadr (assoc-string org-export-e-odt-convert-process
1597 org-export-e-odt-convert-processes t
))
1598 org-export-e-odt-convert-capabilities
))
1600 (SPECIAL-STRING-REGEXPS org-export-e-odt-special-string-regexps
)
1601 (INLINE-IMAGES 'maybe
)
1602 (INLINE-IMAGE-EXTENSIONS '("png" "jpeg" "jpg" "gif" "svg"))
1603 (PLAIN-TEXT-MAP '(("&" .
"&") ("<" .
"<") (">" .
">")))
1604 (TABLE-FIRST-COLUMN-AS-LABELS nil
)
1605 (FOOTNOTE-SEPARATOR )
1606 (CODING-SYSTEM-FOR-WRITE 'utf-8
)
1607 (CODING-SYSTEM-FOR-SAVE 'utf-8
)
1608 (t (error "Unknown property: %s" what
))))
1610 (defun org-export-e-odt-do-preprocess-latex-fragments ()
1611 "Convert LaTeX fragments to images."
1612 (let* ((latex-frag-opt (plist-get org-lparse-opt-plist
:LaTeX-fragments
))
1613 (latex-frag-opt ; massage the options
1614 (or (and (member latex-frag-opt
'(mathjax t
))
1615 (not (and (fboundp 'org-format-latex-mathml-available-p
)
1616 (org-format-latex-mathml-available-p)))
1617 (prog1 org-lparse-latex-fragment-fallback
1620 "LaTeX to MathML converter not available. "
1621 (format "Using %S instead."
1622 org-lparse-latex-fragment-fallback
)))))
1624 cache-dir display-msg
)
1626 ((eq latex-frag-opt
'dvipng
)
1627 (setq cache-dir
"ltxpng/")
1628 (setq display-msg
"Creating LaTeX image %s"))
1629 ((member latex-frag-opt
'(mathjax t
))
1630 (setq latex-frag-opt
'mathml
)
1631 (setq cache-dir
"ltxmathml/")
1632 (setq display-msg
"Creating MathML formula %s")))
1633 (when (and org-current-export-file
)
1635 (concat cache-dir
(file-name-sans-extension
1636 (file-name-nondirectory org-current-export-file
)))
1637 org-current-export-dir nil display-msg
1638 nil nil latex-frag-opt
))))
1640 (defadvice org-format-latex-as-mathml
1641 (after org-e-odt-protect-latex-fragment activate
)
1642 "Encode LaTeX fragment as XML.
1643 Do this when translation to MathML fails."
1644 (when (or (not (> (length ad-return-value
) 0))
1645 (get-text-property 0 'org-protected ad-return-value
))
1646 (setq ad-return-value
1647 (org-propertize (org-e-odt-encode-plain-text (ad-get-arg 0))
1648 'org-protected t
))))
1650 (defun org-export-e-odt-preprocess-latex-fragments ()
1651 (when (equal org-export-current-backend
'odt
)
1652 (org-export-e-odt-do-preprocess-latex-fragments)))
1654 (defun org-export-e-odt-preprocess-label-references ()
1655 (goto-char (point-min))
1656 (let (label label-components category value pretty-label
)
1657 (while (re-search-forward "\\\\ref{\\([^{}\n]+\\)}" nil t
)
1658 (org-if-unprotected-at (match-beginning 1)
1660 (let ((org-lparse-encode-pending t
)
1661 (label (match-string 1)))
1662 ;; markup generated below is mostly an eye-candy. At
1663 ;; pre-processing stage, there is no information on which
1664 ;; entity a label reference points to. The actual markup
1665 ;; is generated as part of `org-e-odt-fixup-label-references'
1666 ;; which gets called at the fag end of export. By this
1667 ;; time we would have seen and collected all the label
1668 ;; definitions in `org-e-odt-entity-labels-alist'.
1669 (org-e-odt-format-tags
1670 '("<text:sequence-ref text:ref-name=\"%s\">" .
1671 "</text:sequence-ref>")
1672 "" (org-add-props label
'(org-protected t
)))) t t
)))))
1674 ;; process latex fragments as part of
1675 ;; `org-export-preprocess-after-blockquote-hook'. Note that this hook
1676 ;; is the one that is closest and well before the call to
1677 ;; `org-export-attach-captions-and-attributes' in
1678 ;; `org-export-preprocess-string'. The above arrangement permits
1679 ;; captions, labels and attributes to be attached to png images
1680 ;; generated out of latex equations.
1681 (add-hook 'org-export-preprocess-after-blockquote-hook
1682 'org-export-e-odt-preprocess-latex-fragments
)
1684 (defun org-export-e-odt-preprocess (parameters)
1685 (org-export-e-odt-preprocess-label-references))
1688 (defun org-e-odt-zip-extract-one (archive member
&optional target
)
1690 (let* ((target (or target default-directory
))
1691 (archive (expand-file-name archive
))
1692 (archive-zip-extract
1693 (list "unzip" "-qq" "-o" "-d" target
))
1694 exit-code command-output
)
1695 (setq command-output
1697 (setq exit-code
(archive-zip-extract archive member
))
1699 (unless (zerop exit-code
)
1700 (message command-output
)
1701 (error "Extraction failed"))))
1703 (defun org-e-odt-zip-extract (archive members
&optional target
)
1704 (when (atom members
) (setq members
(list members
)))
1705 (mapc (lambda (member)
1706 (org-e-odt-zip-extract-one archive member target
))
1709 (defun org-e-odt-copy-styles-file (&optional styles-file
)
1710 ;; Non-availability of styles.xml is not a critical error. For now
1711 ;; throw an error purely for aesthetic reasons.
1712 (setq styles-file
(or styles-file
1713 org-export-e-odt-styles-file
1714 (expand-file-name "OrgOdtStyles.xml"
1715 org-e-odt-styles-dir
)
1716 (error "org-e-odt: Missing styles file?")))
1718 ((listp styles-file
)
1719 (let ((archive (nth 0 styles-file
))
1720 (members (nth 1 styles-file
)))
1721 (org-e-odt-zip-extract archive members
)
1724 (when (org-file-image-p member
)
1725 (let* ((image-type (file-name-extension member
))
1726 (media-type (format "image/%s" image-type
)))
1727 (org-e-odt-create-manifest-file-entry media-type member
))))
1729 ((and (stringp styles-file
) (file-exists-p styles-file
))
1730 (let ((styles-file-type (file-name-extension styles-file
)))
1732 ((string= styles-file-type
"xml")
1733 (copy-file styles-file
"styles.xml" t
))
1734 ((member styles-file-type
'("odt" "ott"))
1735 (org-e-odt-zip-extract styles-file
"styles.xml")))))
1737 (error (format "Invalid specification of styles.xml file: %S"
1738 org-export-e-odt-styles-file
))))
1740 ;; create a manifest entry for styles.xml
1741 (org-e-odt-create-manifest-file-entry "text/xml" "styles.xml"))
1743 (defun org-e-odt-configure-outline-numbering (level)
1744 "Outline numbering is retained only upto LEVEL.
1745 To disable outline numbering pass a LEVEL of 0."
1746 (goto-char (point-min))
1748 "<text:outline-level-style\\([^>]*\\)text:level=\"\\([^\"]*\\)\"\\([^>]*\\)>")
1750 "<text:outline-level-style\\1text:level=\"\\2\" style:num-format=\"\">"))
1751 (while (re-search-forward regex nil t
)
1752 (when (> (string-to-number (match-string 2)) level
)
1753 (replace-match replacement t nil
))))
1757 (defun org-export-as-odf (latex-frag &optional odf-file
)
1758 "Export LATEX-FRAG as OpenDocument formula file ODF-FILE.
1759 Use `org-create-math-formula' to convert LATEX-FRAG first to
1760 MathML. When invoked as an interactive command, use
1761 `org-latex-regexps' to infer LATEX-FRAG from currently active
1762 region. If no LaTeX fragments are found, prompt for it. Push
1763 MathML source to kill ring, if `org-export-copy-to-kill-ring' is
1767 (setq frag
(and (setq frag
(and (region-active-p)
1768 (buffer-substring (region-beginning)
1770 (loop for e in org-latex-regexps
1771 thereis
(when (string-match (nth 1 e
) frag
)
1772 (match-string (nth 2 e
) frag
)))))
1773 (read-string "LaTeX Fragment: " frag nil frag
))
1774 ,(let ((odf-filename (expand-file-name
1776 (file-name-sans-extension
1777 (or (file-name-nondirectory buffer-file-name
)))
1779 (file-name-directory buffer-file-name
))))
1780 (read-file-name "ODF filename: " nil odf-filename nil
1781 (file-name-nondirectory odf-filename
)))))
1782 (let* ((org-lparse-backend 'odf
)
1783 org-lparse-opt-plist
1784 (filename (or odf-file
1787 (file-name-sans-extension
1788 (or (file-name-nondirectory buffer-file-name
)))
1790 (file-name-directory buffer-file-name
))))
1791 (buffer (find-file-noselect (org-e-odt-init-outfile filename
)))
1792 (coding-system-for-write 'utf-8
)
1793 (save-buffer-coding-system 'utf-8
))
1795 (set-buffer-file-coding-system coding-system-for-write
)
1796 (let ((mathml (org-create-math-formula latex-frag
)))
1797 (unless mathml
(error "No Math formula created"))
1799 (or (org-export-push-to-kill-ring
1800 (upcase (symbol-name org-lparse-backend
)))
1801 (message "Exporting... done")))
1802 (org-e-odt-save-as-outfile filename nil
; FIXME
1806 (defun org-export-as-odf-and-open ()
1807 "Export LaTeX fragment as OpenDocument formula and immediately open it.
1808 Use `org-export-as-odf' to read LaTeX fragment and OpenDocument
1811 (org-lparse-and-open
1812 nil nil nil
(call-interactively 'org-export-as-odf
)))
1817 ;;; Driver Starts here
1820 (require 'format-spec
)
1821 (eval-when-compile (require 'cl
) (require 'table
))
1827 (defvar org-e-odt-after-blockquotes-hook nil
1828 "Hook run during HTML export, after blockquote, verse, center are done.")
1830 (defvar org-e-odt-final-hook nil
1831 "Hook run at the end of HTML export, in the new buffer.")
1833 ;; FIXME: it already exists in org-e-odt.el
1834 ;;; Function Declarations
1836 (declare-function org-element-property
"org-element" (property element
))
1837 (declare-function org-element-normalize-string
"org-element" (s))
1838 (declare-function org-element-parse-secondary-string
1839 "org-element" (string restriction
&optional buffer
))
1840 (defvar org-element-string-restrictions
)
1841 (defvar org-element-object-restrictions
)
1843 (declare-function org-export-clean-table
"org-export" (table specialp
))
1844 (declare-function org-export-data
"org-export" (data backend info
))
1845 (declare-function org-export-directory
"org-export" (type plist
))
1846 (declare-function org-export-expand-macro
"org-export" (macro info
))
1847 (declare-function org-export-first-sibling-p
"org-export" (headline info
))
1848 (declare-function org-export-footnote-first-reference-p
"org-export"
1849 (footnote-reference info
))
1850 (declare-function org-export-get-coderef-format
"org-export" (path desc
))
1851 (declare-function org-export-get-footnote-definition
"org-export"
1852 (footnote-reference info
))
1853 (declare-function org-export-get-footnote-number
"org-export" (footnote info
))
1854 (declare-function org-export-get-previous-element
"org-export" (blob info
))
1855 (declare-function org-export-get-relative-level
"org-export" (headline info
))
1856 (declare-function org-export-handle-code
1857 "org-export" (element info
&optional num-fmt ref-fmt delayed
))
1858 (declare-function org-export-included-file
"org-export" (keyword backend info
))
1859 (declare-function org-export-inline-image-p
"org-export"
1860 (link &optional extensions
))
1861 (declare-function org-export-last-sibling-p
"org-export" (headline info
))
1862 (declare-function org-export-low-level-p
"org-export" (headline info
))
1863 (declare-function org-export-output-file-name
1864 "org-export" (extension &optional subtreep pub-dir
))
1865 (declare-function org-export-resolve-coderef
"org-export" (ref info
))
1866 (declare-function org-export-resolve-fuzzy-link
"org-export" (link info
))
1867 (declare-function org-export-secondary-string
"org-export"
1868 (secondary backend info
))
1869 (declare-function org-export-solidify-link-text
"org-export" (s))
1870 (declare-function org-export-table-format-info
"org-export" (table))
1872 org-export-to-buffer
"org-export"
1873 (backend buffer
&optional subtreep visible-only body-only ext-plist
))
1875 org-export-to-file
"org-export"
1876 (backend file
&optional subtreep visible-only body-only ext-plist
))
1878 (declare-function org-id-find-id-file
"org-id" (id))
1879 (declare-function htmlize-region
"ext:htmlize" (beg end
))
1880 (declare-function org-pop-to-buffer-same-window
1881 "org-compat" (&optional buffer-or-name norecord label
))
1887 (declare-function hfy-face-to-style
"htmlfontify" (fn))
1888 (declare-function hfy-face-or-def-to-name
"htmlfontify" (fn))
1889 (declare-function archive-zip-extract
"arc-mode.el" (archive name
))
1891 ;;; Internal Variables
1893 ;;;; ODT Internal Variables
1895 (defconst org-e-odt-lib-dir
1896 (file-name-directory load-file-name
)
1897 "Location of ODT exporter.
1898 Use this to infer values of `org-e-odt-styles-dir' and
1899 `org-export-e-odt-schema-dir'.")
1901 (defvar org-e-odt-data-dir
1902 (expand-file-name "../etc/" org-e-odt-lib-dir
)
1903 "Data directory for ODT exporter.
1904 Use this to infer values of `org-e-odt-styles-dir' and
1905 `org-export-e-odt-schema-dir'.")
1910 (defconst org-export-e-odt-special-string-regexps
1911 '(("\\\\-" .
"­\\1") ; shy
1912 ("---\\([^-]\\)" .
"—\\1") ; mdash
1913 ("--\\([^-]\\)" .
"–\\1") ; ndash
1914 ("\\.\\.\\." .
"…")) ; hellip
1915 "Regular expressions for special string conversion.")
1917 (defconst org-e-odt-schema-dir-list
1919 (and org-e-odt-data-dir
1920 (expand-file-name "./schema/" org-e-odt-data-dir
)) ; bail out
1922 (and (boundp 'org-e-odt-data-dir
) org-e-odt-data-dir
; see make install
1923 (expand-file-name "./schema/" org-e-odt-data-dir
)))
1924 (expand-file-name "../contrib/odt/etc/schema/" org-e-odt-lib-dir
) ; git
1926 "List of directories to search for OpenDocument schema files.
1927 Use this list to set the default value of
1928 `org-export-e-odt-schema-dir'. The entries in this list are
1929 populated heuristically based on the values of `org-e-odt-lib-dir'
1930 and `org-e-odt-data-dir'.")
1933 (defconst org-e-odt-styles-dir-list
1935 (and org-e-odt-data-dir
1936 (expand-file-name "./styles/" org-e-odt-data-dir
)) ; bail out
1938 (and (boundp 'org-e-odt-data-dir
) org-e-odt-data-dir
; see make install
1939 (expand-file-name "./styles/" org-e-odt-data-dir
)))
1940 (expand-file-name "../etc/styles/" org-e-odt-lib-dir
) ; git
1941 (expand-file-name "./etc/styles/" org-e-odt-lib-dir
) ; elpa
1942 (expand-file-name "./org/" data-directory
) ; system
1944 "List of directories to search for OpenDocument styles files.
1945 See `org-e-odt-styles-dir'. The entries in this list are populated
1946 heuristically based on the values of `org-e-odt-lib-dir' and
1947 `org-e-odt-data-dir'.")
1949 (defconst org-e-odt-styles-dir
1952 (message "Debug (org-e-odt): Searching for OpenDocument styles files...")
1953 (mapc (lambda (styles-dir)
1955 (message "Debug (org-e-odt): Trying %s..." styles-dir
)
1956 (when (and (file-readable-p
1958 "OrgOdtContentTemplate.xml" styles-dir
))
1961 "OrgOdtStyles.xml" styles-dir
)))
1962 (message "Debug (org-e-odt): Using styles under %s"
1964 (throw 'styles-dir styles-dir
))))
1965 org-e-odt-styles-dir-list
)
1968 (error "Error (org-e-odt): Cannot find factory styles files. Aborting."))
1970 "Directory that holds auxiliary XML files used by the ODT exporter.
1972 This directory contains the following XML files -
1973 \"OrgOdtStyles.xml\" and \"OrgOdtContentTemplate.xml\". These
1974 XML files are used as the default values of
1975 `org-export-e-odt-styles-file' and
1976 `org-export-e-odt-content-template-file'.
1978 The default value of this variable varies depending on the
1979 version of org in use and is initialized from
1980 `org-e-odt-styles-dir-list'. Note that the user could be using org
1981 from one of: org's own private git repository, GNU ELPA tar or
1984 (defconst org-export-e-odt-tmpdir-prefix
"%s-")
1985 (defconst org-export-e-odt-bookmark-prefix
"OrgXref.")
1987 (defconst org-e-odt-manifest-file-entry-tag
1989 <manifest:file-entry manifest:media-type=\"%s\" manifest:full-path=\"%s\"%s/>")
1993 (defvar org-lparse-dyn-first-heading-pos
) ; let bound during org-do-lparse
1995 (defvar org-e-odt-suppress-xref nil
)
1996 (defvar org-e-odt-file-extensions
1997 '(("odt" .
"OpenDocument Text")
1998 ("ott" .
"OpenDocument Text Template")
1999 ("odm" .
"OpenDocument Master Document")
2000 ("ods" .
"OpenDocument Spreadsheet")
2001 ("ots" .
"OpenDocument Spreadsheet Template")
2002 ("odg" .
"OpenDocument Drawing (Graphics)")
2003 ("otg" .
"OpenDocument Drawing Template")
2004 ("odp" .
"OpenDocument Presentation")
2005 ("otp" .
"OpenDocument Presentation Template")
2006 ("odi" .
"OpenDocument Image")
2007 ("odf" .
"OpenDocument Formula")
2008 ("odc" .
"OpenDocument Chart")))
2010 (defvar org-export-e-odt-embed-images t
2011 "Should the images be copied in to the odt file or just linked?")
2013 (defvar org-export-e-odt-inline-images
'maybe
)
2014 (defvar org-export-e-odt-default-org-styles-alist
2015 '((paragraph .
((default .
"Text_20_body")
2016 (fixedwidth .
"OrgFixedWidthBlock")
2017 (verse .
"OrgVerse")
2018 (quote .
"Quotations")
2019 (blockquote .
"Quotations")
2020 (center .
"OrgCenter")
2022 (right .
"OrgRight")
2023 (title .
"OrgTitle")
2024 (subtitle .
"OrgSubtitle")
2025 (footnote .
"Footnote")
2026 (src .
"OrgSrcBlock")
2027 (illustration .
"Illustration")
2029 (definition-term .
"Text_20_body_20_bold")
2030 (horizontal-line .
"Horizontal_20_Line")))
2031 (character .
((bold .
"Bold")
2032 (emphasis .
"Emphasis")
2034 (verbatim .
"OrgCode")
2035 (strike .
"Strikethrough")
2036 (underline .
"Underline")
2037 (subscript .
"OrgSubscript")
2038 (superscript .
"OrgSuperscript")))
2039 (list .
((ordered .
"OrgNumberedList")
2040 (unordered .
"OrgBulletedList")
2041 (descriptive .
"OrgDescriptionList"))))
2042 "Default styles for various entities.")
2044 (defvar org-export-e-odt-org-styles-alist org-export-e-odt-default-org-styles-alist
)
2047 ;;;_. control callbacks
2048 ;;;_ , document body
2050 (defvar org-lparse-body-only
) ; let bound during org-do-lparse
2051 (defvar org-lparse-opt-plist
) ; bound during org-do-lparse
2052 (defvar org-lparse-list-stack
) ; dynamically bound in org-do-lparse
2053 (defvar org-e-odt-list-stack-stashed
)
2054 (defvar org-lparse-table-ncols
)
2055 (defvar org-e-odt-table-rowgrp-open
)
2056 (defvar org-e-odt-table-rownum
)
2057 (defvar org-e-odt-table-cur-rowgrp-is-hdr
)
2058 (defvar org-lparse-table-is-styled
)
2059 (defvar org-lparse-table-rowgrp-info
)
2060 (defvar org-lparse-table-colalign-vector
)
2062 (defvar org-e-odt-table-style nil
2063 "Table style specified by \"#+ATTR_ODT: <style-name>\" line.
2064 This is set during `org-e-odt-begin-table'.")
2066 (defvar org-e-odt-table-style-spec nil
2067 "Entry for `org-e-odt-table-style' in `org-export-e-odt-table-styles'.")
2070 (defvar org-e-odt-table-style-format
2072 <style:style style:name=\"%s\" style:family=\"table\">
2073 <style:table-properties style:rel-width=\"%d%%\" fo:margin-top=\"0cm\" fo:margin-bottom=\"0.20cm\" table:align=\"center\"/>
2076 "Template for auto-generated Table styles.")
2078 (defvar org-e-odt-automatic-styles
'()
2079 "Registry of automatic styles for various OBJECT-TYPEs.
2080 The variable has the following form:
2082 \(\(OBJECT-NAME-A.1 OBJECT-PROPS-A.1\)
2083 \(OBJECT-NAME-A.2 OBJECT-PROPS-A.2\) ...\)\)
2085 \(\(OBJECT-NAME-B.1 OBJECT-PROPS-B.1\)
2086 \(OBJECT-NAME-B.2 OBJECT-PROPS-B.2\) ...\)\)
2089 OBJECT-TYPEs could be \"Section\", \"Table\", \"Figure\" etc.
2090 OBJECT-PROPS is (typically) a plist created by passing
2091 \"#+ATTR_ODT: \" option to `org-lparse-get-block-params'.
2093 Use `org-e-odt-add-automatic-style' to add update this variable.'")
2095 (defvar org-e-odt-object-counters nil
2096 "Running counters for various OBJECT-TYPEs.
2097 Use this to generate automatic names and style-names. See
2098 `org-e-odt-add-automatic-style'.")
2100 (defvar org-e-odt-table-indentedp nil
)
2101 (defvar org-lparse-table-colalign-info
)
2102 (defvar org-lparse-link-description-is-image nil
)
2105 (defvar org-src-block-paragraph-format
2106 "<style:style style:name=\"OrgSrcBlock\" style:family=\"paragraph\" style:parent-style-name=\"Preformatted_20_Text\">
2107 <style:paragraph-properties fo:background-color=\"%s\" fo:padding=\"0.049cm\" fo:border=\"0.51pt solid #000000\" style:shadow=\"none\">
2108 <style:background-image/>
2109 </style:paragraph-properties>
2110 <style:text-properties fo:color=\"%s\"/>
2112 "Custom paragraph style for colorized source and example blocks.
2113 This style is much the same as that of \"OrgFixedWidthBlock\"
2114 except that the foreground and background colors are set
2115 according to the default face identified by the `htmlfontify'.")
2117 (defvar hfy-optimisations
)
2118 (defvar org-e-odt-embedded-formulas-count
0)
2119 (defvar org-e-odt-entity-frame-styles
2120 '(("As-CharImage" "__Figure__" ("OrgInlineImage" nil
"as-char"))
2121 ("ParagraphImage" "__Figure__" ("OrgDisplayImage" nil
"paragraph"))
2122 ("PageImage" "__Figure__" ("OrgPageImage" nil
"page"))
2123 ("CaptionedAs-CharImage" "__Figure__"
2124 ("OrgCaptionedImage"
2125 " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph")
2126 ("OrgInlineImage" nil
"as-char"))
2127 ("CaptionedParagraphImage" "__Figure__"
2128 ("OrgCaptionedImage"
2129 " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph")
2130 ("OrgImageCaptionFrame" nil
"paragraph"))
2131 ("CaptionedPageImage" "__Figure__"
2132 ("OrgCaptionedImage"
2133 " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph")
2134 ("OrgPageImageCaptionFrame" nil
"page"))
2135 ("InlineFormula" "__MathFormula__" ("OrgInlineFormula" nil
"as-char"))
2136 ("DisplayFormula" "__MathFormula__" ("OrgDisplayFormula" nil
"as-char"))
2137 ("CaptionedDisplayFormula" "__MathFormula__"
2138 ("OrgCaptionedFormula" nil
"paragraph")
2139 ("OrgFormulaCaptionFrame" nil
"as-char"))))
2141 (defvar org-e-odt-embedded-images-count
0)
2143 (defvar org-export-e-odt-image-size-probe-method
2144 (append (and (executable-find "identify") '(imagemagick)) ; See Bug#10675
2146 "Ordered list of methods for determining image sizes.")
2148 (defvar org-export-e-odt-default-image-sizes-alist
2149 '(("as-char" .
(5 .
0.4))
2150 ("paragraph" .
(5 .
5)))
2151 "Hardcoded image dimensions one for each of the anchor
2154 ;; A4 page size is 21.0 by 29.7 cms
2155 ;; The default page settings has 2cm margin on each of the sides. So
2156 ;; the effective text area is 17.0 by 25.7 cm
2157 (defvar org-export-e-odt-max-image-size
'(17.0 .
20.0)
2158 "Limiting dimensions for an embedded image.")
2160 (defvar org-e-odt-entity-labels-alist nil
2161 "Associate Labels with the Labeled entities.
2162 Each element of the alist is of the form (LABEL-NAME
2163 CATEGORY-NAME SEQNO LABEL-STYLE-NAME). LABEL-NAME is same as
2164 that specified by \"#+LABEL: ...\" line. CATEGORY-NAME is the
2165 type of the entity that LABEL-NAME is attached to. CATEGORY-NAME
2166 can be one of \"Table\", \"Figure\" or \"Equation\". SEQNO is
2167 the unique number assigned to the referenced entity on a
2168 per-CATEGORY basis. It is generated sequentially and is 1-based.
2169 LABEL-STYLE-NAME is a key `org-e-odt-label-styles'.
2171 See `org-e-odt-add-label-definition' and
2172 `org-e-odt-fixup-label-references'.")
2174 (defvar org-e-odt-entity-counts-plist nil
2175 "Plist of running counters of SEQNOs for each of the CATEGORY-NAMEs.
2176 See `org-e-odt-entity-labels-alist' for known CATEGORY-NAMEs.")
2178 (defvar org-e-odt-label-styles
2179 '(("text" "(%n)" "text" "(%n)")
2180 ("category-and-value" "%e %n%c" "category-and-value" "%e %n")
2181 ("value" "%e %n%c" "value" "%n"))
2182 "Specify how labels are applied and referenced.
2183 This is an alist where each element is of the
2184 form (LABEL-STYLE-NAME LABEL-ATTACH-FMT LABEL-REF-MODE
2187 LABEL-ATTACH-FMT controls how labels and captions are attached to
2188 an entity. It may contain following specifiers - %e, %n and %c.
2189 %e is replaced with the CATEGORY-NAME. %n is replaced with
2190 \"<text:sequence ...> SEQNO </text:sequence>\". %c is replaced
2191 with CAPTION. See `org-e-odt-format-label-definition'.
2193 LABEL-REF-MODE and LABEL-REF-FMT controls how label references
2194 are generated. The following XML is generated for a label
2195 reference - \"<text:sequence-ref
2196 text:reference-format=\"LABEL-REF-MODE\" ...> LABEL-REF-FMT
2197 </text:sequence-ref>\". LABEL-REF-FMT may contain following
2198 specifiers - %e and %n. %e is replaced with the CATEGORY-NAME.
2199 %n is replaced with SEQNO. See
2200 `org-e-odt-format-label-reference'.")
2202 (defvar org-e-odt-category-map-alist
2203 '(("__Table__" "Table" "value")
2204 ("__Figure__" "Figure" "value")
2205 ("__MathFormula__" "Equation" "text")
2206 ("__DvipngImage__" "Equation" "value")
2207 ;; ("__Table__" "Table" "category-and-value")
2208 ;; ("__Figure__" "Figure" "category-and-value")
2209 ;; ("__DvipngImage__" "Equation" "category-and-value")
2211 "Map a CATEGORY-HANDLE to CATEGORY-NAME and LABEL-STYLE.
2212 This is an alist where each element is of the form
2213 \\(CATEGORY-HANDLE CATEGORY-NAME LABEL-STYLE\\). CATEGORY_HANDLE
2214 could either be one of the internal handles (as seen above) or be
2215 derived from the \"#+LABEL:<label-name>\" specification. See
2216 `org-export-e-odt-get-category-from-label'. CATEGORY-NAME and
2217 LABEL-STYLE are used for generating ODT labels. See
2218 `org-e-odt-label-styles'.")
2220 (defvar org-export-e-odt-user-categories
2221 '("Illustration" "Table" "Text" "Drawing" "Equation" "Figure"))
2223 (defvar org-export-e-odt-get-category-from-label nil
2224 "Should category of label be inferred from label itself.
2225 When this option is non-nil, a label is parsed in to two
2226 component parts delimited by a \":\" (colon) as shown here -
2227 #+LABEL:[CATEGORY-HANDLE:]EXTRA. The CATEGORY-HANDLE is mapped
2228 to a CATEGORY-NAME and LABEL-STYLE using
2229 `org-e-odt-category-map-alist'. (If no such map is provided and
2230 CATEGORY-NAME is set to CATEGORY-HANDLE and LABEL-STYLE is set to
2231 \"category-and-value\"). If CATEGORY-NAME so obtained is listed
2232 under `org-export-e-odt-user-categories' then the user specified
2233 styles are used. Otherwise styles as determined by the internal
2234 CATEGORY-HANDLE is used. See
2235 `org-e-odt-get-label-category-and-style' for details.")
2237 (defvar org-e-odt-manifest-file-entries nil
)
2238 (defvar hfy-user-sheet-assoc
) ; bound during org-do-lparse
2239 (defvar org-lparse-latex-fragment-fallback
) ; set by org-do-lparse
2242 ;;;; HTML Internal Variables
2244 (defvar org-e-odt-option-alist
2246 ;; (:agenda-style nil nil org-agenda-export-html-style)
2247 ;; (:convert-org-links nil nil org-e-odt-link-org-files-as-html)
2248 ;; ;; FIXME Use (org-xml-encode-org-text-skip-links s) ??
2249 ;; ;; (:expand-quoted-html nil "@" org-e-odt-expand)
2250 ;; (:inline-images nil nil org-e-odt-inline-images)
2251 ;; ;; (:link-home nil nil org-e-odt-link-home) FIXME
2252 ;; ;; (:link-up nil nil org-e-odt-link-up) FIXME
2253 ;; (:style nil nil org-e-odt-style)
2254 ;; (:style-extra nil nil org-e-odt-style-extra)
2255 ;; (:style-include-default nil nil org-e-odt-style-include-default)
2256 ;; (:style-include-scripts nil nil org-e-odt-style-include-scripts)
2257 ;; ;; (:timestamp nil nil org-e-odt-with-timestamp)
2258 ;; (:html-extension nil nil org-e-odt-extension)
2259 ;; (:html-postamble nil nil org-e-odt-postamble)
2260 ;; (:html-preamble nil nil org-e-odt-preamble)
2261 ;; (:html-table-tag nil nil org-e-odt-table-tag)
2262 ;; (:xml-declaration nil nil org-e-odt-xml-declaration)
2263 (:LaTeX-fragments nil
"LaTeX" org-export-with-LaTeX-fragments
))
2264 "Alist between export properties and ways to set them.
2266 The car of the alist is the property name, and the cdr is a list
2267 like \(KEYWORD OPTION DEFAULT BEHAVIOUR\) where:
2269 KEYWORD is a string representing a buffer keyword, or nil.
2270 OPTION is a string that could be found in an #+OPTIONS: line.
2271 DEFAULT is the default value for the property.
2272 BEHAVIOUR determine how Org should handle multiple keywords for
2273 the same property. It is a symbol among:
2274 nil Keep old value and discard the new one.
2275 t Replace old value with the new one.
2276 `space' Concatenate the values, separating them with a space.
2277 `newline' Concatenate the values, separating them with
2279 `split' Split values at white spaces, and cons them to the
2282 KEYWORD and OPTION have precedence over DEFAULT.
2284 All these properties should be back-end agnostic. For back-end
2285 specific properties, define a similar variable named
2286 `org-BACKEND-option-alist', replacing BACKEND with the name of
2287 the appropriate back-end. You can also redefine properties
2288 there, as they have precedence over these.")
2290 (defvar html-table-tag nil
) ; dynamically scoped into this.
2292 ;; FIXME: it already exists in org-e-odt.el
2293 (defconst org-e-odt-cvt-link-fn
2295 "Function to convert link URLs to exportable URLs.
2296 Takes two arguments, TYPE and PATH.
2297 Returns exportable url as (TYPE PATH), or nil to signal that it
2298 didn't handle this case.
2299 Intended to be locally bound around a call to `org-export-as-html'." )
2304 (defvar org-e-odt-format-table-no-css
)
2305 (defvar htmlize-buffer-places
) ; from htmlize.el
2306 (defvar body-only
) ; dynamically scoped into this.
2308 (defvar org-e-odt-table-rowgrp-open
)
2309 (defvar org-e-odt-table-rownum
)
2310 (defvar org-e-odt-table-cur-rowgrp-is-hdr
)
2311 (defvar org-lparse-table-is-styled
)
2314 (defvar org-e-odt-headline-formatter
2315 (lambda (level snumber todo todo-type priority
2316 title tags target extra-targets extra-class
)
2317 (concat snumber
" " title
)))
2321 ;;; User Configuration Variables
2323 (defgroup org-export-e-odt nil
2324 "Options for exporting Org mode files to HTML."
2325 :tag
"Org Export HTML"
2328 (defcustom org-e-odt-protect-char-alist
2332 "Alist of characters to be converted by `org-e-html-protect'."
2333 :group
'org-export-e-html
2334 :type
'(repeat (cons (string :tag
"Character")
2335 (string :tag
"ODT equivalent"))))
2336 (defcustom org-export-e-odt-schema-dir
2339 (message "Debug (org-e-odt): Searching for OpenDocument schema files...")
2341 (lambda (schema-dir)
2343 (message "Debug (org-e-odt): Trying %s..." schema-dir
)
2344 (when (and (file-readable-p
2345 (expand-file-name "od-manifest-schema-v1.2-cs01.rnc"
2348 (expand-file-name "od-schema-v1.2-cs01.rnc"
2351 (expand-file-name "schemas.xml" schema-dir
)))
2352 (message "Debug (org-e-odt): Using schema files under %s"
2354 (throw 'schema-dir schema-dir
))))
2355 org-e-odt-schema-dir-list
)
2356 (message "Debug (org-e-odt): No OpenDocument schema files installed")
2359 "Directory that contains OpenDocument schema files.
2361 This directory contains:
2362 1. rnc files for OpenDocument schema
2363 2. a \"schemas.xml\" file that specifies locating rules needed
2364 for auto validation of OpenDocument XML files.
2366 Use the customize interface to set this variable. This ensures
2367 that `rng-schema-locating-files' is updated and auto-validation
2368 of OpenDocument XML takes place based on the value
2369 `rng-nxml-auto-validate-flag'.
2371 The default value of this variable varies depending on the
2372 version of org in use and is initialized from
2373 `org-e-odt-schema-dir-list'. The OASIS schema files are available
2374 only in the org's private git repository. It is *not* bundled
2375 with GNU ELPA tar or standard Emacs distribution."
2377 (const :tag
"Not set" nil
)
2378 (directory :tag
"Schema directory"))
2379 :group
'org-export-e-odt
2383 "Set `org-export-e-odt-schema-dir'.
2384 Also add it to `rng-schema-locating-files'."
2385 (let ((schema-dir value
))
2389 (expand-file-name "od-manifest-schema-v1.2-cs01.rnc" schema-dir
))
2391 (expand-file-name "od-schema-v1.2-cs01.rnc" schema-dir
))
2393 (expand-file-name "schemas.xml" schema-dir
)))
2396 (message "Error (org-e-odt): %s has no OpenDocument schema files"
2399 (when org-export-e-odt-schema-dir
2400 (eval-after-load 'rng-loc
2401 '(add-to-list 'rng-schema-locating-files
2402 (expand-file-name "schemas.xml"
2403 org-export-e-odt-schema-dir
))))))
2405 (defcustom org-export-e-odt-content-template-file nil
2406 "Template file for \"content.xml\".
2407 The exporter embeds the exported content just before
2408 \"</office:text>\" element.
2410 If unspecified, the file named \"OrgOdtContentTemplate.xml\"
2411 under `org-e-odt-styles-dir' is used."
2413 :group
'org-export-e-odt
2416 (defcustom org-export-e-odt-styles-file nil
2417 "Default styles file for use with ODT export.
2418 Valid values are one of:
2420 2. path to a styles.xml file
2421 3. path to a *.odt or a *.ott file
2422 4. list of the form (ODT-OR-OTT-FILE (FILE-MEMBER-1 FILE-MEMBER-2
2425 In case of option 1, an in-built styles.xml is used. See
2426 `org-e-odt-styles-dir' for more information.
2428 In case of option 3, the specified file is unzipped and the
2429 styles.xml embedded therein is used.
2431 In case of option 4, the specified ODT-OR-OTT-FILE is unzipped
2432 and FILE-MEMBER-1, FILE-MEMBER-2 etc are copied in to the
2433 generated odt file. Use relative path for specifying the
2434 FILE-MEMBERS. styles.xml must be specified as one of the
2437 Use options 1, 2 or 3 only if styles.xml alone suffices for
2438 achieving the desired formatting. Use option 4, if the styles.xml
2439 references additional files like header and footer images for
2440 achieving the desired formatting.
2442 Use \"#+ODT_STYLES_FILE: ...\" directive to set this variable on
2443 a per-file basis. For example,
2445 #+ODT_STYLES_FILE: \"/path/to/styles.xml\" or
2446 #+ODT_STYLES_FILE: (\"/path/to/file.ott\" (\"styles.xml\" \"image/hdr.png\"))."
2447 :group
'org-export-e-odt
2451 (const :tag
"Factory settings" nil
)
2452 (file :must-match t
:tag
"styles.xml")
2453 (file :must-match t
:tag
"ODT or OTT file")
2454 (list :tag
"ODT or OTT file + Members"
2455 (file :must-match t
:tag
"ODF Text or Text Template file")
2456 (cons :tag
"Members"
2457 (file :tag
" Member" "styles.xml")
2458 (repeat (file :tag
"Member"))))))
2461 (defcustom org-export-e-odt-inline-image-extensions
2462 '("png" "jpeg" "jpg" "gif")
2463 "Extensions of image files that can be inlined into HTML."
2464 :type
'(repeat (string :tag
"Extension"))
2465 :group
'org-export-e-odt
2468 (defcustom org-export-e-odt-pixels-per-inch display-pixels-per-inch
2469 "Scaling factor for converting images pixels to inches.
2470 Use this for sizing of embedded images. See Info node `(org)
2471 Images in ODT export' for more information."
2473 :group
'org-export-e-odt
2476 (defcustom org-export-e-odt-create-custom-styles-for-srcblocks t
2477 "Whether custom styles for colorized source blocks be automatically created.
2478 When this option is turned on, the exporter creates custom styles
2479 for source blocks based on the advice of `htmlfontify'. Creation
2480 of custom styles happen as part of `org-e-odt-hfy-face-to-css'.
2482 When this option is turned off exporter does not create such
2485 Use the latter option if you do not want the custom styles to be
2486 based on your current display settings. It is necessary that the
2487 styles.xml already contains needed styles for colorizing to work.
2489 This variable is effective only if
2490 `org-export-e-odt-fontify-srcblocks' is turned on."
2491 :group
'org-export-e-odt
2495 (defcustom org-export-e-odt-preferred-output-format nil
2496 "Automatically post-process to this format after exporting to \"odt\".
2497 Interactive commands `org-export-as-e-odt' and
2498 `org-export-as-e-odt-and-open' export first to \"odt\" format and
2499 then use `org-export-e-odt-convert-process' to convert the
2500 resulting document to this format. During customization of this
2501 variable, the list of valid values are populated based on
2502 `org-export-e-odt-convert-capabilities'."
2503 :group
'org-export-e-odt
2505 :type
'(choice :convert-widget
2507 (apply 'widget-convert
(widget-type w
)
2508 (eval (car (widget-get w
:args
)))))
2509 `((const :tag
"None" nil
)
2510 ,@(mapcar (lambda (c)
2511 `(const :tag
,c
,c
))
2512 (org-lparse-reachable-formats "odt")))))
2514 (defcustom org-export-e-odt-table-styles
2515 '(("OrgEquation" "OrgEquation"
2516 ((use-first-column-styles . t
)
2517 (use-last-column-styles . t
))))
2518 "Specify how Table Styles should be derived from a Table Template.
2519 This is a list where each element is of the
2520 form (TABLE-STYLE-NAME TABLE-TEMPLATE-NAME TABLE-CELL-OPTIONS).
2522 TABLE-STYLE-NAME is the style associated with the table through
2523 `org-e-odt-table-style'.
2525 TABLE-TEMPLATE-NAME is a set of - upto 9 - automatic
2526 TABLE-CELL-STYLE-NAMEs and PARAGRAPH-STYLE-NAMEs (as defined
2527 below) that is included in
2528 `org-export-e-odt-content-template-file'.
2530 TABLE-CELL-STYLE-NAME := TABLE-TEMPLATE-NAME + TABLE-CELL-TYPE +
2532 PARAGRAPH-STYLE-NAME := TABLE-TEMPLATE-NAME + TABLE-CELL-TYPE +
2534 TABLE-CELL-TYPE := \"FirstRow\" | \"LastColumn\" |
2535 \"FirstRow\" | \"LastRow\" |
2536 \"EvenRow\" | \"OddRow\" |
2537 \"EvenColumn\" | \"OddColumn\" | \"\"
2538 where \"+\" above denotes string concatenation.
2540 TABLE-CELL-OPTIONS is an alist where each element is of the
2541 form (TABLE-CELL-STYLE-SELECTOR . ON-OR-OFF).
2542 TABLE-CELL-STYLE-SELECTOR := `use-first-row-styles' |
2543 `use-last-row-styles' |
2544 `use-first-column-styles' |
2545 `use-last-column-styles' |
2546 `use-banding-rows-styles' |
2547 `use-banding-columns-styles' |
2548 `use-first-row-styles'
2549 ON-OR-OFF := `t' | `nil'
2551 For example, with the following configuration
2553 \(setq org-export-e-odt-table-styles
2554 '\(\(\"TableWithHeaderRowsAndColumns\" \"Custom\"
2555 \(\(use-first-row-styles . t\)
2556 \(use-first-column-styles . t\)\)\)
2557 \(\"TableWithHeaderColumns\" \"Custom\"
2558 \(\(use-first-column-styles . t\)\)\)\)\)
2560 1. A table associated with \"TableWithHeaderRowsAndColumns\"
2561 style will use the following table-cell styles -
2562 \"CustomFirstRowTableCell\", \"CustomFirstColumnTableCell\",
2563 \"CustomTableCell\" and the following paragraph styles
2564 \"CustomFirstRowTableParagraph\",
2565 \"CustomFirstColumnTableParagraph\", \"CustomTableParagraph\"
2568 2. A table associated with \"TableWithHeaderColumns\" style will
2569 use the following table-cell styles -
2570 \"CustomFirstColumnTableCell\", \"CustomTableCell\" and the
2571 following paragraph styles
2572 \"CustomFirstColumnTableParagraph\", \"CustomTableParagraph\"
2575 Note that TABLE-TEMPLATE-NAME corresponds to the
2576 \"<table:table-template>\" elements contained within
2577 \"<office:styles>\". The entries (TABLE-STYLE-NAME
2578 TABLE-TEMPLATE-NAME TABLE-CELL-OPTIONS) correspond to
2579 \"table:template-name\" and \"table:use-first-row-styles\" etc
2580 attributes of \"<table:table>\" element. Refer ODF-1.2
2581 specification for more information. Also consult the
2582 implementation filed under `org-e-odt-get-table-cell-styles'.
2584 The TABLE-STYLE-NAME \"OrgEquation\" is used internally for
2585 formatting of numbered display equations. Do not delete this
2586 style from the list."
2587 :group
'org-export-e-odt
2590 (const :tag
"None" nil
)
2591 (repeat :tag
"Table Styles"
2592 (list :tag
"Table Style Specification"
2593 (string :tag
"Table Style Name")
2594 (string :tag
"Table Template Name")
2595 (alist :options
(use-first-row-styles
2597 use-first-column-styles
2598 use-last-column-styles
2599 use-banding-rows-styles
2600 use-banding-columns-styles
)
2602 :value-type
(const :tag
"True" t
))))))
2603 (defcustom org-export-e-odt-fontify-srcblocks t
2604 "Specify whether or not source blocks need to be fontified.
2605 Turn this option on if you want to colorize the source code
2606 blocks in the exported file. For colorization to work, you need
2607 to make available an enhanced version of `htmlfontify' library."
2609 :group
'org-export-e-odt
2612 (defcustom org-export-e-odt-prettify-xml t
; FIXME
2613 "Specify whether or not the xml output should be prettified.
2614 When this option is turned on, `indent-region' is run on all
2615 component xml buffers before they are saved. Turn this off for
2616 regular use. Turn this on if you need to examine the xml
2618 :group
'org-export-e-odt
2622 (defcustom org-export-e-odt-convert-processes
2624 "soffice --headless --convert-to %f%x --outdir %d %i")
2626 "unoconv -f %f -o %d %i"))
2627 "Specify a list of document converters and their usage.
2628 The converters in this list are offered as choices while
2629 customizing `org-export-e-odt-convert-process'.
2631 This variable is a list where each element is of the
2632 form (CONVERTER-NAME CONVERTER-CMD). CONVERTER-NAME is the name
2633 of the converter. CONVERTER-CMD is the shell command for the
2634 converter and can contain format specifiers. These format
2635 specifiers are interpreted as below:
2637 %i input file name in full
2638 %I input file name as a URL
2639 %f format of the output file
2640 %o output file name in full
2641 %O output file name as a URL
2642 %d output dir in full
2643 %D output dir as a URL.
2644 %x extra options as set in `org-export-e-odt-convert-capabilities'."
2645 :group
'org-export-e-odt
2649 (const :tag
"None" nil
)
2650 (alist :tag
"Converters"
2651 :key-type
(string :tag
"Converter Name")
2652 :value-type
(group (string :tag
"Command line")))))
2654 (defcustom org-export-e-odt-convert-process
"LibreOffice"
2655 "Use this converter to convert from \"odt\" format to other formats.
2656 During customization, the list of converter names are populated
2657 from `org-export-e-odt-convert-processes'."
2658 :group
'org-export-e-odt
2660 :type
'(choice :convert-widget
2662 (apply 'widget-convert
(widget-type w
)
2663 (eval (car (widget-get w
:args
)))))
2664 `((const :tag
"None" nil
)
2665 ,@(mapcar (lambda (c)
2666 `(const :tag
,(car c
) ,(car c
)))
2667 org-export-e-odt-convert-processes
))))
2669 (defcustom org-export-e-odt-convert-capabilities
2671 ("odt" "ott" "doc" "rtf" "docx")
2672 (("pdf" "pdf") ("odt" "odt") ("rtf" "rtf") ("ott" "ott")
2673 ("doc" "doc" ":\"MS Word 97\"") ("docx" "docx") ("html" "html")))
2676 (("pdf" "pdf") ("odt" "odt") ("html" "html")))
2678 ("ods" "ots" "xls" "csv" "xlsx")
2679 (("pdf" "pdf") ("ots" "ots") ("html" "html") ("csv" "csv") ("ods" "ods")
2680 ("xls" "xls") ("xlsx" "xlsx")))
2682 ("odp" "otp" "ppt" "pptx")
2683 (("pdf" "pdf") ("swf" "swf") ("odp" "odp") ("otp" "otp") ("ppt" "ppt")
2684 ("pptx" "pptx") ("odg" "odg"))))
2685 "Specify input and output formats of `org-export-e-odt-convert-process'.
2686 More correctly, specify the set of input and output formats that
2687 the user is actually interested in.
2689 This variable is an alist where each element is of the
2690 form (DOCUMENT-CLASS INPUT-FMT-LIST OUTPUT-FMT-ALIST).
2691 INPUT-FMT-LIST is a list of INPUT-FMTs. OUTPUT-FMT-ALIST is an
2692 alist where each element is of the form (OUTPUT-FMT
2693 OUTPUT-FILE-EXTENSION EXTRA-OPTIONS).
2695 The variable is interpreted as follows:
2696 `org-export-e-odt-convert-process' can take any document that is in
2697 INPUT-FMT-LIST and produce any document that is in the
2698 OUTPUT-FMT-LIST. A document converted to OUTPUT-FMT will have
2699 OUTPUT-FILE-EXTENSION as the file name extension. OUTPUT-FMT
2700 serves dual purposes:
2701 - It is used for populating completion candidates during
2702 `org-export-e-odt-convert' commands.
2703 - It is used as the value of \"%f\" specifier in
2704 `org-export-e-odt-convert-process'.
2706 EXTRA-OPTIONS is used as the value of \"%x\" specifier in
2707 `org-export-e-odt-convert-process'.
2709 DOCUMENT-CLASS is used to group a set of file formats in
2710 INPUT-FMT-LIST in to a single class.
2712 Note that this variable inherently captures how LibreOffice based
2713 converters work. LibreOffice maps documents of various formats
2714 to classes like Text, Web, Spreadsheet, Presentation etc and
2715 allow document of a given class (irrespective of it's source
2716 format) to be converted to any of the export formats associated
2719 See default setting of this variable for an typical
2721 :group
'org-export-e-odt
2725 (const :tag
"None" nil
)
2726 (alist :tag
"Capabilities"
2727 :key-type
(string :tag
"Document Class")
2729 (group (repeat :tag
"Input formats" (string :tag
"Input format"))
2730 (alist :tag
"Output formats"
2731 :key-type
(string :tag
"Output format")
2733 (group (string :tag
"Output file extension")
2735 (const :tag
"None" nil
)
2736 (string :tag
"Extra options"))))))))
2743 ;;;; Document Header (Styles)
2745 ;;;; Document Header (Scripts)
2747 ;;;; Document Header (Mathjax)
2760 ;;;; Statistics Cookie
2780 ;;;; Horizontal Rule
2781 ;;;; Inline Babel Call
2782 ;;;; Inline Src Block
2786 ;;;; Latex Environment
2795 ;;;; Property Drawer
2821 ;;; User Configurable Variables (MAYBE)
2829 (defcustom org-e-odt-format-headline-function nil
2830 "Function to format headline text.
2832 This function will be called with 5 arguments:
2833 TODO the todo keyword \(string or nil\).
2834 TODO-TYPE the type of todo \(symbol: `todo', `done', nil\)
2835 PRIORITY the priority of the headline \(integer or nil\)
2836 TEXT the main headline text \(string\).
2837 TAGS the tags string, separated with colons \(string or nil\).
2839 The function result will be used in the section format string.
2841 As an example, one could set the variable to the following, in
2842 order to reproduce the default set-up:
2844 \(defun org-e-odt-format-headline \(todo todo-type priority text tags\)
2845 \"Default format function for an headline.\"
2846 \(concat \(when todo
2847 \(format \"\\\\textbf{\\\\textsc{\\\\textsf{%s}}} \" todo\)\)
2849 \(format \"\\\\framebox{\\\\#%c} \" priority\)\)
2851 \(when tags \(format \"\\\\hfill{}\\\\textsc{%s}\" tags\)\)\)\)"
2852 :group
'org-export-e-odt
2859 (defcustom org-e-odt-active-timestamp-format
"\\textit{%s}"
2860 "A printf format string to be applied to active time-stamps."
2861 :group
'org-export-e-odt
2864 (defcustom org-e-odt-inactive-timestamp-format
"\\textit{%s}"
2865 "A printf format string to be applied to inactive time-stamps."
2866 :group
'org-export-e-odt
2869 (defcustom org-e-odt-diary-timestamp-format
"\\textit{%s}"
2870 "A printf format string to be applied to diary time-stamps."
2871 :group
'org-export-e-odt
2877 (defcustom org-e-odt-image-default-option
"width=.9\\linewidth"
2878 "Default option for images."
2879 :group
'org-export-e-odt
2882 (defcustom org-e-odt-default-figure-position
"htb"
2883 "Default position for latex figures."
2884 :group
'org-export-e-odt
2887 (defcustom org-e-odt-inline-image-rules
2888 '(("file" .
"\\.\\(pdf\\|jpeg\\|jpg\\|png\\|ps\\|eps\\)\\'"))
2889 "Rules characterizing image files that can be inlined into HTML.
2891 A rule consists in an association whose key is the type of link
2892 to consider, and value is a regexp that will be matched against
2895 Note that, by default, the image extension *actually* allowed
2896 depend on the way the HTML file is processed. When used with
2897 pdflatex, pdf, jpg and png images are OK. When processing
2898 through dvi to Postscript, only ps and eps are allowed. The
2899 default we use here encompasses both."
2900 :group
'org-export-e-odt
2901 :type
'(alist :key-type
(string :tag
"Type")
2902 :value-type
(regexp :tag
"Path")))
2906 (defcustom org-e-odt-table-caption-above t
2907 "When non-nil, place caption string at the beginning of the table.
2908 Otherwise, place it near the end."
2909 :group
'org-export-e-odt
2914 (defcustom org-e-odt-format-drawer-function nil
2915 "Function called to format a drawer in HTML code.
2917 The function must accept two parameters:
2918 NAME the drawer name, like \"LOGBOOK\"
2919 CONTENTS the contents of the drawer.
2921 The function should return the string to be exported.
2923 For example, the variable could be set to the following function
2924 in order to mimic default behaviour:
2926 \(defun org-e-odt-format-drawer-default \(name contents\)
2927 \"Format a drawer element for HTML export.\"
2929 :group
'org-export-e-odt
2935 (defcustom org-e-odt-format-inlinetask-function nil
2936 "Function called to format an inlinetask in HTML code.
2938 The function must accept six parameters:
2939 TODO the todo keyword, as a string
2940 TODO-TYPE the todo type, a symbol among `todo', `done' and nil.
2941 PRIORITY the inlinetask priority, as a string
2942 NAME the inlinetask name, as a string.
2943 TAGS the inlinetask tags, as a string.
2944 CONTENTS the contents of the inlinetask, as a string.
2946 The function should return the string to be exported.
2948 For example, the variable could be set to the following function
2949 in order to mimic default behaviour:
2951 \(defun org-e-odt-format-inlinetask \(todo type priority name tags contents\)
2952 \"Format an inline task element for HTML export.\"
2953 \(let \(\(full-title
2956 \(format \"\\\\textbf{\\\\textsf{\\\\textsc{%s}}} \" todo\)\)
2957 \(when priority \(format \"\\\\framebox{\\\\#%c} \" priority\)\)
2959 \(when tags \(format \"\\\\hfill{}\\\\textsc{%s}\" tags\)\)\)\)\)
2960 \(format \(concat \"\\\\begin{center}\\n\"
2962 \"\\\\begin{minipage}[c]{.6\\\\textwidth}\\n\"
2964 \"\\\\rule[.8em]{\\\\textwidth}{2pt}\\n\\n\"
2966 \"\\\\end{minipage}}\"
2967 \"\\\\end{center}\"\)
2968 full-title contents\)\)"
2969 :group
'org-export-e-odt
2977 (defcustom org-e-odt-quotes
2978 '(("fr" ("\\(\\s-\\|[[(]\\)\"" .
"«~") ("\\(\\S-\\)\"" .
"~»") ("\\(\\s-\\|(\\)'" .
"'"))
2979 ("en" ("\\(\\s-\\|[[(]\\)\"" .
"``") ("\\(\\S-\\)\"" .
"''") ("\\(\\s-\\|(\\)'" .
"`")))
2980 "Alist for quotes to use when converting english double-quotes.
2982 The CAR of each item in this alist is the language code.
2983 The CDR of each item in this alist is a list of three CONS:
2984 - the first CONS defines the opening quote;
2985 - the second CONS defines the closing quote;
2986 - the last CONS defines single quotes.
2988 For each item in a CONS, the first string is a regexp
2989 for allowed characters before/after the quote, the second
2990 string defines the replacement string for this quote."
2991 :group
'org-export-e-odt
2993 (cons :tag
"Opening quote"
2994 (string :tag
"Regexp for char before")
2995 (string :tag
"Replacement quote "))
2996 (cons :tag
"Closing quote"
2997 (string :tag
"Regexp for char after ")
2998 (string :tag
"Replacement quote "))
2999 (cons :tag
"Single quote"
3000 (string :tag
"Regexp for char before")
3001 (string :tag
"Replacement quote "))))
3008 ;;; Internal Functions (HTML)
3010 ;; (defun org-e-odt-format-inline-image (path &optional caption label attr)
3011 ;; ;; FIXME: alt text missing here?
3012 ;; (let ((inline-image (format "<img src=\"%s\" alt=\"%s\"/>"
3013 ;; path (file-name-nondirectory path))))
3014 ;; (if (not label) inline-image
3015 ;; (org-e-odt-format-section inline-image "figure" label))))
3017 (defun org-e-odt-format-image (src)
3018 "Create image tag with source and attributes."
3020 (let* ((caption (org-find-text-property-in-string 'org-caption src
))
3021 (attr (org-find-text-property-in-string 'org-attributes src
))
3022 (label (org-find-text-property-in-string 'org-label src
))
3023 (caption (and caption
(org-xml-encode-org-text caption
)))
3024 (img-extras (if (string-match "^ltxpng/" src
)
3025 (format " alt=\"%s\""
3026 (org-find-text-property-in-string
3027 'org-latex-src src
))
3028 (if (string-match "\\<alt=" (or attr
""))
3030 (concat " " attr
" alt=\"" src
"\""))))
3031 (img (format "<img src=\"%s\"%s />" src img-extras
))
3034 (format "id=\"%s\" " (org-solidify-link-text label
)))
3035 "class=\"figure\"")))
3038 (with-org-lparse-preserve-paragraph-state
3041 '("<div %s>" .
"\n</div>")
3043 (org-lparse-format '("\n<p>" .
"</p>") img
)
3044 (org-lparse-format '("\n<p>" .
"</p>") caption
))
3051 (defun org-e-odt-bibliography ()
3052 "Find bibliography, cut it out and return it."
3054 (let (beg end
(cnt 1) bib
)
3056 (goto-char (point-min))
3057 (when (re-search-forward
3058 "^[ \t]*<div \\(id\\|class\\)=\"bibliography\"" nil t
)
3059 (setq beg
(match-beginning 0))
3060 (while (re-search-forward "</?div\\>" nil t
)
3061 (setq cnt
(+ cnt
(if (string= (match-string 0) "<div") +1 -
1)))
3063 (and (looking-at ">") (forward-char 1))
3064 (setq bib
(buffer-substring beg
(point)))
3065 (delete-region beg
(point))
3066 (throw 'exit bib
))))
3071 (defun org-e-odt-format-table (lines olines
)
3072 (let ((org-e-odt-format-table-no-css nil
))
3073 (org-lparse-format-table lines olines
)))
3075 (defun org-e-odt-splice-attributes (tag attributes
)
3076 "Read attributes in string ATTRIBUTES, add and replace in HTML tag TAG."
3077 (if (not attributes
)
3079 (let (oldatt newatt
)
3080 (setq oldatt
(org-extract-attributes-from-string tag
)
3082 newatt
(cdr (org-extract-attributes-from-string attributes
)))
3084 (setq oldatt
(plist-put oldatt
(pop newatt
) (pop newatt
))))
3085 (if (string-match ">" tag
)
3087 (replace-match (concat (org-attributes-to-string oldatt
) ">")
3091 (defun org-export-splice-style (style extra
)
3092 "Splice EXTRA into STYLE, just before \"</style>\"."
3093 (if (and (stringp extra
)
3094 (string-match "\\S-" extra
)
3095 (string-match "</style>" style
))
3096 (concat (substring style
0 (match-beginning 0))
3098 (substring style
(match-beginning 0)))
3101 ;; (defun org-e-odt-format-toc-entry (snumber todo headline tags href)
3102 ;; (setq headline (concat
3103 ;; ;; section number
3104 ;; (and org-export-with-section-numbers (concat snumber " "))
3108 ;; (and tags (concat
3109 ;; (org-e-odt-format-spaces 3)
3110 ;; (org-e-odt-format-fontify tags "tag")))))
3111 ;; ;; fontify headline based on TODO keyword
3112 ;; (when todo (setq headline (org-e-odt-format-fontify headline "todo")))
3113 ;; (org-e-odt-format-link headline (concat "#" href)))
3115 (defun org-e-odt-toc-entry-formatter
3116 (level snumber todo todo-type priority
3117 headline tags target extra-targets extra-class
)
3118 (org-e-odt-format-toc-entry snumber todo headline tags target
))
3120 (defun org-e-odt-make-string (n string
)
3121 (let (out) (dotimes (i n out
) (setq out
(concat string out
)))))
3123 (defun org-e-odt-toc-text (toc-entries)
3124 (let* ((prev-level (1- (nth 1 (car toc-entries
))))
3125 (start-level prev-level
))
3128 (let ((headline (nth 0 entry
))
3129 (level (nth 1 entry
)))
3130 (prog1 (org-e-odt-format-toc-item headline level prev-level
)
3131 (setq prev-level level
))))
3134 (defun org-e-odt-toc (depth info
)
3135 (assert (wholenump depth
))
3136 (let* ((headlines (org-export-collect-headlines info depth
))
3138 (loop for headline in headlines collect
3139 (list (org-e-odt-headline-text
3140 headline info
'org-e-odt-toc-entry-formatter
)
3141 (org-export-get-relative-level headline info
)))))
3143 (let* ((lang-specific-heading "Table of Contents")) ; FIXME
3145 (org-e-odt-begin-toc lang-specific-heading depth
)
3146 (org-e-odt-toc-text toc-entries
)
3147 (org-e-odt-end-toc))))))
3149 (defun org-e-odt-begin-outline (level1 snumber title tags
3150 target extra-targets extra-class
)
3151 (let* ((class (format "outline-%d" level1
))
3152 (class (if extra-class
(concat class
" " extra-class
) class
))
3153 (id (format "outline-container-%s"
3154 (org-lparse-suffix-from-snumber snumber
)))
3155 (extra (concat (when id
(format " id=\"%s\"" id
))
3156 (when class
(format " class=\"%s\"" class
)))))
3157 (org-lparse-insert-tag "<div%s>" extra
)
3159 (org-lparse-format 'HEADING
3161 'HEADLINE title extra-targets tags snumber level1
)
3164 (defun org-e-odt-end-outline ()
3165 (org-lparse-insert-tag "</div>"))
3167 (defun org-e-odt-suffix-from-snumber (snumber)
3168 (let* ((snu (replace-regexp-in-string "\\." "-" snumber
))
3169 (href (cdr (assoc (concat "sec-" snu
)
3170 org-export-preferred-target-alist
))))
3171 (org-solidify-link-text (or href snu
))))
3173 (defun org-e-odt-format-outline (contents level1 snumber title
3174 tags target extra-targets extra-class
)
3176 (org-e-odt-format-heading
3177 (org-e-odt-format-headline title extra-targets tags snumber level1
)
3181 ;; (defun org-e-odt-format-line (line)
3182 ;; (case org-lparse-dyn-current-environment
3183 ;; ((quote fixedwidth) (concat (org-e-odt-encode-plain-text line) "\n"))
3184 ;; (t (concat line "\n"))))
3186 (defun org-e-odt-fix-class-name (kwd) ; audit callers of this function
3187 "Turn todo keyword into a valid class name.
3188 Replaces invalid characters with \"_\"."
3190 (while (string-match "[^a-zA-Z0-9_]" kwd
)
3191 (setq kwd
(replace-match "_" t t kwd
))))
3194 (defun org-e-odt-format-internal-link (text href
&optional extra
)
3195 (org-e-odt-format-link text
(concat "#" href
) extra
))
3197 (defun org-e-odt-format-extra-targets (extra-targets)
3198 (if (not extra-targets
) ""
3199 (mapconcat (lambda (x)
3201 (setq x
(org-solidify-link-text
3202 (if (org-uuidgen-p x
) (concat "ID-" x
) x
)))
3203 (org-e-odt-format-anchor "" x
))) extra-targets
"")))
3205 (defun org-e-odt-format-org-tags (tags)
3207 (org-e-odt-format-fontify
3210 (org-e-odt-format-fontify
3211 x
(concat "" ;; org-e-odt-tag-class-prefix
3212 (org-e-odt-fix-class-name x
))))
3213 (org-split-string tags
":")
3214 (org-e-odt-format-spaces 1)) "tag")))
3216 (defun org-e-odt-format-section-number (&optional snumber level
)
3218 (and nil org-export-with-section-numbers
3219 ;; (not org-lparse-body-only)
3221 (org-e-odt-format-fontify snumber
(format "section-number-%d" level
))))
3223 ;; (defun org-e-odt-format-headline (title extra-targets tags
3224 ;; &optional snumber level)
3226 ;; (org-e-odt-format-extra-targets extra-targets)
3227 ;; (concat (org-e-odt-format-section-number snumber level) " ")
3229 ;; (and tags (concat (org-e-odt-format-spaces 3)
3230 ;; (org-e-odt-format-org-tags tags)))))
3232 (defun org-e-odt-get-coding-system-for-write ()
3233 (or org-e-odt-coding-system
3234 (and (boundp 'buffer-file-coding-system
) buffer-file-coding-system
)))
3236 (defun org-e-odt-get-coding-system-for-save ()
3237 (or org-e-odt-coding-system
3238 (and (boundp 'buffer-file-coding-system
) buffer-file-coding-system
)))
3240 ;; (defun org-e-odt-format-date (info)
3241 ;; (let ((date (plist-get info :date)))
3243 ;; ((and date (string-match "%" date))
3244 ;; (format-time-string date))
3246 ;; (t (format-time-string "%Y-%m-%d %T %Z")))))
3250 ;;; Internal Functions (Ngz)
3252 (defun org-e-odt--caption/label-string
(caption label info
)
3253 "Return caption and label HTML string for floats.
3255 CAPTION is a cons cell of secondary strings, the car being the
3256 standard caption and the cdr its short form. LABEL is a string
3257 representing the label. INFO is a plist holding contextual
3260 If there's no caption nor label, return the empty string.
3262 For non-floats, see `org-e-odt--wrap-label'."
3263 (setq label nil
) ;; FIXME
3265 (let ((label-str (if label
(format "\\label{%s}" label
) "")))
3267 ((and (not caption
) (not label
)) "")
3268 ((not caption
) (format "\\label{%s}\n" label
))
3269 ;; Option caption format with short name.
3271 (format "\\caption[%s]{%s%s}\n"
3272 (org-export-secondary-string (cdr caption
) 'e-odt info
)
3274 (org-export-secondary-string (car caption
) 'e-odt info
)))
3275 ;; Standard caption format.
3276 ;; (t (format "\\caption{%s%s}\n"
3278 ;; (org-export-secondary-string (car caption) 'e-odt info)))
3280 (t (org-export-secondary-string (car caption
) 'e-odt info
)))))
3282 (defun org-e-odt--find-verb-separator (s)
3283 "Return a character not used in string S.
3284 This is used to choose a separator for constructs like \\verb."
3285 (let ((ll "~,./?;':\"|!@#%^&-_=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<>()[]{}"))
3286 (loop for c across ll
3287 when
(not (string-match (regexp-quote (char-to-string c
)) s
))
3288 return
(char-to-string c
))))
3290 (defun org-e-odt--make-option-string (options)
3291 "Return a comma separated string of keywords and values.
3292 OPTIONS is an alist where the key is the options keyword as
3293 a string, and the value a list containing the keyword value, or
3295 (mapconcat (lambda (pair)
3296 (concat (first pair
)
3297 (when (> (length (second pair
)) 0)
3298 (concat "=" (second pair
)))))
3302 (defun org-e-odt--quotation-marks (text info
)
3303 "Export quotation marks depending on language conventions.
3304 TEXT is a string containing quotation marks to be replaced. INFO
3305 is a plist used as a communication channel."
3308 (while (setq start
(string-match (car l
) text start
))
3309 (let ((new-quote (concat (match-string 1 text
) (cdr l
))))
3310 (setq text
(replace-match new-quote t t text
))))))
3311 (cdr (or (assoc (plist-get info
:language
) org-e-odt-quotes
)
3312 ;; Falls back on English.
3313 (assoc "en" org-e-odt-quotes
))))
3316 (defun org-e-odt--wrap-label (element output
)
3317 "Wrap label associated to ELEMENT around OUTPUT, if appropriate.
3318 This function shouldn't be used for floats. See
3319 `org-e-odt--caption/label-string'."
3320 ;; (let ((label (org-element-property :name element)))
3321 ;; (if (or (not output) (not label) (string= output "") (string= label ""))
3323 ;; (concat (format "\\label{%s}\n" label) output)))
3330 (defun org-e-odt-template (contents info
)
3331 "Return complete document string after HTML conversion.
3332 CONTENTS is the transcoded contents string. RAW-DATA is the
3333 original parsed data. INFO is a plist holding export options."
3337 (org-e-odt-update-meta-file info
)
3341 (insert-file-contents
3342 (or org-export-e-odt-content-template-file
3343 (expand-file-name "OrgOdtContentTemplate.xml"
3344 org-e-odt-styles-dir
)))
3345 (goto-char (point-min))
3346 (re-search-forward "</office:text>" nil nil
)
3347 (goto-char (match-beginning 0))
3350 (insert (org-e-odt-format-preamble info
))
3351 ;; Table of Contents
3352 (let ((depth (plist-get info
:with-toc
)))
3353 (when (wholenump depth
) (org-e-odt-toc depth info
)))
3357 (buffer-substring-no-properties (point-min) (point-max))))
3361 ;;; Transcode Functions
3365 (defun org-e-odt-center-block (center-block contents info
)
3366 "Transcode a CENTER-BLOCK element from Org to HTML.
3367 CONTENTS holds the contents of the block. INFO is a plist
3368 holding contextual information."
3369 (org-e-odt--wrap-label center-block contents
))
3374 ;; Comments are ignored.
3379 ;; Comment Blocks are ignored.
3384 (defun org-e-odt-drawer (drawer contents info
)
3385 "Transcode a DRAWER element from Org to HTML.
3386 CONTENTS holds the contents of the block. INFO is a plist
3387 holding contextual information."
3388 (let* ((name (org-element-property :drawer-name drawer
))
3389 (output (if (functionp org-e-odt-format-drawer-function
)
3390 (funcall org-e-odt-format-drawer-function
3392 ;; If there's no user defined function: simply
3393 ;; display contents of the drawer.
3395 (org-e-odt--wrap-label drawer output
)))
3400 (defun org-e-odt-dynamic-block (dynamic-block contents info
)
3401 "Transcode a DYNAMIC-BLOCK element from Org to HTML.
3402 CONTENTS holds the contents of the block. INFO is a plist
3403 holding contextual information. See
3405 (org-e-odt--wrap-label dynamic-block contents
))
3410 (defun org-e-odt-emphasis (emphasis contents info
)
3411 "Transcode EMPHASIS from Org to HTML.
3412 CONTENTS is the contents of the emphasized text. INFO is a plist
3413 holding contextual information.."
3414 ;; (format (cdr (assoc (org-element-property :marker emphasis)
3415 ;; org-e-odt-emphasis-alist))
3417 (org-e-odt-format-fontify
3418 contents
(cadr (assoc
3419 (org-element-property :marker emphasis
)
3430 (defun org-e-odt-entity (entity contents info
)
3431 "Transcode an ENTITY object from Org to HTML.
3432 CONTENTS are the definition itself. INFO is a plist holding
3433 contextual information."
3434 ;; (let ((ent (org-element-property :latex entity)))
3435 ;; (if (org-element-property :latex-math-p entity)
3436 ;; (format "$%s$" ent)
3438 (org-element-property :utf-8 entity
))
3443 (defun org-e-odt-example-block (example-block contents info
)
3444 "Transcode a EXAMPLE-BLOCK element from Org to HTML.
3445 CONTENTS is nil. INFO is a plist holding contextual information."
3446 (let* ((options (or (org-element-property :options example-block
) ""))
3447 (value (org-export-handle-code example-block info nil nil t
)))
3448 (org-e-odt--wrap-label
3449 example-block
(org-e-odt-format-source-code-or-example value nil
))))
3454 (defun org-e-odt-export-snippet (export-snippet contents info
)
3455 "Transcode a EXPORT-SNIPPET object from Org to HTML.
3456 CONTENTS is nil. INFO is a plist holding contextual information."
3457 (when (eq (org-export-snippet-backend export-snippet
) 'e-odt
)
3458 (org-element-property :value export-snippet
)))
3463 (defun org-e-odt-export-block (export-block contents info
)
3464 "Transcode a EXPORT-BLOCK element from Org to HTML.
3465 CONTENTS is nil. INFO is a plist holding contextual information."
3466 (when (string= (org-element-property :type export-block
) "latex")
3467 (org-remove-indentation (org-element-property :value export-block
))))
3472 (defun org-e-odt-fixed-width (fixed-width contents info
)
3473 "Transcode a FIXED-WIDTH element from Org to HTML.
3474 CONTENTS is nil. INFO is a plist holding contextual information."
3475 (let* ((value (org-element-normalize-string
3476 (replace-regexp-in-string
3478 (org-element-property :value fixed-width
)))))
3479 (org-e-odt--wrap-label
3480 fixed-width
(org-e-odt-format-source-code-or-example value nil
))))
3483 ;;;; Footnote Definition
3485 ;; Footnote Definitions are ignored.
3488 ;;;; Footnote Reference
3490 (defun org-e-odt-footnote-def (raw info
) ; FIXME
3491 (if (equal (org-element-type raw
) 'org-data
)
3492 (org-trim (org-export-data raw
'e-odt info
)) ; fix paragraph
3494 (org-odt-format-stylized-paragraph
3495 'footnote
(org-trim (org-export-secondary-string raw
'e-odt info
)))))
3497 (defvar org-e-odt-footnote-separator
3498 (org-e-odt-format-fontify "," 'superscript
))
3500 (defun org-e-odt-footnote-reference (footnote-reference contents info
)
3501 "Transcode a FOOTNOTE-REFERENCE element from Org to HTML.
3502 CONTENTS is nil. INFO is a plist holding contextual information."
3504 ;; Insert separator between two footnotes in a row.
3505 (let ((prev (org-export-get-previous-element footnote-reference info
)))
3506 (when (eq (org-element-type prev
) 'footnote-reference
)
3507 org-e-odt-footnote-separator
))
3509 ((not (org-export-footnote-first-reference-p footnote-reference info
))
3510 (let* ((n (org-export-get-footnote-number footnote-reference info
)))
3511 (org-e-odt-format-footnote-reference n
"IGNORED" 100)))
3512 ;; Inline definitions are secondary strings.
3513 ((eq (org-element-property :type footnote-reference
) 'inline
)
3514 (let* ((raw (org-export-get-footnote-definition footnote-reference info
))
3515 (n (org-export-get-footnote-number footnote-reference info
))
3516 (def (org-e-odt-footnote-def raw info
)))
3517 (org-e-odt-format-footnote-reference n def
1)))
3518 ;; Non-inline footnotes definitions are full Org data.
3520 (let* ((raw (org-export-get-footnote-definition footnote-reference info
))
3521 (n (org-export-get-footnote-number footnote-reference info
))
3522 (def (org-e-odt-footnote-def raw info
)))
3523 (org-e-odt-format-footnote-reference n def
1))))))
3528 (defun org-e-odt-todo (todo)
3530 (org-e-odt-format-fontify
3532 "" ; org-e-odt-todo-kwd-class-prefix
3533 (org-e-odt-fix-class-name todo
))
3534 (list (if (member todo org-done-keywords
) "done" "todo")
3537 (defun org-e-odt-headline-text (headline info
&optional formatter
)
3538 "Transcode an HEADLINE element from Org to HTML.
3539 CONTENTS holds the contents of the headline. INFO is a plist
3540 holding contextual information."
3541 (let* ((numberedp (org-export-numbered-headline-p headline info
))
3542 (level (org-export-get-relative-level headline info
))
3543 (todo (and (plist-get info
:with-todo-keywords
)
3544 (let ((todo (org-element-property
3545 :todo-keyword headline
)))
3547 (org-export-secondary-string todo
'e-odt info
)))))
3548 (todo-type (and todo
(org-element-property :todo-type headline
)))
3549 (priority (and (plist-get info
:with-priority
)
3550 (org-element-property :priority headline
)))
3551 (text (org-export-secondary-string
3552 (org-element-property :title headline
) 'e-odt info
))
3553 (tags (and (plist-get info
:with-tags
)
3554 (org-element-property :tags headline
)))
3556 (headline-no (org-export-get-headline-number headline info
))
3558 (format "sec-%s" (mapconcat 'number-to-string headline-no
"-")))
3559 (headline-labels (list headline-label
))
3560 (headline-no (org-export-get-headline-number headline info
))
3561 (section-no (mapconcat 'number-to-string headline-no
"."))
3562 (primary-target (car (last headline-labels
)))
3563 (secondary-targets (butlast headline-labels
))
3565 (formatter (or (and (functionp formatter
) formatter
)
3566 org-e-odt-headline-formatter
)))
3567 (funcall formatter level section-no todo todo-type priority
3568 text tags primary-target secondary-targets extra-class
)))
3570 (defun org-e-odt-headline (headline contents info
)
3571 "Transcode an HEADLINE element from Org to HTML.
3572 CONTENTS holds the contents of the headline. INFO is a plist
3573 holding contextual information."
3574 (let* ((class (plist-get info
:latex-class
))
3575 (numberedp (org-export-numbered-headline-p headline info
))
3576 ;; Get level relative to current parsed data.
3577 (level (org-export-get-relative-level headline info
))
3578 ;; (class-sectionning (assoc class org-e-odt-classes))
3579 ;; Section formatting will set two placeholders: one for the
3580 ;; title and the other for the contents.
3582 ;; (let ((sec (if (and (symbolp (nth 2 class-sectionning))
3583 ;; (fboundp (nth 2 class-sectionning)))
3584 ;; (funcall (nth 2 class-sectionning) level numberedp)
3585 ;; (nth (1+ level) class-sectionning))))
3587 ;; ;; No section available for that LEVEL.
3589 ;; ;; Section format directly returned by a function.
3590 ;; ((stringp sec) sec)
3591 ;; ;; (numbered-section . unnumbered-section)
3592 ;; ((not (consp (cdr sec)))
3593 ;; (concat (funcall (if numberedp #'car #'cdr) sec) "\n%s"))
3594 ;; ;; (numbered-open numbered-close)
3595 ;; ((= (length sec) 2)
3596 ;; (when numberedp (concat (car sec) "\n%s" (nth 1 sec))))
3597 ;; ;; (num-in num-out no-num-in no-num-out)
3598 ;; ((= (length sec) 4)
3600 ;; (concat (car sec) "\n%s" (nth 1 sec))
3601 ;; (concat (nth 2 sec) "\n%s" (nth 3 sec)))))))
3602 (text (org-export-secondary-string
3603 (org-element-property :title headline
) 'e-odt info
))
3604 (todo (and (plist-get info
:with-todo-keywords
)
3605 (let ((todo (org-element-property
3606 :todo-keyword headline
)))
3608 (org-export-secondary-string todo
'e-odt info
)))))
3609 (todo-type (and todo
(org-element-property :todo-type headline
)))
3610 (tags (and (plist-get info
:with-tags
)
3611 (org-element-property :tags headline
)))
3612 (priority (and (plist-get info
:with-priority
)
3613 (org-element-property :priority headline
)))
3614 ;; Create the headline text.
3615 (full-text (if (functionp org-e-odt-format-headline-function
)
3616 ;; User-defined formatting function.
3617 (funcall org-e-odt-format-headline-function
3618 todo todo-type priority text tags
)
3619 ;; Default formatting.
3622 ;; (format "\\textbf{\\textsf{\\textsc{%s}}} " todo))
3623 (org-e-odt-todo todo
) " "
3624 (when priority
(format "\\framebox{\\#%c} " priority
))
3626 ;; (when tags (format "\\hfill{}\\textsc{%s}" tags))
3628 ;; Associate some \label to the headline for internal links.
3630 ;; (format "\\label{sec-%s}\n"
3631 ;; (mapconcat 'number-to-string
3632 ;; (org-export-get-headline-number headline info)
3636 (headline-no (org-export-get-headline-number headline info
))
3638 (format "sec-%s" (mapconcat 'number-to-string headline-no
"-")))
3639 (headline-labels (list headline-label
))
3640 (headline-no (org-export-get-headline-number headline info
))
3641 (section-no (mapconcat 'number-to-string headline-no
"."))
3644 (pre-blanks (make-string
3645 (org-element-property :pre-blank headline
) 10)))
3647 ;; Case 1: This is a footnote section: ignore it.
3648 ((org-element-property :footnote-section-p headline
) nil
)
3649 ;; Case 2. This is a deep sub-tree: export it as a list item.
3650 ;; Also export as items headlines for which no section
3651 ;; format has been found.
3652 ((org-export-low-level-p headline info
) ; FIXME (or (not section-fmt))
3653 ;; Build the real contents of the sub-tree.
3654 (let* ((type (if numberedp
'unordered
'unordered
)) ; FIXME
3655 (itemized-body (org-e-odt-format-list-item
3656 contents type nil nil full-text
)))
3658 (and (org-export-first-sibling-p headline info
)
3659 (org-e-odt-begin-plain-list type
))
3661 (and (org-export-last-sibling-p headline info
)
3662 (org-e-odt-end-plain-list type
)))))
3663 ;; Case 3. Standard headline. Export it as a section.
3665 ;; (format section-fmt full-text
3666 ;; (concat headline-label pre-blanks contents))
3668 (org-e-odt-format-outline contents level section-no full-text tags
3669 (car (last headline-labels
))
3670 (butlast headline-labels
) nil
)))))
3673 ;;;; Horizontal Rule
3675 (defun org-e-odt-horizontal-rule (horizontal-rule contents info
)
3676 "Transcode an HORIZONTAL-RULE object from Org to HTML.
3677 CONTENTS is nil. INFO is a plist holding contextual information."
3678 (let ((attr (mapconcat #'identity
3679 (org-element-property :attr_odt horizontal-rule
)
3681 (org-e-odt--wrap-label horizontal-rule
3682 (org-e-odt-format-horizontal-line))))
3685 ;;;; Inline Babel Call
3687 ;; Inline Babel Calls are ignored.
3690 ;;;; Inline Src Block
3692 (defun org-e-odt-inline-src-block (inline-src-block contents info
)
3693 "Transcode an INLINE-SRC-BLOCK element from Org to HTML.
3694 CONTENTS holds the contents of the item. INFO is a plist holding
3695 contextual information."
3696 (let* ((org-lang (org-element-property :language inline-src-block
))
3697 (code (org-element-property :value inline-src-block
))
3698 (separator (org-e-odt--find-verb-separator code
)))
3704 (defun org-e-odt-format-section (text class
&optional id
)
3705 (let ((extra (concat (when id
(format " id=\"%s\"" id
)))))
3706 (concat (format "<div class=\"%s\"%s>\n" class extra
) text
"</div>\n")))
3708 (defun org-e-odt-inlinetask (inlinetask contents info
)
3709 "Transcode an INLINETASK element from Org to HTML.
3710 CONTENTS holds the contents of the block. INFO is a plist
3711 holding contextual information."
3712 (let ((title (org-export-secondary-string
3713 (org-element-property :title inlinetask
) 'e-odt info
))
3714 (todo (and (plist-get info
:with-todo-keywords
)
3715 (let ((todo (org-element-property
3716 :todo-keyword inlinetask
)))
3718 (org-export-secondary-string todo
'e-odt info
)))))
3719 (todo-type (org-element-property :todo-type inlinetask
))
3720 (tags (and (plist-get info
:with-tags
)
3721 (org-element-property :tags inlinetask
)))
3722 (priority (and (plist-get info
:with-priority
)
3723 (org-element-property :priority inlinetask
))))
3724 ;; If `org-e-odt-format-inlinetask-function' is provided, call it
3725 ;; with appropriate arguments.
3726 (if (functionp org-e-odt-format-inlinetask-function
)
3727 (funcall org-e-odt-format-inlinetask-function
3728 todo todo-type priority title tags contents
)
3729 ;; Otherwise, use a default template.
3730 (org-e-odt--wrap-label
3734 (when todo
(format "\\textbf{\\textsf{\\textsc{%s}}} " todo
))
3735 (when priority
(format "\\framebox{\\#%c} " priority
))
3737 (when tags
(format "\\hfill{}\\textsc{%s}" tags
)))))
3738 (format (concat "\\begin{center}\n"
3740 "\\begin{minipage}[c]{.6\\textwidth}\n"
3742 "\\rule[.8em]{\\textwidth}{2pt}\n\n"
3747 full-title contents
))))))
3752 (defun org-e-odt-format-list-item (contents type checkbox
3753 &optional term-counter-id
3757 (org-e-odt-format-fontify (case checkbox
3760 (trans "[-]")) 'code
)))
3762 (org-e-odt-begin-list-item type term-counter-id headline
)
3763 ;; FIXME checkbox (and checkbox " ")
3765 (org-e-odt-end-list-item type
)))
3767 (defun org-e-odt-item (item contents info
)
3768 "Transcode an ITEM element from Org to HTML.
3769 CONTENTS holds the contents of the item. INFO is a plist holding
3770 contextual information."
3771 ;; Grab `:level' from plain-list properties, which is always the
3772 ;; first element above current item.
3773 (let* ((plain-list (org-export-get-parent item info
))
3774 (type (org-element-property :type plain-list
))
3775 (level (org-element-property :level plain-list
))
3776 (counter (org-element-property :counter item
))
3777 (checkbox (org-element-property :checkbox item
))
3778 (tag (let ((tag (org-element-property :tag item
)))
3779 (and tag
(org-export-secondary-string tag
'e-odt info
)))))
3780 (org-e-odt-format-list-item
3781 contents type checkbox
(or tag counter
))))
3786 (defun org-e-odt-keyword (keyword contents info
)
3787 "Transcode a KEYWORD element from Org to HTML.
3788 CONTENTS is nil. INFO is a plist holding contextual information."
3789 (let ((key (downcase (org-element-property :key keyword
)))
3790 (value (org-element-property :value keyword
)))
3792 ((string= key
"latex") value
)
3793 ((string= key
"index") (format "\\index{%s}" value
))
3794 ((string= key
"target") nil
; FIXME
3795 ;; (format "\\label{%s}" (org-export-solidify-link-text value))
3797 ((string= key
"toc")
3798 (let ((value (downcase value
)))
3800 ((string-match "\\<headlines\\>" value
)
3801 (let ((depth (or (and (string-match "[0-9]+" value
)
3802 (string-to-number (match-string 0 value
)))
3803 (plist-get info
:with-toc
))))
3804 (when (wholenump depth
) (org-e-odt-toc depth info
))))
3805 ((string= "tables" value
) "FIXME")
3806 ((string= "figures" value
) "FIXME")
3807 ((string= "listings" value
)
3809 ;; At the moment, src blocks with a caption are wrapped
3810 ;; into a figure environment.
3814 ;;;; Latex Environment
3816 (defun org-e-odt-format-latex (latex-frag processing-type
)
3817 (let* ((prefix (case processing-type
3819 (mathml "ltxmathml/")))
3821 (concat prefix
(file-name-sans-extension
3822 (file-name-nondirectory (buffer-file-name)))))
3823 (cache-dir (file-name-directory (buffer-file-name )))
3824 (display-msg (case processing-type
3825 (dvipng "Creating LaTeX Image...")
3826 (mathml "Creating MathML snippet..."))))
3829 (org-format-latex cache-relpath cache-dir nil display-msg
3830 nil nil processing-type
)
3833 (defun org-e-odt-latex-environment (latex-environment contents info
)
3834 "Transcode a LATEX-ENVIRONMENT element from Org to HTML.
3835 CONTENTS is nil. INFO is a plist holding contextual information."
3836 (org-e-odt--wrap-label
3839 (org-remove-indentation
3840 (org-element-property :value latex-environment
)))
3841 (processing-type (plist-get info
:LaTeX-fragments
)))
3843 ((member processing-type
'(t mathjax
))
3844 (org-e-odt-format-latex latex-frag
'mathml
))
3845 ((equal processing-type
'dvipng
)
3846 (let* ((formula-link (org-e-odt-format-latex
3847 latex-frag processing-type
)))
3848 (when (and formula-link
3849 (string-match "file:\\([^]]*\\)" formula-link
))
3850 (org-e-odt-format-inline-image (match-string 1 formula-link
)))))
3857 (defun org-e-odt-latex-fragment (latex-fragment contents info
)
3858 "Transcode a LATEX-FRAGMENT object from Org to HTML.
3859 CONTENTS is nil. INFO is a plist holding contextual information."
3860 ;; (org-element-property :value latex-fragment)
3861 (let* ((latex-frag (org-element-property :value latex-fragment
)))
3863 ((string-match "\\\\ref{\\([^{}\n]+\\)}" latex-frag
)
3864 (let* ((label (match-string 1 latex-frag
))
3865 (href (and label
(org-export-solidify-link-text label
)))
3866 (text (if (string-match "\\`[a-z]\\{1,10\\}:\\(.+\\)" label
)
3867 (substring label
(match-beginning 1))
3869 (org-e-odt-format-internal-link text href
)))
3870 (t (let ((processing-type (plist-get info
:LaTeX-fragments
)))
3872 ((member processing-type
'(t mathjax
))
3873 (org-e-odt-format-latex latex-frag
'mathjax
))
3874 ((equal processing-type
'dvipng
)
3875 (let* ((formula-link (org-e-odt-format-latex
3876 latex-frag processing-type
)))
3877 (when (and formula-link
3878 (string-match "file:\\([^]]*\\)" formula-link
))
3879 (org-e-odt-format-inline-image
3880 (match-string 1 formula-link
)))))
3881 (t latex-frag
)))))))
3886 (defun org-e-odt-line-break (line-break contents info
)
3887 "Transcode a LINE-BREAK object from Org to HTML.
3888 CONTENTS is nil. INFO is a plist holding contextual information."
3889 "<text:line-break/>\n")
3894 (defun org-e-odt-link--inline-image (link info
)
3895 "Return HTML code for an inline image.
3896 LINK is the link pointing to the inline image. INFO is a plist
3897 used as a communication channel."
3898 (let* ((parent (org-export-get-parent-paragraph link info
))
3899 (path (let ((raw-path (org-element-property :path link
)))
3900 (if (not (file-name-absolute-p raw-path
)) raw-path
3901 (expand-file-name raw-path
))))
3902 (caption (org-e-odt--caption/label-string
3903 (org-element-property :caption parent
)
3904 (org-element-property :name parent
)
3906 (label (org-element-property :name parent
))
3907 ;; Retrieve latex attributes from the element around.
3908 (attr (let ((raw-attr
3909 (mapconcat #'identity
3910 (org-element-property :attr_odt parent
)
3912 (unless (string= raw-attr
"") raw-attr
))))
3913 ;; Now clear ATTR from any special keyword and set a default
3914 ;; value if nothing is left.
3915 (setq attr
(if (not attr
) "" (org-trim attr
)))
3916 ;; Return proper string, depending on DISPOSITION.
3917 (let ((href (and label
(org-export-solidify-link-text label
))))
3918 (org-e-odt-format-inline-image path caption href attr
))))
3920 (defun org-e-odt-link (link desc info
)
3921 "Transcode a LINK object from Org to HTML.
3923 DESC is the description part of the link, or the empty string.
3924 INFO is a plist holding contextual information. See
3926 (let* ((type (org-element-property :type link
))
3927 (raw-path (org-element-property :path link
))
3928 ;; Ensure DESC really exists, or set it to nil.
3929 (desc (and (not (string= desc
"")) desc
))
3930 (imagep (org-export-inline-image-p
3931 link org-e-odt-inline-image-rules
))
3933 ((member type
'("http" "https" "ftp" "mailto"))
3934 (concat type
":" raw-path
))
3935 ((string= type
"file")
3936 (when (string-match "\\(.+\\)::.+" raw-path
)
3937 (setq raw-path
(match-string 1 raw-path
)))
3938 (if (file-name-absolute-p raw-path
)
3939 (concat "file://" (expand-file-name raw-path
))
3940 ;; TODO: Not implemented yet. Concat also:
3941 ;; (org-export-directory :HTML info)
3942 (concat "file://" raw-path
)))
3947 (imagep (org-e-odt-link--inline-image link info
))
3948 ;; Radioed target: Target's name is obtained from original raw
3949 ;; link. Path is parsed and transcoded in order to have a proper
3950 ;; display of the contents.
3951 ((string= type
"radio")
3952 (org-e-odt-format-internal-link
3953 (org-export-secondary-string
3954 (org-element-parse-secondary-string
3955 path
(cdr (assq 'radio-target org-element-object-restrictions
)))
3957 (org-export-solidify-link-text path
)))
3958 ;; Links pointing to an headline: Find destination and build
3959 ;; appropriate referencing command.
3960 ((member type
'("custom-id" "fuzzy" "id"))
3961 (let ((destination (if (string= type
"fuzzy")
3962 (org-export-resolve-fuzzy-link link info
)
3963 (org-export-resolve-id-link link info
))))
3964 (case (org-element-type destination
)
3965 ;; Fuzzy link points nowhere.
3967 (org-e-odt-format-fontify
3968 (or desc
(org-export-secondary-string
3969 (org-element-property :raw-link link
)
3970 'e-odt info
)) 'emphasis
))
3971 ;; Fuzzy link points to an invisible target.
3973 ;; LINK points to an headline. If headlines are numbered
3974 ;; and the link has no description, display headline's
3975 ;; number. Otherwise, display description or headline's
3978 (let* ((headline-no (org-export-get-headline-number destination info
))
3979 (label (format "sec-%s" (mapconcat 'number-to-string
3981 (section-no (mapconcat 'number-to-string headline-no
".")))
3985 ((plist-get info
:section-numbers
) section-no
)
3986 (t (org-export-secondary-string
3987 (org-element-property :title destination
)
3989 (org-e-odt-format-internal-link desc label
)))
3990 ;; Fuzzy link points to a target. Do as above.
3992 (let ((path (org-export-solidify-link-text path
)))
3994 (setq desc
(let ((number (org-export-get-ordinal
3997 (if (atom number
) (number-to-string number
)
3998 (mapconcat 'number-to-string number
"."))))))
3999 (org-e-odt-format-internal-link (or desc
"FIXME") path
))))))
4000 ;; Coderef: replace link with the reference name or the
4001 ;; equivalent line number.
4002 ((string= type
"coderef")
4003 (let* ((fmt (org-export-get-coderef-format path
(or desc
"%s")))
4004 (res (org-export-resolve-coderef path info
))
4005 (org-e-odt-suppress-xref nil
)
4006 (href (org-xml-format-href (concat "#coderef-" path
))))
4007 (format fmt
(org-e-odt-format-link res href
))))
4008 ;; Link type is handled by a special function.
4009 ((functionp (setq protocol
(nth 2 (assoc type org-link-protocols
))))
4010 (funcall protocol
(org-link-unescape path
) desc
'html
))
4011 ;; External link with a description part.
4012 ((and path desc
) (org-e-odt-format-link desc path
))
4013 ;; External link without a description part.
4014 (path (org-e-odt-format-link path path
))
4015 ;; No path, only description. Try to do something useful.
4016 (t (org-e-odt-format-fontify desc
'emphasis
)))))
4021 ;; Babel Calls are ignored.
4026 (defun org-e-odt-macro (macro contents info
)
4027 "Transcode a MACRO element from Org to HTML.
4028 CONTENTS is nil. INFO is a plist holding contextual information."
4029 ;; Use available tools.
4030 (org-export-expand-macro macro info
))
4035 (defun org-e-odt-paragraph (paragraph contents info
)
4036 "Transcode a PARAGRAPH element from Org to HTML.
4037 CONTENTS is the contents of the paragraph, as a string. INFO is
4038 the plist used as a communication channel."
4039 (let* ((style nil
) ; FIXME
4040 (class (cdr (assoc style
'((footnote .
"footnote")
4042 (extra (if class
(format " class=\"%s\"" class
) ""))
4043 (parent (org-export-get-parent paragraph info
))
4044 (parent-type (org-element-type parent
))
4045 (style (case parent-type
4046 (quote-block 'quote
)
4047 (center-block 'center
)
4049 (org-e-odt-format-stylized-paragraph style contents
)))
4054 (defun org-e-odt-plain-list (plain-list contents info
)
4055 "Transcode a PLAIN-LIST element from Org to HTML.
4056 CONTENTS is the contents of the list. INFO is a plist holding
4057 contextual information."
4058 (let* (arg1 ;; FIXME
4059 (type (org-element-property :type plain-list
))
4060 (attr (mapconcat #'identity
4061 (org-element-property :attr_odt plain-list
)
4063 (org-e-odt--wrap-label
4064 plain-list
(format "%s\n%s%s"
4065 (org-e-odt-begin-plain-list type
)
4066 contents
(org-e-odt-end-plain-list type
)))))
4070 (defun org-e-odt-convert-special-strings (string)
4071 "Convert special characters in STRING to ODT."
4072 (let ((all org-export-e-odt-special-string-regexps
)
4074 (while (setq a
(pop all
))
4075 (setq re
(car a
) rpl
(cdr a
) start
0)
4076 (while (string-match re string start
)
4077 (setq string
(replace-match rpl t nil string
))))
4080 ;; (defun org-e-odt-encode-plain-text (s)
4081 ;; "Convert plain text characters to HTML equivalent.
4082 ;; Possible conversions are set in `org-export-html-protect-char-alist'."
4083 ;; (let ((cl org-e-odt-protect-char-alist) c)
4084 ;; (while (setq c (pop cl))
4086 ;; (while (string-match (car c) s start)
4087 ;; (setq s (replace-match (cdr c) t t s)
4088 ;; start (1+ (match-beginning 0))))))
4091 (defun org-e-odt-plain-text (text info
)
4092 "Transcode a TEXT string from Org to HTML.
4093 TEXT is the string to transcode. INFO is a plist holding
4094 contextual information."
4095 (setq text
(org-e-odt-encode-plain-text text t
))
4096 ;; Protect %, #, &, $, ~, ^, _, { and }.
4097 ;; (while (string-match "\\([^\\]\\|^\\)\\([%$#&{}~^_]\\)" text)
4099 ;; (replace-match (format "\\%s" (match-string 2 text)) nil t text 2)))
4101 ;; (setq text (replace-regexp-in-string
4102 ;; "\\(?:[^\\]\\|^\\)\\(\\\\\\)\\(?:[^%$#&{}~^_\\]\\|$\\)"
4103 ;; "$\\backslash$" text nil t 1))
4104 ;; HTML into \HTML{} and TeX into \TeX{}.
4105 ;; (let ((case-fold-search nil)
4107 ;; (while (string-match "\\<\\(\\(?:La\\)?TeX\\)\\>" text start)
4108 ;; (setq text (replace-match
4109 ;; (format "\\%s{}" (match-string 1 text)) nil t text)
4110 ;; start (match-end 0))))
4111 ;; Handle quotation marks
4112 ;; (setq text (org-e-odt--quotation-marks text info))
4113 ;; Convert special strings.
4114 ;; (when (plist-get info :with-special-strings)
4115 ;; (while (string-match (regexp-quote "...") text)
4116 ;; (setq text (replace-match "\\ldots{}" nil t text))))
4117 (when (plist-get info
:with-special-strings
)
4118 (setq text
(org-e-odt-convert-special-strings text
)))
4119 ;; Handle break preservation if required.
4120 (when (plist-get info
:preserve-breaks
)
4121 (setq text
(replace-regexp-in-string "\\(\\\\\\\\\\)?[ \t]*\n" " \\\\\\\\\n"
4127 ;;;; Property Drawer
4129 (defun org-e-odt-property-drawer (property-drawer contents info
)
4130 "Transcode a PROPERTY-DRAWER element from Org to HTML.
4131 CONTENTS is nil. INFO is a plist holding contextual
4133 ;; The property drawer isn't exported but we want separating blank
4134 ;; lines nonetheless.
4140 (defun org-e-odt-quote-block (quote-block contents info
)
4141 "Transcode a QUOTE-BLOCK element from Org to HTML.
4142 CONTENTS holds the contents of the block. INFO is a plist
4143 holding contextual information."
4144 (org-e-odt--wrap-label quote-block contents
))
4149 (defun org-e-odt-quote-section (quote-section contents info
)
4150 "Transcode a QUOTE-SECTION element from Org to HTML.
4151 CONTENTS is nil. INFO is a plist holding contextual information."
4152 (let ((value (org-remove-indentation
4153 (org-element-property :value quote-section
))))
4154 (when value
(org-e-odt-format-source-code-or-example value nil
))))
4159 (defun org-e-odt-section (section contents info
) ; FIXME
4160 "Transcode a SECTION element from Org to HTML.
4161 CONTENTS holds the contents of the section. INFO is a plist
4162 holding contextual information."
4167 (defun org-e-odt-radio-target (radio-target text info
)
4168 "Transcode a RADIO-TARGET object from Org to HTML.
4169 TEXT is the text of the target. INFO is a plist holding
4170 contextual information."
4171 (org-e-odt-format-anchor
4172 text
(org-export-solidify-link-text
4173 (org-element-property :raw-value radio-target
))))
4178 (defun org-e-odt-special-block (special-block contents info
)
4179 "Transcode a SPECIAL-BLOCK element from Org to HTML.
4180 CONTENTS holds the contents of the block. INFO is a plist
4181 holding contextual information."
4182 (let ((type (downcase (org-element-property :type special-block
))))
4183 (org-e-odt--wrap-label
4185 (format "\\begin{%s}\n%s\\end{%s}" type contents type
))))
4190 (defun org-e-odt-src-block (src-block contents info
)
4191 "Transcode a SRC-BLOCK element from Org to HTML.
4192 CONTENTS holds the contents of the item. INFO is a plist holding
4193 contextual information."
4194 (let* ((lang (org-element-property :language src-block
))
4195 (code (org-export-handle-code src-block info nil nil t
))
4196 (caption (org-element-property :caption src-block
))
4197 (label (org-element-property :name src-block
)))
4198 ;; FIXME: Handle caption
4200 ;; caption-str (when caption)
4201 ;; (main (org-export-secondary-string (car caption) 'e-odt info))
4202 ;; (secondary (org-export-secondary-string (cdr caption) 'e-odt info))
4203 ;; (caption-str (org-e-odt--caption/label-string caption label info))
4204 (org-e-odt-format-source-code-or-example code lang
)))
4207 ;;;; Statistics Cookie
4209 (defun org-e-odt-statistics-cookie (statistics-cookie contents info
)
4210 "Transcode a STATISTICS-COOKIE object from Org to HTML.
4211 CONTENTS is nil. INFO is a plist holding contextual information."
4212 (let ((cookie-value (org-element-property :value statistics-cookie
)))
4213 (org-e-odt-format-fontify cookie-value
'code
)))
4218 (defun org-e-odt-subscript (subscript contents info
)
4219 "Transcode a SUBSCRIPT object from Org to HTML.
4220 CONTENTS is the contents of the object. INFO is a plist holding
4221 contextual information."
4222 ;; (format (if (= (length contents) 1) "$_%s$" "$_{\\mathrm{%s}}$") contents)
4223 (org-e-odt-format-fontify contents
'subscript
))
4228 (defun org-e-odt-superscript (superscript contents info
)
4229 "Transcode a SUPERSCRIPT object from Org to HTML.
4230 CONTENTS is the contents of the object. INFO is a plist holding
4231 contextual information."
4232 ;; (format (if (= (length contents) 1) "$^%s$" "$^{\\mathrm{%s}}$") contents)
4233 (org-e-odt-format-fontify contents
'superscript
))
4238 (defun org-e-odt-get-colwidth (c)
4239 (let ((col-widths (plist-get table-info
:width
)))
4240 (or (and org-lparse-table-is-styled
(aref col-widths c
)) 0)))
4242 (defun org-e-odt-table-row (fields &optional text-for-empty-fields
)
4243 (incf org-e-odt-table-rownum
)
4245 (org-e-odt-format-table-row
4248 (when (and (string= x
"") text-for-empty-fields
)
4249 (setq x text-for-empty-fields
))
4251 (let ((horiz-span (org-e-odt-get-colwidth i
)))
4252 (org-e-odt-format-table-cell
4253 x org-e-odt-table-rownum i horiz-span
)))
4256 (defun org-e-odt-table-preamble ()
4257 (let ((colgroup-vector (plist-get table-info
:column-groups
)) ;; FIXME
4258 c gr colgropen preamble
)
4259 (unless (aref colgroup-vector
0)
4260 (setf (aref colgroup-vector
0) 'start
))
4261 (dotimes (c columns-number preamble
)
4262 (setq gr
(aref colgroup-vector c
))
4266 (when (memq gr
'(start start-end
))
4267 (prog1 (if colgropen
"</colgroup>\n<colgroup>" "\n<colgroup>")
4268 (setq colgropen t
)))
4269 (let* ((colalign-vector (plist-get table-info
:alignment
)) ;; FIXME
4270 (align (cdr (assoc (aref colalign-vector c
)
4273 ("c" .
"center")))))
4274 (alignspec (if (and (boundp 'org-e-odt-format-table-no-css
)
4275 org-e-odt-format-table-no-css
)
4276 " align=\"%s\"" " class=\"%s\""))
4277 (extra (format alignspec align
)))
4278 (format "<col%s />" extra
))
4279 (when (memq gr
'(end start-end
))
4280 (setq colgropen nil
)
4282 (concat preamble
(if colgropen
"</colgroup>"))))
4284 (defun org-e-odt-list-table (lines caption label attributes
)
4285 (setq lines
(org-e-odt-org-table-to-list-table lines
))
4286 (let* ((splice nil
) head
4287 (org-e-odt-table-rownum -
1)
4290 org-e-odt-table-cur-rowgrp-is-hdr
4291 org-e-odt-table-rowgrp-open
4293 (org-lparse-table-style 'org-table
)
4294 org-lparse-table-is-styled
)
4297 (setq org-lparse-table-is-styled nil
)
4298 (mapconcat 'org-e-odt-table-row lines
"\n"))
4300 (setq org-lparse-table-is-styled t
)
4303 (org-e-odt-begin-table caption label attributes
)
4304 ;; FIXME (org-e-odt-table-preamble)
4305 (org-e-odt-begin-table-rowgroup head
)
4310 ((equal line
'hline
) (org-e-odt-begin-table-rowgroup))
4311 (t (org-e-odt-table-row line
))))
4314 (org-e-odt-end-table-rowgroup)
4315 (org-e-odt-end-table))))))
4317 (defun org-e-odt-transcode-table-row (row)
4318 (if (string-match org-table-hline-regexp row
) 'hline
4321 (org-export-secondary-string
4322 (let ((cell (org-element-parse-secondary-string
4324 (cdr (assq 'table org-element-string-restrictions
)))))
4327 (org-split-string row
"[ \t]*|[ \t]*"))))
4329 (defun org-e-odt-org-table-to-list-table (lines &optional splice
)
4330 "Convert org-table to list-table.
4331 LINES is a list of the form (ROW1 ROW2 ROW3 ...) where each
4332 element is a `string' representing a single row of org-table.
4333 Thus each ROW has vertical separators \"|\" separating the table
4334 fields. A ROW could also be a row-group separator of the form
4335 \"|---...|\". Return a list of the form (ROW1 ROW2 ROW3
4336 ...). ROW could either be symbol `'hline' or a list of the
4337 form (FIELD1 FIELD2 FIELD3 ...) as appropriate."
4341 (while (setq line
(pop lines
))
4342 (unless (string-match "^[ \t]*|-" line
)
4343 (push (org-e-odt-transcode-table-row line
) lines-1
))))
4344 (t (while (setq line
(pop lines
))
4346 ((string-match "^[ \t]*|-" line
)
4347 (when lines
(push 'hline lines-1
)))
4348 (t (push (org-e-odt-transcode-table-row line
) lines-1
))))))
4349 (nreverse lines-1
)))
4351 (defun org-e-odt-table-table (raw-table)
4353 (with-current-buffer (get-buffer-create "*org-export-table*")
4355 (let ((output (with-temp-buffer
4358 (re-search-forward "^[ \t]*|[^|]" nil t
)
4359 (table-generate-source 'html
"*org-export-table*")
4360 (with-current-buffer "*org-export-table*"
4361 (org-trim (buffer-string))))))
4362 (kill-buffer (get-buffer "*org-export-table*"))
4365 (defun org-e-odt-table (table contents info
)
4366 "Transcode a TABLE element from Org to HTML.
4367 CONTENTS is nil. INFO is a plist holding contextual information."
4368 (let* ((label (org-element-property :name table
))
4369 (caption (org-e-odt--caption/label-string
4370 (org-element-property :caption table
) label info
))
4371 (attr (mapconcat #'identity
4372 (org-element-property :attr_odt table
)
4374 (raw-table (org-element-property :raw-table table
))
4375 (table-type (org-element-property :type table
)))
4378 ;; (org-e-odt-table-table raw-table)
4381 (let* ((table-info (org-export-table-format-info raw-table
))
4382 (columns-number (length (plist-get table-info
:alignment
)))
4383 (lines (org-split-string
4384 (org-export-clean-table
4385 raw-table
(plist-get table-info
:special-column-p
)) "\n"))
4387 (genealogy (org-export-get-genealogy table info
))
4388 (parent (car genealogy
))
4389 (parent-type (org-element-type parent
)))
4390 (org-e-odt-list-table lines caption label attr
))))))
4395 (defun org-e-odt-target (target contents info
)
4396 "Transcode a TARGET object from Org to HTML.
4397 CONTENTS is nil. INFO is a plist holding contextual
4399 (org-e-odt-format-anchor
4400 "" (org-export-solidify-link-text (org-element-property :value target
))))
4405 (defun org-e-odt-time-stamp (time-stamp contents info
)
4406 "Transcode a TIME-STAMP object from Org to HTML.
4407 CONTENTS is nil. INFO is a plist holding contextual
4409 ;; (let ((value (org-element-property :value time-stamp))
4410 ;; (type (org-element-property :type time-stamp))
4411 ;; (appt-type (org-element-property :appt-type time-stamp)))
4412 ;; (concat (cond ((eq appt-type 'scheduled)
4413 ;; (format "\\textbf{\\textsc{%s}} " org-scheduled-string))
4414 ;; ((eq appt-type 'deadline)
4415 ;; (format "\\textbf{\\textsc{%s}} " org-deadline-string))
4416 ;; ((eq appt-type 'closed)
4417 ;; (format "\\textbf{\\textsc{%s}} " org-closed-string)))
4418 ;; (cond ((memq type '(active active-range))
4419 ;; (format org-e-odt-active-timestamp-format value))
4420 ;; ((memq type '(inactive inactive-range))
4421 ;; (format org-e-odt-inactive-timestamp-format value))
4423 ;; (format org-e-odt-diary-timestamp-format value)))))
4424 (let ((value (org-element-property :value time-stamp
))
4425 (type (org-element-property :type time-stamp
))
4426 (appt-type (org-element-property :appt-type time-stamp
)))
4427 (setq value
(org-export-secondary-string value
'e-odt info
))
4428 (org-e-odt-format-fontify
4430 (org-e-odt-format-fontify
4431 (cond ((eq appt-type
'scheduled
) org-scheduled-string
)
4432 ((eq appt-type
'deadline
) org-deadline-string
)
4433 ((eq appt-type
'closed
) org-closed-string
)) "timestamp-kwd")
4434 ;; FIXME: (org-translate-time value)
4435 (org-e-odt-format-fontify value
"timestamp"))
4436 "timestamp-wrapper")))
4441 (defun org-e-odt-verbatim (verbatim contents info
)
4442 "Transcode a VERBATIM object from Org to HTML.
4443 CONTENTS is nil. INFO is a plist used as a communication
4446 verbatim
(org-element-property :value verbatim
) info
))
4451 (defun org-e-odt-verse-block (verse-block contents info
)
4452 "Transcode a VERSE-BLOCK element from Org to HTML.
4453 CONTENTS is nil. INFO is a plist holding contextual information."
4454 ;; Replace each newline character with line break. Also replace
4455 ;; each blank line with a line break.
4456 (setq contents
(replace-regexp-in-string
4457 "^ *\\\\\\\\$" "<br/>\n"
4458 (replace-regexp-in-string
4459 "\\(\\\\\\\\\\)?[ \t]*\n" " <br/>\n"
4460 (org-remove-indentation
4461 (org-export-secondary-string
4462 (org-element-property :value verse-block
)
4465 ;; Replace each white space at beginning of a line with a
4466 ;; non-breaking space.
4467 (while (string-match "^[ \t]+" contents
)
4468 (let ((new-str (org-e-odt-format-spaces
4469 (length (match-string 0 contents
)))))
4470 (setq contents
(replace-match new-str nil t contents
))))
4472 (org-e-odt--wrap-label
4473 verse-block
(format "<p class=\"verse\">\n%s</p>" contents
)))
4478 ;;; Filter Functions
4480 ;;;; Filter Settings
4483 ;;; Interactive functions
4485 (defun org-e-odt-export-to-odt
4486 (&optional subtreep visible-only body-only ext-plist pub-dir
)
4487 "Export current buffer to a HTML file.
4489 If narrowing is active in the current buffer, only export its
4492 If a region is active, export that region.
4494 When optional argument SUBTREEP is non-nil, export the sub-tree
4495 at point, extracting information from the headline properties
4498 When optional argument VISIBLE-ONLY is non-nil, don't export
4499 contents of hidden elements.
4501 When optional argument BODY-ONLY is non-nil, only write code
4502 between \"\\begin{document}\" and \"\\end{document}\".
4504 EXT-PLIST, when provided, is a property list with external
4505 parameters overriding Org default settings, but still inferior to
4506 file-local settings.
4508 When optional argument PUB-DIR is set, use it as the publishing
4511 Return output file's name."
4515 (with-current-buffer (get-buffer-create "*debug*")
4518 ;; (let* ((outfile (org-export-output-file-name ".html" subtreep pub-dir))
4519 ;; (outfile "content.xml"))
4520 ;; (org-export-to-file
4521 ;; 'e-odt outfile subtreep visible-only body-only ext-plist))
4523 (let* ((outbuf (org-e-odt-init-outfile))
4524 (target (org-export-output-file-name ".odt" subtreep pub-dir
))
4525 (outdir (file-name-directory (buffer-file-name outbuf
)))
4526 (default-directory outdir
))
4528 ;; FIXME: for copying embedded images
4529 (setq org-current-export-file
4530 (file-name-directory
4531 (org-export-output-file-name ".odt" subtreep nil
)))
4533 (org-export-to-buffer
4535 (memq 'subtree optns
) (memq 'visible optns
) (memq 'body optns
))
4537 (setq org-lparse-opt-plist nil
) ; FIXME
4538 (org-e-odt-save-as-outfile target
;; info
4548 ;;; FIXMES, TODOS, FOR REVIEW etc
4550 ;;;; org-format-table-html
4551 ;;;; org-format-org-table-html
4552 ;;;; org-format-table-table-html
4553 ;;;; org-table-number-fraction
4554 ;;;; org-table-number-regexp
4555 ;;;; org-e-odt-table-caption-above
4558 ;;;; "<span style=\"visibility:hidden;\">%s</span>"
4559 ;;;; Remove display properties
4560 ;;;; org-e-odt-final-hook
4562 ;;;; org-e-odt-with-timestamp
4563 ;;;; org-e-odt-html-helper-timestamp
4565 ;;;; org-export-as-html-and-open
4566 ;;;; org-export-as-html-batch
4567 ;;;; org-export-as-html-to-buffer
4568 ;;;; org-replace-region-by-html
4569 ;;;; org-export-region-as-html
4570 ;;;; org-export-as-html
4572 ;;;; (org-export-directory :html opt-plist)
4573 ;;;; (plist-get opt-plist :html-extension)
4574 ;;;; org-e-odt-toplevel-hlevel
4575 ;;;; org-e-odt-special-string-regexps
4576 ;;;; org-e-odt-coding-system
4577 ;;;; org-e-odt-coding-system
4578 ;;;; org-e-odt-inline-images
4579 ;;;; org-e-odt-inline-image-extensions
4580 ;;;; org-e-odt-protect-char-alist
4581 ;;;; org-e-odt-table-use-header-tags-for-first-column
4582 ;;;; org-e-odt-todo-kwd-class-prefix
4583 ;;;; org-e-odt-tag-class-prefix
4584 ;;;; org-e-odt-footnote-separator
4587 ;;; Library Initializations
4591 ;; Let Org open all OpenDocument files using system-registered app
4592 (add-to-list 'org-file-apps
4593 (cons (concat "\\." (car desc
) "\\'") 'system
))
4594 ;; Let Emacs open all OpenDocument files in archive mode
4595 (add-to-list 'auto-mode-alist
4596 (cons (concat "\\." (car desc
) "\\'") 'archive-mode
)))
4597 org-e-odt-file-extensions
)
4600 ;; (eval-after-load 'org-exp
4601 ;; '(add-to-list 'org-export-inbuffer-options-extra
4602 ;; '("ODT_STYLES_FILE" :odt-styles-file)))
4604 (provide 'org-e-odt
)
4606 ;;; org-e-odt.el ends here